summaryrefslogtreecommitdiffstats
path: root/libs/hwui/font
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/font')
-rw-r--r--libs/hwui/font/CacheTexture.cpp53
-rw-r--r--libs/hwui/font/CacheTexture.h33
-rw-r--r--libs/hwui/font/Font.cpp37
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);
}
}