【安卓源码】TextureView 的BufferQueue 生产者消费者机制

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的工作过程:

  1. 图像生产者通过调用dequeue方法向BufferQueue请求一块图形缓冲区内存,即一块GraphicBuffer;
  2. 图像生产者将产生的图像数据(比如相机预览的图像或解码器解码出的视频帧)写入图形缓冲区GraphicBuffer,并通过queue方法提交给BufferQueue;
  3. BufferQueue收到图形缓冲区GraphicBuffer的入队列消息,通知图像消费者调用acquire方法取得已填充数据的buffer进行处理或显示;
  4. 图像消费者处理完毕,调用release方法把buffer归还给BufferQueue,这个buffer之后可再重复使用;
  5. 图像生产者、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 生产和消费的流程:

  1. 初始化一个BufferQueue
  2. 图形数据的生产者通过BufferQueue申请一块GraphicBuffer,对应图中的dequeueBuffer方法
  3. 申请到GraphicBuffer后,获取GraphicBuffer,通过函数requestBuffer获取
  4. 获取到GraphicBuffer后,通过各种形式往GraphicBuffer中填充图形数据后,然后将GraphicBuffer入队到BufferQueue中,对应上图中的queueBuffer方法
  5. 在新的GraphicBuffer入队BufferQueue时,BufferQueue会通过回调通知图形数据的消费者,有新的图形数据被生产出来了
  6. 然后消费者从BufferQueue中出队一个GraphicBuffer,对应图中的acquireBuffer方法
  7. 待消费者消费完图形数据后,将空的GraphicBuffer还给BufferQueue以便重复利用,此时对应上图中的releaseBuffer方法
  8. 此时BufferQueue再通过回调通知图形数据的生产者有空的GraphicBuffer了,图形数据的生产者又可以从BufferQueue中获取一个空的GraphicBuffer来填充数据
  9. 一直循环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();

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是利用Linux源码和字符串模拟生产者消费者问题的步骤: 1. 创建一个共享缓冲区,用于生产者和消费者之间的通信。可以使用Linux系统提供的共享内存机制来实现。 2. 创建两个线程,一个是生产者线程,一个是消费者线程。 3. 生产者线程负责向共享缓冲区中写入数据。它不断地生成随机字符串,并将其写入到共享缓冲区中。 4. 消费者线程负责从共享缓冲区中读取数据。它不断地从共享缓冲区中读取数据,并打印出来。 5. 在生产者和消费者之间使用信号量来进行同步。当共享缓冲区已满时,生产者线程需要等待消费者线程读取数据;当共享缓冲区为空时,消费者线程需要等待生产者线程写入数据。 6. 当生产者线程和消费者线程完成它们的工作后,需要释放共享缓冲区和信号量的资源。 上述步骤可以参考下面的伪代码: ``` // 创建共享缓冲区和信号量 buffer = create_shared_buffer(); semaphore1 = create_semaphore(1); // 控制生产者线程的访问 semaphore2 = create_semaphore(0); // 控制消费者线程的访问 // 创建生产者线程 create_thread(producer_thread, buffer, semaphore1, semaphore2); // 创建消费者线程 create_thread(consumer_thread, buffer, semaphore1, semaphore2); // 生产者线程代码 void producer_thread(buffer, semaphore1, semaphore2) { while (true) { // 生成随机字符串 str = generate_random_string(); // 等待共享缓冲区未满 wait(semaphore1); // 将字符串写入共享缓冲区 write_to_buffer(buffer, str); // 通知消费者线程共享缓冲区已有数据 signal(semaphore2); } } // 消费者线程代码 void consumer_thread(buffer, semaphore1, semaphore2) { while (true) { // 等待共享缓冲区非空 wait(semaphore2); // 从共享缓冲区读取数据 str = read_from_buffer(buffer); // 打印读取的数据 printf("%s\n", str); // 通知生产者线程共享缓冲区已有空间 signal(semaphore1); } } // 释放资源 delete_shared_buffer(buffer); delete_semaphore(semaphore1); delete_semaphore(semaphore2); ``` 以上就是利用Linux源码和字符串模拟生产者消费者问题的基本步骤和伪代码。需要注意的是,实现时要考虑多线程的同步和竞争条件,确保程序的正确性和稳定性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值