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