Optimize FBO drawing with regions.
This optimization is currently disabled until Launcher is modified to take advantage of it. The optimization can be enabled by turning on RENDER_LAYERS_AS_REGIONS in the OpenGLRenderer.h file. Change-Id: I2fdf59d0f4dc690a3d7f712173ab8db3848b27b1
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,42 +511,36 @@ 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]);
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
|
||||
resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
// When the layer is stored in an FBO, we can save a bit of fillrate by
|
||||
// drawing only the dirty region
|
||||
if (fboLayer) {
|
||||
dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *previous->transform);
|
||||
composeLayerRegion(layer, rect);
|
||||
} else {
|
||||
dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
|
||||
composeLayerRect(layer, rect, true);
|
||||
}
|
||||
|
||||
if (fboLayer) {
|
||||
// Detach the texture from the 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);
|
||||
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);
|
||||
|
||||
// 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
|
||||
|
||||
@@ -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
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -175,6 +179,34 @@ private:
|
||||
bool createLayer(sp<Snapshot> snapshot, float left, float top, float right, float bottom,
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -21,12 +21,6 @@
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Shaders
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define SHADER_SOURCE(name, source) const char* name = #source
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Base program
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user