BufferQueue学习

 

https://blog.csdn.net/aaajj/article/details/93653074

https://blog.csdn.net/aaajj/article/details/102537628

里面讨论了从SurfaceFlinger中获取layer图像的一个试验

 

通过获取GraphicBuffer来进行处理的,在实际使用中,GraphicBuffer的管理和获取都是通过BufferQueue来进行的,

 

 

这篇博客写的很好,关于BufferQueue的测试试验,

最简单的BufferQueue测试程序(三)

 

https://blog.csdn.net/hexiaolong2009/article/details/99093375

 

 

通过查看资料,大概可以知道,

 

    sp<IGraphicBufferProducer> producer;

    sp<IGraphicBufferConsumer> consumer;

BufferQueue::createBufferQueue(&producer, &consumer);

 

 

这里我们从进程的角度去查看,BufferQueue在一个进程中生成了,一般是Surfaceflinger,

然后,BufferQueue对象有相关联的2个对象,producer和consumer来分布对应生产者和消费者,producer和BufferQueue是在同一个进程中的,这样就可以进行资源的获取,

但是,producer又作为一个binder服务端对象,这样客户端就可以通过proxy代理对象来和producer来进行通信,进而使客户端进程可以获取到资源。

 

这里再看看画图的例子,

Surface程序

 

修改自https://blog.csdn.net/tung214/article/details/36628897

Android用C++创建surface显示RGB数据

 

很多api变化了,在Android8.1上报错。进行了修改

 

 

 

 

#define LOG_TAG "bindertest"

 

#include <stdio.h>

#include <binder/IInterface.h>

#include <binder/Parcel.h>

#include <binder/IBinder.h>

#include <binder/Binder.h>

#include <binder/ProcessState.h>

#include <binder/IPCThreadState.h>

#include <binder/IServiceManager.h>

 

#include <iostream>

#include <iomanip>

 

#include <unistd.h>

 

//for ALOGD

#include <log/log.h>

 

#include <cutils/memory.h>

 

//test socketpair

#include <sys/types.h>

#include <error.h>

#include <errno.h>

 

#include <gui/Surface.h>

#include <gui/SurfaceComposerClient.h>

#include <android/native_window.h>

 

 

using namespace android;

using namespace std;

//

 

int main(int argc, char** argv)

{

       //the color is ABGR

       int color = 0xFF0000FF;

       if (argc == 2 && argv[1][0] == '1') color = 0xFFFF0000;

       if (argc == 2 && argv[1][0] == '2') color = 0xFF000000;

       if (argc == 2 && argv[1][0] == '3') color = 0xFF00FF00;

       if (argc == 2 && argv[1][0] == '4') color = 0x00FF00FF;

       if (argc == 2 && argv[1][0] == 'b') color = 0x00000000;

       if (argc == 2 && argv[1][0] == 'a') color = 0x00FF00FF;

             

    // set up the thread-pool

    sp<ProcessState> proc(ProcessState::self());

    ProcessState::self()->startThreadPool();

 

    // create a client to surfaceflinger

    sp<SurfaceComposerClient> client = new SurfaceComposerClient();

   

    sp<SurfaceControl> surfaceControl = client->createSurface(String8("testDraw"),

            160, 240, PIXEL_FORMAT_RGBA_8888, 0);

 

    sp<Surface> surface = surfaceControl->getSurface();

 

    SurfaceComposerClient::openGlobalTransaction();

    surfaceControl->setLayer(100000);

    SurfaceComposerClient::closeGlobalTransaction();

 

    ANativeWindow_Buffer outBuffer;

    surface->lock(&outBuffer, NULL);

    ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);

    android_memset32((uint32_t*)outBuffer.bits, color, bpr*outBuffer.height);

    surface->unlockAndPost();

 

              cout << "outBuffer.stride = " << outBuffer.stride << ", bytesPerPixel(outBuffer.format) = "

               << bytesPerPixel(outBuffer.format) << ", outBuffer.height = " << outBuffer.height << endl;

/*

    surface->lock(&outBuffer, NULL);

    android_memset16((uint16_t*)outBuffer.bits, 0x07E0, bpr*outBuffer.height);

    surface->unlockAndPost();

 

    SurfaceComposerClient::openGlobalTransaction();

    surfaceControl->setSize(320, 240);

    SurfaceComposerClient::closeGlobalTransaction();

 */  

    IPCThreadState::self()->joinThreadPool();

   

    return 0;

}

 

Android.mk

LOCAL_PATH := $(call my-dir)

 

#for service

 

include $(CLEAR_VARS)

 

 

LOCAL_SRC_FILES:= \

        service.cpp

       

 

LOCAL_SHARED_LIBRARIES := \

        libbase \

        libutils \

        liblog \

        libbinder \

        libcutils libskia libui libgui

 

 

LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code       

 

 

LOCAL_MODULE:= testDraw

 

include $(BUILD_EXECUTABLE)

 

 

执行程序,在手机上显示160*240的surface

 

 

 

 

看上去通过这么简单的几个操作就获取到了GraphicBuffer

    sp<SurfaceComposerClient> client = new SurfaceComposerClient();

   

    sp<SurfaceControl> surfaceControl = client->createSurface(String8("testDraw"),

            160, 240, PIXEL_FORMAT_RGBA_8888, 0);

 

    sp<Surface> surface = surfaceControl->getSurface();

 

    ANativeWindow_Buffer outBuffer;

    surface->lock(&outBuffer, NULL);

    ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);

    android_memset32((uint32_t*)outBuffer.bits, color, bpr*outBuffer.height);

 

 

看上去没有BufferQueue,producer什么事情一样,

 

 

在client->createSurface的时候,已经创建了producer对象

//frameworks/native/libs/gui/SurfaceComposerClient.cpp

sp<SurfaceControl> SurfaceComposerClient::createSurface(

        const String8& name,

        uint32_t w,

        uint32_t h,

        PixelFormat format,

        uint32_t flags)

{

    sp<SurfaceControl> sur;

    if (mStatus == NO_ERROR) {

        sp<IBinder> handle;

        sp<IGraphicBufferProducer> gbp;

        status_t err = mClient->createSurface(name, w, h, format, flags,

                &handle, &gbp);

        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));

        if (err == NO_ERROR) {

            sur = new SurfaceControl(this, handle, gbp);

        }

    }

    return sur;

}

 

里面的mClient->createSurface调用到

//frameworks/native/services/surfaceflinger/Client.cpp

status_t Client::createSurface(

        const String8& name,

        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,

        sp<IBinder>* handle,

        sp<IGraphicBufferProducer>* gbp)

{

    /*

     * createSurface must be called from the GL thread so that it can

     * have access to the GL context.

     */

 

    class MessageCreateLayer : public MessageBase {

        SurfaceFlinger* flinger;

        Client* client;

        sp<IBinder>* handle;

        sp<IGraphicBufferProducer>* gbp;

        status_t result;

        const String8& name;

        uint32_t w, h;

        PixelFormat format;

        uint32_t flags;

    public:

        MessageCreateLayer(SurfaceFlinger* flinger,

                const String8& name, Client* client,

                uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,

                sp<IBinder>* handle,

                sp<IGraphicBufferProducer>* gbp)

            : flinger(flinger), client(client),

              handle(handle), gbp(gbp), result(NO_ERROR),

              name(name), w(w), h(h), format(format), flags(flags) {

        }

        status_t getResult() const { return result; }

        virtual bool handler() {

            result = flinger->createLayer(name, client, w, h, format, flags,

                    handle, gbp);

            return true;

        }

    };

 

    sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),

            name, this, w, h, format, flags, handle, gbp);

    mFlinger->postMessageSync(msg);

    return static_cast<MessageCreateLayer*>( msg.get() )->getResult();

}

 

然后调用到SurfaceFlinger里面去了

 

status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,

        const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,

        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)

{

    ......

    *outLayer = new Layer(this, client, name, w, h, flags);

    status_t err = (*outLayer)->setBuffers(w, h, format, flags);

    if (err == NO_ERROR) {

        *handle = (*outLayer)->getHandle();

        *gbp = (*outLayer)->getProducer();

    }

 

    return err;

}

在SurfaceFliger里创建了Layer对象,并且和gbp即producer关联起来了,

 

注意看,Layer创建的时候,创建了BufferQueue对象,

 

//frameworks/native/services/surfaceflinger/Layer.cpp

void Layer::onFirstRef() {

    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use

    sp<IGraphicBufferProducer> producer;

    sp<IGraphicBufferConsumer> consumer;

    BufferQueue::createBufferQueue(&producer, &consumer);

    mProducer = new MonitoredProducer(producer, mFlinger);

    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);

    ......

}

 

通过这样一系列操作,画图进程其实里面已经有了produce对象,

再看看这个最基本的绘图程序,

    sp<SurfaceComposerClient> client = new SurfaceComposerClient();

   

    sp<SurfaceControl> surfaceControl = client->createSurface(String8("testDraw"),

            160, 240, PIXEL_FORMAT_RGBA_8888, 0);

 

    sp<Surface> surface = surfaceControl->getSurface();

 

    ANativeWindow_Buffer outBuffer;

    surface->lock(&outBuffer, NULL);

    ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);

    android_memset32((uint32_t*)outBuffer.bits, color, bpr*outBuffer.height);

    surface->unlockAndPost();

 

createSurface操作后,在画图进程中已经有了producer对象,

按照BufferQueue的资料介绍,需要通过dequeueBuffer操作来获取GraphicBuffer,现在好像没有看到dequeueBuffer,

我们来看看lock的实现,

//frameworks/native/libs/gui/Surface.cpp

status_t Surface::lock(

        ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)

{

    ......

    ANativeWindowBuffer* out;

    int fenceFd = -1;

    //拿到一个缓冲区

    status_t err = dequeueBuffer(&out, &fenceFd);

    if (err == NO_ERROR) {

        sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));

        ......

        void* vaddr;

        status_t res = backBuffer->lockAsync(

                GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,

                newDirtyRegion.bounds(), &vaddr, fenceFd);

        if (res != 0) {

            err = INVALID_OPERATION;

        } else {

            mLockedBuffer = backBuffer;

            outBuffer->width  = backBuffer->width;

            outBuffer->height = backBuffer->height;

            outBuffer->stride = backBuffer->stride;

            outBuffer->format = backBuffer->format;

            outBuffer->bits   = vaddr;

        }

    }

    return err;

}

里面的dequeueBuffer调用到

231int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {



260    int buf = -1;
261    sp<Fence> fence;
262    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
263            reqWidth, reqHeight, reqFormat, reqUsage);
264
265    if (result < 0) {
266        ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
267                "(%d, %d, %d, %d) failed: %d", reqWidth, reqHeight, reqFormat,
268                reqUsage, result);
269        return result;
270    }
271
272    Mutex::Autolock lock(mMutex);
273
274    sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
275
276    // this should never happen
277    ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
278
279    if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
280        freeAllBuffers();
281    }
282
283    if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
284        result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
285        if (result != NO_ERROR) {
286            ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
287            mGraphicBufferProducer->cancelBuffer(buf, fence);
288            return result;
289        }
290    }
291
292    if (fence->isValid()) {
293        *fenceFd = fence->dup();
294        if (*fenceFd == -1) {
295            ALOGE("dequeueBuffer: error duping fence: %d", errno);
296            // dup() should never fail; something is badly wrong. Soldier on
297            // and hope for the best; the worst that should happen is some
298            // visible corruption that lasts until the next frame.
299        }
300    } else {
301        *fenceFd = -1;
302    }
303
304    *buffer = gbuf.get();
305
306    if (mSharedBufferMode && mAutoRefresh) {
307        mSharedBufferSlot = buf;
308        mSharedBufferHasBeenQueued = false;
309    } else if (mSharedBufferSlot == buf) {
310        mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
311        mSharedBufferHasBeenQueued = false;
312    }
313
314    return OK;
315}

 

 

可以看到,调用了producer的dequeueBuffer方法,

 

    sp<SurfaceControl> surfaceControl = client->createSurface(String8("testDraw"),

            160, 240, PIXEL_FORMAT_RGBA_8888, 0);

 

    sp<Surface> surface = surfaceControl->getSurface();

 

    ANativeWindow_Buffer outBuffer;

    surface->lock(&outBuffer, NULL);

 

这几句代码中,真是暗潮汹涌,隐藏了BufferQueue的相关操作细节。

 

 

 

参考资料:

https://www.jianshu.com/p/993e66015c18

Android 绘图机制

 

 

https://blog.csdn.net/tung214/article/details/36628897

Android用C++创建surface显示RGB数据

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值