xref: /aosp_15_r20/frameworks/native/libs/nativedisplay/surfacetexture/ImageConsumer.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2019 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #include <gui/BufferQueue.h>
18*38e8c45fSAndroid Build Coastguard Worker #include <surfacetexture/ImageConsumer.h>
19*38e8c45fSAndroid Build Coastguard Worker #include <surfacetexture/SurfaceTexture.h>
20*38e8c45fSAndroid Build Coastguard Worker 
21*38e8c45fSAndroid Build Coastguard Worker // Macro for including the SurfaceTexture name in log messages
22*38e8c45fSAndroid Build Coastguard Worker #define IMG_LOGE(x, ...) ALOGE("[%s] " x, st.mName.c_str(), ##__VA_ARGS__)
23*38e8c45fSAndroid Build Coastguard Worker 
24*38e8c45fSAndroid Build Coastguard Worker namespace android {
25*38e8c45fSAndroid Build Coastguard Worker 
onReleaseBufferLocked(int buf)26*38e8c45fSAndroid Build Coastguard Worker void ImageConsumer::onReleaseBufferLocked(int buf) {
27*38e8c45fSAndroid Build Coastguard Worker     mImageSlots[buf].eglFence() = EGL_NO_SYNC_KHR;
28*38e8c45fSAndroid Build Coastguard Worker }
29*38e8c45fSAndroid Build Coastguard Worker 
dequeueBuffer(int * outSlotid,android_dataspace * outDataspace,HdrMetadata * outHdrMetadata,bool * outQueueEmpty,SurfaceTexture & st,SurfaceTexture_createReleaseFence createFence,SurfaceTexture_fenceWait fenceWait,void * fencePassThroughHandle)30*38e8c45fSAndroid Build Coastguard Worker sp<GraphicBuffer> ImageConsumer::dequeueBuffer(int* outSlotid, android_dataspace* outDataspace,
31*38e8c45fSAndroid Build Coastguard Worker                                                HdrMetadata* outHdrMetadata, bool* outQueueEmpty,
32*38e8c45fSAndroid Build Coastguard Worker                                                SurfaceTexture& st,
33*38e8c45fSAndroid Build Coastguard Worker                                                SurfaceTexture_createReleaseFence createFence,
34*38e8c45fSAndroid Build Coastguard Worker                                                SurfaceTexture_fenceWait fenceWait,
35*38e8c45fSAndroid Build Coastguard Worker                                                void* fencePassThroughHandle) {
36*38e8c45fSAndroid Build Coastguard Worker     BufferItem item;
37*38e8c45fSAndroid Build Coastguard Worker     status_t err;
38*38e8c45fSAndroid Build Coastguard Worker     err = st.acquireBufferLocked(&item, 0);
39*38e8c45fSAndroid Build Coastguard Worker     if (err != OK) {
40*38e8c45fSAndroid Build Coastguard Worker         if (err != BufferQueue::NO_BUFFER_AVAILABLE) {
41*38e8c45fSAndroid Build Coastguard Worker             IMG_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
42*38e8c45fSAndroid Build Coastguard Worker         } else {
43*38e8c45fSAndroid Build Coastguard Worker             int slot = st.mCurrentTexture;
44*38e8c45fSAndroid Build Coastguard Worker             if (slot != BufferItem::INVALID_BUFFER_SLOT) {
45*38e8c45fSAndroid Build Coastguard Worker                 *outQueueEmpty = true;
46*38e8c45fSAndroid Build Coastguard Worker                 *outDataspace = st.mCurrentDataSpace;
47*38e8c45fSAndroid Build Coastguard Worker                 *outSlotid = slot;
48*38e8c45fSAndroid Build Coastguard Worker                 return st.mSlots[slot].mGraphicBuffer;
49*38e8c45fSAndroid Build Coastguard Worker             }
50*38e8c45fSAndroid Build Coastguard Worker         }
51*38e8c45fSAndroid Build Coastguard Worker         return nullptr;
52*38e8c45fSAndroid Build Coastguard Worker     }
53*38e8c45fSAndroid Build Coastguard Worker 
54*38e8c45fSAndroid Build Coastguard Worker     int slot = item.mSlot;
55*38e8c45fSAndroid Build Coastguard Worker     *outQueueEmpty = false;
56*38e8c45fSAndroid Build Coastguard Worker     if (item.mFence->isValid()) {
57*38e8c45fSAndroid Build Coastguard Worker         // If fence is not signaled, that means frame is not ready and
58*38e8c45fSAndroid Build Coastguard Worker         // outQueueEmpty is set to true. By the time the fence is signaled,
59*38e8c45fSAndroid Build Coastguard Worker         // there may be a new buffer queued. This is a proper detection for an
60*38e8c45fSAndroid Build Coastguard Worker         // empty queue and it is needed to avoid infinite loop in
61*38e8c45fSAndroid Build Coastguard Worker         // ASurfaceTexture_dequeueBuffer (see b/159921224).
62*38e8c45fSAndroid Build Coastguard Worker         *outQueueEmpty = item.mFence->getStatus() == Fence::Status::Unsignaled;
63*38e8c45fSAndroid Build Coastguard Worker 
64*38e8c45fSAndroid Build Coastguard Worker         // Wait on the producer fence for the buffer to be ready.
65*38e8c45fSAndroid Build Coastguard Worker         err = fenceWait(item.mFence->get(), fencePassThroughHandle);
66*38e8c45fSAndroid Build Coastguard Worker         if (err != OK) {
67*38e8c45fSAndroid Build Coastguard Worker             st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer);
68*38e8c45fSAndroid Build Coastguard Worker             return nullptr;
69*38e8c45fSAndroid Build Coastguard Worker         }
70*38e8c45fSAndroid Build Coastguard Worker     }
71*38e8c45fSAndroid Build Coastguard Worker 
72*38e8c45fSAndroid Build Coastguard Worker     // Release old buffer.
73*38e8c45fSAndroid Build Coastguard Worker     if (st.mCurrentTexture != BufferItem::INVALID_BUFFER_SLOT) {
74*38e8c45fSAndroid Build Coastguard Worker         // If needed, set the released slot's fence to guard against a producer
75*38e8c45fSAndroid Build Coastguard Worker         // accessing the buffer before the outstanding accesses have completed.
76*38e8c45fSAndroid Build Coastguard Worker         int releaseFenceId = -1;
77*38e8c45fSAndroid Build Coastguard Worker         EGLDisplay display = EGL_NO_DISPLAY;
78*38e8c45fSAndroid Build Coastguard Worker         err = createFence(st.mUseFenceSync, &mImageSlots[slot].eglFence(), &display,
79*38e8c45fSAndroid Build Coastguard Worker                           &releaseFenceId, fencePassThroughHandle);
80*38e8c45fSAndroid Build Coastguard Worker         if (OK != err) {
81*38e8c45fSAndroid Build Coastguard Worker             st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer);
82*38e8c45fSAndroid Build Coastguard Worker             return nullptr;
83*38e8c45fSAndroid Build Coastguard Worker         }
84*38e8c45fSAndroid Build Coastguard Worker 
85*38e8c45fSAndroid Build Coastguard Worker         if (releaseFenceId != -1) {
86*38e8c45fSAndroid Build Coastguard Worker             sp<Fence> releaseFence(new Fence(releaseFenceId));
87*38e8c45fSAndroid Build Coastguard Worker             status_t err = st.addReleaseFenceLocked(st.mCurrentTexture,
88*38e8c45fSAndroid Build Coastguard Worker                                                     st.mSlots[st.mCurrentTexture].mGraphicBuffer,
89*38e8c45fSAndroid Build Coastguard Worker                                                     releaseFence);
90*38e8c45fSAndroid Build Coastguard Worker             if (err != OK) {
91*38e8c45fSAndroid Build Coastguard Worker                 IMG_LOGE("dequeueImage: error adding release fence: %s (%d)", strerror(-err), err);
92*38e8c45fSAndroid Build Coastguard Worker                 st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer);
93*38e8c45fSAndroid Build Coastguard Worker                 return nullptr;
94*38e8c45fSAndroid Build Coastguard Worker             }
95*38e8c45fSAndroid Build Coastguard Worker         }
96*38e8c45fSAndroid Build Coastguard Worker 
97*38e8c45fSAndroid Build Coastguard Worker         // Finally release the old buffer.
98*38e8c45fSAndroid Build Coastguard Worker         status_t status =
99*38e8c45fSAndroid Build Coastguard Worker                 st.releaseBufferLocked(st.mCurrentTexture,
100*38e8c45fSAndroid Build Coastguard Worker                                        st.mSlots[st.mCurrentTexture].mGraphicBuffer, display,
101*38e8c45fSAndroid Build Coastguard Worker                                        mImageSlots[st.mCurrentTexture].eglFence());
102*38e8c45fSAndroid Build Coastguard Worker         if (status < NO_ERROR) {
103*38e8c45fSAndroid Build Coastguard Worker             IMG_LOGE("dequeueImage: failed to release buffer: %s (%d)", strerror(-status), status);
104*38e8c45fSAndroid Build Coastguard Worker             err = status;
105*38e8c45fSAndroid Build Coastguard Worker             // Keep going, with error raised.
106*38e8c45fSAndroid Build Coastguard Worker         }
107*38e8c45fSAndroid Build Coastguard Worker     }
108*38e8c45fSAndroid Build Coastguard Worker 
109*38e8c45fSAndroid Build Coastguard Worker     // Update the state.
110*38e8c45fSAndroid Build Coastguard Worker     st.mCurrentTexture = slot;
111*38e8c45fSAndroid Build Coastguard Worker     st.mCurrentCrop = item.mCrop;
112*38e8c45fSAndroid Build Coastguard Worker     st.mCurrentTransform = item.mTransform;
113*38e8c45fSAndroid Build Coastguard Worker     st.mCurrentScalingMode = item.mScalingMode;
114*38e8c45fSAndroid Build Coastguard Worker     st.mCurrentTimestamp = item.mTimestamp;
115*38e8c45fSAndroid Build Coastguard Worker     st.mCurrentDataSpace = item.mDataSpace;
116*38e8c45fSAndroid Build Coastguard Worker     st.mCurrentFence = item.mFence;
117*38e8c45fSAndroid Build Coastguard Worker     st.mCurrentFenceTime = item.mFenceTime;
118*38e8c45fSAndroid Build Coastguard Worker     st.mCurrentFrameNumber = item.mFrameNumber;
119*38e8c45fSAndroid Build Coastguard Worker     st.computeCurrentTransformMatrixLocked();
120*38e8c45fSAndroid Build Coastguard Worker 
121*38e8c45fSAndroid Build Coastguard Worker     *outDataspace = item.mDataSpace;
122*38e8c45fSAndroid Build Coastguard Worker     *outHdrMetadata = item.mHdrMetadata;
123*38e8c45fSAndroid Build Coastguard Worker     *outSlotid = slot;
124*38e8c45fSAndroid Build Coastguard Worker     return st.mSlots[slot].mGraphicBuffer;
125*38e8c45fSAndroid Build Coastguard Worker }
126*38e8c45fSAndroid Build Coastguard Worker 
127*38e8c45fSAndroid Build Coastguard Worker } /* namespace android */
128