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_tresult = 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数据

BufferQueue学习相关推荐

  1. BufferQueue 学习总结(内附动态图)

    一.前言 <最简单的BufferQueue测试程序(一)> <最简单的BufferQueue测试程序(二)> <最简单的BufferQueue测试程序(三)> 本文 ...

  2. 【转】自上而下解读Android显示流程

    同济大学 计算机系统结构硕士 107 人赞同了该文章 当我们点击"知乎"这个应用后,它是怎么在屏幕上显示出来的? 这个问题困扰我很久了,当我刚接触显示的时候,大约是十年前的事情了, ...

  3. Android Camera App

    主要从APP层梳理Android Camera 相关的内容,暂时以记账的形式记录. stream imageReader surface BufferQueue 参考文档: BufferQueue 学 ...

  4. Android SurfaceFlinger 学习之路(五)----VSync 工作原理

    原址 VSync信号的科普我们上一篇已经介绍过了,这篇我们要分析在SurfaceFlinger中的作用.(愈发觉得做笔记对自己记忆模块巩固有很多帮助,整理文章不一定是用来给别人看的,但一定是为加强自己 ...

  5. 关于Android Framework渲染机制,你需要学习哪些?

    聊到Android的渲染流程部分,部分Android开发脑海中估计又会想起面试官在面试时提出的那些死亡面试题: Android渲染的整体架构是怎样的? Android渲染的生产者包括哪些?Skia与O ...

  6. Android学习资源汇总

    镇楼:Android官方培训课程中文版 学习网址 Android官网API,文档,开发,资讯 玩Android–鸿洋名下 trinea segmentfault头条 Google Android De ...

  7. 安卓框架,分析项目中surfaceFlinger出现的bug ---queueBuffer: BufferQueue has been abandoned

    学习android graphic很好的系列文章:https://blog.csdn.net/lewif/article/details/50526494 GlSurfaceview和egl的相关文章 ...

  8. Android高级架构师系统学习——Android-音频可视化,程序员怎样优雅度过35岁中年危机

    Android Visualizer 系统 Visualizer 提供了方便的 api 来获取播放音频的波形或 FFT 数据,一般使用方式是: 用 audio session ID 创建 Visual ...

  9. SurfaceFlinger学习笔记(三)之SurfaceFlinger进程

    概述 本系列是基于android Q 即android10 SurfaceFlinger学习笔记(一)应用启动流程 SurfaceFlinger学习笔记(二)之Surface SurfaceFling ...

最新文章

  1. Ubuntu16.04下arm-linux-gcc交叉编译环境搭建
  2. Eclipse(properties)插件:PropertyEditor在线安装
  3. 发起一个ajax请求,发送ajax请求
  4. 【c++】5.函数传指针与传值特容易混淆的点
  5. 杭电1203java实现
  6. leetcode 打印_剑指 Offer 32 - III 从上到下打印二叉树 III - leetcode 剑指offer
  7. IDEA 程序包org.springframework.web.bind.annotation不存在
  8. caffe源码解析—image_data_layer层
  9. js 里面的键盘事件对应的键码
  10. 阿里云实时计算,前世功,今生能!
  11. Annotation request in WebIDE automatic generated project
  12. js javascript UTF-8 GB2312编码转换
  13. desktop docker 无法卸载_Docker容器无法停止或移除-权限被拒绝错误
  14. 【Java进阶营】Java多线程基础学习(一)
  15. JS实现数字千位符格式化方法
  16. python字符串_Python的字符串和编码
  17. 终于找到可转载的摄影基础知识贴了
  18. 2021数学建模国赛A题思路
  19. 利用Python实现图片信息隐藏
  20. 最全Media 响应式 设置方法

热门文章

  1. 【寒江雪】中点画椭圆算法
  2. canvas模拟中国铁路运行图
  3. python实战代码
  4. 实战 | SSRF攻击内网的实战案例
  5. QN8025FM接收机
  6. iPhone和ipad键盘高度及键盘响应事件
  7. 怪物农场2修改日志1 - FirstBlood
  8. yolo图像检测数据集格式转换:xml 与 txt格式相互转换
  9. php导出试卷,PHP生成word文档格式试卷的代码
  10. SQL Serve [SQL Server无法连接到服务器]标题: 连接到服务器 ------------------------------ 无法连接到******。 ---解决方法