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