xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  **
3*38e8c45fSAndroid Build Coastguard Worker  ** Copyright 2012 The Android Open Source Project
4*38e8c45fSAndroid Build Coastguard Worker  **
5*38e8c45fSAndroid Build Coastguard Worker  ** Licensed under the Apache License Version 2.0(the "License");
6*38e8c45fSAndroid Build Coastguard Worker  ** you may not use this file except in compliance with the License.
7*38e8c45fSAndroid Build Coastguard Worker  ** You may obtain a copy of the License at
8*38e8c45fSAndroid Build Coastguard Worker  **
9*38e8c45fSAndroid Build Coastguard Worker  **     http://www.apache.org/licenses/LICENSE-2.0
10*38e8c45fSAndroid Build Coastguard Worker  **
11*38e8c45fSAndroid Build Coastguard Worker  ** Unless required by applicable law or agreed to in writing software
12*38e8c45fSAndroid Build Coastguard Worker  ** distributed under the License is distributed on an "AS IS" BASIS
13*38e8c45fSAndroid Build Coastguard Worker  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
14*38e8c45fSAndroid Build Coastguard Worker  ** See the License for the specific language governing permissions and
15*38e8c45fSAndroid Build Coastguard Worker  ** limitations under the License.
16*38e8c45fSAndroid Build Coastguard Worker  */
17*38e8c45fSAndroid Build Coastguard Worker 
18*38e8c45fSAndroid Build Coastguard Worker // TODO(b/129481165): remove the #pragma below and fix conversion issues
19*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic push
20*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wconversion"
21*38e8c45fSAndroid Build Coastguard Worker 
22*38e8c45fSAndroid Build Coastguard Worker // #define LOG_NDEBUG 0
23*38e8c45fSAndroid Build Coastguard Worker #undef LOG_TAG
24*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "FramebufferSurface"
25*38e8c45fSAndroid Build Coastguard Worker 
26*38e8c45fSAndroid Build Coastguard Worker #include <errno.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <stdio.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <stdlib.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <string.h>
30*38e8c45fSAndroid Build Coastguard Worker 
31*38e8c45fSAndroid Build Coastguard Worker #include <utils/String8.h>
32*38e8c45fSAndroid Build Coastguard Worker #include <log/log.h>
33*38e8c45fSAndroid Build Coastguard Worker 
34*38e8c45fSAndroid Build Coastguard Worker #include <com_android_graphics_libgui_flags.h>
35*38e8c45fSAndroid Build Coastguard Worker #include <gui/BufferItem.h>
36*38e8c45fSAndroid Build Coastguard Worker #include <gui/BufferQueue.h>
37*38e8c45fSAndroid Build Coastguard Worker #include <gui/Surface.h>
38*38e8c45fSAndroid Build Coastguard Worker #include <hardware/hardware.h>
39*38e8c45fSAndroid Build Coastguard Worker 
40*38e8c45fSAndroid Build Coastguard Worker #include <ui/DebugUtils.h>
41*38e8c45fSAndroid Build Coastguard Worker #include <ui/GraphicBuffer.h>
42*38e8c45fSAndroid Build Coastguard Worker #include <ui/Rect.h>
43*38e8c45fSAndroid Build Coastguard Worker 
44*38e8c45fSAndroid Build Coastguard Worker #include "FramebufferSurface.h"
45*38e8c45fSAndroid Build Coastguard Worker #include "HWComposer.h"
46*38e8c45fSAndroid Build Coastguard Worker #include "../SurfaceFlinger.h"
47*38e8c45fSAndroid Build Coastguard Worker 
48*38e8c45fSAndroid Build Coastguard Worker namespace android {
49*38e8c45fSAndroid Build Coastguard Worker 
50*38e8c45fSAndroid Build Coastguard Worker using ui::Dataspace;
51*38e8c45fSAndroid Build Coastguard Worker 
52*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
FramebufferSurface(HWComposer & hwc,PhysicalDisplayId displayId,const sp<IGraphicBufferProducer> & producer,const sp<IGraphicBufferConsumer> & consumer,const ui::Size & size,const ui::Size & maxSize)53*38e8c45fSAndroid Build Coastguard Worker FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
54*38e8c45fSAndroid Build Coastguard Worker                                        const sp<IGraphicBufferProducer>& producer,
55*38e8c45fSAndroid Build Coastguard Worker                                        const sp<IGraphicBufferConsumer>& consumer,
56*38e8c45fSAndroid Build Coastguard Worker                                        const ui::Size& size, const ui::Size& maxSize)
57*38e8c45fSAndroid Build Coastguard Worker       : ConsumerBase(producer, consumer),
58*38e8c45fSAndroid Build Coastguard Worker #else
59*38e8c45fSAndroid Build Coastguard Worker FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
60*38e8c45fSAndroid Build Coastguard Worker                                        const sp<IGraphicBufferConsumer>& consumer,
61*38e8c45fSAndroid Build Coastguard Worker                                        const ui::Size& size, const ui::Size& maxSize)
62*38e8c45fSAndroid Build Coastguard Worker       : ConsumerBase(consumer),
63*38e8c45fSAndroid Build Coastguard Worker #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
64*38e8c45fSAndroid Build Coastguard Worker         mDisplayId(displayId),
65*38e8c45fSAndroid Build Coastguard Worker         mMaxSize(maxSize),
66*38e8c45fSAndroid Build Coastguard Worker         mCurrentBufferSlot(-1),
67*38e8c45fSAndroid Build Coastguard Worker         mCurrentBuffer(),
68*38e8c45fSAndroid Build Coastguard Worker         mCurrentFence(Fence::NO_FENCE),
69*38e8c45fSAndroid Build Coastguard Worker         mHwc(hwc),
70*38e8c45fSAndroid Build Coastguard Worker         mHasPendingRelease(false),
71*38e8c45fSAndroid Build Coastguard Worker         mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
72*38e8c45fSAndroid Build Coastguard Worker         mPreviousBuffer() {
73*38e8c45fSAndroid Build Coastguard Worker     ALOGV("Creating for display %s", to_string(displayId).c_str());
74*38e8c45fSAndroid Build Coastguard Worker 
75*38e8c45fSAndroid Build Coastguard Worker     mName = "FramebufferSurface";
76*38e8c45fSAndroid Build Coastguard Worker     mConsumer->setConsumerName(mName);
77*38e8c45fSAndroid Build Coastguard Worker     mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
78*38e8c45fSAndroid Build Coastguard Worker                                        GRALLOC_USAGE_HW_RENDER |
79*38e8c45fSAndroid Build Coastguard Worker                                        GRALLOC_USAGE_HW_COMPOSER);
80*38e8c45fSAndroid Build Coastguard Worker     const auto limitedSize = limitSize(size);
81*38e8c45fSAndroid Build Coastguard Worker     mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
82*38e8c45fSAndroid Build Coastguard Worker     mConsumer->setMaxAcquiredBufferCount(
83*38e8c45fSAndroid Build Coastguard Worker             SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
84*38e8c45fSAndroid Build Coastguard Worker 
85*38e8c45fSAndroid Build Coastguard Worker     for (size_t i = 0; i < sizeof(mHwcBufferIds) / sizeof(mHwcBufferIds[0]); ++i) {
86*38e8c45fSAndroid Build Coastguard Worker         mHwcBufferIds[i] = UINT64_MAX;
87*38e8c45fSAndroid Build Coastguard Worker     }
88*38e8c45fSAndroid Build Coastguard Worker }
89*38e8c45fSAndroid Build Coastguard Worker 
resizeBuffers(const ui::Size & newSize)90*38e8c45fSAndroid Build Coastguard Worker void FramebufferSurface::resizeBuffers(const ui::Size& newSize) {
91*38e8c45fSAndroid Build Coastguard Worker     const auto limitedSize = limitSize(newSize);
92*38e8c45fSAndroid Build Coastguard Worker     mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
93*38e8c45fSAndroid Build Coastguard Worker }
94*38e8c45fSAndroid Build Coastguard Worker 
beginFrame(bool)95*38e8c45fSAndroid Build Coastguard Worker status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
96*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
97*38e8c45fSAndroid Build Coastguard Worker }
98*38e8c45fSAndroid Build Coastguard Worker 
prepareFrame(CompositionType)99*38e8c45fSAndroid Build Coastguard Worker status_t FramebufferSurface::prepareFrame(CompositionType /*compositionType*/) {
100*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
101*38e8c45fSAndroid Build Coastguard Worker }
102*38e8c45fSAndroid Build Coastguard Worker 
advanceFrame(float hdrSdrRatio)103*38e8c45fSAndroid Build Coastguard Worker status_t FramebufferSurface::advanceFrame(float hdrSdrRatio) {
104*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
105*38e8c45fSAndroid Build Coastguard Worker 
106*38e8c45fSAndroid Build Coastguard Worker     BufferItem item;
107*38e8c45fSAndroid Build Coastguard Worker     status_t err = acquireBufferLocked(&item, 0);
108*38e8c45fSAndroid Build Coastguard Worker     if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
109*38e8c45fSAndroid Build Coastguard Worker         mDataspace = Dataspace::UNKNOWN;
110*38e8c45fSAndroid Build Coastguard Worker         return NO_ERROR;
111*38e8c45fSAndroid Build Coastguard Worker     } else if (err != NO_ERROR) {
112*38e8c45fSAndroid Build Coastguard Worker         ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);
113*38e8c45fSAndroid Build Coastguard Worker         mDataspace = Dataspace::UNKNOWN;
114*38e8c45fSAndroid Build Coastguard Worker         return err;
115*38e8c45fSAndroid Build Coastguard Worker     }
116*38e8c45fSAndroid Build Coastguard Worker 
117*38e8c45fSAndroid Build Coastguard Worker     // If the BufferQueue has freed and reallocated a buffer in mCurrentSlot
118*38e8c45fSAndroid Build Coastguard Worker     // then we may have acquired the slot we already own.  If we had released
119*38e8c45fSAndroid Build Coastguard Worker     // our current buffer before we call acquireBuffer then that release call
120*38e8c45fSAndroid Build Coastguard Worker     // would have returned STALE_BUFFER_SLOT, and we would have called
121*38e8c45fSAndroid Build Coastguard Worker     // freeBufferLocked on that slot.  Because the buffer slot has already
122*38e8c45fSAndroid Build Coastguard Worker     // been overwritten with the new buffer all we have to do is skip the
123*38e8c45fSAndroid Build Coastguard Worker     // releaseBuffer call and we should be in the same state we'd be in if we
124*38e8c45fSAndroid Build Coastguard Worker     // had released the old buffer first.
125*38e8c45fSAndroid Build Coastguard Worker     if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
126*38e8c45fSAndroid Build Coastguard Worker         item.mSlot != mCurrentBufferSlot) {
127*38e8c45fSAndroid Build Coastguard Worker         mHasPendingRelease = true;
128*38e8c45fSAndroid Build Coastguard Worker         mPreviousBufferSlot = mCurrentBufferSlot;
129*38e8c45fSAndroid Build Coastguard Worker         mPreviousBuffer = mCurrentBuffer;
130*38e8c45fSAndroid Build Coastguard Worker     }
131*38e8c45fSAndroid Build Coastguard Worker     mCurrentBufferSlot = item.mSlot;
132*38e8c45fSAndroid Build Coastguard Worker     mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
133*38e8c45fSAndroid Build Coastguard Worker     mCurrentFence = item.mFence;
134*38e8c45fSAndroid Build Coastguard Worker     mDataspace = static_cast<Dataspace>(item.mDataSpace);
135*38e8c45fSAndroid Build Coastguard Worker 
136*38e8c45fSAndroid Build Coastguard Worker     // assume HWC has previously seen the buffer in this slot
137*38e8c45fSAndroid Build Coastguard Worker     sp<GraphicBuffer> hwcBuffer = sp<GraphicBuffer>(nullptr);
138*38e8c45fSAndroid Build Coastguard Worker     if (mCurrentBuffer->getId() != mHwcBufferIds[mCurrentBufferSlot]) {
139*38e8c45fSAndroid Build Coastguard Worker         mHwcBufferIds[mCurrentBufferSlot] = mCurrentBuffer->getId();
140*38e8c45fSAndroid Build Coastguard Worker         hwcBuffer = mCurrentBuffer; // HWC hasn't previously seen this buffer in this slot
141*38e8c45fSAndroid Build Coastguard Worker     }
142*38e8c45fSAndroid Build Coastguard Worker     status_t result = mHwc.setClientTarget(mDisplayId, mCurrentBufferSlot, mCurrentFence, hwcBuffer,
143*38e8c45fSAndroid Build Coastguard Worker                                            mDataspace, hdrSdrRatio);
144*38e8c45fSAndroid Build Coastguard Worker     if (result != NO_ERROR) {
145*38e8c45fSAndroid Build Coastguard Worker         ALOGE("error posting framebuffer: %s (%d)", strerror(-result), result);
146*38e8c45fSAndroid Build Coastguard Worker         return result;
147*38e8c45fSAndroid Build Coastguard Worker     }
148*38e8c45fSAndroid Build Coastguard Worker 
149*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
150*38e8c45fSAndroid Build Coastguard Worker }
151*38e8c45fSAndroid Build Coastguard Worker 
freeBufferLocked(int slotIndex)152*38e8c45fSAndroid Build Coastguard Worker void FramebufferSurface::freeBufferLocked(int slotIndex) {
153*38e8c45fSAndroid Build Coastguard Worker     ConsumerBase::freeBufferLocked(slotIndex);
154*38e8c45fSAndroid Build Coastguard Worker     if (slotIndex == mCurrentBufferSlot) {
155*38e8c45fSAndroid Build Coastguard Worker         mCurrentBufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
156*38e8c45fSAndroid Build Coastguard Worker     }
157*38e8c45fSAndroid Build Coastguard Worker }
158*38e8c45fSAndroid Build Coastguard Worker 
onFrameCommitted()159*38e8c45fSAndroid Build Coastguard Worker void FramebufferSurface::onFrameCommitted() {
160*38e8c45fSAndroid Build Coastguard Worker     if (mHasPendingRelease) {
161*38e8c45fSAndroid Build Coastguard Worker         sp<Fence> fence = mHwc.getPresentFence(mDisplayId);
162*38e8c45fSAndroid Build Coastguard Worker         if (fence->isValid()) {
163*38e8c45fSAndroid Build Coastguard Worker             status_t result = addReleaseFence(mPreviousBufferSlot,
164*38e8c45fSAndroid Build Coastguard Worker                     mPreviousBuffer, fence);
165*38e8c45fSAndroid Build Coastguard Worker             ALOGE_IF(result != NO_ERROR, "onFrameCommitted: failed to add the"
166*38e8c45fSAndroid Build Coastguard Worker                     " fence: %s (%d)", strerror(-result), result);
167*38e8c45fSAndroid Build Coastguard Worker         }
168*38e8c45fSAndroid Build Coastguard Worker         status_t result = releaseBufferLocked(mPreviousBufferSlot, mPreviousBuffer);
169*38e8c45fSAndroid Build Coastguard Worker         ALOGE_IF(result != NO_ERROR, "onFrameCommitted: error releasing buffer:"
170*38e8c45fSAndroid Build Coastguard Worker                 " %s (%d)", strerror(-result), result);
171*38e8c45fSAndroid Build Coastguard Worker 
172*38e8c45fSAndroid Build Coastguard Worker         mPreviousBuffer.clear();
173*38e8c45fSAndroid Build Coastguard Worker         mHasPendingRelease = false;
174*38e8c45fSAndroid Build Coastguard Worker     }
175*38e8c45fSAndroid Build Coastguard Worker }
176*38e8c45fSAndroid Build Coastguard Worker 
limitSize(const ui::Size & size)177*38e8c45fSAndroid Build Coastguard Worker ui::Size FramebufferSurface::limitSize(const ui::Size& size) {
178*38e8c45fSAndroid Build Coastguard Worker     return limitSizeInternal(size, mMaxSize);
179*38e8c45fSAndroid Build Coastguard Worker }
180*38e8c45fSAndroid Build Coastguard Worker 
limitSizeInternal(const ui::Size & size,const ui::Size & maxSize)181*38e8c45fSAndroid Build Coastguard Worker ui::Size FramebufferSurface::limitSizeInternal(const ui::Size& size, const ui::Size& maxSize) {
182*38e8c45fSAndroid Build Coastguard Worker     ui::Size limitedSize = size;
183*38e8c45fSAndroid Build Coastguard Worker     bool wasLimited = false;
184*38e8c45fSAndroid Build Coastguard Worker     if (size.width > maxSize.width && maxSize.width != 0) {
185*38e8c45fSAndroid Build Coastguard Worker         const float aspectRatio = static_cast<float>(size.width) / size.height;
186*38e8c45fSAndroid Build Coastguard Worker         limitedSize.height = maxSize.width / aspectRatio;
187*38e8c45fSAndroid Build Coastguard Worker         limitedSize.width = maxSize.width;
188*38e8c45fSAndroid Build Coastguard Worker         wasLimited = true;
189*38e8c45fSAndroid Build Coastguard Worker     }
190*38e8c45fSAndroid Build Coastguard Worker     if (limitedSize.height > maxSize.height && maxSize.height != 0) {
191*38e8c45fSAndroid Build Coastguard Worker         const float aspectRatio = static_cast<float>(size.width) / size.height;
192*38e8c45fSAndroid Build Coastguard Worker         limitedSize.height = maxSize.height;
193*38e8c45fSAndroid Build Coastguard Worker         limitedSize.width = maxSize.height * aspectRatio;
194*38e8c45fSAndroid Build Coastguard Worker         wasLimited = true;
195*38e8c45fSAndroid Build Coastguard Worker     }
196*38e8c45fSAndroid Build Coastguard Worker     ALOGI_IF(wasLimited, "Framebuffer size has been limited to [%dx%d] from [%dx%d]",
197*38e8c45fSAndroid Build Coastguard Worker              limitedSize.width, limitedSize.height, size.width, size.height);
198*38e8c45fSAndroid Build Coastguard Worker     return limitedSize;
199*38e8c45fSAndroid Build Coastguard Worker }
200*38e8c45fSAndroid Build Coastguard Worker 
dumpAsString(String8 & result) const201*38e8c45fSAndroid Build Coastguard Worker void FramebufferSurface::dumpAsString(String8& result) const {
202*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
203*38e8c45fSAndroid Build Coastguard Worker     result.append("   FramebufferSurface\n");
204*38e8c45fSAndroid Build Coastguard Worker     result.appendFormat("      mDataspace=%s (%d)\n",
205*38e8c45fSAndroid Build Coastguard Worker                         dataspaceDetails(static_cast<android_dataspace>(mDataspace)).c_str(),
206*38e8c45fSAndroid Build Coastguard Worker                         mDataspace);
207*38e8c45fSAndroid Build Coastguard Worker     ConsumerBase::dumpLocked(result, "      ");
208*38e8c45fSAndroid Build Coastguard Worker }
209*38e8c45fSAndroid Build Coastguard Worker 
dumpLocked(String8 & result,const char * prefix) const210*38e8c45fSAndroid Build Coastguard Worker void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const {
211*38e8c45fSAndroid Build Coastguard Worker     ConsumerBase::dumpLocked(result, prefix);
212*38e8c45fSAndroid Build Coastguard Worker }
213*38e8c45fSAndroid Build Coastguard Worker 
getClientTargetAcquireFence() const214*38e8c45fSAndroid Build Coastguard Worker const sp<Fence>& FramebufferSurface::getClientTargetAcquireFence() const {
215*38e8c45fSAndroid Build Coastguard Worker     return mCurrentFence;
216*38e8c45fSAndroid Build Coastguard Worker }
217*38e8c45fSAndroid Build Coastguard Worker 
218*38e8c45fSAndroid Build Coastguard Worker } // namespace android
219*38e8c45fSAndroid Build Coastguard Worker 
220*38e8c45fSAndroid Build Coastguard Worker // TODO(b/129481165): remove the #pragma below and fix conversion issues
221*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic pop // ignored "-Wconversion"
222