OSDN Git Service

Use glops for text rendering
authorChris Craik <ccraik@google.com>
Fri, 13 Mar 2015 22:07:52 +0000 (15:07 -0700)
committerChris Craik <ccraik@google.com>
Wed, 18 Mar 2015 23:10:24 +0000 (16:10 -0700)
Change-Id: I5e155c8baf3149f0ff231ec3c89dbff6bb8eae92

libs/hwui/FontRenderer.cpp
libs/hwui/FontRenderer.h
libs/hwui/OpenGLRenderer.cpp
libs/hwui/PathCache.cpp
libs/hwui/PathCache.h
libs/hwui/Texture.h
libs/hwui/font/CacheTexture.cpp
libs/hwui/font/CacheTexture.h
libs/hwui/utils/Macros.h

index d1d2fcc..fd2bdc6 100644 (file)
@@ -19,6 +19,8 @@
 #include "Caches.h"
 #include "Debug.h"
 #include "Extensions.h"
+#include "Glop.h"
+#include "GlopBuilder.h"
 #include "OpenGLRenderer.h"
 #include "PixelBuffer.h"
 #include "Rect.h"
@@ -44,10 +46,12 @@ namespace uirenderer {
 // blur inputs smaller than this constant will bypass renderscript
 #define RS_MIN_INPUT_CUTOFF 10000
 
+#define USE_GLOPS true
+
 ///////////////////////////////////////////////////////////////////////////////
 // TextSetupFunctor
 ///////////////////////////////////////////////////////////////////////////////
-status_t TextSetupFunctor::setup(GLenum glyphFormat) {
+void TextSetupFunctor::setup(GLenum glyphFormat) {
     renderer->setupDraw();
     renderer->setupDrawTextGamma(paint);
     renderer->setupDrawDirtyRegionsDisabled();
@@ -84,8 +88,24 @@ status_t TextSetupFunctor::setup(GLenum glyphFormat) {
     renderer->setupDrawColorFilterUniforms(paint->getColorFilter());
     renderer->setupDrawShaderUniforms(paint->getShader(), pureTranslate);
     renderer->setupDrawTextGammaUniforms();
+}
 
-    return NO_ERROR;
+void TextSetupFunctor::draw(CacheTexture& texture, bool linearFiltering) {
+    int textureFillFlags = static_cast<int>(texture.getFormat() == GL_ALPHA
+            ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
+    if (linearFiltering) {
+        textureFillFlags |= TextureFillFlags::kForceFilter;
+    }
+    const Matrix4& transform = pureTranslate ? Matrix4::identity() : *(renderer->currentTransform());
+    Glop glop;
+    GlopBuilder(renderer->mRenderState, renderer->mCaches, &glop)
+            .setMeshTexturedIndexedQuads(texture.mesh(), texture.meshElementCount())
+            .setFillTexturePaint(texture.getTexture(), textureFillFlags, paint, renderer->currentSnapshot()->alpha)
+            .setTransform(renderer->currentSnapshot()->getOrthoMatrix(), transform, false)
+            .setModelViewOffsetRect(0, 0, Rect(0, 0, 0, 0))
+            .setRoundRectClipState(renderer->currentSnapshot()->roundRectClipState)
+            .build();
+    renderer->renderGlop(glop);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -196,7 +216,7 @@ void FontRenderer::flushLargeCaches(Vector<CacheTexture*>& cacheTextures) {
             while (it.next()) {
                 it.value()->invalidateTextureCache(cacheTexture);
             }
-            cacheTexture->releaseTexture();
+            cacheTexture->releasePixelBuffer();
         }
     }
 }
@@ -290,7 +310,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
     if (!cacheTexture->getPixelBuffer()) {
         Caches::getInstance().textureState().activateTexture(0);
         // Large-glyph texture memory is allocated only as needed
-        cacheTexture->allocateTexture();
+        cacheTexture->allocatePixelBuffer();
     }
     if (!cacheTexture->mesh()) {
         cacheTexture->allocateMesh();
@@ -402,7 +422,7 @@ CacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum for
 
     if (allocate) {
         Caches::getInstance().textureState().activateTexture(0);
-        cacheTexture->allocateTexture();
+        cacheTexture->allocatePixelBuffer();
         cacheTexture->allocateMesh();
     }
 
@@ -497,9 +517,10 @@ void FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) {
         CacheTexture* texture = cacheTextures[i];
         if (texture->canDraw()) {
             if (first) {
+                checkTextureUpdate();
+#if !USE_GLOPS
                 mFunctor->setup(texture->getFormat());
 
-                checkTextureUpdate();
                 renderState.meshState().bindQuadIndicesBuffer();
 
                 // If returns true, a VBO was bound and we must
@@ -508,12 +529,17 @@ void FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) {
                 forceRebind = renderState.meshState().unbindMeshBuffer();
 
                 caches.textureState().activateTexture(0);
+#endif
                 first = false;
                 mDrawn = true;
             }
+#if USE_GLOPS
+            mFunctor->draw(*texture, mLinearFiltering);
+#endif
 
+#if !USE_GLOPS
             caches.textureState().bindTexture(texture->getTextureId());
-            texture->setLinearFiltering(mLinearFiltering, false);
+            texture->setLinearFiltering(mLinearFiltering);
 
             TextureVertex* mesh = texture->mesh();
             MeshState& meshState = renderState.meshState();
@@ -522,7 +548,7 @@ void FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) {
 
             glDrawElements(GL_TRIANGLES, texture->meshElementCount(),
                     GL_UNSIGNED_SHORT, texture->indices());
-
+#endif
             texture->resetMesh();
             forceRebind = false;
         }
index cb63684..0603389 100644 (file)
@@ -59,7 +59,9 @@ public:
         , paint(paint) {
     }
 
-    status_t setup(GLenum glyphFormat);
+    void setup(GLenum glyphFormat);
+
+    void draw(CacheTexture& texture, bool linearFiltering);
 
     OpenGLRenderer* renderer;
     float x;
index 622b570..3781969 100644 (file)
@@ -2935,27 +2935,27 @@ int OpenGLRenderer::save(int flags) {
 }
 
 void OpenGLRenderer::restore() {
-    return mState.restore();
+    mState.restore();
 }
 
 void OpenGLRenderer::restoreToCount(int saveCount) {
-    return mState.restoreToCount(saveCount);
+    mState.restoreToCount(saveCount);
 }
 
 void OpenGLRenderer::translate(float dx, float dy, float dz) {
-    return mState.translate(dx, dy, dz);
+    mState.translate(dx, dy, dz);
 }
 
 void OpenGLRenderer::rotate(float degrees) {
-    return mState.rotate(degrees);
+    mState.rotate(degrees);
 }
 
 void OpenGLRenderer::scale(float sx, float sy) {
-    return mState.scale(sx, sy);
+    mState.scale(sx, sy);
 }
 
 void OpenGLRenderer::skew(float sx, float sy) {
-    return mState.skew(sx, sy);
+    mState.skew(sx, sy);
 }
 
 void OpenGLRenderer::setMatrix(const Matrix4& matrix) {
index 5b2e5e2..2703072 100644 (file)
@@ -40,25 +40,25 @@ namespace uirenderer {
 // Cache entries
 ///////////////////////////////////////////////////////////////////////////////
 
-PathDescription::PathDescription():
-        type(kShapeNone),
-        join(SkPaint::kDefault_Join),
-        cap(SkPaint::kDefault_Cap),
-        style(SkPaint::kFill_Style),
-        miter(4.0f),
-        strokeWidth(1.0f),
-        pathEffect(nullptr) {
+PathDescription::PathDescription()
+        : type(kShapeNone)
+        , join(SkPaint::kDefault_Join)
+        , cap(SkPaint::kDefault_Cap)
+        , style(SkPaint::kFill_Style)
+        , miter(4.0f)
+        , strokeWidth(1.0f)
+        pathEffect(nullptr) {
     memset(&shape, 0, sizeof(Shape));
 }
 
-PathDescription::PathDescription(ShapeType type, const SkPaint* paint):
-        type(type),
-        join(paint->getStrokeJoin()),
-        cap(paint->getStrokeCap()),
-        style(paint->getStyle()),
-        miter(paint->getStrokeMiter()),
-        strokeWidth(paint->getStrokeWidth()),
-        pathEffect(paint->getPathEffect()) {
+PathDescription::PathDescription(ShapeType type, const SkPaint* paint)
+        : type(type)
+        , join(paint->getStrokeJoin())
+        , cap(paint->getStrokeCap())
+        , style(paint->getStyle())
+        , miter(paint->getStrokeMiter())
+        , strokeWidth(paint->getStrokeWidth())
+        pathEffect(paint->getPathEffect()) {
     memset(&shape, 0, sizeof(Shape));
 }
 
@@ -132,18 +132,6 @@ static void drawPath(const SkPath *path, const SkPaint* paint, SkBitmap& bitmap,
     canvas.drawPath(*path, pathPaint);
 }
 
-static PathTexture* createTexture(float left, float top, float offset,
-        uint32_t width, uint32_t height, uint32_t id) {
-    PathTexture* texture = new PathTexture(Caches::getInstance());
-    texture->left = left;
-    texture->top = top;
-    texture->offset = offset;
-    texture->width = width;
-    texture->height = height;
-    texture->generation = id;
-    return texture;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Cache constructor/destructor
 ///////////////////////////////////////////////////////////////////////////////
@@ -267,7 +255,8 @@ PathTexture* PathCache::addTexture(const PathDescription& entry, const SkPath *p
     SkBitmap bitmap;
     drawPath(path, paint, bitmap, left, top, offset, width, height);
 
-    PathTexture* texture = createTexture(left, top, offset, width, height,
+    PathTexture* texture = new PathTexture(Caches::getInstance(),
+            left, top, offset, width, height,
             path->getGenerationID());
     generateTexture(entry, &bitmap, texture);
 
@@ -441,7 +430,7 @@ void PathCache::precache(const SkPath* path, const SkPaint* paint) {
     if (generate) {
         // It is important to specify the generation ID so we do not
         // attempt to precache the same path several times
-        texture = createTexture(0.0f, 0.0f, 0.0f, 0, 0, path->getGenerationID());
+        texture = new PathTexture(Caches::getInstance(), path->getGenerationID());
         sp<PathTask> task = new PathTask(path, paint, texture);
         texture->setTask(task);
 
index 23e35cb..4297693 100644 (file)
@@ -59,7 +59,19 @@ class Caches;
  * Alpha texture used to represent a path.
  */
 struct PathTexture: public Texture {
-    PathTexture(Caches& caches): Texture(caches) {
+    PathTexture(Caches& caches, float left, float top,
+            float offset, int width, int height, int generation)
+            : Texture(caches)
+            , left(left)
+            , top(top)
+            , offset(offset) {
+        this->width = width;
+        this->height = height;
+        this->generation = generation;
+    }
+    PathTexture(Caches& caches, int generation)
+        : Texture(caches) {
+        this->generation = generation;
     }
 
     ~PathTexture() {
@@ -69,15 +81,15 @@ struct PathTexture: public Texture {
     /**
      * Left coordinate of the path bounds.
      */
-    float left;
+    float left = 0;
     /**
      * Top coordinate of the path bounds.
      */
-    float top;
+    float top = 0;
     /**
      * Offset to draw the path at the correct origin.
      */
-    float offset;
+    float offset = 0;
 
     sp<Task<SkBitmap*> > task() const {
         return mTask;
index dfec462..7227ce0 100644 (file)
@@ -78,7 +78,7 @@ public:
     /**
      * Indicates whether this texture should be cleaned up after use.
      */
-    bool cleanup= false;
+    bool cleanup = false;
     /**
      * Optional, size of the original bitmap.
      */
index 9314126..845cf30 100644 (file)
@@ -109,13 +109,17 @@ CacheBlock* CacheBlock::removeBlock(CacheBlock* head, CacheBlock* blockToRemove)
 // CacheTexture
 ///////////////////////////////////////////////////////////////////////////////
 
-CacheTexture::CacheTexture(uint16_t width, uint16_t height, GLenum format, uint32_t maxQuadCount) :
-            mTexture(nullptr), mTextureId(0), mWidth(width), mHeight(height), mFormat(format),
-            mLinearFiltering(false), mDirty(false), mNumGlyphs(0),
-            mMesh(nullptr), mCurrentQuad(0), mMaxQuadCount(maxQuadCount),
-            mCaches(Caches::getInstance()) {
+CacheTexture::CacheTexture(uint16_t width, uint16_t height, GLenum format, uint32_t maxQuadCount)
+        : mTexture(Caches::getInstance())
+        , mFormat(format)
+        , mMaxQuadCount(maxQuadCount)
+        , mCaches(Caches::getInstance()) {
+    mTexture.width = width;
+    mTexture.height = height;
+    mTexture.blend = true;
+
     mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
-            mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE);
+            getWidth() - TEXTURE_BORDER_SIZE, getHeight() - TEXTURE_BORDER_SIZE);
 
     // OpenGL ES 3.0+ lets us specify the row length for unpack operations such
     // as glTexSubImage2D(). This allows us to upload a sub-rectangle of a texture.
@@ -125,7 +129,7 @@ CacheTexture::CacheTexture(uint16_t width, uint16_t height, GLenum format, uint3
 
 CacheTexture::~CacheTexture() {
     releaseMesh();
-    releaseTexture();
+    releasePixelBuffer();
     reset();
 }
 
@@ -144,35 +148,28 @@ void CacheTexture::init() {
     // reset, then create a new remainder space to start again
     reset();
     mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
-            mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE);
+            getWidth() - TEXTURE_BORDER_SIZE, getHeight() - TEXTURE_BORDER_SIZE);
 }
 
 void CacheTexture::releaseMesh() {
     delete[] mMesh;
 }
 
-void CacheTexture::releaseTexture() {
-    if (mTexture) {
-        delete mTexture;
-        mTexture = nullptr;
+void CacheTexture::releasePixelBuffer() {
+    if (mPixelBuffer) {
+        delete mPixelBuffer;
+        mPixelBuffer = nullptr;
     }
-    if (mTextureId) {
-        mCaches.textureState().deleteTexture(mTextureId);
-        mTextureId = 0;
+    if (mTexture.id) {
+        mCaches.textureState().deleteTexture(mTexture.id);
+        mTexture.id = 0;
     }
     mDirty = false;
     mCurrentQuad = 0;
 }
 
-void CacheTexture::setLinearFiltering(bool linearFiltering, bool bind) {
-   if (linearFiltering != mLinearFiltering) {
-       mLinearFiltering = linearFiltering;
-
-       const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
-       if (bind) mCaches.textureState().bindTexture(getTextureId());
-       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
-       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
-   }
+void CacheTexture::setLinearFiltering(bool linearFiltering) {
+    mTexture.setFilter(linearFiltering ? GL_LINEAR : GL_NEAREST);
 }
 
 void CacheTexture::allocateMesh() {
@@ -181,18 +178,18 @@ void CacheTexture::allocateMesh() {
     }
 }
 
-void CacheTexture::allocateTexture() {
-    if (!mTexture) {
-        mTexture = PixelBuffer::create(mFormat, mWidth, mHeight);
+void CacheTexture::allocatePixelBuffer() {
+    if (!mPixelBuffer) {
+        mPixelBuffer = PixelBuffer::create(mFormat, getWidth(), getHeight());
     }
 
-    if (!mTextureId) {
-        glGenTextures(1, &mTextureId);
+    if (!mTexture.id) {
+        glGenTextures(1, &mTexture.id);
 
-        mCaches.textureState().bindTexture(mTextureId);
+        mCaches.textureState().bindTexture(mTexture.id);
         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
         // Initialize texture dimensions
-        glTexImage2D(GL_TEXTURE_2D, 0, mFormat, mWidth, mHeight, 0,
+        glTexImage2D(GL_TEXTURE_2D, 0, mFormat, getWidth(), getHeight(), 0,
                 mFormat, GL_UNSIGNED_BYTE, nullptr);
 
         const GLenum filtering = getLinearFiltering() ? GL_LINEAR : GL_NEAREST;
@@ -209,16 +206,16 @@ bool CacheTexture::upload() {
 
     uint32_t x = mHasUnpackRowLength ? dirtyRect.left : 0;
     uint32_t y = dirtyRect.top;
-    uint32_t width = mHasUnpackRowLength ? dirtyRect.getWidth() : mWidth;
+    uint32_t width = mHasUnpackRowLength ? dirtyRect.getWidth() : getWidth();
     uint32_t height = dirtyRect.getHeight();
 
     // The unpack row length only needs to be specified when a new
     // texture is bound
     if (mHasUnpackRowLength) {
-        glPixelStorei(GL_UNPACK_ROW_LENGTH, mWidth);
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, getWidth());
     }
 
-    mTexture->upload(x, y, width, height);
+    mPixelBuffer->upload(x, y, width, height);
     setDirty(false);
 
     return mHasUnpackRowLength;
@@ -258,7 +255,7 @@ bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_
             return false;
     }
 
-    if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > mHeight) {
+    if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > getHeight()) {
         return false;
     }
 
@@ -295,10 +292,10 @@ bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_
                 cacheBlock->mWidth -= roundedUpW;
                 cacheBlock->mX += roundedUpW;
 
-                if (mHeight - glyphH >= glyphH) {
+                if (getHeight() - glyphH >= glyphH) {
                     // There's enough height left over to create a new CacheBlock
                     CacheBlock* newBlock = new CacheBlock(oldX, glyphH + TEXTURE_BORDER_SIZE,
-                            roundedUpW, mHeight - glyphH - TEXTURE_BORDER_SIZE);
+                            roundedUpW, getHeight() - glyphH - TEXTURE_BORDER_SIZE);
 #if DEBUG_FONT_RENDERER
                     ALOGD("fitBitmap: Created new block: this, x, y, w, h = %p, %d, %d, %d, %d",
                             newBlock, newBlock->mX, newBlock->mY,
index 5d3f959..6dabc76 100644 (file)
 #ifndef ANDROID_HWUI_CACHE_TEXTURE_H
 #define ANDROID_HWUI_CACHE_TEXTURE_H
 
-#include <GLES3/gl3.h>
+#include "PixelBuffer.h"
+#include "Rect.h"
+#include "Texture.h"
+#include "Vertex.h"
 
+#include <GLES3/gl3.h>
 #include <SkScalerContext.h>
-
 #include <utils/Log.h>
 
-#include "../PixelBuffer.h"
-#include "../Rect.h"
-#include "../Vertex.h"
 
 namespace android {
 namespace uirenderer {
@@ -80,9 +80,9 @@ public:
     void init();
 
     void releaseMesh();
-    void releaseTexture();
+    void releasePixelBuffer();
 
-    void allocateTexture();
+    void allocatePixelBuffer();
     void allocateMesh();
 
     // Returns true if glPixelStorei(GL_UNPACK_ROW_LENGTH) must be reset
@@ -92,11 +92,11 @@ public:
     bool fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY);
 
     inline uint16_t getWidth() const {
-        return mWidth;
+        return mTexture.width;
     }
 
     inline uint16_t getHeight() const {
-        return mHeight;
+        return mTexture.height;
     }
 
     inline GLenum getFormat() const {
@@ -104,7 +104,7 @@ public:
     }
 
     inline uint32_t getOffset(uint16_t x, uint16_t y) const {
-        return (y * mWidth + x) * PixelBuffer::formatSize(mFormat);
+        return (y * getWidth() + x) * PixelBuffer::formatSize(mFormat);
     }
 
     inline const Rect* getDirtyRect() const {
@@ -112,12 +112,17 @@ public:
     }
 
     inline PixelBuffer* getPixelBuffer() const {
+        return mPixelBuffer;
+    }
+
+    Texture& getTexture() {
+        allocatePixelBuffer();
         return mTexture;
     }
 
     GLuint getTextureId() {
-        allocateTexture();
-        return mTextureId;
+        allocatePixelBuffer();
+        return mTexture.id;
     }
 
     inline bool isDirty() const {
@@ -131,7 +136,7 @@ public:
     /**
      * This method assumes that the proper texture unit is active.
      */
-    void setLinearFiltering(bool linearFiltering, bool bind = true);
+    void setLinearFiltering(bool linearFiltering);
 
     inline uint16_t getGlyphCount() const {
         return mNumGlyphs;
@@ -176,16 +181,14 @@ public:
 private:
     void setDirty(bool dirty);
 
-    PixelBuffer* mTexture;
-    GLuint mTextureId;
-    uint16_t mWidth;
-    uint16_t mHeight;
+    PixelBuffer* mPixelBuffer = nullptr;
+    Texture mTexture;
     GLenum mFormat;
-    bool mLinearFiltering;
-    bool mDirty;
-    uint16_t mNumGlyphs;
-    TextureVertex* mMesh;
-    uint32_t mCurrentQuad;
+    bool mLinearFiltering = false;
+    bool mDirty = false;
+    uint16_t mNumGlyphs = 0;
+    TextureVertex* mMesh = nullptr;
+    uint32_t mCurrentQuad = 0;
     uint32_t mMaxQuadCount;
     Caches& mCaches;
     CacheBlock* mCacheBlocks;
index 9f7ac1c..1b31059 100644 (file)
@@ -36,8 +36,8 @@
         #Type " must have standard layout")
 
 #define MAKE_FLAGS_ENUM(enumType) \
-        inline int operator|=(int lhs, enumType rhs) { \
-            return lhs | static_cast<int>(rhs); \
+        inline void operator|=(int& lhs, enumType rhs) { \
+            lhs |= static_cast<int>(rhs); \
         } \
         inline int operator|(int lhs, enumType rhs) { \
             return lhs | static_cast<int>(rhs); \
@@ -48,8 +48,8 @@
         inline int operator|(enumType lhs, enumType rhs) { \
             return static_cast<int>(lhs) | static_cast<int>(rhs); \
         } \
-        inline int operator&=(int lhs, enumType rhs) { \
-            return lhs & static_cast<int>(rhs); \
+        inline void operator&=(int& lhs, enumType rhs) { \
+            lhs &= static_cast<int>(rhs); \
         } \
         inline int operator&(int lhs, enumType rhs) { \
             return lhs & static_cast<int>(rhs); \