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