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