Merge "Fix layer damage and clipping for Text shadows" into nyc-dev

This commit is contained in:
Chris Craik
2016-03-31 17:08:03 +00:00
committed by Android (Google) Code Review
6 changed files with 55 additions and 5 deletions

View File

@@ -195,7 +195,7 @@ void BakedOpDispatcher::onMergedPatchOps(BakedOpRenderer& renderer,
} }
static void renderTextShadow(BakedOpRenderer& renderer, FontRenderer& fontRenderer, static void renderTextShadow(BakedOpRenderer& renderer, FontRenderer& fontRenderer,
const TextOp& op, const BakedOpState& state) { const TextOp& op, const BakedOpState& textOpState) {
renderer.caches().textureState().activateTexture(0); renderer.caches().textureState().activateTexture(0);
PaintUtils::TextShadow textShadow; PaintUtils::TextShadow textShadow;
@@ -216,13 +216,41 @@ static void renderTextShadow(BakedOpRenderer& renderer, FontRenderer& fontRender
Glop glop; Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop) GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
.setRoundRectClipState(state.roundRectClipState) .setRoundRectClipState(textOpState.roundRectClipState)
.setMeshTexturedUnitQuad(nullptr) .setMeshTexturedUnitQuad(nullptr)
.setFillShadowTexturePaint(*texture, textShadow.color, *op.paint, state.alpha) .setFillShadowTexturePaint(*texture, textShadow.color, *op.paint, textOpState.alpha)
.setTransform(state.computedState.transform, TransformFlags::None) .setTransform(textOpState.computedState.transform, TransformFlags::None)
.setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width(), sy + texture->height())) .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width(), sy + texture->height()))
.build(); .build();
renderer.renderGlop(state, glop);
// Compute damage bounds and clip (since may differ from those in textOpState).
// Bounds should be same as text op, but with dx/dy offset and radius outset
// applied in local space.
auto& transform = textOpState.computedState.transform;
Rect shadowBounds = op.unmappedBounds; // STROKE
const bool expandForStroke = op.paint->getStyle() != SkPaint::kFill_Style;
if (expandForStroke) {
shadowBounds.outset(op.paint->getStrokeWidth() * 0.5f);
}
shadowBounds.translate(textShadow.dx, textShadow.dy);
shadowBounds.outset(textShadow.radius, textShadow.radius);
transform.mapRect(shadowBounds);
if (CC_UNLIKELY(expandForStroke &&
(!transform.isPureTranslate() || op.paint->getStrokeWidth() < 1.0f))) {
shadowBounds.outset(0.5f);
}
auto clipState = textOpState.computedState.clipState;
if (clipState->mode != ClipMode::Rectangle
|| !clipState->rect.contains(shadowBounds)) {
// need clip, so pass it and clip bounds
shadowBounds.doIntersect(clipState->rect);
} else {
// don't need clip, ignore
clipState = nullptr;
}
renderer.renderGlop(&shadowBounds, clipState, glop);
} }
enum class TextRenderType { enum class TextRenderType {

View File

@@ -163,11 +163,13 @@ public:
GLenum dst; GLenum dst;
} blend; } blend;
#if !HWUI_NEW_OPS
/** /**
* Bounds of the drawing command in layer space. Only mapped into layer * Bounds of the drawing command in layer space. Only mapped into layer
* space once GlopBuilder::build() is called. * space once GlopBuilder::build() is called.
*/ */
Rect bounds; // TODO: remove for HWUI_NEW_OPS Rect bounds; // TODO: remove for HWUI_NEW_OPS
#endif
/** /**
* Additional render state to enumerate: * Additional render state to enumerate:

View File

@@ -492,7 +492,9 @@ GlopBuilder& GlopBuilder::setModelViewMapUnitToRect(const Rect destination) {
mOutGlop->transform.modelView.loadTranslate(destination.left, destination.top, 0.0f); mOutGlop->transform.modelView.loadTranslate(destination.left, destination.top, 0.0f);
mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f); mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f);
#if !HWUI_NEW_OPS
mOutGlop->bounds = destination; mOutGlop->bounds = destination;
#endif
return *this; return *this;
} }
@@ -516,7 +518,9 @@ GlopBuilder& GlopBuilder::setModelViewMapUnitToRectSnap(const Rect destination)
mOutGlop->transform.modelView.loadTranslate(left, top, 0.0f); mOutGlop->transform.modelView.loadTranslate(left, top, 0.0f);
mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f); mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f);
#if !HWUI_NEW_OPS
mOutGlop->bounds = destination; mOutGlop->bounds = destination;
#endif
return *this; return *this;
} }
@@ -524,8 +528,10 @@ GlopBuilder& GlopBuilder::setModelViewOffsetRect(float offsetX, float offsetY, c
TRIGGER_STAGE(kModelViewStage); TRIGGER_STAGE(kModelViewStage);
mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f); mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f);
#if !HWUI_NEW_OPS
mOutGlop->bounds = source; mOutGlop->bounds = source;
mOutGlop->bounds.translate(offsetX, offsetY); mOutGlop->bounds.translate(offsetX, offsetY);
#endif
return *this; return *this;
} }
@@ -545,8 +551,10 @@ GlopBuilder& GlopBuilder::setModelViewOffsetRectSnap(float offsetX, float offset
} }
mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f); mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f);
#if !HWUI_NEW_OPS
mOutGlop->bounds = source; mOutGlop->bounds = source;
mOutGlop->bounds.translate(offsetX, offsetY); mOutGlop->bounds.translate(offsetX, offsetY);
#endif
return *this; return *this;
} }
@@ -643,7 +651,9 @@ void GlopBuilder::build() {
// Final step: populate program and map bounds into render target space // Final step: populate program and map bounds into render target space
mOutGlop->fill.program = mCaches.programCache.get(mDescription); mOutGlop->fill.program = mCaches.programCache.get(mDescription);
#if !HWUI_NEW_OPS
mOutGlop->transform.meshTransform().mapRect(mOutGlop->bounds); mOutGlop->transform.meshTransform().mapRect(mOutGlop->bounds);
#endif
} }
void GlopBuilder::dump(const Glop& glop) { void GlopBuilder::dump(const Glop& glop) {
@@ -683,7 +693,9 @@ void GlopBuilder::dump(const Glop& glop) {
ALOGD_IF(glop.roundRectClipState, "Glop RRCS %p", glop.roundRectClipState); ALOGD_IF(glop.roundRectClipState, "Glop RRCS %p", glop.roundRectClipState);
ALOGD("Glop blend %d %d", glop.blend.src, glop.blend.dst); ALOGD("Glop blend %d %d", glop.blend.src, glop.blend.dst);
#if !HWUI_NEW_OPS
ALOGD("Glop bounds " RECT_STRING, RECT_ARGS(glop.bounds)); ALOGD("Glop bounds " RECT_STRING, RECT_ARGS(glop.bounds));
#endif
} }
} /* namespace uirenderer */ } /* namespace uirenderer */

View File

@@ -1413,7 +1413,9 @@ void OpenGLRenderer::renderGlop(const Glop& glop, GlopRenderType type) {
if (type == GlopRenderType::Standard && !mRenderState.stencil().isWriteEnabled()) { if (type == GlopRenderType::Standard && !mRenderState.stencil().isWriteEnabled()) {
// TODO: specify more clearly when a draw should dirty the layer. // TODO: specify more clearly when a draw should dirty the layer.
// is writing to the stencil the only time we should ignore this? // is writing to the stencil the only time we should ignore this?
#if !HWUI_NEW_OPS
dirtyLayer(glop.bounds.left, glop.bounds.top, glop.bounds.right, glop.bounds.bottom); dirtyLayer(glop.bounds.left, glop.bounds.top, glop.bounds.right, glop.bounds.bottom);
#endif
mDirty = true; mDirty = true;
} }
} }

View File

@@ -85,7 +85,9 @@ RENDERTHREAD_TEST(BakedOpDispatcher, onArc_position) {
<< "Should see conservative offset from PathCache::computeBounds"; << "Should see conservative offset from PathCache::computeBounds";
Rect expectedBounds(10, 15, 20, 25); Rect expectedBounds(10, 15, 20, 25);
expectedBounds.outset(expectedOffset); expectedBounds.outset(expectedOffset);
#if !HWUI_NEW_OPS
EXPECT_EQ(expectedBounds, glop.bounds) << "bounds outset by stroke 'offset'"; EXPECT_EQ(expectedBounds, glop.bounds) << "bounds outset by stroke 'offset'";
#endif
Matrix4 expectedModelView; Matrix4 expectedModelView;
expectedModelView.loadTranslate(10 - expectedOffset, 15 - expectedOffset, 0); expectedModelView.loadTranslate(10 - expectedOffset, 15 - expectedOffset, 0);
expectedModelView.scale(10 + 2 * expectedOffset, 10 + 2 * expectedOffset, 1); expectedModelView.scale(10 + 2 * expectedOffset, 10 + 2 * expectedOffset, 1);

View File

@@ -85,7 +85,9 @@ static void expectTransformEq(Glop::Transform& expectedTransform, Glop::Transfor
} }
static void expectGlopEq(Glop& expectedGlop, Glop& builtGlop) { static void expectGlopEq(Glop& expectedGlop, Glop& builtGlop) {
#if !HWUI_NEW_OPS
EXPECT_EQ(expectedGlop.bounds, builtGlop.bounds); EXPECT_EQ(expectedGlop.bounds, builtGlop.bounds);
#endif
expectBlendEq(expectedGlop.blend, builtGlop.blend); expectBlendEq(expectedGlop.blend, builtGlop.blend);
expectFillEq(expectedGlop.fill, builtGlop.fill); expectFillEq(expectedGlop.fill, builtGlop.fill);
expectMeshEq(expectedGlop.mesh, builtGlop.mesh); expectMeshEq(expectedGlop.mesh, builtGlop.mesh);
@@ -136,7 +138,9 @@ RENDERTHREAD_TEST(GlopBuilder, rectSnapTest) {
// unit quad also should be translate by additional (0.3, 0.3) to snap to exact pixels. // unit quad also should be translate by additional (0.3, 0.3) to snap to exact pixels.
goldenGlop->transform.modelView.loadTranslate(1.3, 1.3, 0); goldenGlop->transform.modelView.loadTranslate(1.3, 1.3, 0);
goldenGlop->transform.modelView.scale(99, 99, 1); goldenGlop->transform.modelView.scale(99, 99, 1);
#if !HWUI_NEW_OPS
goldenGlop->bounds = android::uirenderer::Rect(1.70, 1.70, 100.70, 100.70); goldenGlop->bounds = android::uirenderer::Rect(1.70, 1.70, 100.70, 100.70);
#endif
goldenGlop->transform.canvas = simpleTranslate; goldenGlop->transform.canvas = simpleTranslate;
goldenGlop->fill.texture.filter = GL_NEAREST; goldenGlop->fill.texture.filter = GL_NEAREST;
expectGlopEq(*goldenGlop, glop); expectGlopEq(*goldenGlop, glop);