Add TextureView support to new renderer/reorderer
bug:22480459 Change-Id: I2e4c0bc6b904706132f3f5087ededc9cac9b40fb
This commit is contained in:
@@ -2,7 +2,7 @@ LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
|
||||
|
||||
HWUI_NEW_OPS := false
|
||||
HWUI_NEW_OPS := true
|
||||
|
||||
hwui_src_files := \
|
||||
font/CacheTexture.cpp \
|
||||
|
||||
@@ -735,6 +735,20 @@ void BakedOpDispatcher::onTextOnPathOp(BakedOpRenderer& renderer, const TextOnPa
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -53,8 +53,7 @@ void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
|
||||
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 @@ bool DeferredLayerUpdater::apply() {
|
||||
setTransform(nullptr);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void DeferredLayerUpdater::doUpdateTexImage() {
|
||||
|
||||
@@ -77,13 +77,13 @@ public:
|
||||
|
||||
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
|
||||
|
||||
@@ -287,7 +287,7 @@ Layer* LayerRenderer::createTextureLayer(RenderState& renderState) {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
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);
|
||||
|
||||
|
||||
@@ -139,9 +139,11 @@ public:
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -783,7 +783,7 @@ void OpReorderer::deferCirclePropsOp(const CirclePropsOp& op) {
|
||||
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 @@ void OpReorderer::deferTextOnPathOp(const TextOnPathOp& op) {
|
||||
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,
|
||||
|
||||
@@ -43,7 +43,6 @@ typedef const void* mergeid_t;
|
||||
|
||||
namespace OpBatchType {
|
||||
enum {
|
||||
None = 0, // Don't batch
|
||||
Bitmap,
|
||||
MergedPatch,
|
||||
AlphaVertices,
|
||||
@@ -52,6 +51,8 @@ namespace OpBatchType {
|
||||
Text,
|
||||
ColorText,
|
||||
Shadow,
|
||||
TextureLayer,
|
||||
Functor,
|
||||
|
||||
Count // must be last
|
||||
};
|
||||
|
||||
@@ -63,6 +63,7 @@ struct Vertex;
|
||||
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 @@ struct TextOnPathOp : RecordedOp {
|
||||
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.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "RecordingCanvas.h"
|
||||
|
||||
#include "DeferredLayerUpdater.h"
|
||||
#include "RecordedOp.h"
|
||||
#include "RenderNode.h"
|
||||
|
||||
@@ -542,6 +543,21 @@ void RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
|
||||
}
|
||||
}
|
||||
|
||||
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(
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
class OpReceiver;
|
||||
class DeferredLayerUpdater;
|
||||
struct RecordedOp;
|
||||
|
||||
class RecordingCanvas: public Canvas, public CanvasStateClient {
|
||||
@@ -59,6 +59,8 @@ public:
|
||||
mDeferredBarrierType = enableReorder
|
||||
? DeferredBarrierType::OutOfOrder : DeferredBarrierType::InOrder;
|
||||
}
|
||||
|
||||
void drawLayer(DeferredLayerUpdater* layerHandle);
|
||||
void drawRenderNode(RenderNode* renderNode);
|
||||
|
||||
// TODO: rename for consistency
|
||||
|
||||
@@ -182,16 +182,6 @@ void CanvasContext::makeCurrent() {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,6 @@ public:
|
||||
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();
|
||||
|
||||
@@ -117,7 +117,7 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
|
||||
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);
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
#include "TestUtils.h"
|
||||
|
||||
#include "DeferredLayerUpdater.h"
|
||||
#include "LayerRenderer.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
@@ -36,6 +39,22 @@ SkColor TestUtils::interpolateColor(float fraction, SkColor start, SkColor end)
|
||||
| (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)
|
||||
|
||||
@@ -113,6 +113,10 @@ public:
|
||||
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) {
|
||||
|
||||
@@ -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 @@ TEST(OpReorderer, textStrikethrough) {
|
||||
<< "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 @@ TEST(OpReorderer, renderNode) {
|
||||
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();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user