123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634 |
- /*
- * Copyright 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // #define LOG_NDEBUG 0
- #include "VirtualDisplaySurface.h"
- #include "HWComposer.h"
- #include <gui/BufferItem.h>
- #include <gui/Surface.h>
- // ---------------------------------------------------------------------------
- namespace android {
- // ---------------------------------------------------------------------------
- #if defined(FORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS)
- static const bool sForceHwcCopy = true;
- #else
- static const bool sForceHwcCopy = false;
- #endif
- #ifndef NUM_FRAMEBUFFER_SURFACE_BUFFERS
- #define NUM_FRAMEBUFFER_SURFACE_BUFFERS (2)
- #endif
- #define VDS_LOGE(msg, ...) ALOGE("[%s] " msg, \
- mDisplayName.string(), ##__VA_ARGS__)
- #define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] " msg, \
- mDisplayName.string(), ##__VA_ARGS__)
- #define VDS_LOGV(msg, ...) ALOGV("[%s] " msg, \
- mDisplayName.string(), ##__VA_ARGS__)
- static const char* dbgCompositionTypeStr(DisplaySurface::CompositionType type) {
- switch (type) {
- case DisplaySurface::COMPOSITION_UNKNOWN: return "UNKNOWN";
- case DisplaySurface::COMPOSITION_GLES: return "GLES";
- case DisplaySurface::COMPOSITION_HWC: return "HWC";
- case DisplaySurface::COMPOSITION_MIXED: return "MIXED";
- default: return "<INVALID>";
- }
- }
- VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
- const sp<IGraphicBufferProducer>& sink,
- const sp<IGraphicBufferProducer>& bqProducer,
- const sp<IGraphicBufferConsumer>& bqConsumer,
- const String8& name)
- : ConsumerBase(bqConsumer),
- mHwc(hwc),
- mDisplayId(dispId),
- mDisplayName(name),
- mOutputUsage(GRALLOC_USAGE_HW_COMPOSER),
- mProducerSlotSource(0),
- mDbgState(DBG_STATE_IDLE),
- mDbgLastCompositionType(COMPOSITION_UNKNOWN),
- mMustRecompose(false)
- {
- mSource[SOURCE_SINK] = sink;
- mSource[SOURCE_SCRATCH] = bqProducer;
- sp<Surface> surface(new Surface(bqProducer, false));
- resetPerFrameState();
- int sinkWidth, sinkHeight;
- sink->query(NATIVE_WINDOW_WIDTH, &sinkWidth);
- sink->query(NATIVE_WINDOW_HEIGHT, &sinkHeight);
- mSinkBufferWidth = sinkWidth;
- mSinkBufferHeight = sinkHeight;
- // Pick the buffer format to request from the sink when not rendering to it
- // with GLES. If the consumer needs CPU access, use the default format
- // set by the consumer. Otherwise allow gralloc to decide the format based
- // on usage bits.
- int sinkUsage;
- sink->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &sinkUsage);
- if (sinkUsage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
- int sinkFormat;
- sink->query(NATIVE_WINDOW_FORMAT, &sinkFormat);
- mDefaultOutputFormat = sinkFormat;
- } else {
- mDefaultOutputFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
- }
- mOutputFormat = mDefaultOutputFormat;
- ConsumerBase::mName = String8::format("VDS: %s", mDisplayName.string());
- mConsumer->setConsumerName(ConsumerBase::mName);
- mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
- mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight);
- mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
- surface->allocateBuffers();
- }
- VirtualDisplaySurface::~VirtualDisplaySurface() {
- }
- status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) {
- if (mDisplayId < 0)
- return NO_ERROR;
- mMustRecompose = mustRecompose;
- VDS_LOGW_IF(mDbgState != DBG_STATE_IDLE,
- "Unexpected beginFrame() in %s state", dbgStateStr());
- mDbgState = DBG_STATE_BEGUN;
- return refreshOutputBuffer();
- }
- status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) {
- if (mDisplayId < 0)
- return NO_ERROR;
- VDS_LOGW_IF(mDbgState != DBG_STATE_BEGUN,
- "Unexpected prepareFrame() in %s state", dbgStateStr());
- mDbgState = DBG_STATE_PREPARED;
- mCompositionType = compositionType;
- if (sForceHwcCopy && mCompositionType == COMPOSITION_GLES) {
- // Some hardware can do RGB->YUV conversion more efficiently in hardware
- // controlled by HWC than in hardware controlled by the video encoder.
- // Forcing GLES-composed frames to go through an extra copy by the HWC
- // allows the format conversion to happen there, rather than passing RGB
- // directly to the consumer.
- //
- // On the other hand, when the consumer prefers RGB or can consume RGB
- // inexpensively, this forces an unnecessary copy.
- mCompositionType = COMPOSITION_MIXED;
- }
- if (mCompositionType != mDbgLastCompositionType) {
- VDS_LOGV("prepareFrame: composition type changed to %s",
- dbgCompositionTypeStr(mCompositionType));
- mDbgLastCompositionType = mCompositionType;
- }
- if (mCompositionType != COMPOSITION_GLES &&
- (mOutputFormat != mDefaultOutputFormat ||
- mOutputUsage != GRALLOC_USAGE_HW_COMPOSER)) {
- // We must have just switched from GLES-only to MIXED or HWC
- // composition. Stop using the format and usage requested by the GLES
- // driver; they may be suboptimal when HWC is writing to the output
- // buffer. For example, if the output is going to a video encoder, and
- // HWC can write directly to YUV, some hardware can skip a
- // memory-to-memory RGB-to-YUV conversion step.
- //
- // If we just switched *to* GLES-only mode, we'll change the
- // format/usage and get a new buffer when the GLES driver calls
- // dequeueBuffer().
- mOutputFormat = mDefaultOutputFormat;
- setOutputUsage(GRALLOC_USAGE_HW_COMPOSER);
- refreshOutputBuffer();
- }
- return NO_ERROR;
- }
- status_t VirtualDisplaySurface::compositionComplete() {
- return NO_ERROR;
- }
- status_t VirtualDisplaySurface::advanceFrame() {
- if (mDisplayId < 0)
- return NO_ERROR;
- if (mCompositionType == COMPOSITION_HWC) {
- VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
- "Unexpected advanceFrame() in %s state on HWC frame",
- dbgStateStr());
- } else {
- VDS_LOGW_IF(mDbgState != DBG_STATE_GLES_DONE,
- "Unexpected advanceFrame() in %s state on GLES/MIXED frame",
- dbgStateStr());
- }
- mDbgState = DBG_STATE_HWC;
- if (mOutputProducerSlot < 0 ||
- (mCompositionType != COMPOSITION_HWC && mFbProducerSlot < 0)) {
- // Last chance bailout if something bad happened earlier. For example,
- // in a GLES configuration, if the sink disappears then dequeueBuffer
- // will fail, the GLES driver won't queue a buffer, but SurfaceFlinger
- // will soldier on. So we end up here without a buffer. There should
- // be lots of scary messages in the log just before this.
- VDS_LOGE("advanceFrame: no buffer, bailing out");
- return NO_MEMORY;
- }
- sp<GraphicBuffer> fbBuffer = mFbProducerSlot >= 0 ?
- mProducerBuffers[mFbProducerSlot] : sp<GraphicBuffer>(NULL);
- sp<GraphicBuffer> outBuffer = mProducerBuffers[mOutputProducerSlot];
- VDS_LOGV("advanceFrame: fb=%d(%p) out=%d(%p)",
- mFbProducerSlot, fbBuffer.get(),
- mOutputProducerSlot, outBuffer.get());
- // At this point we know the output buffer acquire fence,
- // so update HWC state with it.
- mHwc.setOutputBuffer(mDisplayId, mOutputFence, outBuffer);
- status_t result = NO_ERROR;
- if (fbBuffer != NULL) {
- result = mHwc.fbPost(mDisplayId, mFbFence, fbBuffer);
- }
- return result;
- }
- void VirtualDisplaySurface::onFrameCommitted() {
- if (mDisplayId < 0)
- return;
- VDS_LOGW_IF(mDbgState != DBG_STATE_HWC,
- "Unexpected onFrameCommitted() in %s state", dbgStateStr());
- mDbgState = DBG_STATE_IDLE;
- sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId);
- if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) {
- // release the scratch buffer back to the pool
- Mutex::Autolock lock(mMutex);
- int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot);
- VDS_LOGV("onFrameCommitted: release scratch sslot=%d", sslot);
- addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot], fbFence);
- releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot],
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
- }
- if (mOutputProducerSlot >= 0) {
- int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot);
- QueueBufferOutput qbo;
- sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId);
- VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot);
- if (mMustRecompose) {
- status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
- QueueBufferInput(
- systemTime(), false /* isAutoTimestamp */,
- HAL_DATASPACE_UNKNOWN,
- Rect(mSinkBufferWidth, mSinkBufferHeight),
- NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */,
- true /* async*/,
- outFence),
- &qbo);
- if (result == NO_ERROR) {
- updateQueueBufferOutput(qbo);
- }
- } else {
- // If the surface hadn't actually been updated, then we only went
- // through the motions of updating the display to keep our state
- // machine happy. We cancel the buffer to avoid triggering another
- // re-composition and causing an infinite loop.
- mSource[SOURCE_SINK]->cancelBuffer(sslot, outFence);
- }
- }
- resetPerFrameState();
- }
- void VirtualDisplaySurface::dumpAsString(String8& /* result */) const {
- }
- void VirtualDisplaySurface::resizeBuffers(const uint32_t w, const uint32_t h) {
- uint32_t tmpW, tmpH, transformHint, numPendingBuffers;
- mQueueBufferOutput.deflate(&tmpW, &tmpH, &transformHint, &numPendingBuffers);
- mQueueBufferOutput.inflate(w, h, transformHint, numPendingBuffers);
- mSinkBufferWidth = w;
- mSinkBufferHeight = h;
- }
- status_t VirtualDisplaySurface::requestBuffer(int pslot,
- sp<GraphicBuffer>* outBuf) {
- if (mDisplayId < 0)
- return mSource[SOURCE_SINK]->requestBuffer(pslot, outBuf);
- VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
- "Unexpected requestBuffer pslot=%d in %s state",
- pslot, dbgStateStr());
- *outBuf = mProducerBuffers[pslot];
- return NO_ERROR;
- }
- status_t VirtualDisplaySurface::setBufferCount(int bufferCount) {
- return mSource[SOURCE_SINK]->setBufferCount(bufferCount);
- }
- status_t VirtualDisplaySurface::dequeueBuffer(Source source,
- PixelFormat format, uint32_t usage, int* sslot, sp<Fence>* fence) {
- LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId);
- // Don't let a slow consumer block us
- bool async = (source == SOURCE_SINK);
- status_t result = mSource[source]->dequeueBuffer(sslot, fence, async,
- mSinkBufferWidth, mSinkBufferHeight, format, usage);
- if (result < 0)
- return result;
- int pslot = mapSource2ProducerSlot(source, *sslot);
- VDS_LOGV("dequeueBuffer(%s): sslot=%d pslot=%d result=%d",
- dbgSourceStr(source), *sslot, pslot, result);
- uint64_t sourceBit = static_cast<uint64_t>(source) << pslot;
- if ((mProducerSlotSource & (1ULL << pslot)) != sourceBit) {
- // This slot was previously dequeued from the other source; must
- // re-request the buffer.
- result |= BUFFER_NEEDS_REALLOCATION;
- mProducerSlotSource &= ~(1ULL << pslot);
- mProducerSlotSource |= sourceBit;
- }
- if (result & RELEASE_ALL_BUFFERS) {
- for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- if ((mProducerSlotSource & (1ULL << i)) == sourceBit)
- mProducerBuffers[i].clear();
- }
- }
- if (result & BUFFER_NEEDS_REALLOCATION) {
- result = mSource[source]->requestBuffer(*sslot, &mProducerBuffers[pslot]);
- if (result < 0) {
- mProducerBuffers[pslot].clear();
- mSource[source]->cancelBuffer(*sslot, *fence);
- return result;
- }
- VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p fmt=%d usage=%#x",
- dbgSourceStr(source), pslot, mProducerBuffers[pslot].get(),
- mProducerBuffers[pslot]->getPixelFormat(),
- mProducerBuffers[pslot]->getUsage());
- }
- return result;
- }
- status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) {
- if (mDisplayId < 0)
- return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, async, w, h, format, usage);
- VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
- "Unexpected dequeueBuffer() in %s state", dbgStateStr());
- mDbgState = DBG_STATE_GLES;
- VDS_LOGW_IF(!async, "EGL called dequeueBuffer with !async despite eglSwapInterval(0)");
- VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#x", w, h, format, usage);
- status_t result = NO_ERROR;
- Source source = fbSourceForCompositionType(mCompositionType);
- if (source == SOURCE_SINK) {
- if (mOutputProducerSlot < 0) {
- // Last chance bailout if something bad happened earlier. For example,
- // in a GLES configuration, if the sink disappears then dequeueBuffer
- // will fail, the GLES driver won't queue a buffer, but SurfaceFlinger
- // will soldier on. So we end up here without a buffer. There should
- // be lots of scary messages in the log just before this.
- VDS_LOGE("dequeueBuffer: no buffer, bailing out");
- return NO_MEMORY;
- }
- // We already dequeued the output buffer. If the GLES driver wants
- // something incompatible, we have to cancel and get a new one. This
- // will mean that HWC will see a different output buffer between
- // prepare and set, but since we're in GLES-only mode already it
- // shouldn't matter.
- usage |= GRALLOC_USAGE_HW_COMPOSER;
- const sp<GraphicBuffer>& buf = mProducerBuffers[mOutputProducerSlot];
- if ((usage & ~buf->getUsage()) != 0 ||
- (format != 0 && format != buf->getPixelFormat()) ||
- (w != 0 && w != mSinkBufferWidth) ||
- (h != 0 && h != mSinkBufferHeight)) {
- VDS_LOGV("dequeueBuffer: dequeueing new output buffer: "
- "want %dx%d fmt=%d use=%#x, "
- "have %dx%d fmt=%d use=%#x",
- w, h, format, usage,
- mSinkBufferWidth, mSinkBufferHeight,
- buf->getPixelFormat(), buf->getUsage());
- mOutputFormat = format;
- setOutputUsage(usage);
- result = refreshOutputBuffer();
- if (result < 0)
- return result;
- }
- }
- if (source == SOURCE_SINK) {
- *pslot = mOutputProducerSlot;
- *fence = mOutputFence;
- } else {
- int sslot;
- result = dequeueBuffer(source, format, usage, &sslot, fence);
- if (result >= 0) {
- *pslot = mapSource2ProducerSlot(source, sslot);
- }
- }
- return result;
- }
- status_t VirtualDisplaySurface::detachBuffer(int /* slot */) {
- VDS_LOGE("detachBuffer is not available for VirtualDisplaySurface");
- return INVALID_OPERATION;
- }
- status_t VirtualDisplaySurface::detachNextBuffer(
- sp<GraphicBuffer>* /* outBuffer */, sp<Fence>* /* outFence */) {
- VDS_LOGE("detachNextBuffer is not available for VirtualDisplaySurface");
- return INVALID_OPERATION;
- }
- status_t VirtualDisplaySurface::attachBuffer(int* /* outSlot */,
- const sp<GraphicBuffer>& /* buffer */) {
- VDS_LOGE("attachBuffer is not available for VirtualDisplaySurface");
- return INVALID_OPERATION;
- }
- status_t VirtualDisplaySurface::queueBuffer(int pslot,
- const QueueBufferInput& input, QueueBufferOutput* output) {
- if (mDisplayId < 0)
- return mSource[SOURCE_SINK]->queueBuffer(pslot, input, output);
- VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
- "Unexpected queueBuffer(pslot=%d) in %s state", pslot,
- dbgStateStr());
- mDbgState = DBG_STATE_GLES_DONE;
- VDS_LOGV("queueBuffer pslot=%d", pslot);
- status_t result;
- if (mCompositionType == COMPOSITION_MIXED) {
- // Queue the buffer back into the scratch pool
- QueueBufferOutput scratchQBO;
- int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, pslot);
- result = mSource[SOURCE_SCRATCH]->queueBuffer(sslot, input, &scratchQBO);
- if (result != NO_ERROR)
- return result;
- // Now acquire the buffer from the scratch pool -- should be the same
- // slot and fence as we just queued.
- Mutex::Autolock lock(mMutex);
- BufferItem item;
- result = acquireBufferLocked(&item, 0);
- if (result != NO_ERROR)
- return result;
- VDS_LOGW_IF(item.mBuf != sslot,
- "queueBuffer: acquired sslot %d from SCRATCH after queueing sslot %d",
- item.mBuf, sslot);
- mFbProducerSlot = mapSource2ProducerSlot(SOURCE_SCRATCH, item.mBuf);
- mFbFence = mSlots[item.mBuf].mFence;
- } else {
- LOG_FATAL_IF(mCompositionType != COMPOSITION_GLES,
- "Unexpected queueBuffer in state %s for compositionType %s",
- dbgStateStr(), dbgCompositionTypeStr(mCompositionType));
- // Extract the GLES release fence for HWC to acquire
- int64_t timestamp;
- bool isAutoTimestamp;
- android_dataspace dataSpace;
- Rect crop;
- int scalingMode;
- uint32_t transform;
- bool async;
- input.deflate(×tamp, &isAutoTimestamp, &dataSpace, &crop,
- &scalingMode, &transform, &async, &mFbFence);
- mFbProducerSlot = pslot;
- mOutputFence = mFbFence;
- }
- *output = mQueueBufferOutput;
- return NO_ERROR;
- }
- void VirtualDisplaySurface::cancelBuffer(int pslot, const sp<Fence>& fence) {
- if (mDisplayId < 0)
- return mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(SOURCE_SINK, pslot), fence);
- VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
- "Unexpected cancelBuffer(pslot=%d) in %s state", pslot,
- dbgStateStr());
- VDS_LOGV("cancelBuffer pslot=%d", pslot);
- Source source = fbSourceForCompositionType(mCompositionType);
- return mSource[source]->cancelBuffer(
- mapProducer2SourceSlot(source, pslot), fence);
- }
- int VirtualDisplaySurface::query(int what, int* value) {
- switch (what) {
- case NATIVE_WINDOW_WIDTH:
- *value = mSinkBufferWidth;
- break;
- case NATIVE_WINDOW_HEIGHT:
- *value = mSinkBufferHeight;
- break;
- default:
- return mSource[SOURCE_SINK]->query(what, value);
- }
- return NO_ERROR;
- }
- status_t VirtualDisplaySurface::connect(const sp<IProducerListener>& listener,
- int api, bool producerControlledByApp,
- QueueBufferOutput* output) {
- QueueBufferOutput qbo;
- status_t result = mSource[SOURCE_SINK]->connect(listener, api,
- producerControlledByApp, &qbo);
- if (result == NO_ERROR) {
- updateQueueBufferOutput(qbo);
- *output = mQueueBufferOutput;
- }
- return result;
- }
- status_t VirtualDisplaySurface::disconnect(int api) {
- return mSource[SOURCE_SINK]->disconnect(api);
- }
- status_t VirtualDisplaySurface::setSidebandStream(const sp<NativeHandle>& /*stream*/) {
- return INVALID_OPERATION;
- }
- void VirtualDisplaySurface::allocateBuffers(bool /* async */,
- uint32_t /* width */, uint32_t /* height */, PixelFormat /* format */,
- uint32_t /* usage */) {
- // TODO: Should we actually allocate buffers for a virtual display?
- }
- status_t VirtualDisplaySurface::allowAllocation(bool /* allow */) {
- return INVALID_OPERATION;
- }
- status_t VirtualDisplaySurface::setGenerationNumber(uint32_t /* generation */) {
- ALOGE("setGenerationNumber not supported on VirtualDisplaySurface");
- return INVALID_OPERATION;
- }
- String8 VirtualDisplaySurface::getConsumerName() const {
- return String8("VirtualDisplaySurface");
- }
- void VirtualDisplaySurface::updateQueueBufferOutput(
- const QueueBufferOutput& qbo) {
- uint32_t w, h, transformHint, numPendingBuffers;
- qbo.deflate(&w, &h, &transformHint, &numPendingBuffers);
- mQueueBufferOutput.inflate(w, h, 0, numPendingBuffers);
- }
- void VirtualDisplaySurface::resetPerFrameState() {
- mCompositionType = COMPOSITION_UNKNOWN;
- mFbFence = Fence::NO_FENCE;
- mOutputFence = Fence::NO_FENCE;
- mOutputProducerSlot = -1;
- mFbProducerSlot = -1;
- }
- status_t VirtualDisplaySurface::refreshOutputBuffer() {
- if (mOutputProducerSlot >= 0) {
- mSource[SOURCE_SINK]->cancelBuffer(
- mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot),
- mOutputFence);
- }
- int sslot;
- status_t result = dequeueBuffer(SOURCE_SINK, mOutputFormat, mOutputUsage,
- &sslot, &mOutputFence);
- if (result < 0)
- return result;
- mOutputProducerSlot = mapSource2ProducerSlot(SOURCE_SINK, sslot);
- // On GLES-only frames, we don't have the right output buffer acquire fence
- // until after GLES calls queueBuffer(). So here we just set the buffer
- // (for use in HWC prepare) but not the fence; we'll call this again with
- // the proper fence once we have it.
- result = mHwc.setOutputBuffer(mDisplayId, Fence::NO_FENCE,
- mProducerBuffers[mOutputProducerSlot]);
- return result;
- }
- // This slot mapping function is its own inverse, so two copies are unnecessary.
- // Both are kept to make the intent clear where the function is called, and for
- // the (unlikely) chance that we switch to a different mapping function.
- int VirtualDisplaySurface::mapSource2ProducerSlot(Source source, int sslot) {
- if (source == SOURCE_SCRATCH) {
- return BufferQueue::NUM_BUFFER_SLOTS - sslot - 1;
- } else {
- return sslot;
- }
- }
- int VirtualDisplaySurface::mapProducer2SourceSlot(Source source, int pslot) {
- return mapSource2ProducerSlot(source, pslot);
- }
- VirtualDisplaySurface::Source
- VirtualDisplaySurface::fbSourceForCompositionType(CompositionType type) {
- return type == COMPOSITION_MIXED ? SOURCE_SCRATCH : SOURCE_SINK;
- }
- const char* VirtualDisplaySurface::dbgStateStr() const {
- switch (mDbgState) {
- case DBG_STATE_IDLE: return "IDLE";
- case DBG_STATE_PREPARED: return "PREPARED";
- case DBG_STATE_GLES: return "GLES";
- case DBG_STATE_GLES_DONE: return "GLES_DONE";
- case DBG_STATE_HWC: return "HWC";
- default: return "INVALID";
- }
- }
- const char* VirtualDisplaySurface::dbgSourceStr(Source s) {
- switch (s) {
- case SOURCE_SINK: return "SINK";
- case SOURCE_SCRATCH: return "SCRATCH";
- default: return "INVALID";
- }
- }
- void VirtualDisplaySurface::setOutputUsage(uint32_t usage) {
- mOutputUsage = usage;
- }
- // ---------------------------------------------------------------------------
- } // namespace android
- // ---------------------------------------------------------------------------
|