在
https://blog.youkuaiyun.com/aaajj/article/details/93653074
https://blog.youkuaiyun.com/aaajj/article/details/102537628
里面讨论了从SurfaceFlinger中获取layer图像的一个试验
通过获取GraphicBuffer来进行处理的,在实际使用中,GraphicBuffer的管理和获取都是通过BufferQueue来进行的,
这篇博客写的很好,关于BufferQueue的测试试验,
最简单的BufferQueue测试程序(三)
https://blog.youkuaiyun.com/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.youkuaiyun.com/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.youkuaiyun.com/tung214/article/details/36628897
Android用C++创建surface显示RGB数据