summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/widget/LockPatternView.java10
-rw-r--r--libs/hwui/Android.mk2
-rw-r--r--libs/hwui/Caches.cpp48
-rw-r--r--libs/hwui/Caches.h32
-rw-r--r--libs/hwui/DisplayListRenderer.cpp17
-rw-r--r--libs/hwui/DisplayListRenderer.h9
-rw-r--r--libs/hwui/Extensions.h6
-rw-r--r--libs/hwui/FboCache.h6
-rw-r--r--libs/hwui/FontRenderer.cpp20
-rw-r--r--libs/hwui/FontRenderer.h12
-rw-r--r--libs/hwui/GammaFontRenderer.h6
-rw-r--r--libs/hwui/GradientCache.h6
-rw-r--r--libs/hwui/Layer.h14
-rw-r--r--libs/hwui/LayerCache.h6
-rw-r--r--libs/hwui/Line.h6
-rw-r--r--libs/hwui/Matrix.cpp13
-rw-r--r--libs/hwui/Matrix.h6
-rw-r--r--libs/hwui/OpenGLDebugRenderer.h6
-rw-r--r--libs/hwui/OpenGLRenderer.cpp405
-rw-r--r--libs/hwui/OpenGLRenderer.h57
-rw-r--r--libs/hwui/Patch.cpp12
-rw-r--r--libs/hwui/Patch.h15
-rw-r--r--libs/hwui/PatchCache.h6
-rw-r--r--libs/hwui/PathCache.h6
-rw-r--r--libs/hwui/Program.cpp6
-rw-r--r--libs/hwui/Program.h6
-rw-r--r--libs/hwui/ProgramCache.h6
-rw-r--r--libs/hwui/Properties.h10
-rw-r--r--libs/hwui/Rect.h47
-rw-r--r--libs/hwui/ResourceCache.h6
-rw-r--r--libs/hwui/SkiaColorFilter.h6
-rw-r--r--libs/hwui/SkiaShader.h6
-rw-r--r--libs/hwui/Snapshot.h26
-rw-r--r--libs/hwui/TextDropShadowCache.h6
-rw-r--r--libs/hwui/Texture.h6
-rw-r--r--libs/hwui/TextureCache.cpp8
-rw-r--r--libs/hwui/TextureCache.h8
-rw-r--r--libs/hwui/Vertex.h6
-rw-r--r--libs/hwui/utils/Compare.h6
-rw-r--r--libs/hwui/utils/GenerationCache.h6
-rw-r--r--libs/hwui/utils/SortedList.h6
-rw-r--r--libs/hwui/utils/SortedListImpl.h6
-rw-r--r--libs/ui/Region.cpp2
43 files changed, 670 insertions, 235 deletions
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 007e7b9..f80fbd8 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -129,6 +129,7 @@ public class LockPatternView extends View {
private long[] mVibePattern;
private int mAspect;
+ private final Matrix mArrowMatrix = new Matrix();
/**
* Represents a cell in the 3 X 3 matrix of the unlock pattern view.
@@ -923,7 +924,6 @@ public class LockPatternView extends View {
// This assumes that the arrow image is drawn at 12:00 with it's top edge
// coincident with the circle bitmap's top edge.
Bitmap arrow = green ? mBitmapArrowGreenUp : mBitmapArrowRedUp;
- Matrix matrix = new Matrix();
final int cellWidth = mBitmapCircleDefault.getWidth();
final int cellHeight = mBitmapCircleDefault.getHeight();
@@ -933,10 +933,10 @@ public class LockPatternView extends View {
final float angle = (float) Math.toDegrees(theta) + 90.0f;
// compose matrix
- matrix.setTranslate(leftX + offsetX, topY + offsetY); // transform to cell position
- matrix.preRotate(angle, cellWidth / 2.0f, cellHeight / 2.0f); // rotate about cell center
- matrix.preTranslate((cellWidth - arrow.getWidth()) / 2.0f, 0.0f); // translate to 12:00 pos
- canvas.drawBitmap(arrow, matrix, mPaint);
+ mArrowMatrix.setTranslate(leftX + offsetX, topY + offsetY); // transform to cell position
+ mArrowMatrix.preRotate(angle, cellWidth / 2.0f, cellHeight / 2.0f); // rotate about cell center
+ mArrowMatrix.preTranslate((cellWidth - arrow.getWidth()) / 2.0f, 0.0f); // translate to 12:00 pos
+ canvas.drawBitmap(arrow, mArrowMatrix, mPaint);
}
/**
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index d661f7b..29158e5 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -38,7 +38,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
- LOCAL_SHARED_LIBRARIES := libcutils libutils libGLESv2 libskia
+ LOCAL_SHARED_LIBRARIES := libcutils libutils libGLESv2 libskia libui
LOCAL_MODULE := libhwui
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := false
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 0994d82..93c5b34 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -46,18 +46,21 @@ Caches::Caches(): Singleton<Caches>(), blend(false), lastSrcMode(GL_ZERO),
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
mCurrentBuffer = meshBuffer;
+ mRegionMesh = NULL;
}
-/**
- * Binds the VBO used to render simple textured quads.
- */
+Caches::~Caches() {
+ delete[] mRegionMesh;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// VBO
+///////////////////////////////////////////////////////////////////////////////
+
void Caches::bindMeshBuffer() {
bindMeshBuffer(meshBuffer);
}
-/**
- * Binds the specified VBO.
- */
void Caches::bindMeshBuffer(const GLuint buffer) {
if (mCurrentBuffer != buffer) {
glBindBuffer(GL_ARRAY_BUFFER, buffer);
@@ -65,9 +68,6 @@ void Caches::bindMeshBuffer(const GLuint buffer) {
}
}
-/**
- * Unbinds the VBO used to render simple textured quads.
- */
void Caches::unbindMeshBuffer() {
if (mCurrentBuffer) {
glBindBuffer(GL_ARRAY_BUFFER, 0);
@@ -75,5 +75,35 @@ void Caches::unbindMeshBuffer() {
}
}
+TextureVertex* Caches::getRegionMesh() {
+ // Create the mesh, 2 triangles and 4 vertices per rectangle in the region
+ if (!mRegionMesh) {
+ mRegionMesh = new TextureVertex[REGION_MESH_QUAD_COUNT * 4];
+
+ uint16_t* regionIndices = new uint16_t[REGION_MESH_QUAD_COUNT * 6];
+ for (int i = 0; i < REGION_MESH_QUAD_COUNT; i++) {
+ uint16_t quad = i * 4;
+ int index = i * 6;
+ regionIndices[index ] = quad; // top-left
+ regionIndices[index + 1] = quad + 1; // top-right
+ regionIndices[index + 2] = quad + 2; // bottom-left
+ regionIndices[index + 3] = quad + 2; // bottom-left
+ regionIndices[index + 4] = quad + 1; // top-right
+ regionIndices[index + 5] = quad + 3; // bottom-right
+ }
+
+ glGenBuffers(1, &mRegionMeshIndices);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mRegionMeshIndices);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, REGION_MESH_QUAD_COUNT * 6 * sizeof(uint16_t),
+ regionIndices, GL_STATIC_DRAW);
+
+ delete[] regionIndices;
+ } else {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mRegionMeshIndices);
+ }
+
+ return mRegionMesh;
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index ca22867..c019fd1 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_CACHES_H
-#define ANDROID_UI_CACHES_H
+#ifndef ANDROID_HWUI_CACHES_H
+#define ANDROID_HWUI_CACHES_H
#ifndef LOG_TAG
#define LOG_TAG "OpenGLRenderer"
@@ -46,6 +46,8 @@ namespace uirenderer {
#define REQUIRED_TEXTURE_UNITS_COUNT 3
+#define REGION_MESH_QUAD_COUNT 512
+
// Generates simple and textured vertices
#define FV(x, y, u, v) { { x, y }, { u, v } }
@@ -77,6 +79,7 @@ struct CacheLogger {
class Caches: public Singleton<Caches> {
Caches();
+ ~Caches();
friend class Singleton<Caches>;
@@ -84,11 +87,33 @@ class Caches: public Singleton<Caches> {
GLuint mCurrentBuffer;
+ // Used to render layers
+ TextureVertex* mRegionMesh;
+ GLuint mRegionMeshIndices;
+
public:
+ /**
+ * Binds the VBO used to render simple textured quads.
+ */
void bindMeshBuffer();
+
+ /**
+ * Binds the specified VBO if needed.
+ */
void bindMeshBuffer(const GLuint buffer);
+
+ /**
+ * Unbinds the VBO used to render simple textured quads.
+ */
void unbindMeshBuffer();
+ /**
+ * Returns the mesh used to draw regions. Calling this method will
+ * bind a VBO of type GL_ELEMENT_ARRAY_BUFFER that contains the
+ * indices for the region mesh.
+ */
+ TextureVertex* getRegionMesh();
+
bool blend;
GLenum lastSrcMode;
GLenum lastDstMode;
@@ -118,7 +143,6 @@ public:
}; // class Caches
}; // namespace uirenderer
-
}; // namespace android
-#endif // ANDROID_UI_CACHES_H
+#endif // ANDROID_HWUI_CACHES_H
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 0dd9c5a..23ccef6 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -169,7 +169,8 @@ void DisplayList::replay(OpenGLRenderer& renderer) {
int saveCount = renderer.getSaveCount() - 1;
while (!mReader.eof()) {
- switch (mReader.readInt()) {
+ int op = mReader.readInt();
+ switch (op) {
case AcquireContext: {
renderer.acquireContext();
}
@@ -195,6 +196,11 @@ void DisplayList::replay(OpenGLRenderer& renderer) {
getPaint(), getInt());
}
break;
+ case SaveLayerAlpha: {
+ renderer.saveLayerAlpha(getFloat(), getFloat(), getFloat(), getFloat(),
+ getInt(), getInt());
+ }
+ break;
case Translate: {
renderer.translate(getFloat(), getFloat());
}
@@ -400,6 +406,15 @@ int DisplayListRenderer::saveLayer(float left, float top, float right, float bot
return OpenGLRenderer::save(flags);
}
+int DisplayListRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
+ int alpha, int flags) {
+ addOp(DisplayList::SaveLayerAlpha);
+ addBounds(left, top, right, bottom);
+ addInt(alpha);
+ addInt(flags);
+ return OpenGLRenderer::save(flags);
+}
+
void DisplayListRenderer::translate(float dx, float dy) {
addOp(DisplayList::Translate);
addPoint(dx, dy);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 6636de6..fd69fab 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_DISPLAY_LIST_RENDERER_H
-#define ANDROID_UI_DISPLAY_LIST_RENDERER_H
+#ifndef ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
+#define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
#include <SkChunkAlloc.h>
#include <SkFlattenable.h>
@@ -85,6 +85,7 @@ public:
Restore,
RestoreToCount,
SaveLayer,
+ SaveLayerAlpha,
Translate,
Rotate,
Scale,
@@ -222,6 +223,8 @@ public:
int saveLayer(float left, float top, float right, float bottom,
SkPaint* p, int flags);
+ int saveLayerAlpha(float left, float top, float right, float bottom,
+ int alpha, int flags);
void translate(float dx, float dy);
void rotate(float degrees);
@@ -411,4 +414,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_DISPLAY_LIST_RENDERER_H
+#endif // ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h
index d50d36e..eceb5c1 100644
--- a/libs/hwui/Extensions.h
+++ b/libs/hwui/Extensions.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_EXTENSIONS_H
-#define ANDROID_UI_EXTENSIONS_H
+#ifndef ANDROID_HWUI_EXTENSIONS_H
+#define ANDROID_HWUI_EXTENSIONS_H
#include <utils/SortedVector.h>
#include <utils/String8.h>
@@ -93,4 +93,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_EXTENSIONS_H
+#endif // ANDROID_HWUI_EXTENSIONS_H
diff --git a/libs/hwui/FboCache.h b/libs/hwui/FboCache.h
index ec4afe9..ad6cc3e 100644
--- a/libs/hwui/FboCache.h
+++ b/libs/hwui/FboCache.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_FBO_CACHE_H
-#define ANDROID_UI_FBO_CACHE_H
+#ifndef ANDROID_HWUI_FBO_CACHE_H
+#define ANDROID_HWUI_FBO_CACHE_H
#include <GLES2/gl2.h>
@@ -76,4 +76,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_FBO_CACHE_H
+#endif // ANDROID_HWUI_FBO_CACHE_H
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index e1a236c..5224689 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -556,6 +556,8 @@ void FontRenderer::issueDrawCommand() {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBufferID);
glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, NULL);
+
+ mDrawn = true;
}
void FontRenderer::appendMeshQuad(float x1, float y1, float z1, float u1, float v1, float x2,
@@ -595,6 +597,13 @@ void FontRenderer::appendMeshQuad(float x1, float y1, float z1, float u1, float
mCurrentQuadIndex++;
+ if (mBounds) {
+ mBounds->left = fmin(mBounds->left, x1);
+ mBounds->top = fmin(mBounds->top, y3);
+ mBounds->right = fmax(mBounds->right, x3);
+ mBounds->bottom = fmax(mBounds->bottom, y1);
+ }
+
if (mCurrentQuadIndex == mMaxNumberOfQuads) {
issueDrawCommand();
mCurrentQuadIndex = 0;
@@ -674,22 +683,27 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch
return image;
}
-void FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text,
- uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y) {
+bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text,
+ uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, Rect* bounds) {
checkInit();
if (!mCurrentFont) {
LOGE("No font set");
- return;
+ return false;
}
+ mDrawn = false;
+ mBounds = bounds;
mClip = clip;
mCurrentFont->renderUTF(paint, text, startIndex, len, numGlyphs, x, y);
+ mBounds = NULL;
if (mCurrentQuadIndex != 0) {
issueDrawCommand();
mCurrentQuadIndex = 0;
}
+
+ return mDrawn;
}
void FontRenderer::computeGaussianWeights(float* weights, int32_t radius) {
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index f10efad..a76cb86 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_FONT_RENDERER_H
-#define ANDROID_UI_FONT_RENDERER_H
+#ifndef ANDROID_HWUI_FONT_RENDERER_H
+#define ANDROID_HWUI_FONT_RENDERER_H
#include <utils/String8.h>
#include <utils/String16.h>
@@ -132,8 +132,8 @@ public:
}
void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
- void renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
- uint32_t len, int numGlyphs, int x, int y);
+ bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
+ uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
struct DropShadow {
DropShadow() { };
@@ -257,6 +257,8 @@ protected:
uint32_t mIndexBufferID;
const Rect* mClip;
+ Rect* mBounds;
+ bool mDrawn;
bool mInitialized;
@@ -273,4 +275,4 @@ protected:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_FONT_RENDERER_H
+#endif // ANDROID_HWUI_FONT_RENDERER_H
diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h
index 5fa45cf..b59ae81 100644
--- a/libs/hwui/GammaFontRenderer.h
+++ b/libs/hwui/GammaFontRenderer.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_GAMMA_FONT_RENDERER_H
-#define ANDROID_UI_GAMMA_FONT_RENDERER_H
+#ifndef ANDROID_HWUI_GAMMA_FONT_RENDERER_H
+#define ANDROID_HWUI_GAMMA_FONT_RENDERER_H
#include <SkPaint.h>
@@ -45,4 +45,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_GAMMA_FONT_RENDERER_H
+#endif // ANDROID_HWUI_GAMMA_FONT_RENDERER_H
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index 48877f6..c9553f4 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_GRADIENT_CACHE_H
-#define ANDROID_UI_GRADIENT_CACHE_H
+#ifndef ANDROID_HWUI_GRADIENT_CACHE_H
+#define ANDROID_HWUI_GRADIENT_CACHE_H
#include <SkShader.h>
@@ -93,4 +93,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_GRADIENT_CACHE_H
+#endif // ANDROID_HWUI_GRADIENT_CACHE_H
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 2afe2fa..a780183 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -14,13 +14,15 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_LAYER_H
-#define ANDROID_UI_LAYER_H
+#ifndef ANDROID_HWUI_LAYER_H
+#define ANDROID_HWUI_LAYER_H
#include <sys/types.h>
#include <GLES2/gl2.h>
+#include <ui/Region.h>
+
#include <SkXfermode.h>
#include "Rect.h"
@@ -85,9 +87,15 @@ struct Layer {
* Height of the layer texture.
*/
uint32_t height;
+
+ /**
+ * Dirty region indicating what parts of the layer
+ * have been drawn.
+ */
+ Region region;
}; // struct Layer
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_LAYER_H
+#endif // ANDROID_HWUI_LAYER_H
diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h
index ae792ab..4df8ab3 100644
--- a/libs/hwui/LayerCache.h
+++ b/libs/hwui/LayerCache.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_LAYER_CACHE_H
-#define ANDROID_UI_LAYER_CACHE_H
+#ifndef ANDROID_HWUI_LAYER_CACHE_H
+#define ANDROID_HWUI_LAYER_CACHE_H
#include "Layer.h"
#include "utils/SortedList.h"
@@ -138,4 +138,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_LAYER_CACHE_H
+#endif // ANDROID_HWUI_LAYER_CACHE_H
diff --git a/libs/hwui/Line.h b/libs/hwui/Line.h
index c529354..5c6f3d8 100644
--- a/libs/hwui/Line.h
+++ b/libs/hwui/Line.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_LINE_H
-#define ANDROID_UI_LINE_H
+#ifndef ANDROID_HWUI_LINE_H
+#define ANDROID_HWUI_LINE_H
#include <GLES2/gl2.h>
@@ -123,4 +123,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_LINE_H
+#endif // ANDROID_HWUI_LINE_H
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 83ea615..7462d5b 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -271,6 +271,19 @@ void Matrix4::mapRect(Rect& r) const {
MUL_ADD_STORE(r.right, data[kScaleX], data[kTranslateX]);
MUL_ADD_STORE(r.top, data[kScaleY], data[kTranslateY]);
MUL_ADD_STORE(r.bottom, data[kScaleY], data[kTranslateY]);
+
+ if (r.left > r.right) {
+ float x = r.left;
+ r.left = r.right;
+ r.right = x;
+ }
+
+ if (r.top > r.bottom) {
+ float y = r.top;
+ r.top = r.bottom;
+ r.bottom = y;
+ }
+
return;
}
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index fe81159..d678bd0 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_MATRIX_H
-#define ANDROID_UI_MATRIX_H
+#ifndef ANDROID_HWUI_MATRIX_H
+#define ANDROID_HWUI_MATRIX_H
#include <SkMatrix.h>
@@ -137,4 +137,4 @@ typedef Matrix4 mat4;
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_MATRIX_H
+#endif // ANDROID_HWUI_MATRIX_H
diff --git a/libs/hwui/OpenGLDebugRenderer.h b/libs/hwui/OpenGLDebugRenderer.h
index ce6a4aa..7787ff1 100644
--- a/libs/hwui/OpenGLDebugRenderer.h
+++ b/libs/hwui/OpenGLDebugRenderer.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_OPENGL_DEBUG_RENDERER_H
-#define ANDROID_UI_OPENGL_DEBUG_RENDERER_H
+#ifndef ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H
+#define ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H
#include "OpenGLRenderer.h"
@@ -66,4 +66,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_OPENGL_DEBUG_RENDERER_H
+#endif // ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index b167131..0f0316f 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -26,6 +26,8 @@
#include <utils/Log.h>
#include <utils/StopWatch.h>
+#include <ui/Rect.h>
+
#include "OpenGLRenderer.h"
namespace android {
@@ -285,7 +287,7 @@ int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
int alpha, int flags) {
- if (alpha == 0xff) {
+ if (alpha >= 255 - ALPHA_THRESHOLD) {
return saveLayer(left, top, right, bottom, NULL, flags);
} else {
SkPaint paint;
@@ -377,7 +379,6 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
bounds.getHeight() > mCaches.maxTextureSize) {
snapshot->invisible = true;
} else {
- // TODO: Should take the mode into account
snapshot->invisible = snapshot->previous->invisible ||
(alpha <= ALPHA_THRESHOLD && fboLayer);
}
@@ -387,8 +388,7 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
return false;
}
- glActiveTexture(GL_TEXTURE0);
-
+ glActiveTexture(gTextureUnits[0]);
Layer* layer = mCaches.layerCache.get(bounds.getWidth(), bounds.getHeight());
if (!layer) {
return false;
@@ -405,56 +405,7 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
snapshot->layer = layer;
if (fboLayer) {
- layer->fbo = mCaches.fboCache.get();
-
- snapshot->flags |= Snapshot::kFlagIsFboLayer;
- snapshot->fbo = layer->fbo;
- snapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
- snapshot->resetClip(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
- snapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
- snapshot->height = bounds.getHeight();
- snapshot->flags |= Snapshot::kFlagDirtyOrtho;
- snapshot->orthoMatrix.load(mOrthoMatrix);
-
- // Bind texture to FBO
- glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo);
- glBindTexture(GL_TEXTURE_2D, layer->texture);
-
- // Initialize the texture if needed
- if (layer->empty) {
- layer->empty = false;
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->width, layer->height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- }
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- layer->texture, 0);
-
-#if DEBUG_LAYERS
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- LOGE("Framebuffer incomplete (GL error code 0x%x)", status);
-
- glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
- glDeleteTextures(1, &layer->texture);
- mCaches.fboCache.put(layer->fbo);
-
- delete layer;
-
- return false;
- }
-#endif
-
- // Clear the FBO
- glScissor(0.0f, 0.0f, bounds.getWidth() + 1.0f, bounds.getHeight() + 1.0f);
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT);
-
- dirtyClip();
-
- // Change the ortho projection
- glViewport(0, 0, bounds.getWidth(), bounds.getHeight());
- mOrthoMatrix.loadOrtho(0.0f, bounds.getWidth(), bounds.getHeight(), 0.0f, -1.0f, 1.0f);
+ return createFboLayer(layer, bounds, snapshot, previousFbo);
} else {
// Copy the framebuffer into the layer
glBindTexture(GL_TEXTURE_2D, layer->texture);
@@ -475,6 +426,82 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
return true;
}
+bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> snapshot,
+ GLuint previousFbo) {
+ layer->fbo = mCaches.fboCache.get();
+
+#if RENDER_LAYERS_AS_REGIONS
+ snapshot->region = &snapshot->layer->region;
+ snapshot->flags |= Snapshot::kFlagFboTarget;
+#endif
+
+ Rect clip(bounds);
+ snapshot->transform->mapRect(clip);
+ clip.intersect(*snapshot->clipRect);
+ clip.snapToPixelBoundaries();
+ clip.intersect(snapshot->previous->viewport);
+
+ mat4 inverse;
+ inverse.loadInverse(*mSnapshot->transform);
+
+ inverse.mapRect(clip);
+ clip.snapToPixelBoundaries();
+ clip.intersect(bounds);
+
+ snapshot->flags |= Snapshot::kFlagIsFboLayer;
+ snapshot->fbo = layer->fbo;
+ snapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
+ //snapshot->resetClip(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
+ snapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
+ snapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
+ snapshot->height = bounds.getHeight();
+ snapshot->flags |= Snapshot::kFlagDirtyOrtho;
+ snapshot->orthoMatrix.load(mOrthoMatrix);
+
+ // Bind texture to FBO
+ glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo);
+ glBindTexture(GL_TEXTURE_2D, layer->texture);
+
+ // Initialize the texture if needed
+ if (layer->empty) {
+ layer->empty = false;
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->width, layer->height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ }
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ layer->texture, 0);
+
+#if DEBUG_LAYERS_AS_REGIONS
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ LOGE("Framebuffer incomplete (GL error code 0x%x)", status);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+ glDeleteTextures(1, &layer->texture);
+ mCaches.fboCache.put(layer->fbo);
+
+ delete layer;
+
+ return false;
+ }
+#endif
+
+ // Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
+ glScissor(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f,
+ clip.getWidth() + 2.0f, clip.getHeight() + 2.0f);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ dirtyClip();
+
+ // Change the ortho projection
+ glViewport(0, 0, bounds.getWidth(), bounds.getHeight());
+ mOrthoMatrix.loadOrtho(0.0f, bounds.getWidth(), bounds.getHeight(), 0.0f, -1.0f, 1.0f);
+
+ return true;
+}
+
/**
* Read the documentation of createLayer() before doing anything in this method.
*/
@@ -484,43 +511,37 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
return;
}
- const bool fboLayer = current->flags & SkCanvas::kClipToLayer_SaveFlag;
+ const bool fboLayer = current->flags & Snapshot::kFlagIsFboLayer;
if (fboLayer) {
// Unbind current FBO and restore previous one
glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo);
}
- // Restore the clip from the previous snapshot
- Rect& clip(*previous->clipRect);
- clip.snapToPixelBoundaries();
- glScissor(clip.left, previous->height - clip.bottom, clip.getWidth(), clip.getHeight());
-
Layer* layer = current->layer;
const Rect& rect = layer->layer;
if (!fboLayer && layer->alpha < 255) {
drawColorRect(rect.left, rect.top, rect.right, rect.bottom,
layer->alpha << 24, SkXfermode::kDstIn_Mode, true);
+ // Required below, composeLayerRect() will divide by 255
+ layer->alpha = 255;
}
- const Rect& texCoords = layer->texCoords;
mCaches.unbindMeshBuffer();
- resetDrawTextureTexCoords(texCoords.left, texCoords.top, texCoords.right, texCoords.bottom);
glActiveTexture(gTextureUnits[0]);
+
+ // When the layer is stored in an FBO, we can save a bit of fillrate by
+ // drawing only the dirty region
if (fboLayer) {
- drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
- layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
- &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount);
+ dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *previous->transform);
+ composeLayerRegion(layer, rect);
} else {
- drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
- 1.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
- &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, true, true);
+ dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
+ composeLayerRect(layer, rect, true);
}
- resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
-
if (fboLayer) {
// Detach the texture from the FBO
glBindFramebuffer(GL_FRAMEBUFFER, current->fbo);
@@ -541,6 +562,159 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
}
}
+void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
+ const Rect& texCoords = layer->texCoords;
+ resetDrawTextureTexCoords(texCoords.left, texCoords.top, texCoords.right, texCoords.bottom);
+
+ drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
+ layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
+ &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, swap, swap);
+
+ resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
+}
+
+void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
+#if RENDER_LAYERS_AS_REGIONS
+ if (layer->region.isRect()) {
+ composeLayerRect(layer, rect);
+ layer->region.clear();
+ return;
+ }
+
+ if (!layer->region.isEmpty()) {
+ size_t count;
+ const android::Rect* rects = layer->region.getArray(&count);
+
+ setupDraw();
+
+ ProgramDescription description;
+ description.hasTexture = true;
+
+ const float alpha = layer->alpha / 255.0f;
+ const bool setColor = description.setColor(alpha, alpha, alpha, alpha);
+ chooseBlending(layer->blend || layer->alpha < 255, layer->mode, description, false);
+
+ useProgram(mCaches.programCache.get(description));
+
+ // Texture
+ bindTexture(layer->texture);
+ glUniform1i(mCaches.currentProgram->getUniform("sampler"), 0);
+
+ // Always premultiplied
+ if (setColor) {
+ mCaches.currentProgram->setColor(alpha, alpha, alpha, alpha);
+ }
+
+ // Mesh
+ int texCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
+ glEnableVertexAttribArray(texCoordsSlot);
+
+ mModelView.loadIdentity();
+ mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
+
+ const float texX = 1.0f / float(layer->width);
+ const float texY = 1.0f / float(layer->height);
+
+ TextureVertex* mesh = mCaches.getRegionMesh();
+ GLsizei numQuads = 0;
+
+ glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
+ gMeshStride, &mesh[0].position[0]);
+ glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE,
+ gMeshStride, &mesh[0].texture[0]);
+
+ for (size_t i = 0; i < count; i++) {
+ const android::Rect* r = &rects[i];
+
+ const float u1 = r->left * texX;
+ const float v1 = (rect.getHeight() - r->top) * texY;
+ const float u2 = r->right * texX;
+ const float v2 = (rect.getHeight() - r->bottom) * texY;
+
+ // TODO: Reject quads outside of the clip
+ TextureVertex::set(mesh++, r->left, r->top, u1, v1);
+ TextureVertex::set(mesh++, r->right, r->top, u2, v1);
+ TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
+ TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
+
+ numQuads++;
+
+ if (numQuads >= REGION_MESH_QUAD_COUNT) {
+ glDrawElements(GL_TRIANGLES, numQuads * 6, GL_UNSIGNED_SHORT, NULL);
+ numQuads = 0;
+ mesh = mCaches.getRegionMesh();
+ }
+ }
+
+ if (numQuads > 0) {
+ glDrawElements(GL_TRIANGLES, numQuads * 6, GL_UNSIGNED_SHORT, NULL);
+ }
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glDisableVertexAttribArray(texCoordsSlot);
+
+#if DEBUG_LAYERS_AS_REGIONS
+ uint32_t colors[] = {
+ 0x7fff0000, 0x7f00ff00,
+ 0x7f0000ff, 0x7fff00ff,
+ };
+
+ int offset = 0;
+ int32_t top = rects[0].top;
+ int i = 0;
+
+ for (size_t i = 0; i < count; i++) {
+ if (top != rects[i].top) {
+ offset ^= 0x2;
+ top = rects[i].top;
+ }
+
+ Rect r(rects[i].left, rects[i].top, rects[i].right, rects[i].bottom);
+ drawColorRect(r.left, r.top, r.right, r.bottom, colors[offset + (i & 0x1)],
+ SkXfermode::kSrcOver_Mode);
+ }
+#endif
+
+ layer->region.clear();
+ }
+#else
+ composeLayerRect(layer, rect);
+#endif
+}
+
+void OpenGLRenderer::dirtyLayer(const float left, const float top,
+ const float right, const float bottom, const mat4 transform) {
+#if RENDER_LAYERS_AS_REGIONS
+ if ((mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region) {
+ Rect bounds(left, top, right, bottom);
+ transform.mapRect(bounds);
+ bounds.intersect(*mSnapshot->clipRect);
+ bounds.snapToPixelBoundaries();
+
+ android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
+ if (!dirty.isEmpty()) {
+ mSnapshot->region->orSelf(dirty);
+ }
+ }
+#endif
+}
+
+void OpenGLRenderer::dirtyLayer(const float left, const float top,
+ const float right, const float bottom) {
+#if RENDER_LAYERS_AS_REGIONS
+ if ((mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region) {
+ Rect bounds(left, top, right, bottom);
+ bounds.intersect(*mSnapshot->clipRect);
+ bounds.snapToPixelBoundaries();
+
+ android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
+ if (!dirty.isEmpty()) {
+ mSnapshot->region->orSelf(dirty);
+ }
+ }
+#endif
+}
+
void OpenGLRenderer::setupDraw() {
clearLayerRegions();
if (mDirtyClip) {
@@ -551,21 +725,26 @@ void OpenGLRenderer::setupDraw() {
void OpenGLRenderer::clearLayerRegions() {
if (mLayers.size() == 0 || mSnapshot->invisible) return;
+ Rect clipRect(*mSnapshot->clipRect);
+ clipRect.snapToPixelBoundaries();
+
for (uint32_t i = 0; i < mLayers.size(); i++) {
Rect* bounds = mLayers.itemAt(i);
-
- // Clear the framebuffer where the layer will draw
- glScissor(bounds->left, mSnapshot->height - bounds->bottom,
- bounds->getWidth(), bounds->getHeight());
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT);
+ if (clipRect.intersects(*bounds)) {
+ // Clear the framebuffer where the layer will draw
+ glScissor(bounds->left, mSnapshot->height - bounds->bottom,
+ bounds->getWidth(), bounds->getHeight());
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ // Restore the clip
+ dirtyClip();
+ }
delete bounds;
}
- mLayers.clear();
- // Restore the clip
- dirtyClip();
+ mLayers.clear();
}
///////////////////////////////////////////////////////////////////////////////
@@ -678,7 +857,12 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* pai
if (!texture) return;
const AutoTexture autoCleanup(texture);
- drawTextureRect(r.left, r.top, r.right, r.bottom, texture, paint);
+ // This could be done in a cheaper way, all we need is pass the matrix
+ // to the vertex shader. The save/restore is a bit overkill.
+ save(SkCanvas::kMatrix_SaveFlag);
+ concatMatrix(matrix);
+ drawTextureRect(0.0f, 0.0f, bitmap->width(), bitmap->height(), texture, paint);
+ restore();
}
void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
@@ -738,11 +922,21 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int
right - left, bottom - top, xDivs, yDivs, colors, width, height, numColors);
if (mesh) {
- // Specify right and bottom as +1.0f from left/top to prevent scaling since the
- // patch mesh already defines the final size
- drawTextureMesh(left, top, left + 1.0f, top + 1.0f, texture->id, alpha / 255.0f,
+ // Mark the current layer dirty where we are going to draw the patch
+ if ((mSnapshot->flags & Snapshot::kFlagFboTarget) &&
+ mSnapshot->region && mesh->hasEmptyQuads) {
+ const size_t count = mesh->quads.size();
+ for (size_t i = 0; i < count; i++) {
+ Rect bounds = mesh->quads.itemAt(i);
+ dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
+ *mSnapshot->transform);
+ }
+ }
+
+ drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f,
mode, texture->blend, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset,
- GL_TRIANGLES, mesh->verticesCount, false, false, mesh->meshBuffer);
+ GL_TRIANGLES, mesh->verticesCount, false, false, mesh->meshBuffer,
+ true, !mesh->hasEmptyQuads);
}
}
@@ -801,6 +995,7 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
mModelView.scale(length, strokeWidth, 1.0f);
}
mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
+ // TODO: Add bounds to the layer's region
if (mShader) {
mShader->updateTransforms(mCaches.currentProgram, mModelView, *mSnapshot);
@@ -904,13 +1099,34 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
// Assume that the modelView matrix does not force scales, rotates, etc.
const bool linearFilter = mSnapshot->transform->changesBounds();
+
+ // Dimensions are set to (0,0), the layer (if any) won't be dirtied
setupTextureAlpha8(fontRenderer.getTexture(linearFilter), 0, 0, textureUnit,
x, y, r, g, b, a, mode, false, true, NULL, NULL);
const Rect& clip = mSnapshot->getLocalClip();
+ Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
+
+#if RENDER_LAYERS_AS_REGIONS
+ bool hasLayer = (mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region;
+#else
+ bool hasLayer = false;
+#endif
mCaches.unbindMeshBuffer();
- fontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y);
+ if (fontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y,
+ hasLayer ? &bounds : NULL)) {
+#if RENDER_LAYERS_AS_REGIONS
+ if (hasLayer) {
+ mSnapshot->transform->mapRect(bounds);
+ bounds.intersect(*mSnapshot->clipRect);
+ bounds.snapToPixelBoundaries();
+
+ android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
+ mSnapshot->region->orSelf(dirty);
+ }
+#endif
+ }
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords"));
@@ -1081,7 +1297,12 @@ void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t
} else {
mModelView.loadIdentity();
}
+
mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
+ if (width > 0 && height > 0) {
+ dirtyLayer(x, y, x + width, y + height, *mSnapshot->transform);
+ }
+
if (setColor) {
mCaches.currentProgram->setColor(r, g, b, a);
}
@@ -1214,9 +1435,11 @@ void OpenGLRenderer::setupColorRect(float left, float top, float right, float bo
mModelView.scale(right - left, bottom - top, 1.0f);
if (!ignoreTransform) {
mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
+ dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
} else {
mat4 identity;
mCaches.currentProgram->set(mOrthoMatrix, mModelView, identity);
+ dirtyLayer(left, top, right, bottom);
}
mCaches.currentProgram->setColor(r, g, b, a);
@@ -1251,7 +1474,7 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b
void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom,
GLuint texture, float alpha, SkXfermode::Mode mode, bool blend,
GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
- bool swapSrcDst, bool ignoreTransform, GLuint vbo) {
+ bool swapSrcDst, bool ignoreTransform, GLuint vbo, bool ignoreScale, bool dirty) {
setupDraw();
ProgramDescription description;
@@ -1262,16 +1485,20 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
}
mModelView.loadTranslate(left, top, 0.0f);
- mModelView.scale(right - left, bottom - top, 1.0f);
+ if (!ignoreScale) {
+ mModelView.scale(right - left, bottom - top, 1.0f);
+ }
chooseBlending(blend || alpha < 1.0f, mode, description, swapSrcDst);
useProgram(mCaches.programCache.get(description));
if (!ignoreTransform) {
mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
+ if (dirty) dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
} else {
- mat4 m;
- mCaches.currentProgram->set(mOrthoMatrix, mModelView, m);
+ mat4 identity;
+ mCaches.currentProgram->set(mOrthoMatrix, mModelView, identity);
+ if (dirty) dirtyLayer(left, top, right, bottom);
}
// Texture
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 3492d2c..2d612d4 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_OPENGL_RENDERER_H
-#define ANDROID_UI_OPENGL_RENDERER_H
+#ifndef ANDROID_HWUI_OPENGL_RENDERER_H
+#define ANDROID_HWUI_OPENGL_RENDERER_H
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
@@ -50,6 +50,10 @@ namespace uirenderer {
// Debug
#define DEBUG_OPENGL 1
+// If turned on, layers drawn inside FBOs are optimized with regions
+#define RENDER_LAYERS_AS_REGIONS 0
+#define DEBUG_LAYERS_AS_REGIONS 0
+
///////////////////////////////////////////////////////////////////////////////
// Renderer
///////////////////////////////////////////////////////////////////////////////
@@ -176,6 +180,34 @@ private:
int alpha, SkXfermode::Mode mode, int flags, GLuint previousFbo);
/**
+ * Creates a new layer stored in the specified snapshot as an FBO.
+ *
+ * @param layer The layer to store as an FBO
+ * @param snapshot The snapshot associated with the new layer
+ * @param bounds The bounds of the layer
+ * @param previousFbo The name of the current framebuffer
+ */
+ bool createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> snapshot,
+ GLuint previousFbo);
+
+ /**
+ * Compose the specified layer as a region.
+ *
+ * @param layer The layer to compose
+ * @param rect The layer's bounds
+ */
+ void composeLayerRegion(Layer* layer, const Rect& rect);
+
+ /**
+ * Compose the specified layer as a simple rectangle.
+ *
+ * @param layer The layer to compose
+ * @param rect The layer's bounds
+ * @param swap If true, the source and destination are swapped
+ */
+ void composeLayerRect(Layer* layer, const Rect& rect, bool swap = false);
+
+ /**
* Clears all the regions corresponding to the current list of layers.
* This method MUST be invoked before any drawing operation.
*/
@@ -192,7 +224,7 @@ private:
* @param color The rectangle's ARGB color, defined as a packed 32 bits word
* @param mode The Skia xfermode to use
* @param ignoreTransform True if the current transform should be ignored
- * @paran ignoreBlending True if the blending is set by the caller
+ * @param ignoreBlending True if the blending is set by the caller
*/
void drawColorRect(float left, float top, float right, float bottom,
int color, SkXfermode::Mode mode, bool ignoreTransform = false);
@@ -252,11 +284,14 @@ private:
* @param swapSrcDst Whether or not the src and dst blending operations should be swapped
* @param ignoreTransform True if the current transform should be ignored
* @param vbo The VBO used to draw the mesh
+ * @param ignoreScale True if the model view matrix should not be scaled
+ * @param dirty True if calling this method should dirty the current layer
*/
void drawTextureMesh(float left, float top, float right, float bottom, GLuint texture,
float alpha, SkXfermode::Mode mode, bool blend,
GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
- bool swapSrcDst = false, bool ignoreTransform = false, GLuint vbo = 0);
+ bool swapSrcDst = false, bool ignoreTransform = false, GLuint vbo = 0,
+ bool ignoreScale = false, bool dirty = true);
/**
* Prepares the renderer to draw the specified shadow. The active texture
@@ -411,6 +446,18 @@ private:
mDirtyClip = true;
}
+ /**
+ * Mark the layer as dirty at the specified coordinates. The coordinates
+ * are transformed with the supplied matrix.
+ */
+ void dirtyLayer(const float left, const float top, const float right, const float bottom,
+ const mat4 transform);
+
+ /**
+ * Mark the layer as dirty at the specified coordinates.
+ */
+ void dirtyLayer(const float left, const float top, const float right, const float bottom);
+
// Dimensions of the drawing surface
int mWidth, mHeight;
@@ -462,4 +509,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_OPENGL_RENDERER_H
+#endif // ANDROID_HWUI_OPENGL_RENDERER_H
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 3d21431..9b2d476 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -34,6 +34,7 @@ Patch::Patch(const uint32_t xCount, const uint32_t yCount, const int8_t emptyQua
// 2 triangles per patch, 3 vertices per triangle
verticesCount = ((xCount + 1) * (yCount + 1) - emptyQuads) * 2 * 3;
mVertices = new TextureVertex[verticesCount];
+ hasEmptyQuads = emptyQuads > 0;
glGenBuffers(1, &meshBuffer);
}
@@ -51,6 +52,8 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
float left, float top, float right, float bottom,
const int32_t* xDivs, const int32_t* yDivs,
const uint32_t width, const uint32_t height, const uint32_t colorKey) {
+ if (hasEmptyQuads) quads.clear();
+
const uint32_t xStretchCount = (width + 1) >> 1;
const uint32_t yStretchCount = (height + 1) >> 1;
@@ -118,7 +121,7 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
mVertices, GL_STATIC_DRAW);
}
-inline void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, float v2,
+void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, float v2,
const int32_t xDivs[], uint32_t xCount, float stretchX, float width, float bitmapWidth,
uint32_t& quadCount, const uint32_t colorKey) {
float previousStepX = 0.0f;
@@ -150,12 +153,17 @@ inline void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float
generateQuad(vertex, x1, y1, width, y2, u1, v1, 1.0f, v2, quadCount, colorKey);
}
-inline void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
+void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
float u1, float v1, float u2, float v2, uint32_t& quadCount, const uint32_t colorKey) {
if (((colorKey >> quadCount++) & 0x1) == 1) {
return;
}
+ if (hasEmptyQuads) {
+ Rect bounds(x1, y1, x2, y2);
+ quads.add(bounds);
+ }
+
// Left triangle
TextureVertex::set(vertex++, x1, y1, u1, v1);
TextureVertex::set(vertex++, x2, y1, u2, v1);
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index ce898937..1e78b2f 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -14,13 +14,16 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_PATCH_H
-#define ANDROID_UI_PATCH_H
+#ifndef ANDROID_HWUI_PATCH_H
+#define ANDROID_HWUI_PATCH_H
#include <sys/types.h>
#include <GLES2/gl2.h>
+#include <utils/Vector.h>
+
+#include "Rect.h"
#include "Vertex.h"
#include "utils/Compare.h"
@@ -96,15 +99,17 @@ struct Patch {
GLuint meshBuffer;
uint32_t verticesCount;
+ Vector<Rect> quads;
+ bool hasEmptyQuads;
private:
TextureVertex* mVertices;
- static inline void generateRow(TextureVertex*& vertex, float y1, float y2,
+ void generateRow(TextureVertex*& vertex, float y1, float y2,
float v1, float v2, const int32_t xDivs[], uint32_t xCount,
float stretchX, float width, float bitmapWidth,
uint32_t& quadCount, const uint32_t colorKey);
- static inline void generateQuad(TextureVertex*& vertex,
+ void generateQuad(TextureVertex*& vertex,
float x1, float y1, float x2, float y2,
float u1, float v1, float u2, float v2,
uint32_t& quadCount, const uint32_t colorKey);
@@ -113,4 +118,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_PATCH_H
+#endif // ANDROID_HWUI_PATCH_H
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index f4eeb09..deba40d 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_PATCH_CACHE_H
-#define ANDROID_UI_PATCH_CACHE_H
+#ifndef ANDROID_HWUI_PATCH_CACHE_H
+#define ANDROID_HWUI_PATCH_CACHE_H
#include <utils/KeyedVector.h>
@@ -62,4 +62,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_PATCH_CACHE_H
+#endif // ANDROID_HWUI_PATCH_CACHE_H
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index 9a5fc45..db5ce08 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_PATH_CACHE_H
-#define ANDROID_UI_PATH_CACHE_H
+#ifndef ANDROID_HWUI_PATH_CACHE_H
+#define ANDROID_HWUI_PATH_CACHE_H
#include <SkBitmap.h>
#include <SkPaint.h>
@@ -170,4 +170,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_PATH_CACHE_H
+#endif // ANDROID_HWUI_PATH_CACHE_H
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index 25674c6..baed5fd 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -22,12 +22,6 @@ namespace android {
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
-// Shaders
-///////////////////////////////////////////////////////////////////////////////
-
-#define SHADER_SOURCE(name, source) const char* name = #source
-
-///////////////////////////////////////////////////////////////////////////////
// Base program
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index 026097c..5981662 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_PROGRAM_H
-#define ANDROID_UI_PROGRAM_H
+#ifndef ANDROID_HWUI_PROGRAM_H
+#define ANDROID_HWUI_PROGRAM_H
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
@@ -131,4 +131,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_PROGRAM_H
+#endif // ANDROID_HWUI_PROGRAM_H
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index 9cb13b3..186e869 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_PROGRAM_CACHE_H
-#define ANDROID_UI_PROGRAM_CACHE_H
+#ifndef ANDROID_HWUI_PROGRAM_CACHE_H
+#define ANDROID_HWUI_PROGRAM_CACHE_H
#include <utils/KeyedVector.h>
#include <utils/Log.h>
@@ -258,4 +258,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_PROGRAM_CACHE_H
+#endif // ANDROID_HWUI_PROGRAM_CACHE_H
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index db3cb4d..813392b 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_PROPERTIES_H
-#define ANDROID_UI_PROPERTIES_H
+#ifndef ANDROID_HWUI_PROPERTIES_H
+#define ANDROID_HWUI_PROPERTIES_H
#include <cutils/properties.h>
@@ -45,15 +45,15 @@
#define MB(s) s * 1024 * 1024
#define DEFAULT_TEXTURE_CACHE_SIZE 20.0f
-#define DEFAULT_LAYER_CACHE_SIZE 6.0f
+#define DEFAULT_LAYER_CACHE_SIZE 8.0f
#define DEFAULT_PATH_CACHE_SIZE 4.0f
#define DEFAULT_PATCH_CACHE_SIZE 512
#define DEFAULT_GRADIENT_CACHE_SIZE 0.5f
#define DEFAULT_DROP_SHADOW_CACHE_SIZE 2.0f
-#define DEFAULT_FBO_CACHE_SIZE 25
+#define DEFAULT_FBO_CACHE_SIZE 12
#define DEFAULT_TEXT_GAMMA 1.4f
#define DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD 64
#define DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD 192
-#endif // ANDROID_UI_PROPERTIES_H
+#endif // ANDROID_HWUI_PROPERTIES_H
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index 8f3655c..71951b7 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -14,8 +14,10 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_RECT_H
-#define ANDROID_UI_RECT_H
+#ifndef ANDROID_HWUI_RECT_H
+#define ANDROID_HWUI_RECT_H
+
+#include <cmath>
#include <utils/Log.h>
@@ -32,25 +34,35 @@ struct Rect {
float right;
float bottom;
- Rect():
+ // Used by Region
+ typedef float value_type;
+
+ inline Rect():
left(0),
top(0),
right(0),
bottom(0) {
}
- Rect(float left, float top, float right, float bottom):
+ inline Rect(float left, float top, float right, float bottom):
left(left),
top(top),
right(right),
bottom(bottom) {
}
- Rect(const Rect& r) {
+ inline Rect(float width, float height):
+ left(0.0f),
+ top(0.0f),
+ right(width),
+ bottom(height) {
+ }
+
+ inline Rect(const Rect& r) {
set(r);
}
- Rect(Rect& r) {
+ inline Rect(Rect& r) {
set(r);
}
@@ -72,22 +84,26 @@ struct Rect {
return memcmp(&a, &b, sizeof(a));
}
- bool isEmpty() const {
+ inline void clear() {
+ left = top = right = bottom = 0.0f;
+ }
+
+ inline bool isEmpty() const {
return left >= right || top >= bottom;
}
- void setEmpty() {
- memset(this, 0, sizeof(*this));
+ inline void setEmpty() {
+ left = top = right = bottom = 0.0f;
}
- void set(float left, float top, float right, float bottom) {
+ inline void set(float left, float top, float right, float bottom) {
this->left = left;
this->right = right;
this->top = top;
this->bottom = bottom;
}
- void set(const Rect& r) {
+ inline void set(const Rect& r) {
set(r.left, r.top, r.right, r.bottom);
}
@@ -148,6 +164,13 @@ struct Rect {
return false;
}
+ void translate(float dx, float dy) {
+ left += dx;
+ right += dx;
+ top += dy;
+ bottom += dy;
+ }
+
void snapToPixelBoundaries() {
left = floorf(left + 0.5f);
top = floorf(top + 0.5f);
@@ -164,4 +187,4 @@ struct Rect {
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_RECT_H
+#endif // ANDROID_HWUI_RECT_H
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index d9b3718..2256fd1 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_RESOURCE_CACHE_H
-#define ANDROID_UI_RESOURCE_CACHE_H
+#ifndef ANDROID_HWUI_RESOURCE_CACHE_H
+#define ANDROID_HWUI_RESOURCE_CACHE_H
#include <SkBitmap.h>
#include <SkiaColorFilter.h>
@@ -75,4 +75,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_RESOURCE_CACHE_H
+#endif // ANDROID_HWUI_RESOURCE_CACHE_H
diff --git a/libs/hwui/SkiaColorFilter.h b/libs/hwui/SkiaColorFilter.h
index 17f49f9..bf45e13 100644
--- a/libs/hwui/SkiaColorFilter.h
+++ b/libs/hwui/SkiaColorFilter.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_SKIA_COLOR_FILTER_H
-#define ANDROID_UI_SKIA_COLOR_FILTER_H
+#ifndef ANDROID_HWUI_SKIA_COLOR_FILTER_H
+#define ANDROID_HWUI_SKIA_COLOR_FILTER_H
#include <GLES2/gl2.h>
#include <SkColorFilter.h>
@@ -123,4 +123,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_SKIA_COLOR_FILTER_H
+#endif // ANDROID_HWUI_SKIA_COLOR_FILTER_H
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 4cd1b8b..1d884ab 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_SKIA_SHADER_H
-#define ANDROID_UI_SKIA_SHADER_H
+#ifndef ANDROID_HWUI_SKIA_SHADER_H
+#define ANDROID_HWUI_SKIA_SHADER_H
#include <SkShader.h>
#include <SkXfermode.h>
@@ -216,4 +216,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_SKIA_SHADER_H
+#endif // ANDROID_HWUI_SKIA_SHADER_H
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 2da1950..9f78063 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_SNAPSHOT_H
-#define ANDROID_UI_SNAPSHOT_H
+#ifndef ANDROID_HWUI_SNAPSHOT_H
+#define ANDROID_HWUI_SNAPSHOT_H
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <utils/RefBase.h>
+#include <ui/Region.h>
#include <SkCanvas.h>
-#include <SkRegion.h>
#include "Layer.h"
#include "Matrix.h"
@@ -46,6 +46,7 @@ public:
Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0), invisible(false) {
transform = &mTransformRoot;
clipRect = &mClipRectRoot;
+ region = NULL;
}
/**
@@ -75,6 +76,13 @@ public:
} else {
flags |= Snapshot::kFlagDirtyLocalClip;
}
+
+ if (s->flags & Snapshot::kFlagFboTarget) {
+ flags |= Snapshot::kFlagFboTarget;
+ region = s->region;
+ } else {
+ region = NULL;
+ }
}
/**
@@ -105,6 +113,11 @@ public:
* Indicates that this snapshot has changed the ortho matrix.
*/
kFlagDirtyOrtho = 0x10,
+ /**
+ * Indicates that this snapshot or an ancestor snapshot is
+ * an FBO layer.
+ */
+ kFlagFboTarget = 0x20
};
/**
@@ -243,6 +256,11 @@ public:
*/
Rect* clipRect;
+ /**
+ * The ancestor layer's dirty region..
+ */
+ Region* region;
+
private:
mat4 mTransformRoot;
Rect mClipRectRoot;
@@ -253,4 +271,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_SNAPSHOT_H
+#endif // ANDROID_HWUI_SNAPSHOT_H
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index 16e2814..adf09e2 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_TEXT_DROP_SHADOW_CACHE_H
-#define ANDROID_UI_TEXT_DROP_SHADOW_CACHE_H
+#ifndef ANDROID_HWUI_TEXT_DROP_SHADOW_CACHE_H
+#define ANDROID_HWUI_TEXT_DROP_SHADOW_CACHE_H
#include <GLES2/gl2.h>
@@ -148,4 +148,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_TEXT_DROP_SHADOW_CACHE_H
+#endif // ANDROID_HWUI_TEXT_DROP_SHADOW_CACHE_H
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index 755074d..4922bb3 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_TEXTURE_H
-#define ANDROID_UI_TEXTURE_H
+#ifndef ANDROID_HWUI_TEXTURE_H
+#define ANDROID_HWUI_TEXTURE_H
#include <GLES2/gl2.h>
@@ -86,4 +86,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_TEXTURE_H
+#endif // ANDROID_HWUI_TEXTURE_H
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index d860953..0c7948f 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -200,9 +200,13 @@ void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool rege
texture->blend = !bitmap->isOpaque();
break;
case SkBitmap::kIndex8_Config:
- uploadPalettedTexture(resize, bitmap, texture->width, texture->height);
+ uploadLoFiTexture(resize, bitmap, texture->width, texture->height);
texture->blend = false;
break;
+ case SkBitmap::kARGB_4444_Config:
+ uploadLoFiTexture(resize, bitmap, texture->width, texture->height);
+ texture->blend = true;
+ break;
default:
LOGW("Unsupported bitmap config: %d", bitmap->getConfig());
break;
@@ -215,7 +219,7 @@ void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool rege
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
-void TextureCache::uploadPalettedTexture(bool resize, SkBitmap* bitmap,
+void TextureCache::uploadLoFiTexture(bool resize, SkBitmap* bitmap,
uint32_t width, uint32_t height) {
SkBitmap rgbaBitmap;
rgbaBitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 6718597..d9d2387 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_TEXTURE_CACHE_H
-#define ANDROID_UI_TEXTURE_CACHE_H
+#ifndef ANDROID_HWUI_TEXTURE_CACHE_H
+#define ANDROID_HWUI_TEXTURE_CACHE_H
#include <SkBitmap.h>
@@ -93,7 +93,7 @@ private:
*/
void generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate = false);
- void uploadPalettedTexture(bool resize, SkBitmap* bitmap, uint32_t width, uint32_t height);
+ void uploadLoFiTexture(bool resize, SkBitmap* bitmap, uint32_t width, uint32_t height);
void uploadToTexture(bool resize, GLenum format, GLsizei width, GLsizei height,
GLenum type, const GLvoid * data);
@@ -115,4 +115,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_TEXTURE_CACHE_H
+#endif // ANDROID_HWUI_TEXTURE_CACHE_H
diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h
index 1f54086..bbf4d4a 100644
--- a/libs/hwui/Vertex.h
+++ b/libs/hwui/Vertex.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_VERTEX_H
-#define ANDROID_UI_VERTEX_H
+#ifndef ANDROID_HWUI_VERTEX_H
+#define ANDROID_HWUI_VERTEX_H
namespace android {
namespace uirenderer {
@@ -43,4 +43,4 @@ struct TextureVertex {
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_VERTEX_H
+#endif // ANDROID_HWUI_VERTEX_H
diff --git a/libs/hwui/utils/Compare.h b/libs/hwui/utils/Compare.h
index 5ea0fc9..6531e78 100644
--- a/libs/hwui/utils/Compare.h
+++ b/libs/hwui/utils/Compare.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_COMPARE_H
-#define ANDROID_UI_COMPARE_H
+#ifndef ANDROID_HWUI_COMPARE_H
+#define ANDROID_HWUI_COMPARE_H
#include <cmath>
@@ -37,4 +37,4 @@
if (a < rhs.a) return true; \
if (a == rhs.a)
-#endif // ANDROID_UI_COMPARE_H
+#endif // ANDROID_HWUI_COMPARE_H
diff --git a/libs/hwui/utils/GenerationCache.h b/libs/hwui/utils/GenerationCache.h
index 5cea30f..2e76236 100644
--- a/libs/hwui/utils/GenerationCache.h
+++ b/libs/hwui/utils/GenerationCache.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_GENERATION_CACHE_H
-#define ANDROID_UI_GENERATION_CACHE_H
+#ifndef ANDROID_HWUI_GENERATION_CACHE_H
+#define ANDROID_HWUI_GENERATION_CACHE_H
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
@@ -242,4 +242,4 @@ void GenerationCache<K, V>::detachFromCache(sp<Entry<K, V> > entry) {
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_GENERATION_CACHE_H
+#endif // ANDROID_HWUI_GENERATION_CACHE_H
diff --git a/libs/hwui/utils/SortedList.h b/libs/hwui/utils/SortedList.h
index 68f5e9d..2fa890a 100644
--- a/libs/hwui/utils/SortedList.h
+++ b/libs/hwui/utils/SortedList.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_SORTED_LIST_H
-#define ANDROID_UI_SORTED_LIST_H
+#ifndef ANDROID_HWUI_SORTED_LIST_H
+#define ANDROID_HWUI_SORTED_LIST_H
#include <stdint.h>
#include <sys/types.h>
@@ -239,4 +239,4 @@ int SortedList<TYPE>::do_compare(const void* lhs, const void* rhs) const {
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_SORTED_LIST_H
+#endif // ANDROID_HWUI_SORTED_LIST_H
diff --git a/libs/hwui/utils/SortedListImpl.h b/libs/hwui/utils/SortedListImpl.h
index 7da09ef..dc385b5 100644
--- a/libs/hwui/utils/SortedListImpl.h
+++ b/libs/hwui/utils/SortedListImpl.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_UI_SORTED_LIST_IMPL_H
-#define ANDROID_UI_SORTED_LIST_IMPL_H
+#ifndef ANDROID_HWUI_SORTED_LIST_IMPL_H
+#define ANDROID_HWUI_SORTED_LIST_IMPL_H
#include <utils/VectorImpl.h>
@@ -62,4 +62,4 @@ private:
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_UI_SORTED_LIST_IMPL_H
+#endif // ANDROID_HWUI_SORTED_LIST_IMPL_H
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 12db908..1994f6a 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -289,7 +289,7 @@ private:
void flushSpan() {
bool merge = false;
if (tail-head == ssize_t(span.size())) {
- Rect const* p = cur;
+ Rect const* p = span.editArray();
Rect const* q = head;
if (p->top == q->bottom) {
merge = true;