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(×tamp, &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