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 
     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 
     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 
     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 
    114 VirtualDisplaySurface::~VirtualDisplaySurface() {
    115     mSource[SOURCE_SCRATCH]->disconnect(NATIVE_WINDOW_API_EGL);
    116 }
    117 
    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 
    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 
    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 
    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 
    278 void VirtualDisplaySurface::dumpAsString(String8& /* result */) const {
    279 }
    280 
    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 
    288 const sp<Fence>& VirtualDisplaySurface::getClientTargetAcquireFence() const {
    289     return mFbFence;
    290 }
    291 
    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 
    305 status_t VirtualDisplaySurface::setMaxDequeuedBufferCount(
    306         int maxDequeuedBuffers) {
    307     return mSource[SOURCE_SINK]->setMaxDequeuedBufferCount(maxDequeuedBuffers);
    308 }
    309 
    310 status_t VirtualDisplaySurface::setAsyncMode(bool async) {
    311     return mSource[SOURCE_SINK]->setAsyncMode(async);
    312 }
    313 
    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 
    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 
    430 status_t VirtualDisplaySurface::detachBuffer(int /* slot */) {
    431     VDS_LOGE("detachBuffer is not available for VirtualDisplaySurface");
    432     return INVALID_OPERATION;
    433 }
    434 
    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 
    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 
    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 
    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 
    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 
    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 
    547 status_t VirtualDisplaySurface::disconnect(int api, DisconnectMode mode) {
    548     return mSource[SOURCE_SINK]->disconnect(api, mode);
    549 }
    550 
    551 status_t VirtualDisplaySurface::setSidebandStream(const sp<NativeHandle>& /*stream*/) {
    552     return INVALID_OPERATION;
    553 }
    554 
    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 
    560 status_t VirtualDisplaySurface::allowAllocation(bool /* allow */) {
    561     return INVALID_OPERATION;
    562 }
    563 
    564 status_t VirtualDisplaySurface::setGenerationNumber(uint32_t /* generation */) {
    565     ALOGE("setGenerationNumber not supported on VirtualDisplaySurface");
    566     return INVALID_OPERATION;
    567 }
    568 
    569 String8 VirtualDisplaySurface::getConsumerName() const {
    570     return String8("VirtualDisplaySurface");
    571 }
    572 
    573 status_t VirtualDisplaySurface::setSharedBufferMode(bool /*sharedBufferMode*/) {
    574     ALOGE("setSharedBufferMode not supported on VirtualDisplaySurface");
    575     return INVALID_OPERATION;
    576 }
    577 
    578 status_t VirtualDisplaySurface::setAutoRefresh(bool /*autoRefresh*/) {
    579     ALOGE("setAutoRefresh not supported on VirtualDisplaySurface");
    580     return INVALID_OPERATION;
    581 }
    582 
    583 status_t VirtualDisplaySurface::setDequeueTimeout(nsecs_t /* timeout */) {
    584     ALOGE("setDequeueTimeout not supported on VirtualDisplaySurface");
    585     return INVALID_OPERATION;
    586 }
    587 
    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 
    595 status_t VirtualDisplaySurface::getUniqueId(uint64_t* /*outId*/) const {
    596     ALOGE("getUniqueId not supported on VirtualDisplaySurface");
    597     return INVALID_OPERATION;
    598 }
    599 
    600 status_t VirtualDisplaySurface::getConsumerUsage(uint64_t* outUsage) const {
    601     return mSource[SOURCE_SINK]->getConsumerUsage(outUsage);
    602 }
    603 
    604 void VirtualDisplaySurface::updateQueueBufferOutput(
    605         QueueBufferOutput&& qbo) {
    606     mQueueBufferOutput = std::move(qbo);
    607     mQueueBufferOutput.transformHint = 0;
    608 }
    609 
    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 
    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.
    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 }
    652 int VirtualDisplaySurface::mapProducer2SourceSlot(Source source, int pslot) {
    653     return mapSource2ProducerSlot(source, pslot);
    654 }
    655 
    656 VirtualDisplaySurface::Source
    657 VirtualDisplaySurface::fbSourceForCompositionType(CompositionType type) {
    658     return type == COMPOSITION_MIXED ? SOURCE_SCRATCH : SOURCE_SINK;
    659 }
    660 
    661 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 
    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