xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2013 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 // TODO(b/129481165): remove the #pragma below and fix conversion issues
18*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic push
19*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wconversion"
20*38e8c45fSAndroid Build Coastguard Worker 
21*38e8c45fSAndroid Build Coastguard Worker // #define LOG_NDEBUG 0
22*38e8c45fSAndroid Build Coastguard Worker 
23*38e8c45fSAndroid Build Coastguard Worker #include <cinttypes>
24*38e8c45fSAndroid Build Coastguard Worker 
25*38e8c45fSAndroid Build Coastguard Worker #include <com_android_graphics_libgui_flags.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <ftl/enum.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <ftl/flags.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <gui/BufferItem.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <gui/BufferQueue.h>
30*38e8c45fSAndroid Build Coastguard Worker #include <gui/IProducerListener.h>
31*38e8c45fSAndroid Build Coastguard Worker #include <system/window.h>
32*38e8c45fSAndroid Build Coastguard Worker 
33*38e8c45fSAndroid Build Coastguard Worker #include "HWComposer.h"
34*38e8c45fSAndroid Build Coastguard Worker #include "SurfaceFlinger.h"
35*38e8c45fSAndroid Build Coastguard Worker #include "VirtualDisplaySurface.h"
36*38e8c45fSAndroid Build Coastguard Worker 
37*38e8c45fSAndroid Build Coastguard Worker #define VDS_LOGE(msg, ...) ALOGE("[%s] " msg, \
38*38e8c45fSAndroid Build Coastguard Worker         mDisplayName.c_str(), ##__VA_ARGS__)
39*38e8c45fSAndroid Build Coastguard Worker #define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] " msg, \
40*38e8c45fSAndroid Build Coastguard Worker         mDisplayName.c_str(), ##__VA_ARGS__)
41*38e8c45fSAndroid Build Coastguard Worker #define VDS_LOGV(msg, ...) ALOGV("[%s] " msg, \
42*38e8c45fSAndroid Build Coastguard Worker         mDisplayName.c_str(), ##__VA_ARGS__)
43*38e8c45fSAndroid Build Coastguard Worker 
44*38e8c45fSAndroid Build Coastguard Worker #define UNSUPPORTED()                                               \
45*38e8c45fSAndroid Build Coastguard Worker     VDS_LOGE("%s: Invalid operation on virtual display", __func__); \
46*38e8c45fSAndroid Build Coastguard Worker     return INVALID_OPERATION
47*38e8c45fSAndroid Build Coastguard Worker 
48*38e8c45fSAndroid Build Coastguard Worker namespace android {
49*38e8c45fSAndroid Build Coastguard Worker 
VirtualDisplaySurface(HWComposer & hwc,VirtualDisplayId displayId,const sp<IGraphicBufferProducer> & sink,const sp<IGraphicBufferProducer> & bqProducer,const sp<IGraphicBufferConsumer> & bqConsumer,const std::string & name)50*38e8c45fSAndroid Build Coastguard Worker VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, VirtualDisplayId displayId,
51*38e8c45fSAndroid Build Coastguard Worker                                              const sp<IGraphicBufferProducer>& sink,
52*38e8c45fSAndroid Build Coastguard Worker                                              const sp<IGraphicBufferProducer>& bqProducer,
53*38e8c45fSAndroid Build Coastguard Worker                                              const sp<IGraphicBufferConsumer>& bqConsumer,
54*38e8c45fSAndroid Build Coastguard Worker                                              const std::string& name)
55*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
56*38e8c45fSAndroid Build Coastguard Worker       : ConsumerBase(bqProducer, bqConsumer),
57*38e8c45fSAndroid Build Coastguard Worker #else
58*38e8c45fSAndroid Build Coastguard Worker       : ConsumerBase(bqConsumer),
59*38e8c45fSAndroid Build Coastguard Worker #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
60*38e8c45fSAndroid Build Coastguard Worker         mHwc(hwc),
61*38e8c45fSAndroid Build Coastguard Worker         mDisplayId(displayId),
62*38e8c45fSAndroid Build Coastguard Worker         mDisplayName(name),
63*38e8c45fSAndroid Build Coastguard Worker         mSource{},
64*38e8c45fSAndroid Build Coastguard Worker         mDefaultOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
65*38e8c45fSAndroid Build Coastguard Worker         mOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
66*38e8c45fSAndroid Build Coastguard Worker         mOutputUsage(GRALLOC_USAGE_HW_COMPOSER),
67*38e8c45fSAndroid Build Coastguard Worker         mProducerSlotSource(0),
68*38e8c45fSAndroid Build Coastguard Worker         mProducerBuffers(),
69*38e8c45fSAndroid Build Coastguard Worker         mProducerSlotNeedReallocation(0),
70*38e8c45fSAndroid Build Coastguard Worker         mQueueBufferOutput(),
71*38e8c45fSAndroid Build Coastguard Worker         mSinkBufferWidth(0),
72*38e8c45fSAndroid Build Coastguard Worker         mSinkBufferHeight(0),
73*38e8c45fSAndroid Build Coastguard Worker         mFbFence(Fence::NO_FENCE),
74*38e8c45fSAndroid Build Coastguard Worker         mOutputFence(Fence::NO_FENCE),
75*38e8c45fSAndroid Build Coastguard Worker         mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
76*38e8c45fSAndroid Build Coastguard Worker         mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
77*38e8c45fSAndroid Build Coastguard Worker         mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv) {
78*38e8c45fSAndroid Build Coastguard Worker     mSource[SOURCE_SINK] = sink;
79*38e8c45fSAndroid Build Coastguard Worker     mSource[SOURCE_SCRATCH] = bqProducer;
80*38e8c45fSAndroid Build Coastguard Worker 
81*38e8c45fSAndroid Build Coastguard Worker     resetPerFrameState();
82*38e8c45fSAndroid Build Coastguard Worker 
83*38e8c45fSAndroid Build Coastguard Worker     int sinkWidth, sinkHeight;
84*38e8c45fSAndroid Build Coastguard Worker     sink->query(NATIVE_WINDOW_WIDTH, &sinkWidth);
85*38e8c45fSAndroid Build Coastguard Worker     sink->query(NATIVE_WINDOW_HEIGHT, &sinkHeight);
86*38e8c45fSAndroid Build Coastguard Worker     mSinkBufferWidth = sinkWidth;
87*38e8c45fSAndroid Build Coastguard Worker     mSinkBufferHeight = sinkHeight;
88*38e8c45fSAndroid Build Coastguard Worker 
89*38e8c45fSAndroid Build Coastguard Worker     // Pick the buffer format to request from the sink when not rendering to it
90*38e8c45fSAndroid Build Coastguard Worker     // with GPU. If the consumer needs CPU access, use the default format
91*38e8c45fSAndroid Build Coastguard Worker     // set by the consumer. Otherwise allow gralloc to decide the format based
92*38e8c45fSAndroid Build Coastguard Worker     // on usage bits.
93*38e8c45fSAndroid Build Coastguard Worker     int sinkUsage;
94*38e8c45fSAndroid Build Coastguard Worker     sink->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &sinkUsage);
95*38e8c45fSAndroid Build Coastguard Worker     if (sinkUsage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
96*38e8c45fSAndroid Build Coastguard Worker         int sinkFormat;
97*38e8c45fSAndroid Build Coastguard Worker         sink->query(NATIVE_WINDOW_FORMAT, &sinkFormat);
98*38e8c45fSAndroid Build Coastguard Worker         mDefaultOutputFormat = sinkFormat;
99*38e8c45fSAndroid Build Coastguard Worker     } else {
100*38e8c45fSAndroid Build Coastguard Worker         mDefaultOutputFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
101*38e8c45fSAndroid Build Coastguard Worker     }
102*38e8c45fSAndroid Build Coastguard Worker     mOutputFormat = mDefaultOutputFormat;
103*38e8c45fSAndroid Build Coastguard Worker 
104*38e8c45fSAndroid Build Coastguard Worker     ConsumerBase::mName = String8::format("VDS: %s", mDisplayName.c_str());
105*38e8c45fSAndroid Build Coastguard Worker     mConsumer->setConsumerName(ConsumerBase::mName);
106*38e8c45fSAndroid Build Coastguard Worker     mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
107*38e8c45fSAndroid Build Coastguard Worker     mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight);
108*38e8c45fSAndroid Build Coastguard Worker     sink->setAsyncMode(true);
109*38e8c45fSAndroid Build Coastguard Worker     IGraphicBufferProducer::QueueBufferOutput output;
110*38e8c45fSAndroid Build Coastguard Worker     mSource[SOURCE_SCRATCH]->connect(nullptr, NATIVE_WINDOW_API_EGL, false, &output);
111*38e8c45fSAndroid Build Coastguard Worker 
112*38e8c45fSAndroid Build Coastguard Worker     for (size_t i = 0; i < sizeof(mHwcBufferIds) / sizeof(mHwcBufferIds[0]); ++i) {
113*38e8c45fSAndroid Build Coastguard Worker         mHwcBufferIds[i] = UINT64_MAX;
114*38e8c45fSAndroid Build Coastguard Worker     }
115*38e8c45fSAndroid Build Coastguard Worker }
116*38e8c45fSAndroid Build Coastguard Worker 
~VirtualDisplaySurface()117*38e8c45fSAndroid Build Coastguard Worker VirtualDisplaySurface::~VirtualDisplaySurface() {
118*38e8c45fSAndroid Build Coastguard Worker     mSource[SOURCE_SCRATCH]->disconnect(NATIVE_WINDOW_API_EGL);
119*38e8c45fSAndroid Build Coastguard Worker }
120*38e8c45fSAndroid Build Coastguard Worker 
beginFrame(bool mustRecompose)121*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) {
122*38e8c45fSAndroid Build Coastguard Worker     if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
123*38e8c45fSAndroid Build Coastguard Worker         return NO_ERROR;
124*38e8c45fSAndroid Build Coastguard Worker     }
125*38e8c45fSAndroid Build Coastguard Worker 
126*38e8c45fSAndroid Build Coastguard Worker     mMustRecompose = mustRecompose;
127*38e8c45fSAndroid Build Coastguard Worker 
128*38e8c45fSAndroid Build Coastguard Worker     VDS_LOGW_IF(mDebugState != DebugState::Idle, "Unexpected %s in %s state", __func__,
129*38e8c45fSAndroid Build Coastguard Worker                 ftl::enum_string(mDebugState).c_str());
130*38e8c45fSAndroid Build Coastguard Worker     mDebugState = DebugState::Begun;
131*38e8c45fSAndroid Build Coastguard Worker 
132*38e8c45fSAndroid Build Coastguard Worker     return refreshOutputBuffer();
133*38e8c45fSAndroid Build Coastguard Worker }
134*38e8c45fSAndroid Build Coastguard Worker 
prepareFrame(CompositionType compositionType)135*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) {
136*38e8c45fSAndroid Build Coastguard Worker     if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
137*38e8c45fSAndroid Build Coastguard Worker         return NO_ERROR;
138*38e8c45fSAndroid Build Coastguard Worker     }
139*38e8c45fSAndroid Build Coastguard Worker 
140*38e8c45fSAndroid Build Coastguard Worker     VDS_LOGW_IF(mDebugState != DebugState::Begun, "Unexpected %s in %s state", __func__,
141*38e8c45fSAndroid Build Coastguard Worker                 ftl::enum_string(mDebugState).c_str());
142*38e8c45fSAndroid Build Coastguard Worker     mDebugState = DebugState::Prepared;
143*38e8c45fSAndroid Build Coastguard Worker 
144*38e8c45fSAndroid Build Coastguard Worker     mCompositionType = compositionType;
145*38e8c45fSAndroid Build Coastguard Worker     if (mForceHwcCopy && mCompositionType == CompositionType::Gpu) {
146*38e8c45fSAndroid Build Coastguard Worker         // Some hardware can do RGB->YUV conversion more efficiently in hardware
147*38e8c45fSAndroid Build Coastguard Worker         // controlled by HWC than in hardware controlled by the video encoder.
148*38e8c45fSAndroid Build Coastguard Worker         // Forcing GPU-composed frames to go through an extra copy by the HWC
149*38e8c45fSAndroid Build Coastguard Worker         // allows the format conversion to happen there, rather than passing RGB
150*38e8c45fSAndroid Build Coastguard Worker         // directly to the consumer.
151*38e8c45fSAndroid Build Coastguard Worker         //
152*38e8c45fSAndroid Build Coastguard Worker         // On the other hand, when the consumer prefers RGB or can consume RGB
153*38e8c45fSAndroid Build Coastguard Worker         // inexpensively, this forces an unnecessary copy.
154*38e8c45fSAndroid Build Coastguard Worker         mCompositionType = CompositionType::Mixed;
155*38e8c45fSAndroid Build Coastguard Worker     }
156*38e8c45fSAndroid Build Coastguard Worker 
157*38e8c45fSAndroid Build Coastguard Worker     if (mCompositionType != mDebugLastCompositionType) {
158*38e8c45fSAndroid Build Coastguard Worker         VDS_LOGV("%s: composition type changed to %s", __func__,
159*38e8c45fSAndroid Build Coastguard Worker                  toString(mCompositionType).c_str());
160*38e8c45fSAndroid Build Coastguard Worker         mDebugLastCompositionType = mCompositionType;
161*38e8c45fSAndroid Build Coastguard Worker     }
162*38e8c45fSAndroid Build Coastguard Worker 
163*38e8c45fSAndroid Build Coastguard Worker     if (mCompositionType != CompositionType::Gpu &&
164*38e8c45fSAndroid Build Coastguard Worker         (mOutputFormat != mDefaultOutputFormat || mOutputUsage != GRALLOC_USAGE_HW_COMPOSER)) {
165*38e8c45fSAndroid Build Coastguard Worker         // We must have just switched from GPU-only to MIXED or HWC
166*38e8c45fSAndroid Build Coastguard Worker         // composition. Stop using the format and usage requested by the GPU
167*38e8c45fSAndroid Build Coastguard Worker         // driver; they may be suboptimal when HWC is writing to the output
168*38e8c45fSAndroid Build Coastguard Worker         // buffer. For example, if the output is going to a video encoder, and
169*38e8c45fSAndroid Build Coastguard Worker         // HWC can write directly to YUV, some hardware can skip a
170*38e8c45fSAndroid Build Coastguard Worker         // memory-to-memory RGB-to-YUV conversion step.
171*38e8c45fSAndroid Build Coastguard Worker         //
172*38e8c45fSAndroid Build Coastguard Worker         // If we just switched *to* GPU-only mode, we'll change the
173*38e8c45fSAndroid Build Coastguard Worker         // format/usage and get a new buffer when the GPU driver calls
174*38e8c45fSAndroid Build Coastguard Worker         // dequeueBuffer().
175*38e8c45fSAndroid Build Coastguard Worker         mOutputFormat = mDefaultOutputFormat;
176*38e8c45fSAndroid Build Coastguard Worker         mOutputUsage = GRALLOC_USAGE_HW_COMPOSER;
177*38e8c45fSAndroid Build Coastguard Worker         refreshOutputBuffer();
178*38e8c45fSAndroid Build Coastguard Worker     }
179*38e8c45fSAndroid Build Coastguard Worker 
180*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
181*38e8c45fSAndroid Build Coastguard Worker }
182*38e8c45fSAndroid Build Coastguard Worker 
advanceFrame(float hdrSdrRatio)183*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::advanceFrame(float hdrSdrRatio) {
184*38e8c45fSAndroid Build Coastguard Worker     if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
185*38e8c45fSAndroid Build Coastguard Worker         return NO_ERROR;
186*38e8c45fSAndroid Build Coastguard Worker     }
187*38e8c45fSAndroid Build Coastguard Worker 
188*38e8c45fSAndroid Build Coastguard Worker     if (mCompositionType == CompositionType::Hwc) {
189*38e8c45fSAndroid Build Coastguard Worker         VDS_LOGW_IF(mDebugState != DebugState::Prepared, "Unexpected %s in %s state on HWC frame",
190*38e8c45fSAndroid Build Coastguard Worker                     __func__, ftl::enum_string(mDebugState).c_str());
191*38e8c45fSAndroid Build Coastguard Worker     } else {
192*38e8c45fSAndroid Build Coastguard Worker         VDS_LOGW_IF(mDebugState != DebugState::GpuDone,
193*38e8c45fSAndroid Build Coastguard Worker                     "Unexpected %s in %s state on GPU/MIXED frame", __func__,
194*38e8c45fSAndroid Build Coastguard Worker                     ftl::enum_string(mDebugState).c_str());
195*38e8c45fSAndroid Build Coastguard Worker     }
196*38e8c45fSAndroid Build Coastguard Worker     mDebugState = DebugState::Hwc;
197*38e8c45fSAndroid Build Coastguard Worker 
198*38e8c45fSAndroid Build Coastguard Worker     if (mOutputProducerSlot < 0 ||
199*38e8c45fSAndroid Build Coastguard Worker         (mCompositionType != CompositionType::Hwc && mFbProducerSlot < 0)) {
200*38e8c45fSAndroid Build Coastguard Worker         // Last chance bailout if something bad happened earlier. For example,
201*38e8c45fSAndroid Build Coastguard Worker         // in a graphics API configuration, if the sink disappears then dequeueBuffer
202*38e8c45fSAndroid Build Coastguard Worker         // will fail, the GPU driver won't queue a buffer, but SurfaceFlinger
203*38e8c45fSAndroid Build Coastguard Worker         // will soldier on. So we end up here without a buffer. There should
204*38e8c45fSAndroid Build Coastguard Worker         // be lots of scary messages in the log just before this.
205*38e8c45fSAndroid Build Coastguard Worker         VDS_LOGE("%s: no buffer, bailing out", __func__);
206*38e8c45fSAndroid Build Coastguard Worker         return NO_MEMORY;
207*38e8c45fSAndroid Build Coastguard Worker     }
208*38e8c45fSAndroid Build Coastguard Worker 
209*38e8c45fSAndroid Build Coastguard Worker     sp<GraphicBuffer> const& fbBuffer =
210*38e8c45fSAndroid Build Coastguard Worker             mFbProducerSlot >= 0 ? mProducerBuffers[mFbProducerSlot] : sp<GraphicBuffer>(nullptr);
211*38e8c45fSAndroid Build Coastguard Worker     sp<GraphicBuffer> const& outBuffer = mProducerBuffers[mOutputProducerSlot];
212*38e8c45fSAndroid Build Coastguard Worker     VDS_LOGV("%s: fb=%d(%p) out=%d(%p)", __func__, mFbProducerSlot, fbBuffer.get(),
213*38e8c45fSAndroid Build Coastguard Worker              mOutputProducerSlot, outBuffer.get());
214*38e8c45fSAndroid Build Coastguard Worker 
215*38e8c45fSAndroid Build Coastguard Worker     const auto halDisplayId = HalVirtualDisplayId::tryCast(mDisplayId);
216*38e8c45fSAndroid Build Coastguard Worker     LOG_FATAL_IF(!halDisplayId);
217*38e8c45fSAndroid Build Coastguard Worker     // At this point we know the output buffer acquire fence,
218*38e8c45fSAndroid Build Coastguard Worker     // so update HWC state with it.
219*38e8c45fSAndroid Build Coastguard Worker     mHwc.setOutputBuffer(*halDisplayId, mOutputFence, outBuffer);
220*38e8c45fSAndroid Build Coastguard Worker 
221*38e8c45fSAndroid Build Coastguard Worker     status_t result = NO_ERROR;
222*38e8c45fSAndroid Build Coastguard Worker     if (fbBuffer != nullptr) {
223*38e8c45fSAndroid Build Coastguard Worker         // assume that HWC has previously seen the buffer in this slot
224*38e8c45fSAndroid Build Coastguard Worker         sp<GraphicBuffer> hwcBuffer = sp<GraphicBuffer>(nullptr);
225*38e8c45fSAndroid Build Coastguard Worker         if (fbBuffer->getId() != mHwcBufferIds[mFbProducerSlot]) {
226*38e8c45fSAndroid Build Coastguard Worker             mHwcBufferIds[mFbProducerSlot] = fbBuffer->getId();
227*38e8c45fSAndroid Build Coastguard Worker             hwcBuffer = fbBuffer; // HWC hasn't previously seen this buffer in this slot
228*38e8c45fSAndroid Build Coastguard Worker         }
229*38e8c45fSAndroid Build Coastguard Worker         // TODO: Correctly propagate the dataspace from GL composition
230*38e8c45fSAndroid Build Coastguard Worker         result = mHwc.setClientTarget(*halDisplayId, mFbProducerSlot, mFbFence, hwcBuffer,
231*38e8c45fSAndroid Build Coastguard Worker                                       ui::Dataspace::UNKNOWN, hdrSdrRatio);
232*38e8c45fSAndroid Build Coastguard Worker     }
233*38e8c45fSAndroid Build Coastguard Worker 
234*38e8c45fSAndroid Build Coastguard Worker     return result;
235*38e8c45fSAndroid Build Coastguard Worker }
236*38e8c45fSAndroid Build Coastguard Worker 
onFrameCommitted()237*38e8c45fSAndroid Build Coastguard Worker void VirtualDisplaySurface::onFrameCommitted() {
238*38e8c45fSAndroid Build Coastguard Worker     const auto halDisplayId = HalVirtualDisplayId::tryCast(mDisplayId);
239*38e8c45fSAndroid Build Coastguard Worker     if (!halDisplayId) {
240*38e8c45fSAndroid Build Coastguard Worker         return;
241*38e8c45fSAndroid Build Coastguard Worker     }
242*38e8c45fSAndroid Build Coastguard Worker 
243*38e8c45fSAndroid Build Coastguard Worker     VDS_LOGW_IF(mDebugState != DebugState::Hwc, "Unexpected %s in %s state", __func__,
244*38e8c45fSAndroid Build Coastguard Worker                 ftl::enum_string(mDebugState).c_str());
245*38e8c45fSAndroid Build Coastguard Worker     mDebugState = DebugState::Idle;
246*38e8c45fSAndroid Build Coastguard Worker 
247*38e8c45fSAndroid Build Coastguard Worker     sp<Fence> retireFence = mHwc.getPresentFence(*halDisplayId);
248*38e8c45fSAndroid Build Coastguard Worker     if (mCompositionType == CompositionType::Mixed && mFbProducerSlot >= 0) {
249*38e8c45fSAndroid Build Coastguard Worker         // release the scratch buffer back to the pool
250*38e8c45fSAndroid Build Coastguard Worker         Mutex::Autolock lock(mMutex);
251*38e8c45fSAndroid Build Coastguard Worker         int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot);
252*38e8c45fSAndroid Build Coastguard Worker         VDS_LOGV("%s: release scratch sslot=%d", __func__, sslot);
253*38e8c45fSAndroid Build Coastguard Worker         addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot],
254*38e8c45fSAndroid Build Coastguard Worker                 retireFence);
255*38e8c45fSAndroid Build Coastguard Worker         releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot]);
256*38e8c45fSAndroid Build Coastguard Worker     }
257*38e8c45fSAndroid Build Coastguard Worker 
258*38e8c45fSAndroid Build Coastguard Worker     if (mOutputProducerSlot >= 0) {
259*38e8c45fSAndroid Build Coastguard Worker         int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot);
260*38e8c45fSAndroid Build Coastguard Worker         QueueBufferOutput qbo;
261*38e8c45fSAndroid Build Coastguard Worker         VDS_LOGV("%s: queue sink sslot=%d", __func__, sslot);
262*38e8c45fSAndroid Build Coastguard Worker         if (mMustRecompose) {
263*38e8c45fSAndroid Build Coastguard Worker             status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
264*38e8c45fSAndroid Build Coastguard Worker                     QueueBufferInput(
265*38e8c45fSAndroid Build Coastguard Worker                         systemTime(), false /* isAutoTimestamp */,
266*38e8c45fSAndroid Build Coastguard Worker                         HAL_DATASPACE_UNKNOWN,
267*38e8c45fSAndroid Build Coastguard Worker                         Rect(mSinkBufferWidth, mSinkBufferHeight),
268*38e8c45fSAndroid Build Coastguard Worker                         NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */,
269*38e8c45fSAndroid Build Coastguard Worker                         retireFence),
270*38e8c45fSAndroid Build Coastguard Worker                     &qbo);
271*38e8c45fSAndroid Build Coastguard Worker             if (result == NO_ERROR) {
272*38e8c45fSAndroid Build Coastguard Worker                 updateQueueBufferOutput(std::move(qbo));
273*38e8c45fSAndroid Build Coastguard Worker             }
274*38e8c45fSAndroid Build Coastguard Worker         } else {
275*38e8c45fSAndroid Build Coastguard Worker             // If the surface hadn't actually been updated, then we only went
276*38e8c45fSAndroid Build Coastguard Worker             // through the motions of updating the display to keep our state
277*38e8c45fSAndroid Build Coastguard Worker             // machine happy. We cancel the buffer to avoid triggering another
278*38e8c45fSAndroid Build Coastguard Worker             // re-composition and causing an infinite loop.
279*38e8c45fSAndroid Build Coastguard Worker             mSource[SOURCE_SINK]->cancelBuffer(sslot, retireFence);
280*38e8c45fSAndroid Build Coastguard Worker         }
281*38e8c45fSAndroid Build Coastguard Worker     }
282*38e8c45fSAndroid Build Coastguard Worker 
283*38e8c45fSAndroid Build Coastguard Worker     resetPerFrameState();
284*38e8c45fSAndroid Build Coastguard Worker }
285*38e8c45fSAndroid Build Coastguard Worker 
dumpAsString(String8 &) const286*38e8c45fSAndroid Build Coastguard Worker void VirtualDisplaySurface::dumpAsString(String8& /* result */) const {
287*38e8c45fSAndroid Build Coastguard Worker }
288*38e8c45fSAndroid Build Coastguard Worker 
resizeBuffers(const ui::Size & newSize)289*38e8c45fSAndroid Build Coastguard Worker void VirtualDisplaySurface::resizeBuffers(const ui::Size& newSize) {
290*38e8c45fSAndroid Build Coastguard Worker     mQueueBufferOutput.width = newSize.width;
291*38e8c45fSAndroid Build Coastguard Worker     mQueueBufferOutput.height = newSize.height;
292*38e8c45fSAndroid Build Coastguard Worker     mSinkBufferWidth = newSize.width;
293*38e8c45fSAndroid Build Coastguard Worker     mSinkBufferHeight = newSize.height;
294*38e8c45fSAndroid Build Coastguard Worker }
295*38e8c45fSAndroid Build Coastguard Worker 
getClientTargetAcquireFence() const296*38e8c45fSAndroid Build Coastguard Worker const sp<Fence>& VirtualDisplaySurface::getClientTargetAcquireFence() const {
297*38e8c45fSAndroid Build Coastguard Worker     return mFbFence;
298*38e8c45fSAndroid Build Coastguard Worker }
299*38e8c45fSAndroid Build Coastguard Worker 
requestBuffer(int pslot,sp<GraphicBuffer> * outBuf)300*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::requestBuffer(int pslot,
301*38e8c45fSAndroid Build Coastguard Worker         sp<GraphicBuffer>* outBuf) {
302*38e8c45fSAndroid Build Coastguard Worker     if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
303*38e8c45fSAndroid Build Coastguard Worker         return mSource[SOURCE_SINK]->requestBuffer(pslot, outBuf);
304*38e8c45fSAndroid Build Coastguard Worker     }
305*38e8c45fSAndroid Build Coastguard Worker 
306*38e8c45fSAndroid Build Coastguard Worker     VDS_LOGW_IF(mDebugState != DebugState::Gpu, "Unexpected %s pslot=%d in %s state", __func__,
307*38e8c45fSAndroid Build Coastguard Worker                 pslot, ftl::enum_string(mDebugState).c_str());
308*38e8c45fSAndroid Build Coastguard Worker 
309*38e8c45fSAndroid Build Coastguard Worker     *outBuf = mProducerBuffers[pslot];
310*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
311*38e8c45fSAndroid Build Coastguard Worker }
312*38e8c45fSAndroid Build Coastguard Worker 
setMaxDequeuedBufferCount(int maxDequeuedBuffers)313*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::setMaxDequeuedBufferCount(
314*38e8c45fSAndroid Build Coastguard Worker         int maxDequeuedBuffers) {
315*38e8c45fSAndroid Build Coastguard Worker     return mSource[SOURCE_SINK]->setMaxDequeuedBufferCount(maxDequeuedBuffers);
316*38e8c45fSAndroid Build Coastguard Worker }
317*38e8c45fSAndroid Build Coastguard Worker 
setAsyncMode(bool async)318*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::setAsyncMode(bool async) {
319*38e8c45fSAndroid Build Coastguard Worker     return mSource[SOURCE_SINK]->setAsyncMode(async);
320*38e8c45fSAndroid Build Coastguard Worker }
321*38e8c45fSAndroid Build Coastguard Worker 
dequeueBuffer(Source source,PixelFormat format,uint64_t usage,int * sslot,sp<Fence> * fence)322*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::dequeueBuffer(Source source,
323*38e8c45fSAndroid Build Coastguard Worker         PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) {
324*38e8c45fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId).has_value());
325*38e8c45fSAndroid Build Coastguard Worker 
326*38e8c45fSAndroid Build Coastguard Worker     status_t result =
327*38e8c45fSAndroid Build Coastguard Worker             mSource[source]->dequeueBuffer(sslot, fence, mSinkBufferWidth, mSinkBufferHeight,
328*38e8c45fSAndroid Build Coastguard Worker                                            format, usage, nullptr, nullptr);
329*38e8c45fSAndroid Build Coastguard Worker     if (result < 0)
330*38e8c45fSAndroid Build Coastguard Worker         return result;
331*38e8c45fSAndroid Build Coastguard Worker     int pslot = mapSource2ProducerSlot(source, *sslot);
332*38e8c45fSAndroid Build Coastguard Worker     VDS_LOGV("%s(%s): sslot=%d pslot=%d result=%d", __func__, ftl::enum_string(source).c_str(),
333*38e8c45fSAndroid Build Coastguard Worker              *sslot, pslot, result);
334*38e8c45fSAndroid Build Coastguard Worker     uint64_t sourceBit = static_cast<uint64_t>(source) << pslot;
335*38e8c45fSAndroid Build Coastguard Worker 
336*38e8c45fSAndroid Build Coastguard Worker     // reset producer slot reallocation flag
337*38e8c45fSAndroid Build Coastguard Worker     mProducerSlotNeedReallocation &= ~(1ULL << pslot);
338*38e8c45fSAndroid Build Coastguard Worker 
339*38e8c45fSAndroid Build Coastguard Worker     if ((mProducerSlotSource & (1ULL << pslot)) != sourceBit) {
340*38e8c45fSAndroid Build Coastguard Worker         // This slot was previously dequeued from the other source; must
341*38e8c45fSAndroid Build Coastguard Worker         // re-request the buffer.
342*38e8c45fSAndroid Build Coastguard Worker         mProducerSlotNeedReallocation |= 1ULL << pslot;
343*38e8c45fSAndroid Build Coastguard Worker 
344*38e8c45fSAndroid Build Coastguard Worker         mProducerSlotSource &= ~(1ULL << pslot);
345*38e8c45fSAndroid Build Coastguard Worker         mProducerSlotSource |= sourceBit;
346*38e8c45fSAndroid Build Coastguard Worker     }
347*38e8c45fSAndroid Build Coastguard Worker 
348*38e8c45fSAndroid Build Coastguard Worker     if (result & RELEASE_ALL_BUFFERS) {
349*38e8c45fSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
350*38e8c45fSAndroid Build Coastguard Worker             if ((mProducerSlotSource & (1ULL << i)) == sourceBit)
351*38e8c45fSAndroid Build Coastguard Worker                 mProducerBuffers[i].clear();
352*38e8c45fSAndroid Build Coastguard Worker         }
353*38e8c45fSAndroid Build Coastguard Worker     }
354*38e8c45fSAndroid Build Coastguard Worker     if (result & BUFFER_NEEDS_REALLOCATION) {
355*38e8c45fSAndroid Build Coastguard Worker         result = mSource[source]->requestBuffer(*sslot, &mProducerBuffers[pslot]);
356*38e8c45fSAndroid Build Coastguard Worker         if (result < 0) {
357*38e8c45fSAndroid Build Coastguard Worker             mProducerBuffers[pslot].clear();
358*38e8c45fSAndroid Build Coastguard Worker             mSource[source]->cancelBuffer(*sslot, *fence);
359*38e8c45fSAndroid Build Coastguard Worker             return result;
360*38e8c45fSAndroid Build Coastguard Worker         }
361*38e8c45fSAndroid Build Coastguard Worker         VDS_LOGV("%s(%s): buffers[%d]=%p fmt=%d usage=%#" PRIx64, __func__,
362*38e8c45fSAndroid Build Coastguard Worker                  ftl::enum_string(source).c_str(), pslot, mProducerBuffers[pslot].get(),
363*38e8c45fSAndroid Build Coastguard Worker                  mProducerBuffers[pslot]->getPixelFormat(), mProducerBuffers[pslot]->getUsage());
364*38e8c45fSAndroid Build Coastguard Worker 
365*38e8c45fSAndroid Build Coastguard Worker         // propagate reallocation to VDS consumer
366*38e8c45fSAndroid Build Coastguard Worker         mProducerSlotNeedReallocation |= 1ULL << pslot;
367*38e8c45fSAndroid Build Coastguard Worker     }
368*38e8c45fSAndroid Build Coastguard Worker 
369*38e8c45fSAndroid Build Coastguard Worker     return result;
370*38e8c45fSAndroid Build Coastguard Worker }
371*38e8c45fSAndroid Build Coastguard Worker 
dequeueBuffer(int * pslot,sp<Fence> * fence,uint32_t w,uint32_t h,PixelFormat format,uint64_t usage,uint64_t * outBufferAge,FrameEventHistoryDelta * outTimestamps)372*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, uint32_t w, uint32_t h,
373*38e8c45fSAndroid Build Coastguard Worker                                               PixelFormat format, uint64_t usage,
374*38e8c45fSAndroid Build Coastguard Worker                                               uint64_t* outBufferAge,
375*38e8c45fSAndroid Build Coastguard Worker                                               FrameEventHistoryDelta* outTimestamps) {
376*38e8c45fSAndroid Build Coastguard Worker     if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
377*38e8c45fSAndroid Build Coastguard Worker         return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, w, h, format, usage, outBufferAge,
378*38e8c45fSAndroid Build Coastguard Worker                                                    outTimestamps);
379*38e8c45fSAndroid Build Coastguard Worker     }
380*38e8c45fSAndroid Build Coastguard Worker 
381*38e8c45fSAndroid Build Coastguard Worker     VDS_LOGW_IF(mDebugState != DebugState::Prepared, "Unexpected %s in %s state", __func__,
382*38e8c45fSAndroid Build Coastguard Worker                 ftl::enum_string(mDebugState).c_str());
383*38e8c45fSAndroid Build Coastguard Worker     mDebugState = DebugState::Gpu;
384*38e8c45fSAndroid Build Coastguard Worker 
385*38e8c45fSAndroid Build Coastguard Worker     VDS_LOGV("%s %dx%d fmt=%d usage=%#" PRIx64, __func__, w, h, format, usage);
386*38e8c45fSAndroid Build Coastguard Worker 
387*38e8c45fSAndroid Build Coastguard Worker     status_t result = NO_ERROR;
388*38e8c45fSAndroid Build Coastguard Worker     Source source = fbSourceForCompositionType(mCompositionType);
389*38e8c45fSAndroid Build Coastguard Worker 
390*38e8c45fSAndroid Build Coastguard Worker     if (source == SOURCE_SINK) {
391*38e8c45fSAndroid Build Coastguard Worker 
392*38e8c45fSAndroid Build Coastguard Worker         if (mOutputProducerSlot < 0) {
393*38e8c45fSAndroid Build Coastguard Worker             // Last chance bailout if something bad happened earlier. For example,
394*38e8c45fSAndroid Build Coastguard Worker             // in a graphics API configuration, if the sink disappears then dequeueBuffer
395*38e8c45fSAndroid Build Coastguard Worker             // will fail, the GPU driver won't queue a buffer, but SurfaceFlinger
396*38e8c45fSAndroid Build Coastguard Worker             // will soldier on. So we end up here without a buffer. There should
397*38e8c45fSAndroid Build Coastguard Worker             // be lots of scary messages in the log just before this.
398*38e8c45fSAndroid Build Coastguard Worker             VDS_LOGE("%s: no buffer, bailing out", __func__);
399*38e8c45fSAndroid Build Coastguard Worker             return NO_MEMORY;
400*38e8c45fSAndroid Build Coastguard Worker         }
401*38e8c45fSAndroid Build Coastguard Worker 
402*38e8c45fSAndroid Build Coastguard Worker         // We already dequeued the output buffer. If the GPU driver wants
403*38e8c45fSAndroid Build Coastguard Worker         // something incompatible, we have to cancel and get a new one. This
404*38e8c45fSAndroid Build Coastguard Worker         // will mean that HWC will see a different output buffer between
405*38e8c45fSAndroid Build Coastguard Worker         // prepare and set, but since we're in GPU-only mode already it
406*38e8c45fSAndroid Build Coastguard Worker         // shouldn't matter.
407*38e8c45fSAndroid Build Coastguard Worker 
408*38e8c45fSAndroid Build Coastguard Worker         usage |= GRALLOC_USAGE_HW_COMPOSER;
409*38e8c45fSAndroid Build Coastguard Worker         const sp<GraphicBuffer>& buf = mProducerBuffers[mOutputProducerSlot];
410*38e8c45fSAndroid Build Coastguard Worker         if ((usage & ~buf->getUsage()) != 0 ||
411*38e8c45fSAndroid Build Coastguard Worker                 (format != 0 && format != buf->getPixelFormat()) ||
412*38e8c45fSAndroid Build Coastguard Worker                 (w != 0 && w != mSinkBufferWidth) ||
413*38e8c45fSAndroid Build Coastguard Worker                 (h != 0 && h != mSinkBufferHeight)) {
414*38e8c45fSAndroid Build Coastguard Worker             VDS_LOGV("%s: dequeueing new output buffer: "
415*38e8c45fSAndroid Build Coastguard Worker                      "want %dx%d fmt=%d use=%#" PRIx64 ", "
416*38e8c45fSAndroid Build Coastguard Worker                      "have %dx%d fmt=%d use=%#" PRIx64,
417*38e8c45fSAndroid Build Coastguard Worker                      __func__, w, h, format, usage, mSinkBufferWidth, mSinkBufferHeight,
418*38e8c45fSAndroid Build Coastguard Worker                      buf->getPixelFormat(), buf->getUsage());
419*38e8c45fSAndroid Build Coastguard Worker             mOutputFormat = format;
420*38e8c45fSAndroid Build Coastguard Worker             mOutputUsage = usage;
421*38e8c45fSAndroid Build Coastguard Worker             result = refreshOutputBuffer();
422*38e8c45fSAndroid Build Coastguard Worker             if (result < 0)
423*38e8c45fSAndroid Build Coastguard Worker                 return result;
424*38e8c45fSAndroid Build Coastguard Worker         }
425*38e8c45fSAndroid Build Coastguard Worker     }
426*38e8c45fSAndroid Build Coastguard Worker 
427*38e8c45fSAndroid Build Coastguard Worker     if (source == SOURCE_SINK) {
428*38e8c45fSAndroid Build Coastguard Worker         *pslot = mOutputProducerSlot;
429*38e8c45fSAndroid Build Coastguard Worker         *fence = mOutputFence;
430*38e8c45fSAndroid Build Coastguard Worker     } else {
431*38e8c45fSAndroid Build Coastguard Worker         int sslot;
432*38e8c45fSAndroid Build Coastguard Worker         result = dequeueBuffer(source, format, usage, &sslot, fence);
433*38e8c45fSAndroid Build Coastguard Worker         if (result >= 0) {
434*38e8c45fSAndroid Build Coastguard Worker             *pslot = mapSource2ProducerSlot(source, sslot);
435*38e8c45fSAndroid Build Coastguard Worker         }
436*38e8c45fSAndroid Build Coastguard Worker     }
437*38e8c45fSAndroid Build Coastguard Worker     if (outBufferAge) {
438*38e8c45fSAndroid Build Coastguard Worker         *outBufferAge = 0;
439*38e8c45fSAndroid Build Coastguard Worker     }
440*38e8c45fSAndroid Build Coastguard Worker 
441*38e8c45fSAndroid Build Coastguard Worker     if ((mProducerSlotNeedReallocation & (1ULL << *pslot)) != 0) {
442*38e8c45fSAndroid Build Coastguard Worker         result |= BUFFER_NEEDS_REALLOCATION;
443*38e8c45fSAndroid Build Coastguard Worker     }
444*38e8c45fSAndroid Build Coastguard Worker 
445*38e8c45fSAndroid Build Coastguard Worker     return result;
446*38e8c45fSAndroid Build Coastguard Worker }
447*38e8c45fSAndroid Build Coastguard Worker 
detachBuffer(int)448*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::detachBuffer(int) {
449*38e8c45fSAndroid Build Coastguard Worker     UNSUPPORTED();
450*38e8c45fSAndroid Build Coastguard Worker }
451*38e8c45fSAndroid Build Coastguard Worker 
detachNextBuffer(sp<GraphicBuffer> *,sp<Fence> *)452*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::detachNextBuffer(sp<GraphicBuffer>*, sp<Fence>*) {
453*38e8c45fSAndroid Build Coastguard Worker     UNSUPPORTED();
454*38e8c45fSAndroid Build Coastguard Worker }
455*38e8c45fSAndroid Build Coastguard Worker 
attachBuffer(int *,const sp<GraphicBuffer> &)456*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::attachBuffer(int*, const sp<GraphicBuffer>&) {
457*38e8c45fSAndroid Build Coastguard Worker     UNSUPPORTED();
458*38e8c45fSAndroid Build Coastguard Worker }
459*38e8c45fSAndroid Build Coastguard Worker 
queueBuffer(int pslot,const QueueBufferInput & input,QueueBufferOutput * output)460*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::queueBuffer(int pslot,
461*38e8c45fSAndroid Build Coastguard Worker         const QueueBufferInput& input, QueueBufferOutput* output) {
462*38e8c45fSAndroid Build Coastguard Worker     if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
463*38e8c45fSAndroid Build Coastguard Worker         return mSource[SOURCE_SINK]->queueBuffer(pslot, input, output);
464*38e8c45fSAndroid Build Coastguard Worker     }
465*38e8c45fSAndroid Build Coastguard Worker 
466*38e8c45fSAndroid Build Coastguard Worker     VDS_LOGW_IF(mDebugState != DebugState::Gpu, "Unexpected %s(pslot=%d) in %s state", __func__,
467*38e8c45fSAndroid Build Coastguard Worker                 pslot, ftl::enum_string(mDebugState).c_str());
468*38e8c45fSAndroid Build Coastguard Worker     mDebugState = DebugState::GpuDone;
469*38e8c45fSAndroid Build Coastguard Worker 
470*38e8c45fSAndroid Build Coastguard Worker     VDS_LOGV("%s pslot=%d", __func__, pslot);
471*38e8c45fSAndroid Build Coastguard Worker 
472*38e8c45fSAndroid Build Coastguard Worker     status_t result;
473*38e8c45fSAndroid Build Coastguard Worker     if (mCompositionType == CompositionType::Mixed) {
474*38e8c45fSAndroid Build Coastguard Worker         // Queue the buffer back into the scratch pool
475*38e8c45fSAndroid Build Coastguard Worker         QueueBufferOutput scratchQBO;
476*38e8c45fSAndroid Build Coastguard Worker         int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, pslot);
477*38e8c45fSAndroid Build Coastguard Worker         result = mSource[SOURCE_SCRATCH]->queueBuffer(sslot, input, &scratchQBO);
478*38e8c45fSAndroid Build Coastguard Worker         if (result != NO_ERROR)
479*38e8c45fSAndroid Build Coastguard Worker             return result;
480*38e8c45fSAndroid Build Coastguard Worker 
481*38e8c45fSAndroid Build Coastguard Worker         // Now acquire the buffer from the scratch pool -- should be the same
482*38e8c45fSAndroid Build Coastguard Worker         // slot and fence as we just queued.
483*38e8c45fSAndroid Build Coastguard Worker         Mutex::Autolock lock(mMutex);
484*38e8c45fSAndroid Build Coastguard Worker         BufferItem item;
485*38e8c45fSAndroid Build Coastguard Worker         result = acquireBufferLocked(&item, 0);
486*38e8c45fSAndroid Build Coastguard Worker         if (result != NO_ERROR)
487*38e8c45fSAndroid Build Coastguard Worker             return result;
488*38e8c45fSAndroid Build Coastguard Worker         VDS_LOGW_IF(item.mSlot != sslot,
489*38e8c45fSAndroid Build Coastguard Worker                     "%s: acquired sslot %d from SCRATCH after queueing sslot %d", __func__,
490*38e8c45fSAndroid Build Coastguard Worker                     item.mSlot, sslot);
491*38e8c45fSAndroid Build Coastguard Worker         mFbProducerSlot = mapSource2ProducerSlot(SOURCE_SCRATCH, item.mSlot);
492*38e8c45fSAndroid Build Coastguard Worker         mFbFence = mSlots[item.mSlot].mFence;
493*38e8c45fSAndroid Build Coastguard Worker 
494*38e8c45fSAndroid Build Coastguard Worker     } else {
495*38e8c45fSAndroid Build Coastguard Worker         LOG_FATAL_IF(mCompositionType != CompositionType::Gpu,
496*38e8c45fSAndroid Build Coastguard Worker                      "Unexpected %s in state %s for composition type %s", __func__,
497*38e8c45fSAndroid Build Coastguard Worker                      ftl::enum_string(mDebugState).c_str(), toString(mCompositionType).c_str());
498*38e8c45fSAndroid Build Coastguard Worker 
499*38e8c45fSAndroid Build Coastguard Worker         // Extract the GPU release fence for HWC to acquire
500*38e8c45fSAndroid Build Coastguard Worker         int64_t timestamp;
501*38e8c45fSAndroid Build Coastguard Worker         bool isAutoTimestamp;
502*38e8c45fSAndroid Build Coastguard Worker         android_dataspace dataSpace;
503*38e8c45fSAndroid Build Coastguard Worker         Rect crop;
504*38e8c45fSAndroid Build Coastguard Worker         int scalingMode;
505*38e8c45fSAndroid Build Coastguard Worker         uint32_t transform;
506*38e8c45fSAndroid Build Coastguard Worker         input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop,
507*38e8c45fSAndroid Build Coastguard Worker                 &scalingMode, &transform, &mFbFence);
508*38e8c45fSAndroid Build Coastguard Worker 
509*38e8c45fSAndroid Build Coastguard Worker         mFbProducerSlot = pslot;
510*38e8c45fSAndroid Build Coastguard Worker         mOutputFence = mFbFence;
511*38e8c45fSAndroid Build Coastguard Worker     }
512*38e8c45fSAndroid Build Coastguard Worker 
513*38e8c45fSAndroid Build Coastguard Worker     // This moves the frame timestamps and keeps a copy of all other fields.
514*38e8c45fSAndroid Build Coastguard Worker     *output = std::move(mQueueBufferOutput);
515*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
516*38e8c45fSAndroid Build Coastguard Worker }
517*38e8c45fSAndroid Build Coastguard Worker 
cancelBuffer(int pslot,const sp<Fence> & fence)518*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::cancelBuffer(int pslot,
519*38e8c45fSAndroid Build Coastguard Worker         const sp<Fence>& fence) {
520*38e8c45fSAndroid Build Coastguard Worker     if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
521*38e8c45fSAndroid Build Coastguard Worker         return mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(SOURCE_SINK, pslot), fence);
522*38e8c45fSAndroid Build Coastguard Worker     }
523*38e8c45fSAndroid Build Coastguard Worker 
524*38e8c45fSAndroid Build Coastguard Worker     VDS_LOGW_IF(mDebugState != DebugState::Gpu, "Unexpected %s(pslot=%d) in %s state", __func__,
525*38e8c45fSAndroid Build Coastguard Worker                 pslot, ftl::enum_string(mDebugState).c_str());
526*38e8c45fSAndroid Build Coastguard Worker     VDS_LOGV("%s pslot=%d", __func__, pslot);
527*38e8c45fSAndroid Build Coastguard Worker     Source source = fbSourceForCompositionType(mCompositionType);
528*38e8c45fSAndroid Build Coastguard Worker     return mSource[source]->cancelBuffer(
529*38e8c45fSAndroid Build Coastguard Worker             mapProducer2SourceSlot(source, pslot), fence);
530*38e8c45fSAndroid Build Coastguard Worker }
531*38e8c45fSAndroid Build Coastguard Worker 
query(int what,int * value)532*38e8c45fSAndroid Build Coastguard Worker int VirtualDisplaySurface::query(int what, int* value) {
533*38e8c45fSAndroid Build Coastguard Worker     switch (what) {
534*38e8c45fSAndroid Build Coastguard Worker         case NATIVE_WINDOW_WIDTH:
535*38e8c45fSAndroid Build Coastguard Worker             *value = mSinkBufferWidth;
536*38e8c45fSAndroid Build Coastguard Worker             break;
537*38e8c45fSAndroid Build Coastguard Worker         case NATIVE_WINDOW_HEIGHT:
538*38e8c45fSAndroid Build Coastguard Worker             *value = mSinkBufferHeight;
539*38e8c45fSAndroid Build Coastguard Worker             break;
540*38e8c45fSAndroid Build Coastguard Worker         default:
541*38e8c45fSAndroid Build Coastguard Worker             return mSource[SOURCE_SINK]->query(what, value);
542*38e8c45fSAndroid Build Coastguard Worker     }
543*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
544*38e8c45fSAndroid Build Coastguard Worker }
545*38e8c45fSAndroid Build Coastguard Worker 
connect(const sp<IProducerListener> & listener,int api,bool producerControlledByApp,QueueBufferOutput * output)546*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::connect(const sp<IProducerListener>& listener,
547*38e8c45fSAndroid Build Coastguard Worker         int api, bool producerControlledByApp,
548*38e8c45fSAndroid Build Coastguard Worker         QueueBufferOutput* output) {
549*38e8c45fSAndroid Build Coastguard Worker     QueueBufferOutput qbo;
550*38e8c45fSAndroid Build Coastguard Worker     status_t result = mSource[SOURCE_SINK]->connect(listener, api,
551*38e8c45fSAndroid Build Coastguard Worker             producerControlledByApp, &qbo);
552*38e8c45fSAndroid Build Coastguard Worker     if (result == NO_ERROR) {
553*38e8c45fSAndroid Build Coastguard Worker         updateQueueBufferOutput(std::move(qbo));
554*38e8c45fSAndroid Build Coastguard Worker         // This moves the frame timestamps and keeps a copy of all other fields.
555*38e8c45fSAndroid Build Coastguard Worker         *output = std::move(mQueueBufferOutput);
556*38e8c45fSAndroid Build Coastguard Worker     }
557*38e8c45fSAndroid Build Coastguard Worker     return result;
558*38e8c45fSAndroid Build Coastguard Worker }
559*38e8c45fSAndroid Build Coastguard Worker 
disconnect(int api,DisconnectMode mode)560*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::disconnect(int api, DisconnectMode mode) {
561*38e8c45fSAndroid Build Coastguard Worker     return mSource[SOURCE_SINK]->disconnect(api, mode);
562*38e8c45fSAndroid Build Coastguard Worker }
563*38e8c45fSAndroid Build Coastguard Worker 
setSidebandStream(const sp<NativeHandle> &)564*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::setSidebandStream(const sp<NativeHandle>&) {
565*38e8c45fSAndroid Build Coastguard Worker     UNSUPPORTED();
566*38e8c45fSAndroid Build Coastguard Worker }
567*38e8c45fSAndroid Build Coastguard Worker 
allocateBuffers(uint32_t,uint32_t,PixelFormat,uint64_t)568*38e8c45fSAndroid Build Coastguard Worker void VirtualDisplaySurface::allocateBuffers(uint32_t /* width */,
569*38e8c45fSAndroid Build Coastguard Worker         uint32_t /* height */, PixelFormat /* format */, uint64_t /* usage */) {
570*38e8c45fSAndroid Build Coastguard Worker     // TODO: Should we actually allocate buffers for a virtual display?
571*38e8c45fSAndroid Build Coastguard Worker }
572*38e8c45fSAndroid Build Coastguard Worker 
allowAllocation(bool)573*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::allowAllocation(bool /* allow */) {
574*38e8c45fSAndroid Build Coastguard Worker     return INVALID_OPERATION;
575*38e8c45fSAndroid Build Coastguard Worker }
576*38e8c45fSAndroid Build Coastguard Worker 
setGenerationNumber(uint32_t)577*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::setGenerationNumber(uint32_t) {
578*38e8c45fSAndroid Build Coastguard Worker     UNSUPPORTED();
579*38e8c45fSAndroid Build Coastguard Worker }
580*38e8c45fSAndroid Build Coastguard Worker 
getConsumerName() const581*38e8c45fSAndroid Build Coastguard Worker String8 VirtualDisplaySurface::getConsumerName() const {
582*38e8c45fSAndroid Build Coastguard Worker     return String8("VirtualDisplaySurface");
583*38e8c45fSAndroid Build Coastguard Worker }
584*38e8c45fSAndroid Build Coastguard Worker 
setSharedBufferMode(bool)585*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::setSharedBufferMode(bool) {
586*38e8c45fSAndroid Build Coastguard Worker     UNSUPPORTED();
587*38e8c45fSAndroid Build Coastguard Worker }
588*38e8c45fSAndroid Build Coastguard Worker 
setAutoRefresh(bool)589*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::setAutoRefresh(bool) {
590*38e8c45fSAndroid Build Coastguard Worker     UNSUPPORTED();
591*38e8c45fSAndroid Build Coastguard Worker }
592*38e8c45fSAndroid Build Coastguard Worker 
setDequeueTimeout(nsecs_t)593*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::setDequeueTimeout(nsecs_t) {
594*38e8c45fSAndroid Build Coastguard Worker     UNSUPPORTED();
595*38e8c45fSAndroid Build Coastguard Worker }
596*38e8c45fSAndroid Build Coastguard Worker 
getLastQueuedBuffer(sp<GraphicBuffer> *,sp<Fence> *,float[16])597*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::getLastQueuedBuffer(sp<GraphicBuffer>*, sp<Fence>*, float[16]) {
598*38e8c45fSAndroid Build Coastguard Worker     UNSUPPORTED();
599*38e8c45fSAndroid Build Coastguard Worker }
600*38e8c45fSAndroid Build Coastguard Worker 
getUniqueId(uint64_t *) const601*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::getUniqueId(uint64_t*) const {
602*38e8c45fSAndroid Build Coastguard Worker     UNSUPPORTED();
603*38e8c45fSAndroid Build Coastguard Worker }
604*38e8c45fSAndroid Build Coastguard Worker 
getConsumerUsage(uint64_t * outUsage) const605*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::getConsumerUsage(uint64_t* outUsage) const {
606*38e8c45fSAndroid Build Coastguard Worker     return mSource[SOURCE_SINK]->getConsumerUsage(outUsage);
607*38e8c45fSAndroid Build Coastguard Worker }
608*38e8c45fSAndroid Build Coastguard Worker 
updateQueueBufferOutput(QueueBufferOutput && qbo)609*38e8c45fSAndroid Build Coastguard Worker void VirtualDisplaySurface::updateQueueBufferOutput(
610*38e8c45fSAndroid Build Coastguard Worker         QueueBufferOutput&& qbo) {
611*38e8c45fSAndroid Build Coastguard Worker     mQueueBufferOutput = std::move(qbo);
612*38e8c45fSAndroid Build Coastguard Worker     mQueueBufferOutput.transformHint = 0;
613*38e8c45fSAndroid Build Coastguard Worker }
614*38e8c45fSAndroid Build Coastguard Worker 
resetPerFrameState()615*38e8c45fSAndroid Build Coastguard Worker void VirtualDisplaySurface::resetPerFrameState() {
616*38e8c45fSAndroid Build Coastguard Worker     mCompositionType = CompositionType::Unknown;
617*38e8c45fSAndroid Build Coastguard Worker     mFbFence = Fence::NO_FENCE;
618*38e8c45fSAndroid Build Coastguard Worker     mOutputFence = Fence::NO_FENCE;
619*38e8c45fSAndroid Build Coastguard Worker     mOutputProducerSlot = -1;
620*38e8c45fSAndroid Build Coastguard Worker     mFbProducerSlot = -1;
621*38e8c45fSAndroid Build Coastguard Worker }
622*38e8c45fSAndroid Build Coastguard Worker 
refreshOutputBuffer()623*38e8c45fSAndroid Build Coastguard Worker status_t VirtualDisplaySurface::refreshOutputBuffer() {
624*38e8c45fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId).has_value());
625*38e8c45fSAndroid Build Coastguard Worker 
626*38e8c45fSAndroid Build Coastguard Worker     if (mOutputProducerSlot >= 0) {
627*38e8c45fSAndroid Build Coastguard Worker         mSource[SOURCE_SINK]->cancelBuffer(
628*38e8c45fSAndroid Build Coastguard Worker                 mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot),
629*38e8c45fSAndroid Build Coastguard Worker                 mOutputFence);
630*38e8c45fSAndroid Build Coastguard Worker     }
631*38e8c45fSAndroid Build Coastguard Worker 
632*38e8c45fSAndroid Build Coastguard Worker     int sslot;
633*38e8c45fSAndroid Build Coastguard Worker     status_t result = dequeueBuffer(SOURCE_SINK, mOutputFormat, mOutputUsage,
634*38e8c45fSAndroid Build Coastguard Worker             &sslot, &mOutputFence);
635*38e8c45fSAndroid Build Coastguard Worker     if (result < 0)
636*38e8c45fSAndroid Build Coastguard Worker         return result;
637*38e8c45fSAndroid Build Coastguard Worker     mOutputProducerSlot = mapSource2ProducerSlot(SOURCE_SINK, sslot);
638*38e8c45fSAndroid Build Coastguard Worker 
639*38e8c45fSAndroid Build Coastguard Worker     // On GPU-only frames, we don't have the right output buffer acquire fence
640*38e8c45fSAndroid Build Coastguard Worker     // until after GPU calls queueBuffer(). So here we just set the buffer
641*38e8c45fSAndroid Build Coastguard Worker     // (for use in HWC prepare) but not the fence; we'll call this again with
642*38e8c45fSAndroid Build Coastguard Worker     // the proper fence once we have it.
643*38e8c45fSAndroid Build Coastguard Worker     const auto halDisplayId = HalVirtualDisplayId::tryCast(mDisplayId);
644*38e8c45fSAndroid Build Coastguard Worker     LOG_FATAL_IF(!halDisplayId);
645*38e8c45fSAndroid Build Coastguard Worker     result = mHwc.setOutputBuffer(*halDisplayId, Fence::NO_FENCE,
646*38e8c45fSAndroid Build Coastguard Worker                                   mProducerBuffers[mOutputProducerSlot]);
647*38e8c45fSAndroid Build Coastguard Worker 
648*38e8c45fSAndroid Build Coastguard Worker     return result;
649*38e8c45fSAndroid Build Coastguard Worker }
650*38e8c45fSAndroid Build Coastguard Worker 
651*38e8c45fSAndroid Build Coastguard Worker // This slot mapping function is its own inverse, so two copies are unnecessary.
652*38e8c45fSAndroid Build Coastguard Worker // Both are kept to make the intent clear where the function is called, and for
653*38e8c45fSAndroid Build Coastguard Worker // the (unlikely) chance that we switch to a different mapping function.
mapSource2ProducerSlot(Source source,int sslot)654*38e8c45fSAndroid Build Coastguard Worker int VirtualDisplaySurface::mapSource2ProducerSlot(Source source, int sslot) {
655*38e8c45fSAndroid Build Coastguard Worker     if (source == SOURCE_SCRATCH) {
656*38e8c45fSAndroid Build Coastguard Worker         return BufferQueue::NUM_BUFFER_SLOTS - sslot - 1;
657*38e8c45fSAndroid Build Coastguard Worker     } else {
658*38e8c45fSAndroid Build Coastguard Worker         return sslot;
659*38e8c45fSAndroid Build Coastguard Worker     }
660*38e8c45fSAndroid Build Coastguard Worker }
mapProducer2SourceSlot(Source source,int pslot)661*38e8c45fSAndroid Build Coastguard Worker int VirtualDisplaySurface::mapProducer2SourceSlot(Source source, int pslot) {
662*38e8c45fSAndroid Build Coastguard Worker     return mapSource2ProducerSlot(source, pslot);
663*38e8c45fSAndroid Build Coastguard Worker }
664*38e8c45fSAndroid Build Coastguard Worker 
fbSourceForCompositionType(CompositionType type)665*38e8c45fSAndroid Build Coastguard Worker auto VirtualDisplaySurface::fbSourceForCompositionType(CompositionType type) -> Source {
666*38e8c45fSAndroid Build Coastguard Worker     return type == CompositionType::Mixed ? SOURCE_SCRATCH : SOURCE_SINK;
667*38e8c45fSAndroid Build Coastguard Worker }
668*38e8c45fSAndroid Build Coastguard Worker 
toString(CompositionType type)669*38e8c45fSAndroid Build Coastguard Worker std::string VirtualDisplaySurface::toString(CompositionType type) {
670*38e8c45fSAndroid Build Coastguard Worker     using namespace std::literals;
671*38e8c45fSAndroid Build Coastguard Worker     return type == CompositionType::Unknown ? "Unknown"s : ftl::Flags(type).string();
672*38e8c45fSAndroid Build Coastguard Worker }
673*38e8c45fSAndroid Build Coastguard Worker 
674*38e8c45fSAndroid Build Coastguard Worker } // namespace android
675*38e8c45fSAndroid Build Coastguard Worker 
676*38e8c45fSAndroid Build Coastguard Worker // TODO(b/129481165): remove the #pragma below and fix conversion issues
677*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic pop // ignored "-Wconversion"
678