Decouple SurfaceTexture from HWUI
Remove all Skia and HWUI types from SurfaceTexture
implementation.
Move SurfaceTexture to libgui (ag/9578265).
Define private C++ API for SurfaceTexture, which is consumed
by DeferredLayerUpdater.
Move AutoBackendTextureRelease/Skia code from SurfaceTexture
to HWUI.
Test: pass CtsUiRenderingTestCases and CtsViewTestCases
Bug: 136263580
Change-Id: I3f971bb490f64a3ac0b2a66a89ba935bf7f08213
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index f300703..d6b516f 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -18,8 +18,15 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#include "AutoBackendTextureRelease.h"
+#include "Matrix.h"
+#include "Properties.h"
#include "renderstate/RenderState.h"
-#include "utils/PaintUtils.h"
+#include "renderthread/EglManager.h"
+#include "renderthread/RenderThread.h"
+#include "renderthread/VulkanManager.h"
+
+using namespace android::uirenderer::renderthread;
namespace android {
namespace uirenderer {
@@ -27,7 +34,6 @@
DeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState)
: mRenderState(renderState)
, mBlend(false)
- , mSurfaceTexture(nullptr)
, mTransform(nullptr)
, mGLContextAttached(false)
, mUpdateTexImage(false)
@@ -41,14 +47,12 @@
destroyLayer();
}
-void DeferredLayerUpdater::setSurfaceTexture(const sp<SurfaceTexture>& consumer) {
- if (consumer.get() != mSurfaceTexture.get()) {
- mSurfaceTexture = consumer;
+void DeferredLayerUpdater::setSurfaceTexture(AutoTextureRelease&& consumer) {
+ mSurfaceTexture = std::move(consumer);
- GLenum target = consumer->getCurrentTextureTarget();
- LOG_ALWAYS_FATAL_IF(target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES,
- "set unsupported SurfaceTexture with target %x", target);
- }
+ GLenum target = ASurfaceTexture_getCurrentTextureTarget(mSurfaceTexture.get());
+ LOG_ALWAYS_FATAL_IF(target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES,
+ "set unsupported SurfaceTexture with target %x", target);
}
void DeferredLayerUpdater::onContextDestroyed() {
@@ -61,13 +65,15 @@
}
if (mSurfaceTexture.get() && mGLContextAttached) {
- mSurfaceTexture->detachFromView();
+ ASurfaceTexture_releaseConsumerOwnership(mSurfaceTexture.get());
mGLContextAttached = false;
}
mLayer->postDecStrong();
mLayer = nullptr;
+
+ mImageSlots.clear();
}
void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
@@ -80,6 +86,35 @@
}
}
+static status_t createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence, EGLDisplay* display,
+ int* releaseFence, void* handle) {
+ *display = EGL_NO_DISPLAY;
+ RenderState* renderState = (RenderState*)handle;
+ status_t err;
+ if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
+ EglManager& eglManager = renderState->getRenderThread().eglManager();
+ *display = eglManager.eglDisplay();
+ err = eglManager.createReleaseFence(useFenceSync, eglFence, releaseFence);
+ } else {
+ err = renderState->getRenderThread().vulkanManager().createReleaseFence(
+ releaseFence, renderState->getRenderThread().getGrContext());
+ }
+ return err;
+}
+
+static status_t fenceWait(int fence, void* handle) {
+ // Wait on the producer fence for the buffer to be ready.
+ status_t err;
+ RenderState* renderState = (RenderState*)handle;
+ if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
+ err = renderState->getRenderThread().eglManager().fenceWait(fence);
+ } else {
+ err = renderState->getRenderThread().vulkanManager().fenceWait(
+ fence, renderState->getRenderThread().getGrContext());
+ }
+ return err;
+}
+
void DeferredLayerUpdater::apply() {
if (!mLayer) {
mLayer = new Layer(mRenderState, mColorFilter, mAlpha, mMode);
@@ -92,24 +127,33 @@
if (!mGLContextAttached) {
mGLContextAttached = true;
mUpdateTexImage = true;
- mSurfaceTexture->attachToView();
+ ASurfaceTexture_takeConsumerOwnership(mSurfaceTexture.get());
}
if (mUpdateTexImage) {
mUpdateTexImage = false;
- sk_sp<SkImage> layerImage;
- SkMatrix textureTransform;
- bool queueEmpty = true;
- // If the SurfaceTexture queue is in synchronous mode, need to discard all
- // but latest frame. Since we can't tell which mode it is in,
- // do this unconditionally.
- do {
- layerImage = mSurfaceTexture->dequeueImage(textureTransform, &queueEmpty,
- mRenderState);
- } while (layerImage.get() && (!queueEmpty));
- if (layerImage.get()) {
- // force filtration if buffer size != layer size
- bool forceFilter = mWidth != layerImage->width() || mHeight != layerImage->height();
- updateLayer(forceFilter, textureTransform, layerImage);
+ float transformMatrix[16];
+ android_dataspace dataspace;
+ int slot;
+ bool newContent = false;
+ // Note: ASurfaceTexture_dequeueBuffer discards all but the last frame. This
+ // is necessary if the SurfaceTexture queue is in synchronous mode, and we
+ // cannot tell which mode it is in.
+ AHardwareBuffer* hardwareBuffer = ASurfaceTexture_dequeueBuffer(
+ mSurfaceTexture.get(), &slot, &dataspace, transformMatrix, &newContent,
+ createReleaseFence, fenceWait, &mRenderState);
+
+ if (hardwareBuffer) {
+ sk_sp<SkImage> layerImage = mImageSlots[slot].createIfNeeded(
+ hardwareBuffer, dataspace, newContent,
+ mRenderState.getRenderThread().getGrContext());
+ if (layerImage.get()) {
+ SkMatrix textureTransform;
+ mat4(transformMatrix).copyTo(textureTransform);
+ // force filtration if buffer size != layer size
+ bool forceFilter =
+ mWidth != layerImage->width() || mHeight != layerImage->height();
+ updateLayer(forceFilter, textureTransform, layerImage);
+ }
}
}
@@ -121,7 +165,7 @@
}
void DeferredLayerUpdater::updateLayer(bool forceFilter, const SkMatrix& textureTransform,
- const sk_sp<SkImage>& layerImage) {
+ const sk_sp<SkImage>& layerImage) {
mLayer->setBlend(mBlend);
mLayer->setForceFilter(forceFilter);
mLayer->setSize(mWidth, mHeight);
@@ -136,5 +180,42 @@
}
}
+sk_sp<SkImage> DeferredLayerUpdater::ImageSlot::createIfNeeded(AHardwareBuffer* buffer,
+ android_dataspace dataspace,
+ bool forceCreate,
+ GrContext* context) {
+ if (!mTextureRelease || !mTextureRelease->getImage().get() || dataspace != mDataspace ||
+ forceCreate || mBuffer != buffer) {
+ if (buffer != mBuffer) {
+ clear();
+ }
+
+ if (!buffer) {
+ return nullptr;
+ }
+
+ if (!mTextureRelease) {
+ mTextureRelease = new AutoBackendTextureRelease(context, buffer);
+ } else {
+ mTextureRelease->newBufferContent(context);
+ }
+
+ mDataspace = dataspace;
+ mBuffer = buffer;
+ mTextureRelease->makeImage(buffer, dataspace, context);
+ }
+ return mTextureRelease ? mTextureRelease->getImage() : nullptr;
+}
+
+void DeferredLayerUpdater::ImageSlot::clear() {
+ if (mTextureRelease) {
+ // The following unref counteracts the initial mUsageCount of 1, set by default initializer.
+ mTextureRelease->unref(true);
+ mTextureRelease = nullptr;
+ }
+
+ mBuffer = nullptr;
+}
+
} /* namespace uirenderer */
} /* namespace android */