status_t VirtualDisplaySurface::advanceFrame() { if (mDisplayId < 0) return NO_ERROR; // When mForceHwcCopy is true, we override the composition type to MIXED. // Therefore, we need to check whether we are in this scenario and add // checks to satisfy the state machine requirements and reduce log spam. // In particular, by setting mForceHwcCopy we can now expect to get an // advanceFrame when composition type is MIXED and our previous state was // PREPARED or GLES_DONE. if (mForceHwcCopy && (mCompositionType == COMPOSITION_MIXED)) { bool isValidState = (mDbgState == DBG_STATE_PREPARED) || (mDbgState == DBG_STATE_GLES_DONE); VDS_LOGW_IF(!isValidState, "Unexpected advanceFrame() in %s state on %s frame", dbgStateStr(), (mDbgState == DBG_STATE_PREPARED) ? "HWC" : "GLES/MIXED"); } else 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) { // 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; }
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; }
status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool async, uint32_t w, uint32_t h, uint32_t format, uint32_t 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 != (uint32_t)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; mOutputUsage = 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::attachBuffer(int* /* outSlot */, const sp<GraphicBuffer>& /* buffer */) { VDS_LOGE("attachBuffer 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::detachBuffer(int /* slot */) { VDS_LOGE("detachBuffer is not available for VirtualDisplaySurface"); return INVALID_OPERATION; }