diff options
-rw-r--r-- | libs/hwui/DisplayListOp.h | 4 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.h | 8 | ||||
-rw-r--r-- | libs/hwui/Matrix.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/Matrix.h | 4 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 74 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 16 | ||||
-rw-r--r-- | libs/hwui/font/Font.cpp | 31 | ||||
-rw-r--r-- | libs/hwui/font/Font.h | 4 |
9 files changed, 81 insertions, 72 deletions
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 4a724772e413..d231907abb6c 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -1175,8 +1175,8 @@ public: SkPaint* paint = getPaint(renderer); FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint); const bool pureTranslate = state.mMatrix.isPureTranslate(); - fontRenderer.precache(paint, mText, mCount, - pureTranslate ? mat4::identity() : state.mMatrix); + const mat4 transform = renderer.findBestFontTransform(state.mMatrix); + fontRenderer.precache(paint, mText, mCount, transform); } virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level, diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 14c7c39b39e3..9aa961587ce6 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -92,11 +92,11 @@ void LayerRenderer::finish() { // who will invoke OpenGLRenderer::resume() } -GLint LayerRenderer::getTargetFbo() { +GLint LayerRenderer::getTargetFbo() const { return mLayer->getFbo(); } -bool LayerRenderer::suppressErrorChecks() { +bool LayerRenderer::suppressErrorChecks() const { return true; } @@ -104,7 +104,7 @@ bool LayerRenderer::suppressErrorChecks() { // Layer support /////////////////////////////////////////////////////////////////////////////// -bool LayerRenderer::hasLayer() { +bool LayerRenderer::hasLayer() const { return true; } @@ -116,7 +116,7 @@ void LayerRenderer::ensureStencilBuffer() { // Dirty region tracking /////////////////////////////////////////////////////////////////////////////// -Region* LayerRenderer::getRegion() { +Region* LayerRenderer::getRegion() const { if (getSnapshot()->flags & Snapshot::kFlagFboTarget) { return OpenGLRenderer::getRegion(); } diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h index 7a8bdc59d688..5f867317ecf6 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -65,10 +65,10 @@ public: protected: virtual void ensureStencilBuffer(); - virtual bool hasLayer(); - virtual Region* getRegion(); - virtual GLint getTargetFbo(); - virtual bool suppressErrorChecks(); + virtual bool hasLayer() const; + virtual Region* getRegion() const; + virtual GLint getTargetFbo() const; + virtual bool suppressErrorChecks() const; private: void generateMesh(); diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp index 204e8f564f11..6a5ea510482b 100644 --- a/libs/hwui/Matrix.cpp +++ b/libs/hwui/Matrix.cpp @@ -232,11 +232,11 @@ void Matrix4::copyTo(float* v) const { memcpy(v, data, sizeof(data)); } -float Matrix4::getTranslateX() { +float Matrix4::getTranslateX() const { return data[kTranslateX]; } -float Matrix4::getTranslateY() { +float Matrix4::getTranslateY() const { return data[kTranslateY]; } diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h index be5bea706e4b..7b7357edf963 100644 --- a/libs/hwui/Matrix.h +++ b/libs/hwui/Matrix.h @@ -161,8 +161,8 @@ public: void mapRect(Rect& r) const; void mapPoint(float& x, float& y) const; - float getTranslateX(); - float getTranslateY(); + float getTranslateX() const; + float getTranslateY() const; void decomposeScale(float& sx, float& sy) const; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 9c1241943236..22ec93b1a5e5 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -2627,6 +2627,31 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count return DrawGlInfo::kStatusDrew; } +mat4 OpenGLRenderer::findBestFontTransform(const mat4& transform) const { + mat4 fontTransform; + if (CC_LIKELY(transform.isPureTranslate())) { + fontTransform = mat4::identity(); + } else { + if (CC_UNLIKELY(transform.isPerspective())) { + // When the below condition is true, we are rendering text with a + // perspective transform inside a layer (either an inline layer + // created by Canvas.saveLayer() or a hardware layer.) + if (hasLayer() || getTargetFbo() != 0) { + float sx, sy; + currentTransform().decomposeScale(sx, sy); + fontTransform.loadScale(sx, sy, 1.0f); + } else { + fontTransform = mat4::identity(); + } + } else { + float sx, sy; + currentTransform().decomposeScale(sx, sy); + fontTransform.loadScale(sx, sy, 1.0f); + } + } + return fontTransform; +} + status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, const float* positions, SkPaint* paint, float length) { if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint)) { @@ -2653,12 +2678,13 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, const float oldX = x; const float oldY = y; - const bool pureTranslate = currentTransform().isPureTranslate(); - const bool isPerspective = currentTransform().isPerspective(); + + const mat4& transform = currentTransform(); + const bool pureTranslate = transform.isPureTranslate(); if (CC_LIKELY(pureTranslate)) { - x = (int) floorf(x + currentTransform().getTranslateX() + 0.5f); - y = (int) floorf(y + currentTransform().getTranslateY() + 0.5f); + x = (int) floorf(x + transform.getTranslateX() + 0.5f); + y = (int) floorf(y + transform.getTranslateY() + 0.5f); } int alpha; @@ -2675,23 +2701,18 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, const bool hasActiveLayer = hasLayer(); - mat4 fontTransform; - if (CC_LIKELY(pureTranslate)) { - fontTransform = mat4::identity(); - } else { - if (CC_UNLIKELY(isPerspective)) { - // When the below condition is true, we are rendering text with a - // perspective transform inside a layer (either an inline layer - // created by Canvas.saveLayer() or a hardware layer.) - if (hasActiveLayer || getTargetFbo() != 0) { - fontTransform = currentTransform(); - } else { - fontTransform = mat4::identity(); - } - } else { - fontTransform = currentTransform(); - } - } + // We only pass a partial transform to the font renderer. That partial + // matrix defines how glyphs are rasterized. Typically we want glyphs + // to be rasterized at their final size on screen, which means the partial + // matrix needs to take the scale factor into account. + // When a partial matrix is used to transform glyphs during rasterization, + // the mesh is generated with the inverse transform (in the case of scale, + // the mesh is generated at 1.0 / scale for instance.) This allows us to + // apply the full transform matrix at draw time in the vertex shader. + // Applying the full matrix in the shader is the easiest way to handle + // rotation and perspective and allows us to always generated quads in the + // font renderer which greatly simplifies the code, clipping in particular. + mat4 fontTransform = findBestFontTransform(transform); fontRenderer.setFont(paint, fontTransform); // Pick the appropriate texture filtering @@ -2708,16 +2729,17 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, setupDrawShader(); setupDrawBlending(true, mode); setupDrawProgram(); - setupDrawModelView(x, y, x, y, !isPerspective, true); + setupDrawModelView(x, y, x, y, pureTranslate, true); // See comment above; the font renderer must use texture unit 0 // assert(mTextureUnit == 0) setupDrawTexture(fontRenderer.getTexture(linearFilter)); setupDrawPureColorUniforms(); setupDrawColorFilterUniforms(); - setupDrawShaderUniforms(!isPerspective); + setupDrawShaderUniforms(pureTranslate); setupDrawTextGammaUniforms(); - const Rect* clip = isPerspective ? NULL : mSnapshot->clipRect; + // TODO: Implement better clipping for scaled/rotated text + const Rect* clip = !pureTranslate ? NULL : mSnapshot->clipRect; Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); bool status; @@ -2732,8 +2754,8 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, } if (status && hasActiveLayer) { - if (isPerspective) { - currentTransform().mapRect(bounds); + if (!pureTranslate) { + transform.mapRect(bounds); } dirtyLayerUnchecked(bounds, getRegion()); } diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index d5423154562d..e961af24161f 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -335,6 +335,12 @@ public: } } + /** + * Return the best transform to use to rasterize text given a full + * transform matrix. + */ + mat4 findBestFontTransform(const mat4& transform) const; + protected: /** * Computes the projection matrix, initialize the first snapshot @@ -384,28 +390,28 @@ protected: /** * Returns the current snapshot. */ - sp<Snapshot> getSnapshot() { + sp<Snapshot> getSnapshot() const { return mSnapshot; } /** * Returns the region of the current layer. */ - virtual Region* getRegion() { + virtual Region* getRegion() const { return mSnapshot->region; } /** * Indicates whether rendering is currently targeted at a layer. */ - virtual bool hasLayer() { + virtual bool hasLayer() const { return (mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region; } /** * Returns the name of the FBO this renderer is rendering into. */ - virtual GLint getTargetFbo() { + virtual GLint getTargetFbo() const { return 0; } @@ -442,7 +448,7 @@ protected: /** * Set to true to suppress error checks at the end of a frame. */ - virtual bool suppressErrorChecks() { + virtual bool suppressErrorChecks() const { return false; } diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp index bf522b7cc734..9307f115392d 100644 --- a/libs/hwui/font/Font.cpp +++ b/libs/hwui/font/Font.cpp @@ -53,10 +53,8 @@ Font::FontDescription::FontDescription(const SkPaint* paint, const mat4& matrix) mStrokeWidth = paint->getStrokeWidth(); mAntiAliasing = paint->isAntiAlias(); mLookupTransform.reset(); - mLookupTransform[SkMatrix::kMScaleX] = matrix.data[mat4::kScaleX]; - mLookupTransform[SkMatrix::kMScaleY] = matrix.data[mat4::kScaleY]; - mLookupTransform[SkMatrix::kMSkewX] = matrix.data[mat4::kSkewX]; - mLookupTransform[SkMatrix::kMSkewY] = matrix.data[mat4::kSkewY]; + mLookupTransform[SkMatrix::kMScaleX] = matrix[mat4::kScaleX]; + mLookupTransform[SkMatrix::kMScaleY] = matrix[mat4::kScaleY]; if (!mLookupTransform.invert(&mInverseLookupTransform)) { ALOGW("Could not query the inverse lookup transform for this font"); } @@ -81,8 +79,6 @@ hash_t Font::FontDescription::hash() const { hash = JenkinsHashMix(hash, int(mAntiAliasing)); hash = JenkinsHashMix(hash, android::hash_type(mLookupTransform[SkMatrix::kMScaleX])); hash = JenkinsHashMix(hash, android::hash_type(mLookupTransform[SkMatrix::kMScaleY])); - hash = JenkinsHashMix(hash, android::hash_type(mLookupTransform[SkMatrix::kMSkewX])); - hash = JenkinsHashMix(hash, android::hash_type(mLookupTransform[SkMatrix::kMSkewY])); return JenkinsHashWhiten(hash); } @@ -122,16 +118,6 @@ int Font::FontDescription::compare(const Font::FontDescription& lhs, if (lhs.mLookupTransform[SkMatrix::kMScaleY] > rhs.mLookupTransform[SkMatrix::kMScaleY]) return +1; - if (lhs.mLookupTransform[SkMatrix::kMSkewX] < - rhs.mLookupTransform[SkMatrix::kMSkewX]) return -1; - if (lhs.mLookupTransform[SkMatrix::kMSkewX] > - rhs.mLookupTransform[SkMatrix::kMSkewX]) return +1; - - if (lhs.mLookupTransform[SkMatrix::kMSkewY] < - rhs.mLookupTransform[SkMatrix::kMSkewY]) return -1; - if (lhs.mLookupTransform[SkMatrix::kMSkewY] > - rhs.mLookupTransform[SkMatrix::kMSkewY]) return +1; - return 0; } @@ -185,7 +171,7 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, nPenX, nPenY - height, u1, v1, glyph->mCacheTexture); } -void Font::drawCachedGlyphPerspective(CachedGlyphInfo* glyph, int x, int y, +void Font::drawCachedGlyphTransformed(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) { SkPoint p[4]; p[0].iset(glyph->mBitmapLeft, glyph->mBitmapTop + glyph->mBitmapHeight); @@ -388,18 +374,17 @@ void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len static RenderGlyph gRenderGlyph[] = { &android::uirenderer::Font::drawCachedGlyph, - &android::uirenderer::Font::drawCachedGlyphPerspective, + &android::uirenderer::Font::drawCachedGlyphTransformed, &android::uirenderer::Font::drawCachedGlyphBitmap, &android::uirenderer::Font::drawCachedGlyphBitmap, &android::uirenderer::Font::measureCachedGlyph, &android::uirenderer::Font::measureCachedGlyph }; - RenderGlyph render = gRenderGlyph[(mode << 1) + mTransform.isPerspective()]; + RenderGlyph render = gRenderGlyph[(mode << 1) + !mIdentityTransform]; text += start; int glyphsCount = 0; - const bool applyTransform = !mTransform.isIdentity() && !mTransform.isPerspective(); const SkPaint::Align align = paint->getTextAlign(); while (glyphsCount < numGlyphs) { @@ -418,10 +403,6 @@ void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len float penX = x + positions[(glyphsCount << 1)]; float penY = y + positions[(glyphsCount << 1) + 1]; - if (applyTransform) { - mTransform.mapPoint(penX, penY); - } - (*this.*render)(cachedGlyph, roundf(penX), roundf(penY), bitmap, bitmapW, bitmapH, bounds, positions); } @@ -495,7 +476,7 @@ Font* Font::create(FontRenderer* state, const SkPaint* paint, const mat4& matrix font = new Font(state, description); state->mActiveFonts.put(description, font); } - font->mTransform.load(matrix); + font->mIdentityTransform = matrix.isIdentity(); return font; } diff --git a/libs/hwui/font/Font.h b/libs/hwui/font/Font.h index b2382f4ea319..52cca1c370f3 100644 --- a/libs/hwui/font/Font.h +++ b/libs/hwui/font/Font.h @@ -125,7 +125,7 @@ private: void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos); - void drawCachedGlyphPerspective(CachedGlyphInfo* glyph, int x, int y, + void drawCachedGlyphTransformed(CachedGlyphInfo* glyph, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos); void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, @@ -142,7 +142,7 @@ private: // Cache of glyphs DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs; - mat4 mTransform; + bool mIdentityTransform; }; inline int strictly_order_type(const Font::FontDescription& lhs, |