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(&timestamp, &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