blob: 247ee23fa75f7ce30d818b3a3cf38046712a5099 [file] [log] [blame]
Jesse Hall99c7dbb2013-03-14 14:29:29 -07001/*
2 * Copyright 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080017// TODO(b/129481165): remove the #pragma below and fix conversion issues
18#pragma clang diagnostic push
19#pragma clang diagnostic ignored "-Wconversion"
20
Jesse Hall38efe862013-04-06 23:12:29 -070021// #define LOG_NDEBUG 0
Jesse Hall99c7dbb2013-03-14 14:29:29 -070022#include "VirtualDisplaySurface.h"
Mathias Agopiancb496ac2017-05-22 14:21:00 -070023
24#include <inttypes.h>
25
Jesse Hall38efe862013-04-06 23:12:29 -070026#include "HWComposer.h"
Fabien Sanglarda34ed632017-03-14 11:43:52 -070027#include "SurfaceFlinger.h"
Jesse Hall99c7dbb2013-03-14 14:29:29 -070028
Dan Stoza11611f92015-03-12 15:12:44 -070029#include <gui/BufferItem.h>
Mathias Agopiana9347642017-02-13 16:42:28 -080030#include <gui/BufferQueue.h>
Pablo Ceballosf133d002015-10-23 12:10:13 -070031#include <gui/IProducerListener.h>
Mathias Agopian6a3c05b2017-04-27 20:06:55 -070032#include <system/window.h>
Dan Stoza11611f92015-03-12 15:12:44 -070033
Jesse Hall99c7dbb2013-03-14 14:29:29 -070034// ---------------------------------------------------------------------------
35namespace android {
36// ---------------------------------------------------------------------------
37
Jesse Hall24cd98e2014-07-13 14:37:16 -070038#define VDS_LOGE(msg, ...) ALOGE("[%s] " msg, \
Dominik Laskowskibf170d92018-04-19 15:08:05 -070039 mDisplayName.c_str(), ##__VA_ARGS__)
Jesse Hall24cd98e2014-07-13 14:37:16 -070040#define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] " msg, \
Dominik Laskowskibf170d92018-04-19 15:08:05 -070041 mDisplayName.c_str(), ##__VA_ARGS__)
Jesse Hall24cd98e2014-07-13 14:37:16 -070042#define VDS_LOGV(msg, ...) ALOGV("[%s] " msg, \
Dominik Laskowskibf170d92018-04-19 15:08:05 -070043 mDisplayName.c_str(), ##__VA_ARGS__)
Jesse Hall38efe862013-04-06 23:12:29 -070044
Lloyd Pique542307f2018-10-19 13:24:08 -070045static const char* dbgCompositionTypeStr(compositionengine::DisplaySurface::CompositionType type) {
Jesse Hall38efe862013-04-06 23:12:29 -070046 switch (type) {
Lloyd Pique542307f2018-10-19 13:24:08 -070047 case compositionengine::DisplaySurface::COMPOSITION_UNKNOWN:
48 return "UNKNOWN";
Peiyong Linf3ffc4e2019-12-13 00:46:24 -080049 case compositionengine::DisplaySurface::COMPOSITION_GPU:
50 return "GPU";
Lloyd Pique542307f2018-10-19 13:24:08 -070051 case compositionengine::DisplaySurface::COMPOSITION_HWC:
52 return "HWC";
53 case compositionengine::DisplaySurface::COMPOSITION_MIXED:
54 return "MIXED";
Peiyong Linf3ffc4e2019-12-13 00:46:24 -080055 default:
56 return "<INVALID>";
Jesse Hall38efe862013-04-06 23:12:29 -070057 }
58}
59
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +020060VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, VirtualDisplayId displayId,
Dominik Laskowski075d3172018-05-24 15:50:06 -070061 const sp<IGraphicBufferProducer>& sink,
62 const sp<IGraphicBufferProducer>& bqProducer,
63 const sp<IGraphicBufferConsumer>& bqConsumer,
64 const std::string& name)
65 : ConsumerBase(bqConsumer),
66 mHwc(hwc),
67 mDisplayId(displayId),
68 mDisplayName(name),
69 mSource{},
70 mDefaultOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
71 mOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
72 mOutputUsage(GRALLOC_USAGE_HW_COMPOSER),
73 mProducerSlotSource(0),
74 mProducerBuffers(),
75 mQueueBufferOutput(),
76 mSinkBufferWidth(0),
77 mSinkBufferHeight(0),
78 mCompositionType(COMPOSITION_UNKNOWN),
79 mFbFence(Fence::NO_FENCE),
80 mOutputFence(Fence::NO_FENCE),
81 mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
82 mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
83 mDbgState(DBG_STATE_IDLE),
84 mDbgLastCompositionType(COMPOSITION_UNKNOWN),
85 mMustRecompose(false),
86 mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv) {
Jesse Hall38efe862013-04-06 23:12:29 -070087 mSource[SOURCE_SINK] = sink;
Dan Stozab9b08832014-03-13 11:55:57 -070088 mSource[SOURCE_SCRATCH] = bqProducer;
Jesse Hall38efe862013-04-06 23:12:29 -070089
90 resetPerFrameState();
91
92 int sinkWidth, sinkHeight;
Jesse Hall497ba0e2013-11-04 16:43:03 -080093 sink->query(NATIVE_WINDOW_WIDTH, &sinkWidth);
94 sink->query(NATIVE_WINDOW_HEIGHT, &sinkHeight);
Michael Lentine47e45402014-07-18 15:34:25 -070095 mSinkBufferWidth = sinkWidth;
96 mSinkBufferHeight = sinkHeight;
Jesse Hall497ba0e2013-11-04 16:43:03 -080097
98 // Pick the buffer format to request from the sink when not rendering to it
Peiyong Linf3ffc4e2019-12-13 00:46:24 -080099 // with GPU. If the consumer needs CPU access, use the default format
Jesse Hall497ba0e2013-11-04 16:43:03 -0800100 // set by the consumer. Otherwise allow gralloc to decide the format based
101 // on usage bits.
102 int sinkUsage;
103 sink->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &sinkUsage);
104 if (sinkUsage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
105 int sinkFormat;
106 sink->query(NATIVE_WINDOW_FORMAT, &sinkFormat);
107 mDefaultOutputFormat = sinkFormat;
108 } else {
109 mDefaultOutputFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
110 }
111 mOutputFormat = mDefaultOutputFormat;
Jesse Hall38efe862013-04-06 23:12:29 -0700112
Dominik Laskowskibf170d92018-04-19 15:08:05 -0700113 ConsumerBase::mName = String8::format("VDS: %s", mDisplayName.c_str());
Mathias Agopiandb89edc2013-08-02 01:40:18 -0700114 mConsumer->setConsumerName(ConsumerBase::mName);
115 mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
116 mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight);
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700117 sink->setAsyncMode(true);
Alec Mouri8d4f90a2018-11-14 22:33:24 +0000118 IGraphicBufferProducer::QueueBufferOutput output;
119 mSource[SOURCE_SCRATCH]->connect(nullptr, NATIVE_WINDOW_API_EGL, false, &output);
Jesse Hallffe1f192013-03-22 15:13:48 -0700120}
Jesse Hall99c7dbb2013-03-14 14:29:29 -0700121
122VirtualDisplaySurface::~VirtualDisplaySurface() {
Pablo Ceballosf133d002015-10-23 12:10:13 -0700123 mSource[SOURCE_SCRATCH]->disconnect(NATIVE_WINDOW_API_EGL);
Jesse Hall99c7dbb2013-03-14 14:29:29 -0700124}
125
Dan Stoza71433162014-02-04 16:22:36 -0800126status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) {
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200127 if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
Jesse Hall38efe862013-04-06 23:12:29 -0700128 return NO_ERROR;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700129 }
Jesse Hall38efe862013-04-06 23:12:29 -0700130
Dan Stoza71433162014-02-04 16:22:36 -0800131 mMustRecompose = mustRecompose;
132
Jesse Hall38efe862013-04-06 23:12:29 -0700133 VDS_LOGW_IF(mDbgState != DBG_STATE_IDLE,
Jesse Hall028dc8f2013-08-20 16:35:32 -0700134 "Unexpected beginFrame() in %s state", dbgStateStr());
135 mDbgState = DBG_STATE_BEGUN;
136
Jesse Hall028dc8f2013-08-20 16:35:32 -0700137 return refreshOutputBuffer();
138}
139
140status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) {
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200141 if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
Jesse Hall028dc8f2013-08-20 16:35:32 -0700142 return NO_ERROR;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700143 }
Jesse Hall028dc8f2013-08-20 16:35:32 -0700144
145 VDS_LOGW_IF(mDbgState != DBG_STATE_BEGUN,
Jesse Hall38efe862013-04-06 23:12:29 -0700146 "Unexpected prepareFrame() in %s state", dbgStateStr());
147 mDbgState = DBG_STATE_PREPARED;
148
149 mCompositionType = compositionType;
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800150 if (mForceHwcCopy && mCompositionType == COMPOSITION_GPU) {
Naseer Ahmed6a968462013-10-04 16:15:22 -0400151 // Some hardware can do RGB->YUV conversion more efficiently in hardware
152 // controlled by HWC than in hardware controlled by the video encoder.
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800153 // Forcing GPU-composed frames to go through an extra copy by the HWC
Naseer Ahmed6a968462013-10-04 16:15:22 -0400154 // allows the format conversion to happen there, rather than passing RGB
155 // directly to the consumer.
156 //
157 // On the other hand, when the consumer prefers RGB or can consume RGB
158 // inexpensively, this forces an unnecessary copy.
159 mCompositionType = COMPOSITION_MIXED;
160 }
161
Jesse Hall38efe862013-04-06 23:12:29 -0700162 if (mCompositionType != mDbgLastCompositionType) {
163 VDS_LOGV("prepareFrame: composition type changed to %s",
164 dbgCompositionTypeStr(mCompositionType));
165 mDbgLastCompositionType = mCompositionType;
166 }
167
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800168 if (mCompositionType != COMPOSITION_GPU &&
169 (mOutputFormat != mDefaultOutputFormat || mOutputUsage != GRALLOC_USAGE_HW_COMPOSER)) {
170 // We must have just switched from GPU-only to MIXED or HWC
171 // composition. Stop using the format and usage requested by the GPU
Jesse Hall1e27ba22013-09-27 09:05:09 -0700172 // driver; they may be suboptimal when HWC is writing to the output
173 // buffer. For example, if the output is going to a video encoder, and
174 // HWC can write directly to YUV, some hardware can skip a
175 // memory-to-memory RGB-to-YUV conversion step.
176 //
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800177 // If we just switched *to* GPU-only mode, we'll change the
178 // format/usage and get a new buffer when the GPU driver calls
Jesse Hall1e27ba22013-09-27 09:05:09 -0700179 // dequeueBuffer().
Jesse Hall497ba0e2013-11-04 16:43:03 -0800180 mOutputFormat = mDefaultOutputFormat;
Jesse Hall1e27ba22013-09-27 09:05:09 -0700181 mOutputUsage = GRALLOC_USAGE_HW_COMPOSER;
182 refreshOutputBuffer();
183 }
184
Jesse Hall38efe862013-04-06 23:12:29 -0700185 return NO_ERROR;
Jesse Hall99c7dbb2013-03-14 14:29:29 -0700186}
187
Jesse Hall99c7dbb2013-03-14 14:29:29 -0700188status_t VirtualDisplaySurface::advanceFrame() {
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200189 if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
Jesse Hall38efe862013-04-06 23:12:29 -0700190 return NO_ERROR;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700191 }
Jesse Hall38efe862013-04-06 23:12:29 -0700192
193 if (mCompositionType == COMPOSITION_HWC) {
194 VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
195 "Unexpected advanceFrame() in %s state on HWC frame",
196 dbgStateStr());
197 } else {
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800198 VDS_LOGW_IF(mDbgState != DBG_STATE_GPU_DONE,
199 "Unexpected advanceFrame() in %s state on GPU/MIXED frame", dbgStateStr());
Jesse Hall38efe862013-04-06 23:12:29 -0700200 }
201 mDbgState = DBG_STATE_HWC;
202
Jesse Hall14e8b012013-11-07 12:28:26 -0800203 if (mOutputProducerSlot < 0 ||
204 (mCompositionType != COMPOSITION_HWC && mFbProducerSlot < 0)) {
Jesse Hall38efe862013-04-06 23:12:29 -0700205 // Last chance bailout if something bad happened earlier. For example,
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800206 // in a graphics API configuration, if the sink disappears then dequeueBuffer
207 // will fail, the GPU driver won't queue a buffer, but SurfaceFlinger
Jesse Hall38efe862013-04-06 23:12:29 -0700208 // will soldier on. So we end up here without a buffer. There should
209 // be lots of scary messages in the log just before this.
210 VDS_LOGE("advanceFrame: no buffer, bailing out");
211 return NO_MEMORY;
212 }
213
Jesse Hall14e8b012013-11-07 12:28:26 -0800214 sp<GraphicBuffer> fbBuffer = mFbProducerSlot >= 0 ?
Peiyong Lin566a3b42018-01-09 18:22:43 -0800215 mProducerBuffers[mFbProducerSlot] : sp<GraphicBuffer>(nullptr);
Jesse Hall38efe862013-04-06 23:12:29 -0700216 sp<GraphicBuffer> outBuffer = mProducerBuffers[mOutputProducerSlot];
217 VDS_LOGV("advanceFrame: fb=%d(%p) out=%d(%p)",
218 mFbProducerSlot, fbBuffer.get(),
219 mOutputProducerSlot, outBuffer.get());
220
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200221 const auto halDisplayId = HalVirtualDisplayId::tryCast(mDisplayId);
222 LOG_FATAL_IF(!halDisplayId);
Jesse Hallb716e572013-10-01 17:25:20 -0700223 // At this point we know the output buffer acquire fence,
224 // so update HWC state with it.
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200225 mHwc.setOutputBuffer(*halDisplayId, mOutputFence, outBuffer);
Jesse Hallb716e572013-10-01 17:25:20 -0700226
Jesse Hall14e8b012013-11-07 12:28:26 -0800227 status_t result = NO_ERROR;
Peiyong Lin566a3b42018-01-09 18:22:43 -0800228 if (fbBuffer != nullptr) {
Chia-I Wu06d63de2017-01-04 14:58:51 +0800229 uint32_t hwcSlot = 0;
230 sp<GraphicBuffer> hwcBuffer;
Valerie Hau13f0d1a2019-03-22 10:35:42 -0700231 mHwcBufferCache.getHwcBuffer(mFbProducerSlot, fbBuffer, &hwcSlot, &hwcBuffer);
Chia-I Wu06d63de2017-01-04 14:58:51 +0800232
Dan Stoza9e56aa02015-11-02 13:00:03 -0800233 // TODO: Correctly propagate the dataspace from GL composition
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200234 result = mHwc.setClientTarget(*halDisplayId, hwcSlot, mFbFence, hwcBuffer,
Dominik Laskowski075d3172018-05-24 15:50:06 -0700235 ui::Dataspace::UNKNOWN);
Jesse Hall14e8b012013-11-07 12:28:26 -0800236 }
237
238 return result;
Jesse Hall99c7dbb2013-03-14 14:29:29 -0700239}
240
Jesse Hall851cfe82013-03-20 13:44:00 -0700241void VirtualDisplaySurface::onFrameCommitted() {
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200242 const auto halDisplayId = HalVirtualDisplayId::tryCast(mDisplayId);
243 if (!halDisplayId) {
Jesse Hall38efe862013-04-06 23:12:29 -0700244 return;
Dominik Laskowski075d3172018-05-24 15:50:06 -0700245 }
Jesse Hall38efe862013-04-06 23:12:29 -0700246
247 VDS_LOGW_IF(mDbgState != DBG_STATE_HWC,
248 "Unexpected onFrameCommitted() in %s state", dbgStateStr());
249 mDbgState = DBG_STATE_IDLE;
250
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200251 sp<Fence> retireFence = mHwc.getPresentFence(*halDisplayId);
Jesse Hall38efe862013-04-06 23:12:29 -0700252 if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) {
253 // release the scratch buffer back to the pool
254 Mutex::Autolock lock(mMutex);
255 int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot);
256 VDS_LOGV("onFrameCommitted: release scratch sslot=%d", sslot);
Dan Stoza9e56aa02015-11-02 13:00:03 -0800257 addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot],
258 retireFence);
Chia-I Wu1e24cce2017-11-10 10:36:01 -0800259 releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot]);
Jesse Hall38efe862013-04-06 23:12:29 -0700260 }
261
262 if (mOutputProducerSlot >= 0) {
263 int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot);
264 QueueBufferOutput qbo;
Jesse Hall38efe862013-04-06 23:12:29 -0700265 VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot);
Dan Stoza71433162014-02-04 16:22:36 -0800266 if (mMustRecompose) {
267 status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
268 QueueBufferInput(
269 systemTime(), false /* isAutoTimestamp */,
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800270 HAL_DATASPACE_UNKNOWN,
Dan Stoza71433162014-02-04 16:22:36 -0800271 Rect(mSinkBufferWidth, mSinkBufferHeight),
272 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */,
Dan Stoza9e56aa02015-11-02 13:00:03 -0800273 retireFence),
Dan Stoza71433162014-02-04 16:22:36 -0800274 &qbo);
275 if (result == NO_ERROR) {
Brian Anderson3d4039d2016-09-23 16:31:30 -0700276 updateQueueBufferOutput(std::move(qbo));
Dan Stoza71433162014-02-04 16:22:36 -0800277 }
278 } else {
279 // If the surface hadn't actually been updated, then we only went
280 // through the motions of updating the display to keep our state
281 // machine happy. We cancel the buffer to avoid triggering another
282 // re-composition and causing an infinite loop.
Dan Stoza9e56aa02015-11-02 13:00:03 -0800283 mSource[SOURCE_SINK]->cancelBuffer(sslot, retireFence);
Jesse Hall38efe862013-04-06 23:12:29 -0700284 }
285 }
286
287 resetPerFrameState();
Jesse Hall99c7dbb2013-03-14 14:29:29 -0700288}
289
Dan Stoza01049c82014-11-11 10:32:31 -0800290void VirtualDisplaySurface::dumpAsString(String8& /* result */) const {
Jesse Hall99c7dbb2013-03-14 14:29:29 -0700291}
292
Michael Lentine47e45402014-07-18 15:34:25 -0700293void VirtualDisplaySurface::resizeBuffers(const uint32_t w, const uint32_t h) {
Brian Andersonbaaad322016-07-22 15:55:13 -0700294 mQueueBufferOutput.width = w;
295 mQueueBufferOutput.height = h;
Michael Lentine47e45402014-07-18 15:34:25 -0700296 mSinkBufferWidth = w;
297 mSinkBufferHeight = h;
298}
299
Dan Stoza9e56aa02015-11-02 13:00:03 -0800300const sp<Fence>& VirtualDisplaySurface::getClientTargetAcquireFence() const {
301 return mFbFence;
302}
Dan Stoza9e56aa02015-11-02 13:00:03 -0800303
Jesse Hall38efe862013-04-06 23:12:29 -0700304status_t VirtualDisplaySurface::requestBuffer(int pslot,
305 sp<GraphicBuffer>* outBuf) {
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200306 if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
Michael Lentine47e45402014-07-18 15:34:25 -0700307 return mSource[SOURCE_SINK]->requestBuffer(pslot, outBuf);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700308 }
Michael Lentine47e45402014-07-18 15:34:25 -0700309
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800310 VDS_LOGW_IF(mDbgState != DBG_STATE_GPU, "Unexpected requestBuffer pslot=%d in %s state", pslot,
311 dbgStateStr());
Jesse Hall38efe862013-04-06 23:12:29 -0700312
313 *outBuf = mProducerBuffers[pslot];
314 return NO_ERROR;
315}
316
Pablo Ceballosfa455352015-08-12 17:47:47 -0700317status_t VirtualDisplaySurface::setMaxDequeuedBufferCount(
318 int maxDequeuedBuffers) {
319 return mSource[SOURCE_SINK]->setMaxDequeuedBufferCount(maxDequeuedBuffers);
320}
321
322status_t VirtualDisplaySurface::setAsyncMode(bool async) {
323 return mSource[SOURCE_SINK]->setAsyncMode(async);
324}
325
Jesse Hall38efe862013-04-06 23:12:29 -0700326status_t VirtualDisplaySurface::dequeueBuffer(Source source,
Mathias Agopiancb496ac2017-05-22 14:21:00 -0700327 PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) {
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200328 LOG_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId));
Jesse Hall8db92552013-08-29 16:03:50 -0700329
Ian Elliotta2eb34c2017-07-18 11:05:49 -0600330 status_t result =
331 mSource[source]->dequeueBuffer(sslot, fence, mSinkBufferWidth, mSinkBufferHeight,
332 format, usage, nullptr, nullptr);
Jesse Hall38efe862013-04-06 23:12:29 -0700333 if (result < 0)
334 return result;
335 int pslot = mapSource2ProducerSlot(source, *sslot);
336 VDS_LOGV("dequeueBuffer(%s): sslot=%d pslot=%d result=%d",
337 dbgSourceStr(source), *sslot, pslot, result);
Dan Stozafebd4f42014-04-09 16:14:51 -0700338 uint64_t sourceBit = static_cast<uint64_t>(source) << pslot;
Jesse Hall38efe862013-04-06 23:12:29 -0700339
Dan Stozafebd4f42014-04-09 16:14:51 -0700340 if ((mProducerSlotSource & (1ULL << pslot)) != sourceBit) {
Jesse Hall38efe862013-04-06 23:12:29 -0700341 // This slot was previously dequeued from the other source; must
342 // re-request the buffer.
343 result |= BUFFER_NEEDS_REALLOCATION;
Dan Stozafebd4f42014-04-09 16:14:51 -0700344 mProducerSlotSource &= ~(1ULL << pslot);
Jesse Hall38efe862013-04-06 23:12:29 -0700345 mProducerSlotSource |= sourceBit;
346 }
347
348 if (result & RELEASE_ALL_BUFFERS) {
349 for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
Dan Stozafebd4f42014-04-09 16:14:51 -0700350 if ((mProducerSlotSource & (1ULL << i)) == sourceBit)
Jesse Hall38efe862013-04-06 23:12:29 -0700351 mProducerBuffers[i].clear();
352 }
353 }
354 if (result & BUFFER_NEEDS_REALLOCATION) {
Jesse Hall0b63cd12014-04-29 16:14:14 -0700355 result = mSource[source]->requestBuffer(*sslot, &mProducerBuffers[pslot]);
356 if (result < 0) {
357 mProducerBuffers[pslot].clear();
358 mSource[source]->cancelBuffer(*sslot, *fence);
359 return result;
360 }
Mathias Agopiancb496ac2017-05-22 14:21:00 -0700361 VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p fmt=%d usage=%#" PRIx64,
Jesse Hall497ba0e2013-11-04 16:43:03 -0800362 dbgSourceStr(source), pslot, mProducerBuffers[pslot].get(),
363 mProducerBuffers[pslot]->getPixelFormat(),
364 mProducerBuffers[pslot]->getUsage());
Jesse Hall38efe862013-04-06 23:12:29 -0700365 }
366
367 return result;
368}
369
Ian Elliotta2eb34c2017-07-18 11:05:49 -0600370status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, uint32_t w, uint32_t h,
371 PixelFormat format, uint64_t usage,
372 uint64_t* outBufferAge,
373 FrameEventHistoryDelta* outTimestamps) {
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200374 if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
Ian Elliotta2eb34c2017-07-18 11:05:49 -0600375 return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, w, h, format, usage, outBufferAge,
376 outTimestamps);
Brian Anderson7c3ba8a2016-07-25 12:48:08 -0700377 }
Michael Lentine47e45402014-07-18 15:34:25 -0700378
Jesse Hall38efe862013-04-06 23:12:29 -0700379 VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
380 "Unexpected dequeueBuffer() in %s state", dbgStateStr());
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800381 mDbgState = DBG_STATE_GPU;
Jesse Hall38efe862013-04-06 23:12:29 -0700382
Mathias Agopiancb496ac2017-05-22 14:21:00 -0700383 VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#" PRIx64, w, h, format, usage);
Jesse Hall38efe862013-04-06 23:12:29 -0700384
Jesse Hall028dc8f2013-08-20 16:35:32 -0700385 status_t result = NO_ERROR;
Jesse Hall38efe862013-04-06 23:12:29 -0700386 Source source = fbSourceForCompositionType(mCompositionType);
Jesse Hall028dc8f2013-08-20 16:35:32 -0700387
Jesse Hall38efe862013-04-06 23:12:29 -0700388 if (source == SOURCE_SINK) {
Mathias Agopian6da15f42013-09-25 20:40:07 -0700389
390 if (mOutputProducerSlot < 0) {
391 // Last chance bailout if something bad happened earlier. For example,
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800392 // in a graphics API configuration, if the sink disappears then dequeueBuffer
393 // will fail, the GPU driver won't queue a buffer, but SurfaceFlinger
Mathias Agopian6da15f42013-09-25 20:40:07 -0700394 // will soldier on. So we end up here without a buffer. There should
395 // be lots of scary messages in the log just before this.
396 VDS_LOGE("dequeueBuffer: no buffer, bailing out");
397 return NO_MEMORY;
398 }
399
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800400 // We already dequeued the output buffer. If the GPU driver wants
Jesse Hall028dc8f2013-08-20 16:35:32 -0700401 // something incompatible, we have to cancel and get a new one. This
402 // will mean that HWC will see a different output buffer between
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800403 // prepare and set, but since we're in GPU-only mode already it
Jesse Hall028dc8f2013-08-20 16:35:32 -0700404 // shouldn't matter.
405
Jesse Hall1e27ba22013-09-27 09:05:09 -0700406 usage |= GRALLOC_USAGE_HW_COMPOSER;
Jesse Hall028dc8f2013-08-20 16:35:32 -0700407 const sp<GraphicBuffer>& buf = mProducerBuffers[mOutputProducerSlot];
Jesse Hall1e27ba22013-09-27 09:05:09 -0700408 if ((usage & ~buf->getUsage()) != 0 ||
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800409 (format != 0 && format != buf->getPixelFormat()) ||
Jesse Hall028dc8f2013-08-20 16:35:32 -0700410 (w != 0 && w != mSinkBufferWidth) ||
411 (h != 0 && h != mSinkBufferHeight)) {
Jesse Hall1e27ba22013-09-27 09:05:09 -0700412 VDS_LOGV("dequeueBuffer: dequeueing new output buffer: "
Mathias Agopiancb496ac2017-05-22 14:21:00 -0700413 "want %dx%d fmt=%d use=%#" PRIx64 ", "
414 "have %dx%d fmt=%d use=%#" PRIx64,
Jesse Hall1e27ba22013-09-27 09:05:09 -0700415 w, h, format, usage,
416 mSinkBufferWidth, mSinkBufferHeight,
417 buf->getPixelFormat(), buf->getUsage());
418 mOutputFormat = format;
419 mOutputUsage = usage;
Jesse Hall028dc8f2013-08-20 16:35:32 -0700420 result = refreshOutputBuffer();
421 if (result < 0)
422 return result;
423 }
Jesse Hall38efe862013-04-06 23:12:29 -0700424 }
425
Jesse Hall028dc8f2013-08-20 16:35:32 -0700426 if (source == SOURCE_SINK) {
427 *pslot = mOutputProducerSlot;
428 *fence = mOutputFence;
429 } else {
430 int sslot;
Jesse Hall1e27ba22013-09-27 09:05:09 -0700431 result = dequeueBuffer(source, format, usage, &sslot, fence);
Jesse Hall028dc8f2013-08-20 16:35:32 -0700432 if (result >= 0) {
433 *pslot = mapSource2ProducerSlot(source, sslot);
434 }
Jesse Hall38efe862013-04-06 23:12:29 -0700435 }
Ian Elliotta2eb34c2017-07-18 11:05:49 -0600436 if (outBufferAge) {
437 *outBufferAge = 0;
438 }
Jesse Hall38efe862013-04-06 23:12:29 -0700439 return result;
440}
441
Dan Stoza88a459a2014-03-12 09:34:36 -0700442status_t VirtualDisplaySurface::detachBuffer(int /* slot */) {
443 VDS_LOGE("detachBuffer is not available for VirtualDisplaySurface");
444 return INVALID_OPERATION;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800445}
446
Dan Stozad9822a32014-03-28 15:25:31 -0700447status_t VirtualDisplaySurface::detachNextBuffer(
448 sp<GraphicBuffer>* /* outBuffer */, sp<Fence>* /* outFence */) {
449 VDS_LOGE("detachNextBuffer is not available for VirtualDisplaySurface");
450 return INVALID_OPERATION;
451}
452
Dan Stoza88a459a2014-03-12 09:34:36 -0700453status_t VirtualDisplaySurface::attachBuffer(int* /* outSlot */,
454 const sp<GraphicBuffer>& /* buffer */) {
455 VDS_LOGE("attachBuffer is not available for VirtualDisplaySurface");
456 return INVALID_OPERATION;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800457}
458
Jesse Hall38efe862013-04-06 23:12:29 -0700459status_t VirtualDisplaySurface::queueBuffer(int pslot,
460 const QueueBufferInput& input, QueueBufferOutput* output) {
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200461 if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
Michael Lentine47e45402014-07-18 15:34:25 -0700462 return mSource[SOURCE_SINK]->queueBuffer(pslot, input, output);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700463 }
Michael Lentine47e45402014-07-18 15:34:25 -0700464
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800465 VDS_LOGW_IF(mDbgState != DBG_STATE_GPU, "Unexpected queueBuffer(pslot=%d) in %s state", pslot,
466 dbgStateStr());
467 mDbgState = DBG_STATE_GPU_DONE;
Jesse Hall38efe862013-04-06 23:12:29 -0700468
469 VDS_LOGV("queueBuffer pslot=%d", pslot);
470
471 status_t result;
472 if (mCompositionType == COMPOSITION_MIXED) {
473 // Queue the buffer back into the scratch pool
474 QueueBufferOutput scratchQBO;
475 int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, pslot);
Mathias Agopiandb89edc2013-08-02 01:40:18 -0700476 result = mSource[SOURCE_SCRATCH]->queueBuffer(sslot, input, &scratchQBO);
Jesse Hall38efe862013-04-06 23:12:29 -0700477 if (result != NO_ERROR)
478 return result;
479
480 // Now acquire the buffer from the scratch pool -- should be the same
481 // slot and fence as we just queued.
482 Mutex::Autolock lock(mMutex);
Dan Stoza11611f92015-03-12 15:12:44 -0700483 BufferItem item;
Jesse Hallbce76112013-07-16 13:46:20 -0700484 result = acquireBufferLocked(&item, 0);
Jesse Hall38efe862013-04-06 23:12:29 -0700485 if (result != NO_ERROR)
486 return result;
Pablo Ceballos47650f42015-08-04 16:38:17 -0700487 VDS_LOGW_IF(item.mSlot != sslot,
Jesse Hall38efe862013-04-06 23:12:29 -0700488 "queueBuffer: acquired sslot %d from SCRATCH after queueing sslot %d",
Pablo Ceballos47650f42015-08-04 16:38:17 -0700489 item.mSlot, sslot);
490 mFbProducerSlot = mapSource2ProducerSlot(SOURCE_SCRATCH, item.mSlot);
491 mFbFence = mSlots[item.mSlot].mFence;
Jesse Hall38efe862013-04-06 23:12:29 -0700492
493 } else {
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800494 LOG_FATAL_IF(mCompositionType != COMPOSITION_GPU,
495 "Unexpected queueBuffer in state %s for compositionType %s", dbgStateStr(),
496 dbgCompositionTypeStr(mCompositionType));
Jesse Hall38efe862013-04-06 23:12:29 -0700497
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800498 // Extract the GPU release fence for HWC to acquire
Jesse Hall38efe862013-04-06 23:12:29 -0700499 int64_t timestamp;
Andy McFadden3c256212013-08-16 14:55:39 -0700500 bool isAutoTimestamp;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800501 android_dataspace dataSpace;
Jesse Hall38efe862013-04-06 23:12:29 -0700502 Rect crop;
503 int scalingMode;
504 uint32_t transform;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800505 input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop,
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700506 &scalingMode, &transform, &mFbFence);
Jesse Hall38efe862013-04-06 23:12:29 -0700507
508 mFbProducerSlot = pslot;
Jesse Hall028dc8f2013-08-20 16:35:32 -0700509 mOutputFence = mFbFence;
Jesse Hall38efe862013-04-06 23:12:29 -0700510 }
511
Brian Anderson3d4039d2016-09-23 16:31:30 -0700512 // This moves the frame timestamps and keeps a copy of all other fields.
513 *output = std::move(mQueueBufferOutput);
Jesse Hall38efe862013-04-06 23:12:29 -0700514 return NO_ERROR;
515}
516
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700517status_t VirtualDisplaySurface::cancelBuffer(int pslot,
518 const sp<Fence>& fence) {
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200519 if (GpuVirtualDisplayId::tryCast(mDisplayId)) {
Michael Lentinefd9d1832014-07-30 15:39:17 -0700520 return mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(SOURCE_SINK, pslot), fence);
Dominik Laskowski075d3172018-05-24 15:50:06 -0700521 }
Michael Lentine47e45402014-07-18 15:34:25 -0700522
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800523 VDS_LOGW_IF(mDbgState != DBG_STATE_GPU, "Unexpected cancelBuffer(pslot=%d) in %s state", pslot,
524 dbgStateStr());
Jesse Hall38efe862013-04-06 23:12:29 -0700525 VDS_LOGV("cancelBuffer pslot=%d", pslot);
526 Source source = fbSourceForCompositionType(mCompositionType);
527 return mSource[source]->cancelBuffer(
528 mapProducer2SourceSlot(source, pslot), fence);
529}
530
531int VirtualDisplaySurface::query(int what, int* value) {
Michael Lentine47e45402014-07-18 15:34:25 -0700532 switch (what) {
533 case NATIVE_WINDOW_WIDTH:
534 *value = mSinkBufferWidth;
535 break;
536 case NATIVE_WINDOW_HEIGHT:
537 *value = mSinkBufferHeight;
538 break;
539 default:
540 return mSource[SOURCE_SINK]->query(what, value);
541 }
542 return NO_ERROR;
Jesse Hall38efe862013-04-06 23:12:29 -0700543}
544
Dan Stozaf0eaf252014-03-21 13:05:51 -0700545status_t VirtualDisplaySurface::connect(const sp<IProducerListener>& listener,
Mathias Agopian365857d2013-09-11 19:35:45 -0700546 int api, bool producerControlledByApp,
Mathias Agopian595264f2013-07-16 22:56:09 -0700547 QueueBufferOutput* output) {
Jesse Hall38efe862013-04-06 23:12:29 -0700548 QueueBufferOutput qbo;
Dan Stozaf0eaf252014-03-21 13:05:51 -0700549 status_t result = mSource[SOURCE_SINK]->connect(listener, api,
550 producerControlledByApp, &qbo);
Jesse Hall38efe862013-04-06 23:12:29 -0700551 if (result == NO_ERROR) {
Brian Anderson3d4039d2016-09-23 16:31:30 -0700552 updateQueueBufferOutput(std::move(qbo));
553 // This moves the frame timestamps and keeps a copy of all other fields.
554 *output = std::move(mQueueBufferOutput);
Jesse Hall38efe862013-04-06 23:12:29 -0700555 }
556 return result;
557}
558
Robert Carr97b9c862016-09-08 13:54:35 -0700559status_t VirtualDisplaySurface::disconnect(int api, DisconnectMode mode) {
560 return mSource[SOURCE_SINK]->disconnect(api, mode);
Jesse Hall38efe862013-04-06 23:12:29 -0700561}
562
Jesse Hall399184a2014-03-03 15:42:54 -0800563status_t VirtualDisplaySurface::setSidebandStream(const sp<NativeHandle>& /*stream*/) {
564 return INVALID_OPERATION;
565}
566
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700567void VirtualDisplaySurface::allocateBuffers(uint32_t /* width */,
Mathias Agopiancb496ac2017-05-22 14:21:00 -0700568 uint32_t /* height */, PixelFormat /* format */, uint64_t /* usage */) {
Dan Stoza29a3e902014-06-20 13:13:57 -0700569 // TODO: Should we actually allocate buffers for a virtual display?
570}
571
Dan Stoza9de72932015-04-16 17:28:43 -0700572status_t VirtualDisplaySurface::allowAllocation(bool /* allow */) {
573 return INVALID_OPERATION;
574}
575
Dan Stoza812ed062015-06-02 15:45:22 -0700576status_t VirtualDisplaySurface::setGenerationNumber(uint32_t /* generation */) {
577 ALOGE("setGenerationNumber not supported on VirtualDisplaySurface");
578 return INVALID_OPERATION;
579}
580
Dan Stozac6f30bd2015-06-08 09:32:50 -0700581String8 VirtualDisplaySurface::getConsumerName() const {
582 return String8("VirtualDisplaySurface");
583}
584
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700585status_t VirtualDisplaySurface::setSharedBufferMode(bool /*sharedBufferMode*/) {
586 ALOGE("setSharedBufferMode not supported on VirtualDisplaySurface");
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800587 return INVALID_OPERATION;
588}
589
590status_t VirtualDisplaySurface::setAutoRefresh(bool /*autoRefresh*/) {
591 ALOGE("setAutoRefresh not supported on VirtualDisplaySurface");
592 return INVALID_OPERATION;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700593}
594
Dan Stoza127fc632015-06-30 13:43:32 -0700595status_t VirtualDisplaySurface::setDequeueTimeout(nsecs_t /* timeout */) {
596 ALOGE("setDequeueTimeout not supported on VirtualDisplaySurface");
597 return INVALID_OPERATION;
598}
599
Dan Stoza50101d02016-04-07 16:53:23 -0700600status_t VirtualDisplaySurface::getLastQueuedBuffer(
John Reck1a61da52016-04-28 13:18:15 -0700601 sp<GraphicBuffer>* /*outBuffer*/, sp<Fence>* /*outFence*/,
602 float[16] /* outTransformMatrix*/) {
Dan Stoza50101d02016-04-07 16:53:23 -0700603 ALOGE("getLastQueuedBuffer not supported on VirtualDisplaySurface");
604 return INVALID_OPERATION;
605}
606
Pablo Ceballos8e3e92b2016-06-27 17:56:53 -0700607status_t VirtualDisplaySurface::getUniqueId(uint64_t* /*outId*/) const {
608 ALOGE("getUniqueId not supported on VirtualDisplaySurface");
609 return INVALID_OPERATION;
610}
611
Chia-I Wue2786ea2017-08-07 10:36:08 -0700612status_t VirtualDisplaySurface::getConsumerUsage(uint64_t* outUsage) const {
613 return mSource[SOURCE_SINK]->getConsumerUsage(outUsage);
614}
615
Jesse Hall38efe862013-04-06 23:12:29 -0700616void VirtualDisplaySurface::updateQueueBufferOutput(
Brian Anderson3d4039d2016-09-23 16:31:30 -0700617 QueueBufferOutput&& qbo) {
618 mQueueBufferOutput = std::move(qbo);
Brian Andersonbaaad322016-07-22 15:55:13 -0700619 mQueueBufferOutput.transformHint = 0;
Jesse Hall38efe862013-04-06 23:12:29 -0700620}
621
622void VirtualDisplaySurface::resetPerFrameState() {
623 mCompositionType = COMPOSITION_UNKNOWN;
mayank parsharb988f852014-01-10 10:27:45 +0530624 mFbFence = Fence::NO_FENCE;
Jesse Hall028dc8f2013-08-20 16:35:32 -0700625 mOutputFence = Fence::NO_FENCE;
Jesse Hall38efe862013-04-06 23:12:29 -0700626 mOutputProducerSlot = -1;
mayank parsharfdfde882014-01-23 15:08:31 +0530627 mFbProducerSlot = -1;
Jesse Hall38efe862013-04-06 23:12:29 -0700628}
629
Jesse Hall028dc8f2013-08-20 16:35:32 -0700630status_t VirtualDisplaySurface::refreshOutputBuffer() {
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200631 LOG_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId));
Dominik Laskowski075d3172018-05-24 15:50:06 -0700632
Jesse Hall028dc8f2013-08-20 16:35:32 -0700633 if (mOutputProducerSlot >= 0) {
634 mSource[SOURCE_SINK]->cancelBuffer(
635 mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot),
636 mOutputFence);
637 }
638
639 int sslot;
Jesse Hall1e27ba22013-09-27 09:05:09 -0700640 status_t result = dequeueBuffer(SOURCE_SINK, mOutputFormat, mOutputUsage,
641 &sslot, &mOutputFence);
Jesse Hall028dc8f2013-08-20 16:35:32 -0700642 if (result < 0)
643 return result;
644 mOutputProducerSlot = mapSource2ProducerSlot(SOURCE_SINK, sslot);
645
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800646 // On GPU-only frames, we don't have the right output buffer acquire fence
647 // until after GPU calls queueBuffer(). So here we just set the buffer
Jesse Hallb716e572013-10-01 17:25:20 -0700648 // (for use in HWC prepare) but not the fence; we'll call this again with
649 // the proper fence once we have it.
Marin Shalamanov0f10d0d2020-08-06 20:04:06 +0200650 const auto halDisplayId = HalVirtualDisplayId::tryCast(mDisplayId);
651 LOG_FATAL_IF(!halDisplayId);
652 result = mHwc.setOutputBuffer(*halDisplayId, Fence::NO_FENCE,
Dominik Laskowski075d3172018-05-24 15:50:06 -0700653 mProducerBuffers[mOutputProducerSlot]);
Jesse Hall028dc8f2013-08-20 16:35:32 -0700654
655 return result;
656}
657
Jesse Hall38efe862013-04-06 23:12:29 -0700658// This slot mapping function is its own inverse, so two copies are unnecessary.
659// Both are kept to make the intent clear where the function is called, and for
660// the (unlikely) chance that we switch to a different mapping function.
661int VirtualDisplaySurface::mapSource2ProducerSlot(Source source, int sslot) {
662 if (source == SOURCE_SCRATCH) {
663 return BufferQueue::NUM_BUFFER_SLOTS - sslot - 1;
664 } else {
665 return sslot;
666 }
667}
668int VirtualDisplaySurface::mapProducer2SourceSlot(Source source, int pslot) {
669 return mapSource2ProducerSlot(source, pslot);
670}
671
672VirtualDisplaySurface::Source
673VirtualDisplaySurface::fbSourceForCompositionType(CompositionType type) {
674 return type == COMPOSITION_MIXED ? SOURCE_SCRATCH : SOURCE_SINK;
675}
676
677const char* VirtualDisplaySurface::dbgStateStr() const {
678 switch (mDbgState) {
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800679 case DBG_STATE_IDLE:
680 return "IDLE";
681 case DBG_STATE_PREPARED:
682 return "PREPARED";
683 case DBG_STATE_GPU:
684 return "GPU";
685 case DBG_STATE_GPU_DONE:
686 return "GPU_DONE";
687 case DBG_STATE_HWC:
688 return "HWC";
689 default:
690 return "INVALID";
Jesse Hall38efe862013-04-06 23:12:29 -0700691 }
692}
693
694const char* VirtualDisplaySurface::dbgSourceStr(Source s) {
695 switch (s) {
696 case SOURCE_SINK: return "SINK";
697 case SOURCE_SCRATCH: return "SCRATCH";
698 default: return "INVALID";
699 }
700}
701
Jesse Hall99c7dbb2013-03-14 14:29:29 -0700702// ---------------------------------------------------------------------------
703} // namespace android
704// ---------------------------------------------------------------------------
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800705
706// TODO(b/129481165): remove the #pragma below and fix conversion issues
707#pragma clang diagnostic pop // ignored "-Wconversion"