Add TextureView support to new renderer/reorderer
bug:22480459
Change-Id: I2e4c0bc6b904706132f3f5087ededc9cac9b40fb
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 0d1ee46..a1ea9ce 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -2,7 +2,7 @@
include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-HWUI_NEW_OPS := false
+HWUI_NEW_OPS := true
hwui_src_files := \
font/CacheTexture.cpp \
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index a892b1b..0f0768f 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -735,6 +735,20 @@
}
}
+void BakedOpDispatcher::onTextureLayerOp(BakedOpRenderer& renderer, const TextureLayerOp& op, const BakedOpState& state) {
+ const bool tryToSnap = !op.layer->getForceFilter();
+ float alpha = (op.layer->getAlpha() / 255.0f) * state.alpha;
+ Glop glop;
+ GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
+ .setRoundRectClipState(state.roundRectClipState)
+ .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
+ .setFillTextureLayer(*(op.layer), alpha)
+ .setTransform(state.computedState.transform, TransformFlags::None)
+ .setModelViewMapUnitToRectOptionalSnap(tryToSnap, Rect(op.layer->getWidth(), op.layer->getHeight()))
+ .build();
+ renderer.renderGlop(state, glop);
+}
+
void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state) {
OffscreenBuffer* buffer = *op.layerHandle;
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 7038334..f833a54 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -53,8 +53,7 @@
SkRefCnt_SafeAssign(mColorFilter, colorFilter);
}
-bool DeferredLayerUpdater::apply() {
- bool success = true;
+void DeferredLayerUpdater::apply() {
// These properties are applied the same to both layer types
mLayer->setColorFilter(mColorFilter);
mLayer->setAlpha(mAlpha, mMode);
@@ -73,7 +72,6 @@
setTransform(nullptr);
}
}
- return success;
}
void DeferredLayerUpdater::doUpdateTexImage() {
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index df7c594..6a3c890 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -77,13 +77,13 @@
ANDROID_API void setPaint(const SkPaint* paint);
- ANDROID_API bool apply();
+ void apply();
Layer* backingLayer() {
return mLayer;
}
- ANDROID_API void detachSurfaceTexture();
+ void detachSurfaceTexture();
private:
// Generic properties
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index e9e5d81..0cf643f 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -287,7 +287,7 @@
}
void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
- bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform) {
+ bool isOpaque, bool forceFilter, GLenum renderTarget, const float* textureTransform) {
if (layer) {
layer->setBlend(!isOpaque);
layer->setForceFilter(forceFilter);
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index e4a54b0..38c3705 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -59,7 +59,7 @@
static Layer* createRenderLayer(RenderState& renderState, uint32_t width, uint32_t height);
static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
- bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform);
+ bool isOpaque, bool forceFilter, GLenum renderTarget, const float* textureTransform);
static void destroyLayer(Layer* layer);
static bool copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap);
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index c017638..1c25f26 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -139,9 +139,11 @@
}
void multiply(const Matrix4& v) {
- Matrix4 u;
- u.loadMultiply(*this, v);
- *this = u;
+ if (!v.isIdentity()) {
+ Matrix4 u;
+ u.loadMultiply(*this, v);
+ *this = u;
+ }
}
void multiply(float v);
diff --git a/libs/hwui/OpReorderer.cpp b/libs/hwui/OpReorderer.cpp
index e147211..bdc8f68 100644
--- a/libs/hwui/OpReorderer.cpp
+++ b/libs/hwui/OpReorderer.cpp
@@ -783,7 +783,7 @@
void OpReorderer::deferFunctorOp(const FunctorOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
- currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::None);
+ currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Functor);
}
void OpReorderer::deferLinesOp(const LinesOp& op) {
@@ -871,6 +871,12 @@
currentLayer().deferUnmergeableOp(mAllocator, bakedState, textBatchId(*(op.paint)));
}
+void OpReorderer::deferTextureLayerOp(const TextureLayerOp& op) {
+ BakedOpState* bakedState = tryBakeOpState(op);
+ if (!bakedState) return; // quick rejected
+ currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::TextureLayer);
+}
+
void OpReorderer::saveForLayer(uint32_t layerWidth, uint32_t layerHeight,
float contentTranslateX, float contentTranslateY,
const Rect& repaintRect,
diff --git a/libs/hwui/OpReorderer.h b/libs/hwui/OpReorderer.h
index 35343c8b..dbbce8b 100644
--- a/libs/hwui/OpReorderer.h
+++ b/libs/hwui/OpReorderer.h
@@ -43,7 +43,6 @@
namespace OpBatchType {
enum {
- None = 0, // Don't batch
Bitmap,
MergedPatch,
AlphaVertices,
@@ -52,6 +51,8 @@
Text,
ColorText,
Shadow,
+ TextureLayer,
+ Functor,
Count // must be last
};
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index bb23005..cfdd0d2 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -63,6 +63,7 @@
U_OP_FN(SimpleRectsOp) \
M_OP_FN(TextOp) \
U_OP_FN(TextOnPathOp) \
+ U_OP_FN(TextureLayerOp) \
U_OP_FN(BeginLayerOp) \
U_OP_FN(EndLayerOp) \
U_OP_FN(LayerOp)
@@ -345,11 +346,17 @@
const float vOffset;
};
+struct TextureLayerOp : RecordedOp {
+ TextureLayerOp(BASE_PARAMS_PAINTLESS, Layer* layer)
+ : SUPER_PAINTLESS(TextureLayerOp)
+ , layer(layer) {}
+ Layer* layer;
+};
+
////////////////////////////////////////////////////////////////////////////////////////////////////
// Layers
////////////////////////////////////////////////////////////////////////////////////////////////////
-
/**
* Stateful operation! denotes the creation of an off-screen layer,
* and that commands following will render into it.
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 46ae790..f75d8d4 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -16,6 +16,7 @@
#include "RecordingCanvas.h"
+#include "DeferredLayerUpdater.h"
#include "RecordedOp.h"
#include "RenderNode.h"
@@ -542,6 +543,21 @@
}
}
+void RecordingCanvas::drawLayer(DeferredLayerUpdater* layerHandle) {
+ // We ref the DeferredLayerUpdater due to its thread-safe ref-counting semantics.
+ mDisplayList->ref(layerHandle);
+
+ Layer* layer = layerHandle->backingLayer();
+ Matrix4 totalTransform(*(mState.currentSnapshot()->transform));
+ totalTransform.multiply(layer->getTransform());
+
+ addOp(new (alloc()) TextureLayerOp(
+ Rect(layer->getWidth(), layer->getHeight()),
+ totalTransform,
+ mState.getRenderTargetClipBounds(),
+ layer));
+}
+
void RecordingCanvas::callDrawGLFunction(Functor* functor) {
mDisplayList->functors.push_back(functor);
addOp(new (alloc()) FunctorOp(
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index ce7d1350..48cc91a 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -36,7 +36,7 @@
namespace android {
namespace uirenderer {
-class OpReceiver;
+class DeferredLayerUpdater;
struct RecordedOp;
class RecordingCanvas: public Canvas, public CanvasStateClient {
@@ -59,6 +59,8 @@
mDeferredBarrierType = enableReorder
? DeferredBarrierType::OutOfOrder : DeferredBarrierType::InOrder;
}
+
+ void drawLayer(DeferredLayerUpdater* layerHandle);
void drawRenderNode(RenderNode* renderNode);
// TODO: rename for consistency
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index ca85dfb..4c58676 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -182,16 +182,6 @@
}
}
-void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater) {
-#if !HWUI_NEW_OPS
- bool success = layerUpdater->apply();
- LOG_ALWAYS_FATAL_IF(!success, "Failed to update layer!");
- if (layerUpdater->backingLayer()->deferredUpdateScheduled) {
- mCanvas->pushLayerUpdate(layerUpdater->backingLayer());
- }
-#endif
-}
-
static bool wasSkipped(FrameInfo* info) {
return info && ((*info)[FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame);
}
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index d36ce99..ca5aa5c 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -83,7 +83,6 @@
void setLightCenter(const Vector3& lightCenter);
void setOpaque(bool opaque);
void makeCurrent();
- void processLayerUpdate(DeferredLayerUpdater* layerUpdater);
void prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
int64_t syncQueued, RenderNode* target);
void draw();
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index ab860c7..e8b9725 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -117,7 +117,7 @@
Caches::getInstance().textureCache.resetMarkInUse(mContext);
for (size_t i = 0; i < mLayers.size(); i++) {
- mContext->processLayerUpdate(mLayers[i].get());
+ mLayers[i]->apply();
}
mLayers.clear();
mContext->prepareTree(info, mFrameInfo, mSyncQueued, mTargetNode);
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 4c8d23d..624f3bd 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -16,6 +16,9 @@
#include "TestUtils.h"
+#include "DeferredLayerUpdater.h"
+#include "LayerRenderer.h"
+
namespace android {
namespace uirenderer {
@@ -36,6 +39,22 @@
| (int)((startB + (int)(fraction * (endB - startB))));
}
+sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater(
+ renderthread::RenderThread& renderThread, uint32_t width, uint32_t height,
+ std::function<void(Matrix4*)> transformSetupCallback) {
+ bool isOpaque = true;
+ bool forceFilter = true;
+ GLenum renderTarget = GL_TEXTURE_EXTERNAL_OES;
+
+ Layer* layer = LayerRenderer::createTextureLayer(renderThread.renderState());
+ LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, forceFilter,
+ renderTarget, Matrix4::identity().data);
+ transformSetupCallback(&(layer->getTransform()));
+
+ sp<DeferredLayerUpdater> layerUpdater = new DeferredLayerUpdater(layer);
+ return layerUpdater;
+}
+
void TestUtils::drawTextToCanvas(TestCanvas* canvas, const char* text,
const SkPaint& paint, float x, float y) {
// drawing text requires GlyphID TextEncoding (which JNI layer would have done)
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 4f84474..d37fad4 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -113,6 +113,10 @@
return bitmap;
}
+ static sp<DeferredLayerUpdater> createTextureLayerUpdater(
+ renderthread::RenderThread& renderThread, uint32_t width, uint32_t height,
+ std::function<void(Matrix4*)> transformSetupCallback);
+
template<class CanvasType>
static std::unique_ptr<DisplayList> createDisplayList(int width, int height,
std::function<void(CanvasType& canvas)> canvasCallback) {
diff --git a/libs/hwui/tests/unit/OpReordererTests.cpp b/libs/hwui/tests/unit/OpReordererTests.cpp
index ab0cc87..288f8af 100644
--- a/libs/hwui/tests/unit/OpReordererTests.cpp
+++ b/libs/hwui/tests/unit/OpReordererTests.cpp
@@ -17,6 +17,7 @@
#include <gtest/gtest.h>
#include <BakedOpState.h>
+#include <DeferredLayerUpdater.h>
#include <LayerUpdateQueue.h>
#include <OpReorderer.h>
#include <RecordedOp.h>
@@ -281,6 +282,39 @@
<< "Expect number of ops = 2 * loop count";
}
+RENDERTHREAD_TEST(OpReorderer, textureLayer) {
+ class TextureLayerTestRenderer : public TestRendererBase {
+ public:
+ void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(0, mIndex++);
+ EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipRect);
+ EXPECT_EQ(Rect(50, 50, 105, 105), state.computedState.clippedBounds);
+
+ Matrix4 expected;
+ expected.loadTranslate(5, 5, 0);
+ EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform);
+ }
+ };
+
+ auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
+ [](Matrix4* transform) {
+ transform->loadTranslate(5, 5, 0);
+ });
+
+ auto node = TestUtils::createNode(0, 0, 200, 200,
+ [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.save(SkCanvas::kMatrixClip_SaveFlag);
+ canvas.clipRect(50, 50, 150, 150, SkRegion::kIntersect_Op);
+ canvas.drawLayer(layerUpdater.get());
+ canvas.restore();
+ });
+ OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ createSyncedNodeList(node), sLightCenter);
+ TextureLayerTestRenderer renderer;
+ reorderer.replayBakedOps<TestDispatcher>(renderer);
+ EXPECT_EQ(1, renderer.getIndex());
+}
+
TEST(OpReorderer, renderNode) {
class RenderNodeTestRenderer : public TestRendererBase {
public:
@@ -307,16 +341,15 @@
canvas.drawRect(0, 0, 100, 100, paint);
});
- RenderNode* childPtr = child.get();
auto parent = TestUtils::createNode(0, 0, 200, 200,
- [childPtr](RenderProperties& props, RecordingCanvas& canvas) {
+ [&child](RenderProperties& props, RecordingCanvas& canvas) {
SkPaint paint;
paint.setColor(SK_ColorDKGRAY);
canvas.drawRect(0, 0, 200, 200, paint);
canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
canvas.translate(40, 40);
- canvas.drawRenderNode(childPtr);
+ canvas.drawRenderNode(child.get());
canvas.restore();
});