Home | History | Annotate | Download | only in DisplayHardware
      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 
     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 
     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 
     98 VirtualDisplaySurface::~VirtualDisplaySurface() {
     99 }
    100 
    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 
    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 
    162 status_t VirtualDisplaySurface::compositionComplete() {
    163     return NO_ERROR;
    164 }
    165 
    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 
    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 
    260 void VirtualDisplaySurface::dumpAsString(String8& /* result */) const {
    261 }
    262 
    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 
    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 
    285 status_t VirtualDisplaySurface::setBufferCount(int bufferCount) {
    286     return mSource[SOURCE_SINK]->setBufferCount(bufferCount);
    287 }
    288 
    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 
    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 
    400 status_t VirtualDisplaySurface::detachBuffer(int /* slot */) {
    401     VDS_LOGE("detachBuffer is not available for VirtualDisplaySurface");
    402     return INVALID_OPERATION;
    403 }
    404 
    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 
    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 
    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 
    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 
    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 
    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 
    515 status_t VirtualDisplaySurface::disconnect(int api) {
    516     return mSource[SOURCE_SINK]->disconnect(api);
    517 }
    518 
    519 status_t VirtualDisplaySurface::setSidebandStream(const sp<NativeHandle>& /*stream*/) {
    520     return INVALID_OPERATION;
    521 }
    522 
    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 
    529 status_t VirtualDisplaySurface::allowAllocation(bool /* allow */) {
    530     return INVALID_OPERATION;
    531 }
    532 
    533 status_t VirtualDisplaySurface::setGenerationNumber(uint32_t /* generation */) {
    534     ALOGE("setGenerationNumber not supported on VirtualDisplaySurface");
    535     return INVALID_OPERATION;
    536 }
    537 
    538 String8 VirtualDisplaySurface::getConsumerName() const {
    539     return String8("VirtualDisplaySurface");
    540 }
    541 
    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 
    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 
    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.
    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 }
    591 int VirtualDisplaySurface::mapProducer2SourceSlot(Source source, int pslot) {
    592     return mapSource2ProducerSlot(source, pslot);
    593 }
    594 
    595 VirtualDisplaySurface::Source
    596 VirtualDisplaySurface::fbSourceForCompositionType(CompositionType type) {
    597     return type == COMPOSITION_MIXED ? SOURCE_SCRATCH : SOURCE_SINK;
    598 }
    599 
    600 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 
    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