xref: /aosp_15_r20/frameworks/native/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <cutils/compiler.h>
18 #include <gui/BufferQueue.h>
19 #include <surfacetexture/ImageConsumer.h>
20 #include <surfacetexture/SurfaceTexture.h>
21 #include <surfacetexture/surface_texture_platform.h>
22 #include <math/mat4.h>
23 #include <system/window.h>
24 #include <utils/Trace.h>
25 
26 #include <com_android_graphics_libgui_flags.h>
27 
28 namespace android {
29 
30 // Macros for including the SurfaceTexture name in log messages
31 #define SFT_LOGV(x, ...) ALOGV("[%s] " x, mName.c_str(), ##__VA_ARGS__)
32 #define SFT_LOGD(x, ...) ALOGD("[%s] " x, mName.c_str(), ##__VA_ARGS__)
33 #define SFT_LOGW(x, ...) ALOGW("[%s] " x, mName.c_str(), ##__VA_ARGS__)
34 #define SFT_LOGE(x, ...) ALOGE("[%s] " x, mName.c_str(), ##__VA_ARGS__)
35 
36 static const mat4 mtxIdentity;
37 
38 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
SurfaceTexture(uint32_t tex,uint32_t texTarget,bool useFenceSync,bool isControlledByApp)39 SurfaceTexture::SurfaceTexture(uint32_t tex, uint32_t texTarget, bool useFenceSync,
40                                bool isControlledByApp)
41       : ConsumerBase(isControlledByApp),
42         mCurrentCrop(Rect::EMPTY_RECT),
43         mCurrentTransform(0),
44         mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
45         mCurrentFence(Fence::NO_FENCE),
46         mCurrentTimestamp(0),
47         mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
48         mCurrentFrameNumber(0),
49         mDefaultWidth(1),
50         mDefaultHeight(1),
51         mFilteringEnabled(true),
52         mTexName(tex),
53         mUseFenceSync(useFenceSync),
54         mTexTarget(texTarget),
55         mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
56         mOpMode(OpMode::attachedToGL) {
57     initialize();
58 }
59 
SurfaceTexture(uint32_t texTarget,bool useFenceSync,bool isControlledByApp)60 SurfaceTexture::SurfaceTexture(uint32_t texTarget, bool useFenceSync, bool isControlledByApp)
61       : ConsumerBase(isControlledByApp),
62         mCurrentCrop(Rect::EMPTY_RECT),
63         mCurrentTransform(0),
64         mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
65         mCurrentFence(Fence::NO_FENCE),
66         mCurrentTimestamp(0),
67         mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
68         mCurrentFrameNumber(0),
69         mDefaultWidth(1),
70         mDefaultHeight(1),
71         mFilteringEnabled(true),
72         mTexName(0),
73         mUseFenceSync(useFenceSync),
74         mTexTarget(texTarget),
75         mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
76         mOpMode(OpMode::detached) {
77     initialize();
78 }
79 #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
80 
SurfaceTexture(const sp<IGraphicBufferConsumer> & bq,uint32_t tex,uint32_t texTarget,bool useFenceSync,bool isControlledByApp)81 SurfaceTexture::SurfaceTexture(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
82                                uint32_t texTarget, bool useFenceSync, bool isControlledByApp)
83       : ConsumerBase(bq, isControlledByApp),
84         mCurrentCrop(Rect::EMPTY_RECT),
85         mCurrentTransform(0),
86         mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
87         mCurrentFence(Fence::NO_FENCE),
88         mCurrentTimestamp(0),
89         mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
90         mCurrentFrameNumber(0),
91         mDefaultWidth(1),
92         mDefaultHeight(1),
93         mFilteringEnabled(true),
94         mTexName(tex),
95         mUseFenceSync(useFenceSync),
96         mTexTarget(texTarget),
97         mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
98         mOpMode(OpMode::attachedToGL) {
99     initialize();
100 }
101 
SurfaceTexture(const sp<IGraphicBufferConsumer> & bq,uint32_t texTarget,bool useFenceSync,bool isControlledByApp)102 SurfaceTexture::SurfaceTexture(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
103                                bool useFenceSync, bool isControlledByApp)
104       : ConsumerBase(bq, isControlledByApp),
105         mCurrentCrop(Rect::EMPTY_RECT),
106         mCurrentTransform(0),
107         mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
108         mCurrentFence(Fence::NO_FENCE),
109         mCurrentTimestamp(0),
110         mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
111         mCurrentFrameNumber(0),
112         mDefaultWidth(1),
113         mDefaultHeight(1),
114         mFilteringEnabled(true),
115         mTexName(0),
116         mUseFenceSync(useFenceSync),
117         mTexTarget(texTarget),
118         mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
119         mOpMode(OpMode::detached) {
120     initialize();
121 }
122 
setDefaultBufferSize(uint32_t w,uint32_t h)123 status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h) {
124     Mutex::Autolock lock(mMutex);
125     if (mAbandoned) {
126         SFT_LOGE("setDefaultBufferSize: SurfaceTexture is abandoned!");
127         return NO_INIT;
128     }
129     mDefaultWidth = w;
130     mDefaultHeight = h;
131     return mConsumer->setDefaultBufferSize(w, h);
132 }
133 
updateTexImage()134 status_t SurfaceTexture::updateTexImage() {
135     ATRACE_CALL();
136     SFT_LOGV("updateTexImage");
137     Mutex::Autolock lock(mMutex);
138 
139     if (mAbandoned) {
140         SFT_LOGE("updateTexImage: SurfaceTexture is abandoned!");
141         return NO_INIT;
142     }
143 
144     return mEGLConsumer.updateTexImage(*this);
145 }
146 
releaseTexImage()147 status_t SurfaceTexture::releaseTexImage() {
148     // releaseTexImage can be invoked even when not attached to a GL context.
149     ATRACE_CALL();
150     SFT_LOGV("releaseTexImage");
151     Mutex::Autolock lock(mMutex);
152 
153     if (mAbandoned) {
154         SFT_LOGE("releaseTexImage: SurfaceTexture is abandoned!");
155         return NO_INIT;
156     }
157 
158     return mEGLConsumer.releaseTexImage(*this);
159 }
160 
acquireBufferLocked(BufferItem * item,nsecs_t presentWhen,uint64_t maxFrameNumber)161 status_t SurfaceTexture::acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
162                                              uint64_t maxFrameNumber) {
163     status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen, maxFrameNumber);
164     if (err != NO_ERROR) {
165         return err;
166     }
167 
168     switch (mOpMode) {
169         case OpMode::attachedToConsumer:
170             break;
171         case OpMode::attachedToGL:
172             mEGLConsumer.onAcquireBufferLocked(item, *this);
173             break;
174         case OpMode::detached:
175             break;
176     }
177 
178     return NO_ERROR;
179 }
180 
releaseBufferLocked(int buf,sp<GraphicBuffer> graphicBuffer,EGLDisplay display,EGLSyncKHR eglFence)181 status_t SurfaceTexture::releaseBufferLocked(int buf, sp<GraphicBuffer> graphicBuffer,
182                                              EGLDisplay display, EGLSyncKHR eglFence) {
183     // release the buffer if it hasn't already been discarded by the
184     // BufferQueue. This can happen, for example, when the producer of this
185     // buffer has reallocated the original buffer slot after this buffer
186     // was acquired.
187     status_t err = ConsumerBase::releaseBufferLocked(buf, graphicBuffer, display, eglFence);
188     // We could be releasing an EGL/Vulkan buffer, even if not currently
189     // attached to a GL context.
190     mImageConsumer.onReleaseBufferLocked(buf);
191     mEGLConsumer.onReleaseBufferLocked(buf);
192     return err;
193 }
194 
detachFromContext()195 status_t SurfaceTexture::detachFromContext() {
196     ATRACE_CALL();
197     SFT_LOGV("detachFromContext");
198     Mutex::Autolock lock(mMutex);
199 
200     if (mAbandoned) {
201         SFT_LOGE("detachFromContext: abandoned SurfaceTexture");
202         return NO_INIT;
203     }
204 
205     if (mOpMode != OpMode::attachedToGL) {
206         SFT_LOGE("detachFromContext: SurfaceTexture is not attached to a GL context");
207         return INVALID_OPERATION;
208     }
209 
210     status_t err = mEGLConsumer.detachFromContext(*this);
211     if (err == OK) {
212         mOpMode = OpMode::detached;
213     }
214 
215     return err;
216 }
217 
attachToContext(uint32_t tex)218 status_t SurfaceTexture::attachToContext(uint32_t tex) {
219     ATRACE_CALL();
220     SFT_LOGV("attachToContext");
221     Mutex::Autolock lock(mMutex);
222 
223     if (mAbandoned) {
224         SFT_LOGE("attachToContext: abandoned SurfaceTexture");
225         return NO_INIT;
226     }
227 
228     if (mOpMode != OpMode::detached) {
229         SFT_LOGE("attachToContext: SurfaceTexture is already attached to a "
230                  "context");
231         return INVALID_OPERATION;
232     }
233 
234     return mEGLConsumer.attachToContext(tex, *this);
235 }
236 
takeConsumerOwnership()237 void SurfaceTexture::takeConsumerOwnership() {
238     ATRACE_CALL();
239     Mutex::Autolock _l(mMutex);
240     if (mAbandoned) {
241         SFT_LOGE("attachToView: abandoned SurfaceTexture");
242         return;
243     }
244     if (mOpMode == OpMode::detached) {
245         mOpMode = OpMode::attachedToConsumer;
246 
247         if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
248             // release possible EGLConsumer texture cache
249             mEGLConsumer.onFreeBufferLocked(mCurrentTexture);
250             mEGLConsumer.onAbandonLocked();
251         }
252     } else {
253         SFT_LOGE("attachToView: already attached");
254     }
255 }
256 
releaseConsumerOwnership()257 void SurfaceTexture::releaseConsumerOwnership() {
258     ATRACE_CALL();
259     Mutex::Autolock _l(mMutex);
260 
261     if (mAbandoned) {
262         SFT_LOGE("detachFromView: abandoned SurfaceTexture");
263         return;
264     }
265 
266     if (mOpMode == OpMode::attachedToConsumer) {
267         mOpMode = OpMode::detached;
268     } else {
269         SFT_LOGE("detachFromView: not attached to View");
270     }
271 }
272 
getCurrentTextureTarget() const273 uint32_t SurfaceTexture::getCurrentTextureTarget() const {
274     return mTexTarget;
275 }
276 
getTransformMatrix(float mtx[16])277 void SurfaceTexture::getTransformMatrix(float mtx[16]) {
278     Mutex::Autolock lock(mMutex);
279     memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
280 }
281 
setFilteringEnabled(bool enabled)282 void SurfaceTexture::setFilteringEnabled(bool enabled) {
283     Mutex::Autolock lock(mMutex);
284     if (mAbandoned) {
285         SFT_LOGE("setFilteringEnabled: SurfaceTexture is abandoned!");
286         return;
287     }
288     bool needsRecompute = mFilteringEnabled != enabled;
289     mFilteringEnabled = enabled;
290 
291     if (needsRecompute && mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT) {
292         SFT_LOGD("setFilteringEnabled called with no current item");
293     }
294 
295     if (needsRecompute && mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
296         computeCurrentTransformMatrixLocked();
297     }
298 }
299 
computeCurrentTransformMatrixLocked()300 void SurfaceTexture::computeCurrentTransformMatrixLocked() {
301     SFT_LOGV("computeCurrentTransformMatrixLocked");
302     sp<GraphicBuffer> buf = (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT)
303             ? nullptr
304             : mSlots[mCurrentTexture].mGraphicBuffer;
305     if (buf == nullptr) {
306         SFT_LOGD("computeCurrentTransformMatrixLocked: no current item");
307     }
308     computeTransformMatrix(mCurrentTransformMatrix, buf, mCurrentCrop, mCurrentTransform,
309                            mFilteringEnabled);
310 }
311 
computeTransformMatrix(float outTransform[16],const sp<GraphicBuffer> & buf,const Rect & cropRect,uint32_t transform,bool filtering)312 void SurfaceTexture::computeTransformMatrix(float outTransform[16], const sp<GraphicBuffer>& buf,
313                                             const Rect& cropRect, uint32_t transform,
314                                             bool filtering) {
315     // Transform matrices
316     static const mat4 mtxFlipH(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
317     static const mat4 mtxFlipV(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1);
318     static const mat4 mtxRot90(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
319 
320     mat4 xform;
321     if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
322         xform *= mtxFlipH;
323     }
324     if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
325         xform *= mtxFlipV;
326     }
327     if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
328         xform *= mtxRot90;
329     }
330 
331     if (!cropRect.isEmpty() && buf.get()) {
332         float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
333         float bufferWidth = buf->getWidth();
334         float bufferHeight = buf->getHeight();
335         float shrinkAmount = 0.0f;
336         if (filtering) {
337             // In order to prevent bilinear sampling beyond the edge of the
338             // crop rectangle we may need to shrink it by 2 texels in each
339             // dimension.  Normally this would just need to take 1/2 a texel
340             // off each end, but because the chroma channels of YUV420 images
341             // are subsampled we may need to shrink the crop region by a whole
342             // texel on each side.
343             switch (buf->getPixelFormat()) {
344                 case PIXEL_FORMAT_RGBA_8888:
345                 case PIXEL_FORMAT_RGBX_8888:
346                 case PIXEL_FORMAT_RGBA_FP16:
347                 case PIXEL_FORMAT_RGBA_1010102:
348                 case PIXEL_FORMAT_RGB_888:
349                 case PIXEL_FORMAT_RGB_565:
350                 case PIXEL_FORMAT_BGRA_8888:
351                     // We know there's no subsampling of any channels, so we
352                     // only need to shrink by a half a pixel.
353                     shrinkAmount = 0.5;
354                     break;
355 
356                 default:
357                     // If we don't recognize the format, we must assume the
358                     // worst case (that we care about), which is YUV420.
359                     shrinkAmount = 1.0;
360                     break;
361             }
362         }
363 
364         // Only shrink the dimensions that are not the size of the buffer.
365         if (cropRect.width() < bufferWidth) {
366             tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
367             sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) / bufferWidth;
368         }
369         if (cropRect.height() < bufferHeight) {
370             ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) / bufferHeight;
371             sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) / bufferHeight;
372         }
373 
374         mat4 crop(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1);
375         xform = crop * xform;
376     }
377 
378     // SurfaceFlinger expects the top of its window textures to be at a Y
379     // coordinate of 0, so SurfaceTexture must behave the same way.  We don't
380     // want to expose this to applications, however, so we must add an
381     // additional vertical flip to the transform after all the other transforms.
382     xform = mtxFlipV * xform;
383 
384     memcpy(outTransform, xform.asArray(), sizeof(xform));
385 }
386 
scaleDownCrop(const Rect & crop,uint32_t bufferWidth,uint32_t bufferHeight)387 Rect SurfaceTexture::scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight) {
388     Rect outCrop = crop;
389 
390     uint32_t newWidth = static_cast<uint32_t>(crop.width());
391     uint32_t newHeight = static_cast<uint32_t>(crop.height());
392 
393     if (newWidth * bufferHeight > newHeight * bufferWidth) {
394         newWidth = newHeight * bufferWidth / bufferHeight;
395         ALOGV("too wide: newWidth = %d", newWidth);
396     } else if (newWidth * bufferHeight < newHeight * bufferWidth) {
397         newHeight = newWidth * bufferHeight / bufferWidth;
398         ALOGV("too tall: newHeight = %d", newHeight);
399     }
400 
401     uint32_t currentWidth = static_cast<uint32_t>(crop.width());
402     uint32_t currentHeight = static_cast<uint32_t>(crop.height());
403 
404     // The crop is too wide
405     if (newWidth < currentWidth) {
406         uint32_t dw = currentWidth - newWidth;
407         auto halfdw = dw / 2;
408         outCrop.left += halfdw;
409         // Not halfdw because it would subtract 1 too few when dw is odd
410         outCrop.right -= (dw - halfdw);
411         // The crop is too tall
412     } else if (newHeight < currentHeight) {
413         uint32_t dh = currentHeight - newHeight;
414         auto halfdh = dh / 2;
415         outCrop.top += halfdh;
416         // Not halfdh because it would subtract 1 too few when dh is odd
417         outCrop.bottom -= (dh - halfdh);
418     }
419 
420     ALOGV("getCurrentCrop final crop [%d,%d,%d,%d]", outCrop.left, outCrop.top, outCrop.right,
421           outCrop.bottom);
422 
423     return outCrop;
424 }
425 
getTimestamp()426 nsecs_t SurfaceTexture::getTimestamp() {
427     SFT_LOGV("getTimestamp");
428     Mutex::Autolock lock(mMutex);
429     return mCurrentTimestamp;
430 }
431 
getCurrentDataSpace()432 android_dataspace SurfaceTexture::getCurrentDataSpace() {
433     SFT_LOGV("getCurrentDataSpace");
434     Mutex::Autolock lock(mMutex);
435     return mCurrentDataSpace;
436 }
437 
getFrameNumber()438 uint64_t SurfaceTexture::getFrameNumber() {
439     SFT_LOGV("getFrameNumber");
440     Mutex::Autolock lock(mMutex);
441     return mCurrentFrameNumber;
442 }
443 
getCurrentCrop() const444 Rect SurfaceTexture::getCurrentCrop() const {
445     Mutex::Autolock lock(mMutex);
446     return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
447             ? scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
448             : mCurrentCrop;
449 }
450 
getCurrentTransform() const451 uint32_t SurfaceTexture::getCurrentTransform() const {
452     Mutex::Autolock lock(mMutex);
453     return mCurrentTransform;
454 }
455 
getCurrentScalingMode() const456 uint32_t SurfaceTexture::getCurrentScalingMode() const {
457     Mutex::Autolock lock(mMutex);
458     return mCurrentScalingMode;
459 }
460 
getCurrentFence() const461 sp<Fence> SurfaceTexture::getCurrentFence() const {
462     Mutex::Autolock lock(mMutex);
463     return mCurrentFence;
464 }
465 
getCurrentFenceTime() const466 std::shared_ptr<FenceTime> SurfaceTexture::getCurrentFenceTime() const {
467     Mutex::Autolock lock(mMutex);
468     return mCurrentFenceTime;
469 }
470 
freeBufferLocked(int slotIndex)471 void SurfaceTexture::freeBufferLocked(int slotIndex) {
472     SFT_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
473     if (slotIndex == mCurrentTexture) {
474         mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
475     }
476     // The slotIndex buffer could have EGL cache, but there is no way to tell
477     // for sure. Buffers can be freed after SurfaceTexture has detached from GL
478     // context or View.
479     mEGLConsumer.onFreeBufferLocked(slotIndex);
480     ConsumerBase::freeBufferLocked(slotIndex);
481 }
482 
abandonLocked()483 void SurfaceTexture::abandonLocked() {
484     SFT_LOGV("abandonLocked");
485     mEGLConsumer.onAbandonLocked();
486     ConsumerBase::abandonLocked();
487 }
488 
setConsumerUsageBits(uint64_t usage)489 status_t SurfaceTexture::setConsumerUsageBits(uint64_t usage) {
490     return ConsumerBase::setConsumerUsageBits(usage | DEFAULT_USAGE_FLAGS);
491 }
492 
dumpLocked(String8 & result,const char * prefix) const493 void SurfaceTexture::dumpLocked(String8& result, const char* prefix) const {
494     result.appendFormat("%smTexName=%d mCurrentTexture=%d\n"
495                         "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
496                         prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
497                         mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
498                         mCurrentTransform);
499 
500     ConsumerBase::dumpLocked(result, prefix);
501 }
502 
dequeueBuffer(int * outSlotid,android_dataspace * outDataspace,HdrMetadata * outHdrMetadata,float * outTransformMatrix,uint32_t * outTransform,bool * outQueueEmpty,SurfaceTexture_createReleaseFence createFence,SurfaceTexture_fenceWait fenceWait,void * fencePassThroughHandle,ARect * currentCrop)503 sp<GraphicBuffer> SurfaceTexture::dequeueBuffer(int* outSlotid, android_dataspace* outDataspace,
504                                                 HdrMetadata* outHdrMetadata,
505                                                 float* outTransformMatrix, uint32_t* outTransform,
506                                                 bool* outQueueEmpty,
507                                                 SurfaceTexture_createReleaseFence createFence,
508                                                 SurfaceTexture_fenceWait fenceWait,
509                                                 void* fencePassThroughHandle, ARect* currentCrop) {
510     Mutex::Autolock _l(mMutex);
511     sp<GraphicBuffer> buffer;
512 
513     if (mAbandoned) {
514         SFT_LOGE("dequeueImage: SurfaceTexture is abandoned!");
515         return buffer;
516     }
517 
518     if (mOpMode != OpMode::attachedToConsumer) {
519         SFT_LOGE("dequeueImage: SurfaceTexture is not attached to a View");
520         return buffer;
521     }
522 
523     buffer = mImageConsumer.dequeueBuffer(outSlotid, outDataspace, outHdrMetadata, outQueueEmpty,
524                                           *this, createFence, fenceWait, fencePassThroughHandle);
525     memcpy(outTransformMatrix, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
526     *outTransform = mCurrentTransform;
527     *currentCrop = mCurrentCrop;
528     return buffer;
529 }
530 
setSurfaceTextureListener(const sp<android::SurfaceTexture::SurfaceTextureListener> & listener)531 void SurfaceTexture::setSurfaceTextureListener(
532         const sp<android::SurfaceTexture::SurfaceTextureListener>& listener) {
533     SFT_LOGV("setSurfaceTextureListener");
534 
535     Mutex::Autolock _l(mMutex);
536     mSurfaceTextureListener = listener;
537     if (mSurfaceTextureListener != nullptr) {
538         mFrameAvailableListenerProxy =
539                 sp<FrameAvailableListenerProxy>::make(mSurfaceTextureListener);
540         setFrameAvailableListener(mFrameAvailableListenerProxy);
541     } else {
542         mFrameAvailableListenerProxy.clear();
543     }
544 }
545 
onFrameAvailable(const BufferItem & item)546 void SurfaceTexture::FrameAvailableListenerProxy::onFrameAvailable(const BufferItem& item) {
547     const auto listener = mSurfaceTextureListener.promote();
548     if (listener) {
549         listener->onFrameAvailable(item);
550     }
551 }
552 
553 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
onSetFrameRate(float frameRate,int8_t compatibility,int8_t changeFrameRateStrategy)554 void SurfaceTexture::onSetFrameRate(float frameRate, int8_t compatibility,
555                                     int8_t changeFrameRateStrategy) {
556     SFT_LOGV("onSetFrameRate: %.2f", frameRate);
557 
558     auto listener = [&] {
559         Mutex::Autolock _l(mMutex);
560         return mSurfaceTextureListener;
561     }();
562 
563     if (listener) {
564         listener->onSetFrameRate(frameRate, compatibility, changeFrameRateStrategy);
565     }
566 }
567 #endif
568 
initialize()569 void SurfaceTexture::initialize() {
570     SFT_LOGV("SurfaceTexture");
571 
572     memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));
573 
574     mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
575 }
576 
577 } // namespace android
578