diff options
Diffstat (limited to 'libs/hwui/font')
-rw-r--r-- | libs/hwui/font/CacheTexture.cpp | 53 | ||||
-rw-r--r-- | libs/hwui/font/CacheTexture.h | 33 | ||||
-rw-r--r-- | libs/hwui/font/Font.cpp | 37 |
3 files changed, 80 insertions, 43 deletions
diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp index 1096642..6c5267d 100644 --- a/libs/hwui/font/CacheTexture.cpp +++ b/libs/hwui/font/CacheTexture.cpp @@ -15,10 +15,11 @@ */ #include <SkGlyph.h> -#include <utils/Log.h> -#include "Debug.h" #include "CacheTexture.h" +#include "../Debug.h" +#include "../Extensions.h" +#include "../PixelBuffer.h" namespace android { namespace uirenderer { @@ -112,6 +113,11 @@ CacheTexture::CacheTexture(uint16_t width, uint16_t height, uint32_t maxQuadCoun mMesh(NULL), mCurrentQuad(0), mMaxQuadCount(maxQuadCount) { mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true); + + // 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. + // With OpenGL ES 2.0 we have to upload entire stripes instead. + mHasES3 = Extensions::getInstance().getMajorGlVersion() >= 3; } CacheTexture::~CacheTexture() { @@ -144,7 +150,7 @@ void CacheTexture::releaseMesh() { void CacheTexture::releaseTexture() { if (mTexture) { - delete[] mTexture; + delete mTexture; mTexture = NULL; } if (mTextureId) { @@ -155,6 +161,17 @@ void CacheTexture::releaseTexture() { mCurrentQuad = 0; } +void CacheTexture::setLinearFiltering(bool linearFiltering, bool bind) { + if (linearFiltering != mLinearFiltering) { + mLinearFiltering = linearFiltering; + + const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST; + if (bind) glBindTexture(GL_TEXTURE_2D, getTextureId()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); + } +} + void CacheTexture::allocateMesh() { if (!mMesh) { mMesh = new TextureVertex[mMaxQuadCount * 4]; @@ -163,7 +180,7 @@ void CacheTexture::allocateMesh() { void CacheTexture::allocateTexture() { if (!mTexture) { - mTexture = new uint8_t[mWidth * mHeight]; + mTexture = PixelBuffer::create(GL_ALPHA, mWidth, mHeight); } if (!mTextureId) { @@ -184,6 +201,34 @@ void CacheTexture::allocateTexture() { } } +bool CacheTexture::upload() { + const Rect& dirtyRect = mDirtyRect; + + uint32_t x = mHasES3 ? dirtyRect.left : 0; + uint32_t y = dirtyRect.top; + uint32_t width = mHasES3 ? dirtyRect.getWidth() : mWidth; + uint32_t height = dirtyRect.getHeight(); + + // The unpack row length only needs to be specified when a new + // texture is bound + if (mHasES3) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, mWidth); + } + + mTexture->upload(x, y, width, height, y * mWidth + x); + + setDirty(false); + + return mHasES3; +} + +void CacheTexture::setDirty(bool dirty) { + mDirty = dirty; + if (!dirty) { + mDirtyRect.setEmpty(); + } +} + bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY) { if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > mHeight) { return false; diff --git a/libs/hwui/font/CacheTexture.h b/libs/hwui/font/CacheTexture.h index 5742941..ddcc836 100644 --- a/libs/hwui/font/CacheTexture.h +++ b/libs/hwui/font/CacheTexture.h @@ -17,7 +17,7 @@ #ifndef ANDROID_HWUI_CACHE_TEXTURE_H #define ANDROID_HWUI_CACHE_TEXTURE_H -#include <GLES2/gl2.h> +#include <GLES3/gl3.h> #include <SkScalerContext.h> @@ -30,6 +30,8 @@ namespace android { namespace uirenderer { +class PixelBuffer; + /** * CacheBlock is a node in a linked list of current free space areas in a CacheTexture. * Using CacheBlocks enables us to pack the cache from top to bottom as well as left to right. @@ -83,6 +85,10 @@ public: void allocateTexture(); void allocateMesh(); + // Returns true if glPixelStorei(GL_UNPACK_ROW_LENGTH) must be reset + // This method will also call setDirty(false) + bool upload(); + bool fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY); inline uint16_t getWidth() const { @@ -97,7 +103,7 @@ public: return &mDirtyRect; } - inline uint8_t* getTexture() const { + inline PixelBuffer* getPixelBuffer() const { return mTexture; } @@ -110,13 +116,6 @@ public: return mDirty; } - inline void setDirty(bool dirty) { - mDirty = dirty; - if (!dirty) { - mDirtyRect.setEmpty(); - } - } - inline bool getLinearFiltering() const { return mLinearFiltering; } @@ -124,16 +123,7 @@ public: /** * This method assumes that the proper texture unit is active. */ - void setLinearFiltering(bool linearFiltering, bool bind = true) { - if (linearFiltering != mLinearFiltering) { - mLinearFiltering = linearFiltering; - - const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST; - if (bind) glBindTexture(GL_TEXTURE_2D, getTextureId()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); - } - } + void setLinearFiltering(bool linearFiltering, bool bind = true); inline uint16_t getGlyphCount() const { return mNumGlyphs; @@ -176,7 +166,9 @@ public: } private: - uint8_t* mTexture; + void setDirty(bool dirty); + + PixelBuffer* mTexture; GLuint mTextureId; uint16_t mWidth; uint16_t mHeight; @@ -188,6 +180,7 @@ private: uint32_t mMaxQuadCount; CacheBlock* mCacheBlocks; Rect mDirtyRect; + bool mHasES3; }; }; // namespace uirenderer diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp index 02c1aa1..011cfc1 100644 --- a/libs/hwui/font/Font.cpp +++ b/libs/hwui/font/Font.cpp @@ -25,11 +25,12 @@ #include <SkGlyph.h> #include <SkUtils.h> -#include "Debug.h" #include "FontUtil.h" #include "Font.h" -#include "FontRenderer.h" -#include "Properties.h" +#include "../Debug.h" +#include "../FontRenderer.h" +#include "../PixelBuffer.h" +#include "../Properties.h" namespace android { namespace uirenderer { @@ -200,25 +201,23 @@ void Font::drawCachedGlyphTransformed(CachedGlyphInfo* glyph, int x, int y, p[3].x(), p[3].y(), u1, v1, glyph->mCacheTexture); } -void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, - uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) { - int nPenX = x + glyph->mBitmapLeft; - int nPenY = y + glyph->mBitmapTop; - - uint32_t endX = glyph->mStartX + glyph->mBitmapWidth; - uint32_t endY = glyph->mStartY + glyph->mBitmapHeight; +void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, + uint32_t bitmapWidth, uint32_t bitmapHeight, Rect* bounds, const float* pos) { + int dstX = x + glyph->mBitmapLeft; + int dstY = y + glyph->mBitmapTop; CacheTexture* cacheTexture = glyph->mCacheTexture; + uint32_t cacheWidth = cacheTexture->getWidth(); - const uint8_t* cacheBuffer = cacheTexture->getTexture(); - - uint32_t cacheX = 0, cacheY = 0; - int32_t bX = 0, bY = 0; - for (cacheX = glyph->mStartX, bX = nPenX; cacheX < endX; cacheX++, bX++) { - for (cacheY = glyph->mStartY, bY = nPenY; cacheY < endY; cacheY++, bY++) { - uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; - bitmap[bY * bitmapW + bX] = tempCol; - } + uint32_t startY = glyph->mStartY * cacheWidth; + uint32_t endY = startY + (glyph->mBitmapHeight * cacheWidth); + + PixelBuffer* pixelBuffer = cacheTexture->getPixelBuffer(); + const uint8_t* cacheBuffer = pixelBuffer->map(); + + for (uint32_t cacheY = startY, bitmapY = dstY * bitmapWidth; cacheY < endY; + cacheY += cacheWidth, bitmapY += bitmapWidth) { + memcpy(&bitmap[bitmapY + dstX], &cacheBuffer[cacheY + glyph->mStartX], glyph->mBitmapWidth); } } |