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