1. 安卓图形界面简介
1)图形组件间的工作流程
无论开发者使用什么渲染 API,一切内容都会渲染到 Surface 上。Surface 表示缓冲区队列中的生产者,而缓冲区队列通常会被 SurfaceFlinger 消耗。在 Android 平台上创建的每个窗口都由 Surface 提供支持。所有被渲染的可见 Surface 都被 SurfaceFlinger 合成到屏幕。
下图显示了关键组件如何协同工作:
从工作流程的角度去看,主要组件如下所述:
图像流生产者(Image Stream Producers)
图像流生产者可以是生成图形缓冲区以供消耗的任何内容。例如 OpenGL ES、Canvas 2D 和 mediaserver 视频解码器。
图像流消费者(Image stream consumers)
图像流的最常见消费者是 SurfaceFlinger,该系统服务会消耗当前可见的 Surface,并使用窗口管理器中提供的信息将它们合成到屏幕。SurfaceFlinger 是可以修改所显示部分内容的唯一服务。SurfaceFlinger 使用 OpenGL 和 Hardware Composer 来合成一组 Surface。
其他 OpenGL ES 应用也可以消耗图像流,例如相机应用会消耗相机预览图像流。非 GL 应用也可以是使用方,例如 ImageReader 类。
硬件混合渲染器(Hardware Composer)
显示子系统的硬件抽象实现。SurfaceFlinger 可以将某些合成工作委托给硬件混合渲染器(HWC),以分担 OpenGL 和 GPU 上的工作量。SurfaceFlinger 只是充当另一个 OpenGL ES 客户端。因此,在 SurfaceFlinger 将一个或两个缓冲区合成到第三个缓冲区中的过程中,它会使用 OpenGL ES。这会让合成的功耗比通过 GPU 执行所有计算时更低。
硬件混合渲染器 HAL 则进行另一半的工作,是所有 Android 图形渲染的中心点。Hardware Composer 必须支持事件,其中之一是 VSYNC(另一个是支持即插即用 HDMI 的热插拔)。
Gralloc
Gralloc可以理解为图形内存分配器,用来分配和管理图像生产者请求的内存(即图形数据缓冲区Graphic Buffers)
2)BufferQueue 的图像流的生产者和消费者模式
BufferQueues 是 Android 图形组件之间的粘合剂。它们是一对图像缓冲区队列,可以调解缓冲区从生产者到消费者的固定周期。一旦生产者移交其缓冲区,SurfaceFlinger 便会负责将所有内容合成到显示部分。
BufferQueue 包含将图像流生产者与图像流消费者结合在一起的逻辑。BufferQueue 类是 Android 中所有图形处理操作的核心。它的作用很简单:将生成图形数据缓冲区的一方(生产方)连接到接受数据以进行显示或进一步处理的一方(消耗方)。几乎所有在系统中移动图形数据缓冲区的内容都依赖于 BufferQueue。
通过上图我们可以大概看到BufferQueue的工作过程:
- 图像生产者通过调用dequeue方法向BufferQueue请求一块图形缓冲区内存,即一块GraphicBuffer;
- 图像生产者将产生的图像数据(比如相机预览的图像或解码器解码出的视频帧)写入图形缓冲区GraphicBuffer,并通过queue方法提交给BufferQueue;
- BufferQueue收到图形缓冲区GraphicBuffer的入队列消息,通知图像消费者调用acquire方法取得已填充数据的buffer进行处理或显示;
- 图像消费者处理完毕,调用release方法把buffer归还给BufferQueue,这个buffer之后可再重复使用;
- 图像生产者、BufferQueue、图像消费者协调工作,图形缓冲区buffer在三者之间协调流转,图像便流畅的显示或处理。
创建Surface的过程会涉及到与SurfaceFlinger的互动,SurfaceFlinger是一个系统级的服务,负责创建/管理/合成Surface对应的Layer
2.上层的一些封装的 view
- SurfaceView 和 GLSurfaceView。SurfaceView 结合了 Surface 和 View。SurfaceView 的 View 组件由 SurfaceFlinger(而不是应用)合成,从而可以通过单独的线程/进程渲染,并与应用界面渲染隔离。GLSurfaceView 提供了用于管理 EGL 上下文、线程间通信以及与 Activity 生命周期的交互的辅助程序类(但不是必须使用 GLES)。
- SurfaceTexture。 SurfaceTexture 将 Surface 和 GLES 纹理相结合来创建 BufferQueue,而您的应用是 BufferQueue 的消费者。当生产者将新的缓冲区排入队列时,它会通知您的应用。您的应用会依次释放先前占用的缓冲区,从队列中获取新缓冲区并执行 EGL 调用,从而使 GLES 可将此缓冲区作为外部纹理使用。Android 7.0 添加了对安全纹理视频播放的支持,以便对受保护的视频内容进行 GPU 后处理。
- TextureView。 TextureView 结合了 View 和 SurfaceTexture。TextureView 对 SurfaceTexture 进行包装,并负责响应回调以及获取新的缓冲区。在绘图时,TextureView 使用最近收到的缓冲区的内容作为其数据源,根据 View 状态指示,在它应该渲染的任何位置和以它应该采用的任何渲染方式进行渲染。View 合成始终通过 GLES 来执行,这意味着内容更新可能会导致其他 View 元素重绘。
3. Java 层创建 surface 对象流程
视频电话中, preview,remoteview 使用到的TextureView中的成员SurfaceTexture就是个自带BufferQueue的组建,在消费者进程
/packages/apps/Dialer/java/com/android/incallui/videosurface/impl/VideoSurfaceTextureImpl.java
在创建 textutreView 的时候,会去监听 surface 是否是可有的,如果可用了,就可以创建 surface 对象了
147 private boolean createSurface(int width, int height) {
148 LogUtil.i(
149 "VideoSurfaceTextureImpl.createSurface",
150 "width: " + width + ", height: " + height + " " + toString());
151 savedSurfaceTexture.setDefaultBufferSize(width, height);
152 if (savedSurface != null) {
153 savedSurface.release();
154 }
// 这里去创建 surface 对象,传入了 SurfaceTexture 对象
155 savedSurface = new Surface(savedSurfaceTexture);
156 return true;
157 }
/frameworks/base/core/java/android/view/Surface.java
*/
public Surface(SurfaceTexture surfaceTexture) {
if (surfaceTexture == null) {
throw new IllegalArgumentException("surfaceTexture must not be null");
}
mIsSingleBuffered = surfaceTexture.isSingleBuffered();
synchronized (mLock) {
mName = surfaceTexture.toString();
// nativeCreateFromSurfaceTexture native 层去创建 surface
setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
}
}
nativeCreateFromSurfaceTexture native 层去创建 surface
/frameworks/base/core/jni/android_view_Surface.cpp
static jlong nativeCreateFromSurfaceTexture(JNIEnv* env, jclass clazz,
jobject surfaceTextureObj) {
// 先获取到 SurfaceTexture_getProducer 生产者
sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, surfaceTextureObj));
if (producer == NULL) {
jniThrowException(env, IllegalArgumentException,
"SurfaceTexture has already been released");
return 0;
}
// native层 创建surface,传入参数:producer,为生产者
sp<Surface> surface(new Surface(producer, true));
if (surface == NULL) {
jniThrowException(env, OutOfResourcesException, NULL);
return 0;
}
surface->incStrong(&sRefBaseOwner);
return jlong(surface.get());
}
先获取到 SurfaceTexture_getProducer 生产者
/frameworks/native/libs/nativedisplay/surfacetexture/surface_texture.cpp
99 static sp<IGraphicBufferProducer> SurfaceTexture_getProducer(JNIEnv* env, jobject thiz) {
100 std::call_once(sInitFieldsOnce, [=]() {
101 register_android_graphics_SurfaceTexture(env);
102 });
103
104 return (IGraphicBufferProducer*)env->GetLongField(thiz, fields.producer);
105 }
初始化中保存了 fields.producer
53 static void SurfaceTexture_classInit(JNIEnv* env, jclass clazz)
54 {
55 fields.surfaceTexture = env->GetFieldID(clazz,
56 ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "J");
57 if (fields.surfaceTexture == NULL) {
58 ALOGE("can't find android/graphics/SurfaceTexture.%s",
59 ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID);
60 }
// fields.producer
61 fields.producer = env->GetFieldID(clazz,
62 ANDROID_GRAPHICS_PRODUCER_JNI_ID, "J");
63 if (fields.producer == NULL) {
64 ALOGE("can't find android/graphics/SurfaceTexture.%s",
65 ANDROID_GRAPHICS_PRODUCER_JNI_ID);
66 }
67 }
Surface为BufferQueue的Producer端;native层 创建surface,传入参数:producer,为生产者
通过 SurfaceTexture_getProducer()获取到BufferQueueProducer
-----
看下哪里 SurfaceTexture_getProducer() 获取到这个 BufferQueueProducer
/frameworks/base/core/jni/android_graphics_SurfaceTexture.cpp
通过下列的接口获取到 producer:fields.producer
sp<IGraphicBufferProducer> SurfaceTexture_getProducer(JNIEnv* env, jobject thiz) {
return (IGraphicBufferProducer*)env->GetLongField(thiz, fields.producer);
}
下列设置了这个接口:
static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jboolean isDetached,
jint texName, jboolean singleBufferMode, jobject weakThiz)
{
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
// 通过 createBufferQueue 创建了 producer 和 consumer
BufferQueue::createBufferQueue(&producer, &consumer);
if (singleBufferMode) {
consumer->setMaxBufferCount(1);
}
sp<SurfaceTexture> surfaceTexture;
if (isDetached) {
surfaceTexture = new SurfaceTexture(consumer, GL_TEXTURE_EXTERNAL_OES,
true, !singleBufferMode);
} else {
surfaceTexture = new SurfaceTexture(consumer, texName,
GL_TEXTURE_EXTERNAL_OES, true, !singleBufferMode);
}
if (surfaceTexture == 0) {
jniThrowException(env, OutOfResourcesException,
"Unable to create native SurfaceTexture");
return;
}
surfaceTexture->setName(String8::format("SurfaceTexture-%d-%d-%d",
(isDetached ? 0 : texName),
getpid(),
createProcessUniqueId()));
// If the current context is protected, inform the producer.
consumer->setConsumerIsProtected(isProtectedContext());
SurfaceTexture_setSurfaceTexture(env, thiz, surfaceTexture);
// 铜鼓下列的方法设置了 producer
SurfaceTexture_setProducer(env, thiz, producer);
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
jniThrowRuntimeException(env,
"Can't find android/graphics/SurfaceTexture");
return;
}
sp<JNISurfaceTextureContext> ctx(new JNISurfaceTextureContext(env, weakThiz,
clazz));
// 这里设置回调 ctx,native 层会回调通知ap 层
surfaceTexture->setFrameAvailableListener(ctx);
SurfaceTexture_setFrameAvailableListener(env, thiz, ctx);
}
// 通过 createBufferQueue 创建了 producer 和 consumer
BufferQueue::createBufferQueue(&producer, &consumer)
BufferQueue的头文件:
/frameworks/native/libs/gui/include/gui/BufferQueue.h
// needed gralloc buffers.
static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
// consumerIsSurfaceFlinger 默认的值为 false
bool consumerIsSurfaceFlinger = false);
/frameworks/native/libs/gui/BufferQueue.cpp
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger) {
LOG_ALWAYS_FATAL_IF(outProducer == nullptr,
"BufferQueue: outProducer must not be NULL");
LOG_ALWAYS_FATAL_IF(outConsumer == nullptr,
"BufferQueue: outConsumer must not be NULL");
// core 为对象 BufferQueueCore
sp<BufferQueueCore> core(new BufferQueueCore());
LOG_ALWAYS_FATAL_IF(core == nullptr,
"BufferQueue: failed to create BufferQueueCore");
// producer 为:BufferQueueProducer传入了对象 BufferQueueCore
sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
LOG_ALWAYS_FATAL_IF(producer == nullptr,
"BufferQueue: failed to create BufferQueueProducer");
// consumer 为:BufferQueueConsumer传入了对象 BufferQueueCore
sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
LOG_ALWAYS_FATAL_IF(consumer == nullptr,
"BufferQueue: failed to create BufferQueueConsumer");
*outProducer = producer;
*outConsumer = consumer;
}
createBufferQueue 方法做了下列几件事情:
1. 创建了 对象 BufferQueueCore
2. 创建了 对象:BufferQueueProducer传入了对象 BufferQueueCore
3. 创建了 对象,consumer 为:BufferQueueConsumer传入了对象 BufferQueueCore
4. native 层具体调用的接口解析
查看native 层设置图层的例子:
https://www.cnblogs.com/roger-yu/p/15707940.html
// 链接surface
native_window_api_connect(surface.get(),---)// 一些buffer 参数的设置
native_window_set_buffers_dismensions(, width, height)// 渲染过程:
// 1.先调用 dequeue 申请一块图形缓冲区内存,即一块GraphicBuffer
native_window_dequeue_buffer_and_wait()// 2. 设置时间戳:
native_window_set_buffers_timestamp// 3. 将surface 的buf 增加到队列中
surface->queueBuffer// 断开这个 surface
native_window_api_disconnect()
1). 先连接 surface
native_window_api_connect(surface, NATIVE_WINDOW_API_MEDIA)
/frameworks/native/libs/nativewindow/include/system/window.h
*/
static inline int native_window_api_connect(
struct ANativeWindow* window, int api)
{
// 调用 surface 的perform 方法
return window->perform(window, NATIVE_WINDOW_API_CONNECT, api);
}
调用 surface 的perform 方法
/frameworks/native/libs/gui/Surface.cpp
int Surface::perform(int operation, va_list args)
{
int res = NO_ERROR;
switch (operation) {
case NATIVE_WINDOW_CONNECT:
// deprecated. must return NO_ERROR.
break;
。。。。
case NATIVE_WINDOW_API_CONNECT:
res = dispatchConnect(args);
break;
dispatchConnect 方法
int Surface::dispatchConnect(va_list args) {
int api = va_arg(args, int);
return connect(api);
}
。。。。。
int Surface::connect(int api) {
// 创建了 生产者的观察者 DummyProducerListener
static sp<IProducerListener> listener = new DummyProducerListener();
return connect(api, listener);
}
int Surface::connect(int api, const sp<IProducerListener>& listener) {
return connect(api, listener, false);
}
int Surface::connect(
int api, bool reportBufferRemoval, const sp<SurfaceListener>& sListener) {
if (sListener != nullptr) {
// 代理模式创建对象:ProducerListenerProxy,将this 指针也传入了
mListenerProxy = new ProducerListenerProxy(this, sListener);
}
return connect(api, mListenerProxy, reportBufferRemoval);
}
int Surface::connect(
int api, const sp<IProducerListener>& listener, bool reportBufferRemoval) {
ATRACE_CALL();
ALOGV("Surface::connect");
Mutex::Autolock lock(mMutex);
IGraphicBufferProducer::QueueBufferOutput output;
mReportRemovedBuffers = reportBufferRemoval;
// 观察者的值是 ProducerListenerProxy
// 调用 BufferProducer 去连接
int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output);
if (err == NO_ERROR) {
mDefaultWidth = output.width;
mDefaultHeight = output.height;
mNextFrameNumber = output.nextFrameNumber;
mMaxBufferCount = output.maxBufferCount;
// Ignore transform hint if sticky transform is set or transform to display inverse flag is
// set. Transform hint should be ignored if the client is expected to always submit buffers
// in the same orientation.
if (mStickyTransform == 0 && !transformToDisplayInverse()) {
mTransformHint = output.transformHint;
}
mConsumerRunningBehind = (output.numPendingBuffers >= 2);
}
if (!err && api == NATIVE_WINDOW_API_CPU) {
mConnectedToCpu = true;
// Clear the dirty region in case we're switching from a non-CPU API
mDirtyRegion.clear();
} else if (!err) {
// Initialize the dirty region for tracking surface damage
mDirtyRegion = Region::INVALID_REGION;
}
return err;
}
调用 BufferQueueProducer 去connect,传入的观察者为:ProducerListenerProxy
/frameworks/native/libs/gui/BufferQueueProducer.cpp
status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
int api, bool producerControlledByApp, QueueBufferOutput *output) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mCore->mMutex);
mConsumerName = mCore->mConsumerName;
BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
producerControlledByApp ? "true" : "false");
。。。。
// mCore 为 BufferQueueCore
int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
mDequeueTimeout < 0 ?
mCore->mConsumerControlledByApp && producerControlledByApp : false,
mCore->mMaxBufferCount) -
mCore->getMaxBufferCountLocked();
if (!mCore->adjustAvailableSlotsLocked(delta)) {
BQ_LOGE("connect: BufferQueue failed to adjust the number of available "
"slots. Delta = %d", delta);
return BAD_VALUE;
}
int status = NO_ERROR;
switch (api) {
case NATIVE_WINDOW_API_EGL:
case NATIVE_WINDOW_API_CPU:
case NATIVE_WINDOW_API_MEDIA:
case NATIVE_WINDOW_API_CAMERA:
mCore->mConnectedApi = api;
// 将 BufferQueueCore 一些属性值赋值给 output
output->width = mCore->mDefaultWidth;
output->height = mCore->mDefaultHeight;
output->transformHint = mCore->mTransformHintInUse = mCore->mTransformHint;
output->numPendingBuffers =
static_cast<uint32_t>(mCore->mQueue.size());
output->nextFrameNumber = mCore->mFrameCounter + 1;
output->bufferReplaced = false;
output->maxBufferCount = mCore->mMaxBufferCount;
if (listener != nullptr) {
// Set up a death notification so that we can disconnect
// automatically if the remote producer dies
#ifndef NO_BINDER
if (IInterface::asBinder(listener)->remoteBinder() != nullptr) {
status = IInterface::asBinder(listener)->linkToDeath(
static_cast<IBinder::DeathRecipient*>(this));
if (status != NO_ERROR) {
BQ_LOGE("connect: linkToDeath failed: %s (%d)",
strerror(-status), status);
}
mCore->mLinkedToDeath = listener;
}
#endif
// 设置 BufferQueueCore 的mConnectedProducerListener 回调观察者
mCore->mConnectedProducerListener = listener;
mCore->mBufferReleasedCbEnabled = listener->needsReleaseNotify();
}
break;
default:
BQ_LOGE("connect: unknown API %d", api);
status = BAD_VALUE;
break;
}
mCore->mConnectedPid = BufferQueueThreadState::getCallingPid();
mCore->mBufferHasBeenQueued = false;
mCore->mDequeueBufferCannotBlock = false;
mCore->mQueueBufferCanDrop = false;
mCore->mLegacyBufferDrop = true;
if (mCore->mConsumerControlledByApp && producerControlledByApp) {
mCore->mDequeueBufferCannotBlock = mDequeueTimeout < 0;
mCore->mQueueBufferCanDrop = mDequeueTimeout <= 0;
}
mCore->mAllowAllocation = true;
VALIDATE_CONSISTENCY();
return status;
}
2). 调用 dequeue 申请一块图形缓冲区内存GraphicBuffer
native_window_dequeue_buffer_and_wait(surface)
/frameworks/native/libs/nativewindow/include/system/window.h
*/
static inline int native_window_dequeue_buffer_and_wait(ANativeWindow *anw,
struct ANativeWindowBuffer** anb) {
return anw->dequeueBuffer_DEPRECATED(anw, anb);
}
/frameworks/native/libs/gui/Surface.cpp
Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp)
: mGraphicBufferProducer(bufferProducer),
mCrop(Rect::EMPTY_RECT),
mBufferAge(0),
mGenerationNumber(0),
mSharedBufferMode(false),
mAutoRefresh(false),
mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
mSharedBufferHasBeenQueued(false),
mQueriedSupportedTimestamps(false),
mFrameTimestampsSupportsPresent(false),
mEnableFrameTimestamps(false),
mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>()) {
// Initialize the ANativeWindow function pointers.
ANativeWindow::setSwapInterval = hook_setSwapInterval;
ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
ANativeWindow::cancelBuffer = hook_cancelBuffer;
ANativeWindow::queueBuffer = hook_queueBuffer;
ANativeWindow::query = hook_query;
ANativeWindow::perform = hook_perform;
// hook_dequeueBuffer_DEPRECATED方法
ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
hook_dequeueBuffer_DEPRECATED方法
int Surface::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window,
ANativeWindowBuffer** buffer) {
Surface* c = getSelf(window);
ANativeWindowBuffer* buf;
int fenceFd = -1;
// Surface的 dequeueBuffer 去获取 buf
int result = c->dequeueBuffer(&buf, &fenceFd);
if (result != OK) {
return result;
}
sp<Fence> fence(new Fence(fenceFd));
int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED");
if (waitResult != OK) {
ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an error: %d",
waitResult);
c->cancelBuffer(buf, -1);
return waitResult;
}
// 赋值给 *buffer
*buffer = buf;
return result;
}
Surface的 dequeueBuffer 去获取 buf,
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
ATRACE_CALL();
。。。。。
if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot !=
BufferItem::INVALID_BUFFER_SLOT) {
// mSlots 结构体保存了 GraphicBuffer
sp<GraphicBuffer>& gbuf(mSlots[mSharedBufferSlot].buffer);
if (gbuf != nullptr) {
*buffer = gbuf.get();
*fenceFd = -1;
return OK;
}
}
} // Drop the lock so that we can still touch the Surface while blocking in IGBP::dequeueBuffer
int buf = -1;
sp<Fence> fence;
nsecs_t startTime = systemTime();
FrameEventHistoryDelta frameTimestamps;
// BufferProducer的 dequeueBuffer 方法获取 buf,buf 是个int 值
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, reqWidth, reqHeight,
reqFormat, reqUsage, &mBufferAge,
enableFrameTimestamps ? &frameTimestamps
: nullptr);
mLastDequeueDuration = systemTime() - startTime;
if (result < 0) {
ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
"(%d, %d, %d, %#" PRIx64 ") failed: %d",
reqWidth, reqHeight, reqFormat, reqUsage, result);
return result;
}
if (buf < 0 || buf >= NUM_BUFFER_SLOTS) {
ALOGE("dequeueBuffer: IGraphicBufferProducer returned invalid slot number %d", buf);
android_errorWriteLog(0x534e4554, "36991414"); // SafetyNet logging
return FAILED_TRANSACTION;
}
Mutex::Autolock lock(mMutex);
// Write this while holding the mutex
mLastDequeueStartTime = startTime;
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
// this should never happen
ALOGE_IF(fence == nullptr, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
static FenceMonitor hwcReleaseThread("HWC release");
hwcReleaseThread.queueFence(fence);
}
if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
freeAllBuffers();
}
if (enableFrameTimestamps) {
mFrameEventHistory->applyDelta(frameTimestamps);
}
if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) {
if (mReportRemovedBuffers && (gbuf != nullptr)) {
mRemovedBuffers.push_back(gbuf);
}
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
if (result != NO_ERROR) {
ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
mGraphicBufferProducer->cancelBuffer(buf, fence);
return result;
}
}
if (fence->isValid()) {
*fenceFd = fence->dup();
if (*fenceFd == -1) {
ALOGE("dequeueBuffer: error duping fence: %d", errno);
// dup() should never fail; something is badly wrong. Soldier on
// and hope for the best; the worst that should happen is some
// visible corruption that lasts until the next frame.
}
} else {
*fenceFd = -1;
}
// gbuf 赋值给 *buffer
*buffer = gbuf.get();
if (mSharedBufferMode && mAutoRefresh) {
mSharedBufferSlot = buf;
mSharedBufferHasBeenQueued = false;
} else if (mSharedBufferSlot == buf) {
mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
mSharedBufferHasBeenQueued = false;
}
// mDequeuedSlots 插入这个buf
mDequeuedSlots.insert(buf);
return OK;
}
==========看下 mSlots ===start=========
/frameworks/native/libs/gui/include/gui/Surface.h
struct BufferSlot {
sp<GraphicBuffer> buffer;
Region dirtyRegion;
};
// mSlots 是数组,元素是结构体 BufferSlot
BufferSlot mSlots[NUM_BUFFER_SLOTS];
NUM_BUFFER_SLOTS 值
protected:
enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };
=========
/frameworks/native/libs/ui/include/ui/BufferQueueDefs.h
namespace BufferQueueDefs {
// BufferQueue will keep track of at most this value of buffers.
// Attempts at runtime to increase the number of buffers past this
// will fail.
static constexpr int NUM_BUFFER_SLOTS = 64;
BufferSlot mSlots[64]
==========看下 mSlots ===end=========
mGraphicBufferProducer->dequeueBuffer(&buf ,获取buf 的值
/frameworks/native/libs/gui/BufferQueueProducer.cpp
status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence,
uint32_t width, uint32_t height, PixelFormat format,
uint64_t usage, uint64_t* outBufferAge,
FrameEventHistoryDelta* outTimestamps) {
ATRACE_CALL();
{ // Autolock scope
std::lock_guard<std::mutex> lock(mCore->mMutex);
mConsumerName = mCore->mConsumerName;
。。。。。。。。
int found = BufferItem::INVALID_BUFFER_SLOT;
while (found == BufferItem::INVALID_BUFFER_SLOT) {
// waitForFreeSlotThenRelock 看是否有free slot
status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, lock, &found);
if (status != NO_ERROR) {
return status;
}
// This should not happen
if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
BQ_LOGE("dequeueBuffer: no available buffer slots");
return -EBUSY;
}
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
// If we are not allowed to allocate new buffers,
// waitForFreeSlotThenRelock must have returned a slot containing a
// buffer. If this buffer would require reallocation to meet the
// requested attributes, we free it and attempt to get another one.
if (!mCore->mAllowAllocation) {
if (buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
if (mCore->mSharedBufferSlot == found) {
BQ_LOGE("dequeueBuffer: cannot re-allocate a sharedbuffer");
return BAD_VALUE;
}
mCore->mFreeSlots.insert(found);
mCore->clearBufferSlotLocked(found);
found = BufferItem::INVALID_BUFFER_SLOT;
continue;
}
}
}
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
if (mCore->mSharedBufferSlot == found &&
buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
"buffer");
return BAD_VALUE;
}
if (mCore->mSharedBufferSlot != found) {
mCore->mActiveBuffers.insert(found);
}
*outSlot = found;
waitForFreeSlotThenRelock 看是否有free slot
status_t BufferQueueProducer::waitForFreeSlotThenRelock(FreeSlotCaller caller,
std::unique_lock<std::mutex>& lock, int* found) const {
auto callerString = (caller == FreeSlotCaller::Dequeue) ?
。。
if (tooManyBuffers) {
BQ_LOGV("%s: queue size is %zu, waiting", callerString,
mCore->mQueue.size());
} else {
// If in shared buffer mode and a shared buffer exists, always
// return it.
// 如果是共享buffer 模式
if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot !=
BufferQueueCore::INVALID_BUFFER_SLOT) {
*found = mCore->mSharedBufferSlot;
} else {
if (caller == FreeSlotCaller::Dequeue) {
// If we're calling this from dequeue, prefer free buffers
// 获取空闲的 buffer: getFreeBufferLocked
int slot = getFreeBufferLocked();
if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
*found = slot;
} else if (mCore->mAllowAllocation) {
*found = getFreeSlotLocked();
}
} else {
// If we're calling this from attach, prefer free slots
int slot = getFreeSlotLocked();
if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
*found = slot;
} else {
*found = getFreeBufferLocked();
}
}
}
}
// 获取空闲的 buffer: getFreeBufferLocked
int BufferQueueProducer::getFreeBufferLocked() const {
if (mCore->mFreeBuffers.empty()) {
return BufferQueueCore::INVALID_BUFFER_SLOT;
}
// 通过 BufferQueueCore 参数 mFreeBuffers 队列获取
int slot = mCore->mFreeBuffers.front();
mCore->mFreeBuffers.pop_front();
return slot;
}
// 通过 BufferQueueCore 参数 mFreeBuffers 队列获取
207 // mFreeBuffers contains all of the slots which are FREE and currently have
208 // a buffer attached.
// mFreeBuffers 应该是个双向循环链表
209 std::list<int> mFreeBuffers;
/frameworks/native/libs/gui/BufferQueueConsumer.cpp
由于 BufferQueueConsumer 持有 BufferQueueCore 对象,所以可以对属性 mFreeBuffers 操作
status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
const sp<Fence>& releaseFence, EGLDisplay eglDisplay,
EGLSyncKHR eglFence) {
ATRACE_CALL();
ATRACE_BUFFER_INDEX(slot);
。。。。。
// Don't put the shared buffer on the free list.
if (!mSlots[slot].mBufferState.isShared()) {
mCore->mActiveBuffers.erase(slot);
// 这里消费了buffer后,将使用完的buffer slot 放到 mFreeBuffers
mCore->mFreeBuffers.push_back(slot);
}
if (mCore->mBufferReleasedCbEnabled) {
listener = mCore->mConnectedProducerListener;
}
BQ_LOGV("releaseBuffer: releasing slot %d", slot);
mCore->mDequeueCondition.notify_all();
3). 设置buffer 的参数宽高
native_window_set_buffers_dimensions(surface, width, height)
/frameworks/native/libs/nativewindow/include/system/window.h
static inline int native_window_set_buffers_dimensions(
struct ANativeWindow* window,
int w, int h)
{
return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS,
w, h);
}
/frameworks/native/libs/gui/Surface.cpp
int Surface::perform(int operation, va_list args)
{
int res = NO_ERROR;
。。。。。
case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
res = dispatchSetBuffersDimensions(args);
break;
。。。。
int Surface::dispatchSetBuffersDimensions(va_list args) {
uint32_t width = va_arg(args, uint32_t);
uint32_t height = va_arg(args, uint32_t);
return setBuffersDimensions(width, height);
}
------
int Surface::setBuffersUserDimensions(uint32_t width, uint32_t height)
{
ATRACE_CALL();
ALOGV("Surface::setBuffersUserDimensions");
if ((width && !height) || (!width && height))
return BAD_VALUE;
Mutex::Autolock lock(mMutex);
if (width != mUserWidth || height != mUserHeight) {
mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
}
// mUserWidth 缓存宽高
mUserWidth = width;
mUserHeight = height;
return NO_ERROR;
}
4). 将surface 的buf 增加到队列中
surface->queueBuffer(surface, buf, -1); 其中buf 是yuv 格式的数据
一般情况下SurfaceTexture承载的数据都是YUV类型,buf传入的是yuv 数据
int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
ATRACE_CALL();
ALOGV("Surface::queueBuffer");
Mutex::Autolock lock(mMutex);
int64_t timestamp;
bool isAutoTimestamp = false;
if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
isAutoTimestamp = true;
ALOGV("Surface::queueBuffer making up timestamp: %.2f ms",
timestamp / 1000000.0);
} else {
timestamp = mTimestamp;
}
。。
IGraphicBufferProducer::QueueBufferOutput output;
IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
static_cast<android_dataspace>(mDataSpace), crop, mScalingMode,
mTransform ^ mStickyTransform, fence, mStickyTransform,
mEnableFrameTimestamps);
// 依据buffer 获取到 slot 的值
int i = getSlotFromBufferLocked(buffer);
。。。
nsecs_t now = systemTime();
// 传入 slot 的值,入队列处理
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
mLastQueueDuration = systemTime() - now;
if (err != OK) {
ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
}
mDequeuedSlots.erase(i);
。。。。
// 通知到上层帧可用: frameAvailableListener->onFrameAvailable
{ // scope for the lock
std::unique_lock<std::mutex> lock(mCallbackMutex);
while (callbackTicket != mCurrentCallbackTicket) {
mCallbackCondition.wait(lock);
}
if (frameAvailableListener != nullptr) {
frameAvailableListener->onFrameAvailable(item);
} else if (frameReplacedListener != nullptr) {
frameReplacedListener->onFrameReplaced(item);
}
SurfaceTexture作为消费方,是Surface和OpenGLES纹理的组合,将buffer数据转换为外部纹理,供gles使用。
Android SurfaceTexture说明_goodnight1994的博客-CSDN博客
=================
通知到上层帧可用: frameAvailableListener->onFrameAvailable
/frameworks/base/core/jni/android_graphics_SurfaceTexture.cpp
static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jboolean isDetached,
jint texName, jboolean singleBufferMode, jobject weakThiz)
{
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
。。。。
sp<SurfaceTexture> surfaceTexture;
if (isDetached) {
surfaceTexture = new SurfaceTexture(consumer, GL_TEXTURE_EXTERNAL_OES,
true, !singleBufferMode);
} else {
// 创建了 SurfaceTexture 对象,传入参数:consumer
surfaceTexture = new SurfaceTexture(consumer, texName,
GL_TEXTURE_EXTERNAL_OES, true, !singleBufferMode);
}
。。。
sp<JNISurfaceTextureContext> ctx(new JNISurfaceTextureContext(env, weakThiz,
clazz));
// 设置了 JNISurfaceTextureContext 为回调对象
surfaceTexture->setFrameAvailableListener(ctx);
SurfaceTexture_setFrameAvailableListener(env, thiz, ctx);
}
创建了 SurfaceTexture 对象,传入参数:consumer
/frameworks/native/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
SurfaceTexture::SurfaceTexture(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
bool useFenceSync, bool isControlledByApp)
// 调用父类方法
: ConsumerBase(bq, isControlledByApp),
52 class ANDROID_API SurfaceTexture : public ConsumerBase {
53 public:
调用父类构造函数,bp 为 BufferQueueCosumer
/frameworks/native/libs/gui/ConsumerBase.cpp
ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
mAbandoned(false),
// BufferQueueCosumer 为 mConsumer
mConsumer(bufferQueue),
mPrevFinalReleaseFence(Fence::NO_FENCE) {
// Choose a name using the PID and a process-unique ID.
mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
// Note that we can't create an sp<...>(this) in a ctor that will not keep a
// reference once the ctor ends, as that would cause the refcount of 'this'
// dropping to 0 at the end of the ctor. Since all we need is a wp<...>
// that's what we create.
wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
// 创建 ProxyConsumerListener 对象
sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
// BufferQueueCosumer 的 consumerConnect方法,proxy是回调的对象
status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
if (err != NO_ERROR) {
CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
strerror(-err), err);
} else {
mConsumer->setConsumerName(mName);
}
}
BufferQueueCosumer 的 consumerConnect方法,proxy是回调的对象
/frameworks/native/libs/gui/include/gui/BufferQueueConsumer.h
165 virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
166 bool controlledByApp) {
// 直接调用 connect 方法
167 return connect(consumer, controlledByApp);
168 }
status_t BufferQueueConsumer::connect(
const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
ATRACE_CALL();
if (consumerListener == nullptr) {
BQ_LOGE("connect: consumerListener may not be NULL");
return BAD_VALUE;
}
BQ_LOGV("connect: controlledByApp=%s",
controlledByApp ? "true" : "false");
std::lock_guard<std::mutex> lock(mCore->mMutex);
if (mCore->mIsAbandoned) {
BQ_LOGE("connect: BufferQueue has been abandoned");
return NO_INIT;
}
// 将观察者对象赋值给了consumerListener 给:mCore->mConsumerListener
mCore->mConsumerListener = consumerListener;
mCore->mConsumerControlledByApp = controlledByApp;
回调 onFrameAvailable 方法
/frameworks/native/libs/gui/BufferQueue.cpp
33 BufferQueue::ProxyConsumerListener::ProxyConsumerListener(
34 const wp<ConsumerListener>& consumerListener):
35 mConsumerListener(consumerListener) {}
。。。。。
67 void BufferQueue::ProxyConsumerListener::onFrameAvailable(
68 const BufferItem& item) {
69 sp<ConsumerListener> listener(mConsumerListener.promote());
70 if (listener != nullptr) {
// 代理模式,直接调用 SurfaceTexture对象的方法
71 listener->onFrameAvailable(item);
72 }
73 }
直接调用 SurfaceTexture对象的方法,在其父类中实现
void ConsumerBase::onFrameAvailable(const BufferItem& item) {
CB_LOGV("onFrameAvailable");
sp<FrameAvailableListener> listener;
{ // scope for the lock
Mutex::Autolock lock(mFrameAvailableMutex);
listener = mFrameAvailableListener.promote();
}
if (listener != nullptr) {
CB_LOGV("actually calling onFrameAvailable");
listener->onFrameAvailable(item);
}
}
// 下列方法设置了观察者
void ConsumerBase::setFrameAvailableListener(
const wp<FrameAvailableListener>& listener) {
CB_LOGV("setFrameAvailableListener");
Mutex::Autolock lock(mFrameAvailableMutex);
mFrameAvailableListener = listener;
}
setFrameAvailableListener 方法
/frameworks/base/core/jni/android_graphics_SurfaceTexture.cpp
295
296 sp<JNISurfaceTextureContext> ctx(new JNISurfaceTextureContext(env, weakThiz,
297 clazz));
// 在这里设置: JNISurfaceTextureContext
298 surfaceTexture->setFrameAvailableListener(ctx);
299 SurfaceTexture_setFrameAvailableListener(env, thiz, ctx);
300 }
JNISurfaceTextureContext
203 void JNISurfaceTextureContext::onFrameAvailable(const BufferItem& /* item */)
204 {
205 bool needsDetach = false;
206 JNIEnv* env = getJNIEnv(&needsDetach);
207 if (env != NULL) {
// fields.postEvent 为java 层的 postEventFromNative,回调给上层app
208 env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
209 } else {
210 ALOGW("onFrameAvailable event will not posted");
211 }
212 if (needsDetach) {
213 detachJNI();
214 }
215 }
。。。。。
246 fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
247 "(Ljava/lang/ref/WeakReference;)V");
248 if (fields.postEvent == NULL) {
249 ALOGE("can't find android/graphics/SurfaceTexture.postEventFromNative");
250 }
postEventFromNative 方法
/frameworks/base/graphics/java/android/graphics/SurfaceTexture.java
392 */
393 @SuppressWarnings({"UnusedDeclaration"})
394 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
395 private static void postEventFromNative(WeakReference<SurfaceTexture> weakSelf) {
396 SurfaceTexture st = weakSelf.get();
397 if (st != null) {
// 看下 mOnFrameAvailableHandler 对象值
398 Handler handler = st.mOnFrameAvailableHandler;
399 if (handler != null) {
400 handler.sendEmptyMessage(0);
401 }
402 }
403 }
看下 mOnFrameAvailableHandler 对象值,下列方法中设置了观察者
201 public void setOnFrameAvailableListener(@Nullable final OnFrameAvailableListener listener,
202 @Nullable Handler handler) {
203 if (listener != null) {
204 // Although we claim the thread is arbitrary, earlier implementation would
205 // prefer to send the callback on the creating looper or the main looper
206 // so we preserve this behavior here.
207 Looper looper = handler != null ? handler.getLooper() :
208 mCreatorLooper != null ? mCreatorLooper : Looper.getMainLooper();
209 mOnFrameAvailableHandler = new Handler(looper, null, true /*async*/) {
210 @Override
211 public void handleMessage(Message msg) {
212 listener.onFrameAvailable(SurfaceTexture.this);
213 }
214 };
215 } else {
216 mOnFrameAvailableHandler = null;
217 }
218 }
/frameworks/base/core/java/android/view/TextureView.java
private SurfaceTexture mSurface;
public void setSurfaceTexture(@NonNull SurfaceTexture surfaceTexture) {
if (surfaceTexture == null) {
throw new NullPointerException("surfaceTexture must not be null");
}
。。。。。
// 在设置 setSurfaceTexture 方法中设置了观察者
if (((mViewFlags & VISIBILITY_MASK) == VISIBLE) && mLayer != null) {
mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler);
}
mUpdateSurface = true;
invalidateParentIfNeeded();
}
// mUpdateListener 执行labmada 表达式
@UnsupportedAppUsage
private final SurfaceTexture.OnFrameAvailableListener mUpdateListener =
surfaceTexture -> {
updateLayer();
invalidate();
};
Android 5.0(Lollipop)中的SurfaceTexture,TextureView, SurfaceView和GLSurfaceView_ariesjzj的博客-CSDN博客
GLConsumer 执行 updatetexImage 方法:
/frameworks/native/libs/gui/GLConsumer.cpp
status_t GLConsumer::updateTexImage() {
ATRACE_CALL();
GLC_LOGV("updateTexImage");
Mutex::Autolock lock(mMutex);
if (mAbandoned) {
GLC_LOGE("updateTexImage: GLConsumer is abandoned!");
return NO_INIT;
}
// Make sure the EGL state is the same as in previous calls.
status_t err = checkAndUpdateEglStateLocked();
if (err != NO_ERROR) {
return err;
}
BufferItem item;
// Acquire the next buffer.
// In asynchronous mode the list is guaranteed to be one buffer
// deep, while in synchronous mode we use the oldest buffer.
// 获取buffer,acquireBufferLocked
err = acquireBufferLocked(&item, 0);
if (err != NO_ERROR) {
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
// We always bind the texture even if we don't update its contents.
GLC_LOGV("updateTexImage: no buffers were available");
glBindTexture(mTexTarget, mTexName);
err = NO_ERROR;
} else {
GLC_LOGE("updateTexImage: acquire failed: %s (%d)",
strerror(-err), err);
}
return err;
}
获取buffer,acquireBufferLocked
status_t GLConsumer::acquireBufferLocked(BufferItem *item,
nsecs_t presentWhen, uint64_t maxFrameNumber) {
// 调用父类ConsumerBase的方法去获取 buffer:acquireBufferLocked
status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen,
maxFrameNumber);
if (err != NO_ERROR) {
return err;
}
// If item->mGraphicBuffer is not null, this buffer has not been acquired
// before, so any prior EglImage created is using a stale buffer. This
// replaces any old EglImage with a new one (using the new buffer).
if (item->mGraphicBuffer != nullptr) {
int slot = item->mSlot;
mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
}
return NO_ERROR;
}
调用父类ConsumerBase的方法去获取 buffer:acquireBufferLocked
/frameworks/native/libs/gui/ConsumerBase.cpp
status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
nsecs_t presentWhen, uint64_t maxFrameNumber) {
if (mAbandoned) {
CB_LOGE("acquireBufferLocked: ConsumerBase is abandoned!");
return NO_INIT;
}
/// 调用 mConsumer 去获取 buffer
status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);
if (err != NO_ERROR) {
return err;
}
if (item->mGraphicBuffer != nullptr) {
if (mSlots[item->mSlot].mGraphicBuffer != nullptr) {
freeBufferLocked(item->mSlot);
}
mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
}
mSlots[item->mSlot].mFrameNumber = item->mFrameNumber;
mSlots[item->mSlot].mFence = item->mFence;
CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
item->mSlot, item->mFrameNumber);
return OK;
}
/frameworks/native/libs/gui/BufferQueueConsumer.cpp
最终还是走的 BufferQueueConsumer::acquireBuffer
status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
nsecs_t expectedPresent, uint64_t maxFrameNumber) {
ATRACE_CALL();
int numDroppedBuffers = 0;
sp<IProducerListener> listener;
{
std::unique_lock<std::mutex> lock(mCore->mMutex);
// Check that the consumer doesn't currently have the maximum number of
// buffers acquired. We allow the max buffer count to be exceeded by one
// buffer so that the consumer can successfully set up the newly acquired
// buffer before releasing the old one.
int numAcquiredBuffers = 0;
for (int s : mCore->mActiveBuffers) {
if (mSlots[s].mBufferState.isAcquired()) {
++numAcquiredBuffers;
}
}
if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
BQ_LOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)",
numAcquiredBuffers, mCore->mMaxAcquiredBufferCount);
return INVALID_OPERATION;
}
bool sharedBufferAvailable = mCore->mSharedBufferMode &&
mCore->mAutoRefresh && mCore->mSharedBufferSlot !=
BufferQueueCore::INVALID_BUFFER_SLOT;
// In asynchronous mode the list is guaranteed to be one buffer deep,
// while in synchronous mode we use the oldest buffer.
if (mCore->mQueue.empty() && !sharedBufferAvailable) {
return NO_BUFFER_AVAILABLE;
}
SurfaceTexture 的消费者生产者模式可以参考下列的文章
SurfaceTexture剖析 | Harries Blog™
5.) 断开这个surface
native_window_api_disconnect()
5. BufferQueue 的运行模式
BufferQueue 的运作模式核心类是 BufferQueueCore,有 BufferQueue,但是其作用只是提供创建 BufferQueueProducer 、 BufferQueueCosumer 和 BufferQueueCore 对象的接口,和消费者回调的中转。
/frameworks/native/libs/gui/BufferQueue.cpp
105
106 void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
107 sp<IGraphicBufferConsumer>* outConsumer,
108 bool consumerIsSurfaceFlinger) {
109 LOG_ALWAYS_FATAL_IF(outProducer == nullptr,
110 "BufferQueue: outProducer must not be NULL");
111 LOG_ALWAYS_FATAL_IF(outConsumer == nullptr,
112 "BufferQueue: outConsumer must not be NULL");
113
// 创建 BufferQueueCore 对象
114 sp<BufferQueueCore> core(new BufferQueueCore());
115 LOG_ALWAYS_FATAL_IF(core == nullptr,
116 "BufferQueue: failed to create BufferQueueCore");
117
// 创建 BufferQueueProducer 对象
118 sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
119 LOG_ALWAYS_FATAL_IF(producer == nullptr,
120 "BufferQueue: failed to create BufferQueueProducer");
121
// 创建 BufferQueueConsumer 对象
122 sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
123 LOG_ALWAYS_FATAL_IF(consumer == nullptr,
124 "BufferQueue: failed to create BufferQueueConsumer");
125
126 *outProducer = producer;
127 *outConsumer = consumer;
128 }
BufferQueue 生产和消费的流程:
- 初始化一个BufferQueue
- 图形数据的生产者通过BufferQueue申请一块GraphicBuffer,对应图中的dequeueBuffer方法
- 申请到GraphicBuffer后,获取GraphicBuffer,通过函数requestBuffer获取
- 获取到GraphicBuffer后,通过各种形式往GraphicBuffer中填充图形数据后,然后将GraphicBuffer入队到BufferQueue中,对应上图中的queueBuffer方法
- 在新的GraphicBuffer入队BufferQueue时,BufferQueue会通过回调通知图形数据的消费者,有新的图形数据被生产出来了
- 然后消费者从BufferQueue中出队一个GraphicBuffer,对应图中的acquireBuffer方法
- 待消费者消费完图形数据后,将空的GraphicBuffer还给BufferQueue以便重复利用,此时对应上图中的releaseBuffer方法
- 此时BufferQueue再通过回调通知图形数据的生产者有空的GraphicBuffer了,图形数据的生产者又可以从BufferQueue中获取一个空的GraphicBuffer来填充数据
- 一直循环2-8步骤,这样就有条不紊的完成了图形数据的生产-消费
1. 生产者通过dequeueBuffer方法申请一块:GraphicBuffer
/frameworks/native/libs/gui/BufferQueueProducer.cpp
// 获取到空闲的 slot 值
status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence,
uint32_t width, uint32_t height, PixelFormat format,
uint64_t usage, uint64_t* outBufferAge,
FrameEventHistoryDelta* outTimestamps) {
ATRACE_CALL();
{ // Autolock scope
。。。。。。。
while (found == BufferItem::INVALID_BUFFER_SLOT) {
status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, lock, &found);
if (status != NO_ERROR) {
return status;
}
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
if (mCore->mSharedBufferSlot == found &&
buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
"buffer");
return BAD_VALUE;
}
if (mCore->mSharedBufferSlot != found) {
mCore->mActiveBuffers.insert(found);
}
// 更换 outSlot的值为找到的slot
*outSlot = found;
2. 生产者 GraphicBuffer中填充图形数据,通过queueBuffer方法将GraphicBuffer入队到BufferQueue
status_t BufferQueueProducer::queueBuffer(int slot,
const QueueBufferInput &input, QueueBufferOutput *output) {
ATRACE_CALL();
ATRACE_BUFFER_INDEX(slot);
。。。。。
mSlots[slot].mFence = acquireFence;
// 设置 BufferState入队列
mSlots[slot].mBufferState.queue();
Slots 为结构体 BufferSlots,属性有 BufferState 结构体
/frameworks/native/libs/gui/include/gui/BufferSlot.h
struct BufferSlot {
BufferSlot()
: mGraphicBuffer(nullptr),
mEglDisplay(EGL_NO_DISPLAY),
mBufferState(),
mRequestBufferCalled(false),
mFrameNumber(0),
mEglFence(EGL_NO_SYNC_KHR),
mFence(Fence::NO_FENCE),
mAcquireCalled(false),
mNeedsReallocation(false) {
}
// mGraphicBuffer points to the buffer allocated for this slot or is NULL
// if no buffer has been allocated.
sp<GraphicBuffer> mGraphicBuffer;
// mEglDisplay is the EGLDisplay used to create EGLSyncKHR objects.
EGLDisplay mEglDisplay;
// mBufferState is the current state of this buffer slot.
BufferState mBufferState;
// mRequestBufferCalled is used for validating that the producer did
// call requestBuffer() when told to do so. Technically this is not
// needed but useful for debugging and catching producer bugs.
bool mRequestBufferCalled;
// mFrameNumber is the number of the queued frame for this slot. This
// is used to dequeue buffers in LRU order (useful because buffers
// may be released before their release fence is signaled).
uint64_t mFrameNumber;
BufferState保存着 当前buffer slot 的状态:
// BufferState tracks the states in which a buffer slot can be.
struct BufferState {
// All slots are initially FREE (not dequeued, queued, acquired, or shared).
BufferState()
: mDequeueCount(0),
mQueueCount(0),
mAcquireCount(0),
mShared(false) {
}
uint32_t mDequeueCount;
uint32_t mQueueCount;
uint32_t mAcquireCount;
bool mShared;
// A buffer can be in one of five states, represented as below:
//
// | mShared | mDequeueCount | mQueueCount | mAcquireCount |
// --------|---------|---------------|-------------|---------------|
// FREE | false | 0 | 0 | 0 |
// DEQUEUED| false | 1 | 0 | 0 |
// QUEUED | false | 0 | 1 | 0 |
// ACQUIRED| false | 0 | 0 | 1 |
// SHARED | true | any | any | any |
// 具体的设置 mQueueCount 和 mDequeueCount 的值:
// 入队列调用的方法
inline void queue() {
if (mDequeueCount > 0) {
mDequeueCount--;
}
mQueueCount++;
}
GraphicBuffer用BufferState来表示其状态,有以下状态:
- FREE:表示该Buffer没有被生产者-消费者所使用,该Buffer的所有权属于BufferQueue
- DEQUEUED:表示该Buffer被生产者获取了,该Buffer的所有权属于生产者
- QUEUED:表示该Buffer被生产者填充了数据,并且入队到BufferQueue了,该Buffer的所有权属于BufferQueue
- ACQUIRED:表示该Buffer被消费者获取了,该Buffer的所有权属于消费者
3. 消费者通过acquireBuffer方法从BufferQueue中出队一个GraphicBuffer
queueBuffer函数中会调用frameAvailableListener->onFrameAvailable(item),通知对应消费者去消费
/frameworks/native/libs/gui/BufferQueueConsumer.cpp
status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
nsecs_t expectedPresent, uint64_t maxFrameNumber) {
ATRACE_CALL();
。。。
// 获取队列中第一个 slot 迭代器
BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
。。
//如果不为空
if (!front->mIsStale) {
// Front buffer is still in mSlots, so mark the slot as free
mSlots[front->mSlot].mBufferState.freeQueued();
// After leaving shared buffer mode, the shared buffer will
// still be around. Mark it as no longer shared if this
// operation causes it to be free.
if (!mCore->mSharedBufferMode &&
mSlots[front->mSlot].mBufferState.isFree()) {
mSlots[front->mSlot].mBufferState.mShared = false;
}
// Don't put the shared buffer on the free list
if (!mSlots[front->mSlot].mBufferState.isShared()) {
// 在 active 的buffers 中删除这个 slot
mCore->mActiveBuffers.erase(front->mSlot);
// 放到 freeBuffers 中
mCore->mFreeBuffers.push_back(front->mSlot);
}
if (mCore->mBufferReleasedCbEnabled) {
listener = mCore->mConnectedProducerListener;
}
++numDroppedBuffers;
}
// 在 queue 中删除这个slot
mCore->mQueue.erase(front);
front = mCore->mQueue.begin();
}
。。
// 条件变量,通知有free 的buffer
mCore->mDequeueCondition.notify_all();
ATRACE_INT(mCore->mConsumerName.string(),
static_cast<int32_t>(mCore->mQueue.size()));
#ifndef NO_BINDER
mCore->mOccupancyTracker.registerOccupancyChange(mCore->mQueue.size());
#endif
VALIDATE_CONSISTENCY();
}
if (listener != nullptr) {
for (int i = 0; i < numDroppedBuffers; ++i) {
// 通知生产者,buffer 释放了
listener->onBufferReleased();
}
}
4. 消费者消费完图形数据后,通过releaseBuffer方法将空的GraphicBuffer还给BufferQueue以便重复利用
}
// Don't put the shared buffer on the free list.
if (!mSlots[slot].mBufferState.isShared()) {
mCore->mActiveBuffers.erase(slot);
mCore->mFreeBuffers.push_back(slot);
}
if (mCore->mBufferReleasedCbEnabled) {
listener = mCore->mConnectedProducerListener;
}
BQ_LOGV("releaseBuffer: releasing slot %d", slot);
mCore->mDequeueCondition.notify_all();