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::beginFrame() { if (mDisplayId < 0) return NO_ERROR; VDS_LOGW_IF(mDbgState != DBG_STATE_IDLE, "Unexpected beginFrame() in %s state", dbgStateStr()); mDbgState = DBG_STATE_BEGUN; uint32_t transformHint, numPendingBuffers; mQueueBufferOutput.deflate(&mSinkBufferWidth, &mSinkBufferHeight, &transformHint, &numPendingBuffers); 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; mOutputUsage = GRALLOC_USAGE_HW_COMPOSER; refreshOutputBuffer(); } return NO_ERROR; }
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; }