Move image creation out of latchBuffer().
GLImage creation isn't necessary until an external texture needs to be
bound.
This also removes the BufferLayerConsumer::Image class, as it's not
really necessary now that image creation is deferred until the external
texture needs to be bound.
Bug: 116277151
Change-Id: Id9420941e9cf7df11233b427c7a98a947f9738d8
Test: SurfaceFlinger_test, libsurfaceflinger_unittest, go/wm-smoke
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index f499f06..8bd98b7 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -232,8 +232,7 @@
return;
}
- auto buffer = mPendingRelease.isPending ? mPendingRelease.graphicBuffer
- : mCurrentTextureImage->graphicBuffer();
+ auto buffer = mPendingRelease.isPending ? mPendingRelease.graphicBuffer : mCurrentTextureBuffer;
auto err = addReleaseFence(slot, buffer, fence);
if (err != OK) {
BLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err);
@@ -269,10 +268,9 @@
}
// If item->mGraphicBuffer is not null, this buffer has not been acquired
- // before, so any prior EglImage created is using a stale buffer. This
- // replaces any old EglImage with a new one (using the new buffer).
+ // before.
if (item->mGraphicBuffer != nullptr) {
- mImages[item->mSlot] = new Image(item->mGraphicBuffer, mRE);
+ mImages[item->mSlot] = nullptr;
}
return NO_ERROR;
@@ -299,19 +297,18 @@
}
BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
- mCurrentTextureImage != nullptr ? mCurrentTextureImage->graphicBufferHandle() : 0,
- slot, mSlots[slot].mGraphicBuffer->handle);
+ mCurrentTextureBuffer != nullptr ? mCurrentTextureBuffer->handle : 0, slot,
+ mSlots[slot].mGraphicBuffer->handle);
// Hang onto the pointer so that it isn't freed in the call to
// releaseBufferLocked() if we're in shared buffer mode and both buffers are
// the same.
- sp<Image> nextTextureImage = mImages[slot];
+ sp<GraphicBuffer> nextTextureBuffer = mSlots[slot].mGraphicBuffer;
// release old buffer
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
if (pendingRelease == nullptr) {
- status_t status =
- releaseBufferLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer());
+ status_t status = releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer);
if (status < NO_ERROR) {
BLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status),
status);
@@ -320,14 +317,15 @@
}
} else {
pendingRelease->currentTexture = mCurrentTexture;
- pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
+ pendingRelease->graphicBuffer = mCurrentTextureBuffer;
pendingRelease->isPending = true;
}
}
// Update the BufferLayerConsumer state.
mCurrentTexture = slot;
- mCurrentTextureImage = nextTextureImage;
+ mCurrentTextureBuffer = nextTextureBuffer;
+ mCurrentTextureImageFreed = nullptr;
mCurrentCrop = item.mCrop;
mCurrentTransform = item.mTransform;
mCurrentScalingMode = item.mScalingMode;
@@ -348,22 +346,46 @@
status_t BufferLayerConsumer::bindTextureImageLocked() {
ATRACE_CALL();
+
mRE.checkErrors();
- if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == nullptr) {
+ // It is possible for the current slot's buffer to be freed before a new one
+ // is bound. In that scenario we still want to bind the image.
+ if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureBuffer == nullptr) {
BLC_LOGE("bindTextureImage: no currently-bound texture");
mRE.bindExternalTextureImage(mTexName, *mRE.createImage());
return NO_INIT;
}
- status_t err = mCurrentTextureImage->createIfNeeded();
- if (err != NO_ERROR) {
- BLC_LOGW("bindTextureImage: can't create image on slot=%d", mCurrentTexture);
- mRE.bindExternalTextureImage(mTexName, *mRE.createImage());
- return UNKNOWN_ERROR;
+ renderengine::Image* imageToRender;
+
+ // mCurrentTextureImageFreed is non-null iff mCurrentTexture ==
+ // BufferQueue::INVALID_BUFFER_SLOT, so we can omit that check.
+ if (mCurrentTextureImageFreed) {
+ imageToRender = mCurrentTextureImageFreed.get();
+ } else if (mImages[mCurrentTexture]) {
+ imageToRender = mImages[mCurrentTexture].get();
+ } else {
+ std::unique_ptr<renderengine::Image> image = mRE.createImage();
+ bool success = image->setNativeWindowBuffer(mCurrentTextureBuffer->getNativeBuffer(),
+ mCurrentTextureBuffer->getUsage() &
+ GRALLOC_USAGE_PROTECTED);
+ if (!success) {
+ BLC_LOGE("bindTextureImage: Failed to create image. size=%ux%u st=%u usage=%#" PRIx64
+ " fmt=%d",
+ mCurrentTextureBuffer->getWidth(), mCurrentTextureBuffer->getHeight(),
+ mCurrentTextureBuffer->getStride(), mCurrentTextureBuffer->getUsage(),
+ mCurrentTextureBuffer->getPixelFormat());
+ BLC_LOGW("bindTextureImage: can't create image on slot=%d", mCurrentTexture);
+ mRE.bindExternalTextureImage(mTexName, *image);
+ return UNKNOWN_ERROR;
+ }
+ imageToRender = image.get();
+ // Cache the image here so that we can reuse it.
+ mImages[mCurrentTexture] = std::move(image);
}
- mRE.bindExternalTextureImage(mTexName, mCurrentTextureImage->image());
+ mRE.bindExternalTextureImage(mTexName, *imageToRender);
// Wait for the new buffer to be ready.
return doFenceWaitLocked();
@@ -380,8 +402,7 @@
return UNKNOWN_ERROR;
}
status_t err =
- addReleaseFenceLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
- releaseFence);
+ addReleaseFenceLocked(mCurrentTexture, mCurrentTextureBuffer, releaseFence);
if (err != OK) {
BLC_LOGE("syncForReleaseLocked: error adding release fence: "
"%s (%d)",
@@ -408,24 +429,22 @@
bool needsRecompute = mFilteringEnabled != enabled;
mFilteringEnabled = enabled;
- if (needsRecompute && mCurrentTextureImage == nullptr) {
- BLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == nullptr");
+ if (needsRecompute && mCurrentTextureBuffer == nullptr) {
+ BLC_LOGD("setFilteringEnabled called with mCurrentTextureBuffer == nullptr");
}
- if (needsRecompute && mCurrentTextureImage != nullptr) {
+ if (needsRecompute && mCurrentTextureBuffer != nullptr) {
computeCurrentTransformMatrixLocked();
}
}
void BufferLayerConsumer::computeCurrentTransformMatrixLocked() {
BLC_LOGV("computeCurrentTransformMatrixLocked");
- sp<GraphicBuffer> buf =
- (mCurrentTextureImage == nullptr) ? nullptr : mCurrentTextureImage->graphicBuffer();
- if (buf == nullptr) {
+ if (mCurrentTextureBuffer == nullptr) {
BLC_LOGD("computeCurrentTransformMatrixLocked: "
- "mCurrentTextureImage is nullptr");
+ "mCurrentTextureBuffer is nullptr");
}
- GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, buf, mCurrentCrop,
+ GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, mCurrentTextureBuffer, mCurrentCrop,
mCurrentTransform, mFilteringEnabled);
}
@@ -474,7 +493,7 @@
*outSlot = mCurrentTexture;
}
- return (mCurrentTextureImage == nullptr) ? nullptr : mCurrentTextureImage->graphicBuffer();
+ return mCurrentTextureBuffer;
}
Rect BufferLayerConsumer::getCurrentCrop() const {
@@ -509,7 +528,6 @@
BLC_LOGE("doFenceWait: RenderEngine is not current");
return INVALID_OPERATION;
}
-
if (mCurrentFence->isValid()) {
if (mRE.useWaitSync()) {
base::unique_fd fenceFd(mCurrentFence->dup());
@@ -537,8 +555,10 @@
BLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
if (slotIndex == mCurrentTexture) {
mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
+ mCurrentTextureImageFreed = std::move(mImages[slotIndex]);
+ } else {
+ mImages[slotIndex] = nullptr;
}
- mImages[slotIndex].clear();
ConsumerBase::freeBufferLocked(slotIndex);
}
@@ -577,7 +597,7 @@
void BufferLayerConsumer::abandonLocked() {
BLC_LOGV("abandonLocked");
- mCurrentTextureImage.clear();
+ mCurrentTextureBuffer.clear();
ConsumerBase::abandonLocked();
}
@@ -595,29 +615,4 @@
ConsumerBase::dumpLocked(result, prefix);
}
-BufferLayerConsumer::Image::Image(sp<GraphicBuffer> graphicBuffer,
- renderengine::RenderEngine& engine)
- : mGraphicBuffer(graphicBuffer),
- mImage{engine.createImage()},
- mCreated(false),
- mCropWidth(0),
- mCropHeight(0) {}
-
-BufferLayerConsumer::Image::~Image() = default;
-
-status_t BufferLayerConsumer::Image::createIfNeeded() {
- if (mCreated) return OK;
-
- mCreated = mImage->setNativeWindowBuffer(mGraphicBuffer->getNativeBuffer(),
- mGraphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
- if (!mCreated) {
- const sp<GraphicBuffer>& buffer = mGraphicBuffer;
- ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
- buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
- buffer->getPixelFormat());
- }
-
- return mCreated ? OK : UNKNOWN_ERROR;
-}
-
}; // namespace android