我们从下面几个文件开始分析Surface相关知识
- frameworks/native/libs/gui/tests/
- frameworks/native/opengl/tests/EGLTest/
- frameworks/native/libs/nativedisplay/surfacetexture/
一. 基本知识
先看下继承关系:
74 class Surface
75 : public ANativeObjectBase<ANativeWindow, Surface, RefBase>
76 {
Surface继承ANativeWindow和RefBase
再看下构造函数:
99 explicit Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp = false,
100 const sp<IBinder>& surfaceControlHandle = nullptr);
可以看到new Surface的时候就会指定producer是谁。一般都是通过下面方式传入的:
148 sp<IGraphicBufferProducer> producer;
149 sp<IGraphicBufferConsumer> consumer;
150 BufferQueue::createBufferQueue(&producer, &consumer);
152 sp<Surface> mSTC = new Surface(producer);
1.先看下BufferQueue的创建
101 void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
102 sp<IGraphicBufferConsumer>* outConsumer,
103 bool consumerIsSurfaceFlinger) { //默认false
109 sp<BufferQueueCore> core(new BufferQueueCore());
113 sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
117 sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
121 *outProducer = producer;
122 *outConsumer = consumer;
123 }
三个对象:BufferQueueCore、BufferQueueProducer、BufferQueueConsumer
1)BufferQueueCore
构造的时候几个关键的变量
️mConsumerName:
String8::format("unnamed-%d-%d", getpid(),
63 android_atomic_inc(&counter));
当然后期也可以通过函数接口重新设置:
719 status_t BufferQueueConsumer::setConsumerName(const String8& name) {
720 ATRACE_CALL();
721 BQ_LOGV("setConsumerName: '%s'", name.string());
722 std::lock_guard<std::mutex> lock(mCore->mMutex);
723 mCore->mConsumerName = name;
724 mConsumerName = name;
725 return NO_ERROR;
726 }
️mFreeSlots
134 int numStartingBuffers = getMaxBufferCountLocked();
135 for (int s = 0; s < numStartingBuffers; s++) {
136 mFreeSlots.insert(s);
137 }
可以看到初始化时mFreeSlots数量由getMaxBufferCountLocked函数决定。
246 int BufferQueueCore::getMaxBufferCountLocked() const {
247 int maxBufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
248 ((mAsyncMode || mDequeueBufferCannotBlock) ? 1 : 0);
249
250 // limit maxBufferCount by mMaxBufferCount always
251 maxBufferCount = std::min(mMaxBufferCount, maxBufferCount);
252
253 return maxBufferCount;
254 }
由于mMaxBufferCount基本等于BufferQueueDefs::NUM_BUFFER_SLOTS,当然也可以调用consumer的BufferQueueConsumer::setMaxBufferCount函数重新设置,因此可以看出getMaxBufferCountLocked由mMaxAcquiredBufferCount和mMaxDequeuedBufferCount以及+1(mAsyncMode/mDequeueBufferCannotBlock)决定。
mMaxAcquiredBufferCount在BufferQueueCore初始化为1,也可以通过BufferQueueConsumer::setMaxAcquiredBufferCount函数重新设置。
mMaxDequeuedBufferCount在BufferQueueCore初始化为1,也可以通过 BufferQueueProducer::setMaxDequeuedBufferCount函数重新设置。
通过mMaxDequeuedBufferCount名字上可以看出由producer设置,而mMaxBufferCount/mMaxAcquiredBufferCount 是由consumer设置。
而mAsyncMode默认是false,也可以由producer端的BufferQueueProducer::setAsyncMode函数进行设置。
mDequeueBufferCannotBlock默认也是false,这个变量容易出问题会使得总buffer数量+1,值得注意下!在producer端connect时:mDequeueBufferCannotBlock默认是false,但是如果producer和consumer端由app控制的话那么下面判断会进入:
1311 if (mCore->mConsumerControlledByApp && producerControlledByApp) {
1312 mCore->mDequeueBufferCannotBlock = mDequeueTimeout < 0;
1313 mCore->mQueueBufferCanDrop = mDequeueTimeout <= 0;
1314 }
会根据mDequeueTimeout变量(默认为-1)决定mDequeueBufferCannotBlock的值,如果是surfaceTexture,那么该判断会进入,但是如果没有调用BufferQueueProducer::setDequeueTimeout,那么mDequeueTimeout为-1,mDequeueBufferCannotBlock值会为true。因此,如果发现buffer多了一个,看下dump信息,是不是这个变量为true了。
️mUnusedSlots
mUnusedSlots表示目前没有使用的buffer,也就是用64-当前buffer数量
138 for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS;
139 s++) {
140 mUnusedSlots.push_front(s);
141 }
️mDefaultWidth/mDefaultHeight
默认为1,可以通过下面的consumer端重新设置,记得和producer端的函数有区是分的哦。Surface.cpp中也有同样的变量,是从当前BufferQueueCore中取的。
595 status_t BufferQueueConsumer::setDefaultBufferSize(uint32_t width,
596 uint32_t height) {
597 ATRACE_CALL();
608 mCore->mDefaultWidth = width;
609 mCore->mDefaultHeight = height;
610 return NO_ERROR;
611 }
对应其他模块调用:mConsumer->setDefaultBufferSize(w, h)
如:frameworks/native/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
️ mConsumerControlledByApp
既有producer端的也有consumer端的,共同决定前面说的mDequeueBufferCannotBlock变量。
如:SurfaceTexture设置过程如下:
frameworks/base/core/jni/android_graphics_SurfaceTexture.cpp
234 static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jboolean isDetached,
235 jint texName, jboolean singleBufferMode, jobject weakThiz)
236 {
237 sp<IGraphicBufferProducer> producer;
238 sp<IGraphicBufferConsumer> consumer;
239 BufferQueue::createBufferQueue(&producer, &consumer);
245 sp<SurfaceTexture> surfaceTexture;
246 if (isDetached) {
247 surfaceTexture = new SurfaceTexture(consumer, GL_TEXTURE_EXTERNAL_OES, //根据singleBuffer确认mConsumerControlledByApp
248 true, !singleBufferMode);
249 } else {
250 surfaceTexture = new SurfaceTexture(consumer, texName,
251 GL_TEXTURE_EXTERNAL_OES, true, !singleBufferMode); //根据singleBuffer确认mConsumerControlledByApp
252 }
frameworks/native/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
36 SurfaceTexture::SurfaceTexture(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
37 uint32_t texTarget, bool useFenceSync, bool isControlledByApp)
38 : ConsumerBase(bq, isControlledByApp),
frameworks/native/libs/gui/ConsumerBase.cpp
58 ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) {
72 status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
frameworks/native/libs/gui/include/gui/BufferQueueConsumer.h
165 virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
166 bool controlledByApp) {
167 return connect(consumer, controlledByApp);
168 }
frameworks/native/libs/gui/BufferQueueConsumer.cpp
511 status_t BufferQueueConsumer::connect(
512 const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
513 ATRACE_CALL();
531 mCore->mConsumerControlledByApp = controlledByApp;
532
533 return NO_ERROR;
534 }
2)BufferQueueProducer
️ mSlots
取的是BufferQueueCore中的mSlots
mSlots(core->mSlots)
3)BufferQueueConsumer
️ mSlots
取的是BufferQueueCore中的mSlots
mSlots(core->mSlots)
2. 回到主线上去看Surface中的成员变量
️mGraphicBufferProducer
指向BufferQueueProducer
️ mProducerControlledByApp
在new Surface的时候传入,这个值会被设置到BufferQueueProducer用于判断上面说的mDequeueBufferCannotBlock值。需要注意哦!
mProducerControlledByApp = controlledByApp
如:
TextureView:
frameworks/base/core/jni/android_view_TextureView.cpp
sp<ANativeWindow> window = new Surface(producer, true);
SurfaceTexture:
frameworks/base/core/jni/com_google_android_gles_jni_EGLImpl.cpp
301 sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(_env, native_window));
302 window = new Surface(producer, true);
frameworks/base/core/jni/android_view_Surface.cpp
android_view_Surface_createFromIGraphicBufferProducer
135 sp<Surface> surface(new Surface(bufferProducer, true));
nativeCreateFromSurfaceTexture
156 sp<Surface> surface(new Surface(producer, true));
️mReqWidth/mReqHeight
2079 int Surface::setBuffersDimensions(uint32_t width, uint32_t height)
2080 {
2081 ATRACE_CALL(); //有trace标签
2082 ALOGV("Surface::setBuffersDimensions"); //有log
2091 mReqWidth = width;
2092 mReqHeight = height;
2093 return NO_ERROR;
2094 }
对应其他模块调用:native_window_set_buffers_dimensions
️ mUserWidth/mUserHeight
Surface::setBuffersUserDimensions
对应其他模块调用:native_window_set_buffers_user_dimensions
可以看到和req的有点类似,使用时二者选1,首选req的:
157 uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight; // in allocateBuffers()
554 dequeueInput->height = mReqHeight ? mReqHeight : mUserHeight; //in getDequeueBufferInputLocked()
query时查询方式:
1234 case NATIVE_WINDOW_DEFAULT_WIDTH:
1235 *value = static_cast<int>(
1236 mUserWidth ? mUserWidth : mDefaultWidth);
1237 return NO_ERROR;
1238 case NATIVE_WINDOW_DEFAULT_HEIGHT:
1239 *value = static_cast<int>(
1240 mUserHeight ? mUserHeight : mDefaultHeight);
1241 return NO_ERROR;
一般user的很少设置,目前没有碰到过这类问题。
️mDefaultWidth/mDefaultHeight
来源于BufferQueue中queueBuffer,取自BufferQueueCore。
1029 output->width = mCore->mDefaultWidth;
1030 output->height = mCore->mDefaultHeight;
️mReqFormat
Surface::setBuffersFormat(PixelFormat format)
对应其他模块调用:native_window_set_buffers_format
️mReqUsage
Surface::setUsage(uint64_t reqUsage)
对应其他模块调用:native_window_set_usage
二.BLASTBufferQueue
147 BLASTBufferQueue::BLASTBufferQueue(const std::string& name, bool updateDestinationFrame) {
155 createBufferQueue(&mProducer, &mConsumer); //保存起来
156 // since the adapter is in the client process, set dequeue timeout
157 // explicitly so that dequeueBuffer will block
158 mProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());//那么mDequeueBufferCannotBlock就不会true了
159
160 // safe default, most producers are expected to override this
161 mProducer->setMaxDequeuedBufferCount(2); //设置dequeuecount=2
162 mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
163 GraphicBuffer::USAGE_HW_COMPOSER |
164 GraphicBuffer::USAGE_HW_TEXTURE,
165 1, false, this); //有usage哦!
166 static std::atomic<uint32_t> nextId = 0;
167 mProducerId = nextId++;
168 mName = name + "#" + std::to_string(mProducerId);
169 auto consumerName = mName + "(BLAST Consumer)" + std::to_string(mProducerId);
170 mQueuedBufferTrace = "QueuedBuffer - " + mName + "BLAST#" + std::to_string(mProducerId);//perfetto名字
171 mBufferItemConsumer->setName(String8(consumerName.c_str())); //设置consumerName
172 mBufferItemConsumer->setFrameAvailableListener(this);
173
174 ComposerServiceAIDL::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);//高刷一般2个,低刷1个
175 mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers); //设置acquirecount
176 mCurrentMaxAcquiredBufferCount = mMaxAcquiredBuffers;
1133 void BLASTBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
1134 sp<IGraphicBufferConsumer>* outConsumer) {
1138 sp<BufferQueueCore> core(new BufferQueueCore());
1141 sp<IGraphicBufferProducer> producer(new BBQBufferQueueProducer(core, this));
1145 sp<BufferQueueConsumer> consumer(new BufferQueueConsumer(core));
1146 consumer->setAllowExtraAcquire(true);
1150 *outProducer = producer;
1151 *outConsumer = consumer;
1152 }
可以看出,和普通BufferQueue的区别是producer换成了BBQBufferQueueProducer,多调用了setAllowExtraAcquire函数。
看下继承关系就一目了然了:
1081 class BBQBufferQueueProducer : public BufferQueueProducer {
1082 public:
1083 BBQBufferQueueProducer(const sp<BufferQueueCore>& core, wp<BLASTBufferQueue> bbq)
1084 : BufferQueueProducer(core, false /* consumerIsSurfaceFlinger*/), //可以看到此处为false
1085 mBLASTBufferQueue(std::move(bbq)) {}
为什么consumerIsSurfaceFlinger为false呢?
我们知道从BLASTBufferQueue出现后buffer的dequeue/queue动作都发生在APP进程了,之前都是发生在SF进程,所以可想而知,此变量就应该是false的。目前代码中好像没有看到有设置true的地方。
再回到BLASTBufferQueue 中看下BLASTBufferItemConsumer
38 class BLASTBufferItemConsumer : public BufferItemConsumer {
39 public:
40 BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
41 int bufferCount, bool controlledByApp, wp<BLASTBufferQueue> bbq)
42 : BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp),
43 mBLASTBufferQueue(std::move(bbq)),
class BufferItemConsumer: public ConsumerBase
35 BufferItemConsumer::BufferItemConsumer(
36 const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
37 int bufferCount, bool controlledByApp) :
38 ConsumerBase(consumer, controlledByApp) //构建consumerBase
39 {
40 status_t err = mConsumer->setConsumerUsageBits(consumerUsage);//设置BufferQueueConsumer的usage
43 if (bufferCount != DEFAULT_MAX_BUFFERS) {
44 err = mConsumer->setMaxAcquiredBufferCount(bufferCount);//设置acquireBufferCount,后面会被覆盖重写
47 }
48 }
58 ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
59 mAbandoned(false),
60 mConsumer(bufferQueue),
61 mPrevFinalReleaseFence(Fence::NO_FENCE) {
62 // Choose a name using the PID and a process-unique ID.
63 mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
64
69 wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
70 sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
71
72 status_t err = mConsumer->consumerConnect(proxy, controlledByApp); //connect,设置consumerControlByApp为false
73 if (err != NO_ERROR) {
74 CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
75 strerror(-err), err);
76 } else {
77 mConsumer->setConsumerName(mName); //setName,后面会被重写
78 }
79 }
以上mConsumer均为BufferQueueConsumer对象!!!!;
usage为GraphicBuffer::USAGE_HW_COMPOSER | GraphicBuffer::USAGE_HW_TEXTURE;bufferCount为1;controlledByApp为false。
再回到BLASTBufferQueue中可以看到后面又重新调用
setName、setMaxAcquiredBufferCount,覆盖了之前new BLASTBufferItemConsumer阶段覆的值,但是usage没有重新赋值。
再看看对应的Surface:
953 sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
954 std::lock_guard _lock{mMutex};
955 sp<IBinder> scHandle = nullptr;
956 if (includeSurfaceControlHandle && mSurfaceControl) {
957 scHandle = mSurfaceControl->getHandle();
958 }
959 return new BBQSurface(mProducer, true, scHandle, this);//记住此处mProducerControlledByApp为true哦。
960 }
873 class BBQSurface : public Surface {
880 BBQSurface(const sp<IGraphicBufferProducer>& igbp, bool controlledByApp,
881 const sp<IBinder>& scHandle, const sp<BLASTBufferQueue>& bbq)
882 : Surface(igbp, controlledByApp, scHandle), mBbq(bbq) {}
884 void allocateBuffers() override {
885 uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
886 uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
887 auto gbp = getIGraphicBufferProducer();
888 std::thread ([reqWidth, reqHeight, gbp=getIGraphicBufferProducer(),
889 reqFormat=mReqFormat, reqUsage=mReqUsage] () {
890 gbp->allocateBuffers(reqWidth, reqHeight,
891 reqFormat, reqUsage); //起单独线程做
892
893 }).detach();
894 }
80 sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
81 return mProducer; //拿BBQBufferQueueProducer
82 }
可以看出来通过拿到BBQSurface来进行buffer申请,而且是启用单独的线程做分配buffer的动作,从perfetto中可以看出来哦。
allocateBuffers在APP冷启动的时候调用,如果后面width/height/usage/format等变化会重新dequeueBuffer,如:旋转。