Fix colored rects clipping and code cleanup
The drawColorRects() method was clipping individual rectangles
using the wrong parameters left, top, right and bottom instead
of l, r, t and b. It also checked for count == 0 after the loop
when it should have checked for vertexCount == 0. The quickReject
is now not part of the loop since it's a bit overkill to perform
so many matrix multiplications. What we really care about is the
final quickReject performed on the max bounds of the entire set
of rectangles.
This change also replaces all instances of mSnapshot->transform
by currentTransform() to make the code slightly more readable.
Change-Id: I6485280414499716852f7dbfba186774eb6763d4
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 2d017df..204e8f5 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -454,6 +454,14 @@
}
}
+void Matrix4::decomposeScale(float& sx, float& sy) const {
+ float len;
+ len = data[mat4::kScaleX] * data[mat4::kScaleX] + data[mat4::kSkewX] * data[mat4::kSkewX];
+ sx = copysignf(sqrtf(len), data[mat4::kScaleX]);
+ len = data[mat4::kScaleY] * data[mat4::kScaleY] + data[mat4::kSkewY] * data[mat4::kSkewY];
+ sy = copysignf(sqrtf(len), data[mat4::kScaleY]);
+}
+
void Matrix4::dump() const {
ALOGD("Matrix4[simple=%d, type=0x%x", isSimple(), getType());
ALOGD(" %f %f %f %f", data[kScaleX], data[kSkewX], data[8], data[kTranslateX]);
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 2fe96bc..be5bea70 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -79,6 +79,20 @@
load(v);
}
+ float operator[](int index) const {
+ return data[index];
+ }
+
+ float& operator[](int index) {
+ mType = kTypeUnknown;
+ return data[index];
+ }
+
+ Matrix4& operator=(const SkMatrix& v) {
+ load(v);
+ return *this;
+ }
+
void loadIdentity();
void load(const float* v);
@@ -150,6 +164,8 @@
float getTranslateX();
float getTranslateY();
+ void decomposeScale(float& sx, float& sy) const;
+
void dump() const;
static const Matrix4& identity();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index c81bf7a..9c12419 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -723,7 +723,7 @@
Rect clip;
Rect bounds(left, top, right, bottom);
Rect untransformedBounds(bounds);
- mSnapshot->transform->mapRect(bounds);
+ currentTransform().mapRect(bounds);
// Layers only make sense if they are in the framebuffer's bounds
if (bounds.intersect(*mSnapshot->clipRect)) {
@@ -738,7 +738,7 @@
} else if (fboLayer) {
clip.set(bounds);
mat4 inverse;
- inverse.loadInverse(*mSnapshot->transform);
+ inverse.loadInverse(currentTransform());
inverse.mapRect(clip);
clip.snapToPixelBoundaries();
if (clip.intersect(untransformedBounds)) {
@@ -938,11 +938,11 @@
} else {
setupDrawExternalTexture(layer->getTexture());
}
- if (mSnapshot->transform->isPureTranslate() &&
+ if (currentTransform().isPureTranslate() &&
layer->getWidth() == (uint32_t) rect.getWidth() &&
layer->getHeight() == (uint32_t) rect.getHeight()) {
- const float x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f);
- const float y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f);
+ const float x = (int) floorf(rect.left + currentTransform().getTranslateX() + 0.5f);
+ const float y = (int) floorf(rect.top + currentTransform().getTranslateY() + 0.5f);
layer->setFilter(GL_NEAREST);
setupDrawModelView(x, y, x + rect.getWidth(), y + rect.getHeight(), true);
@@ -966,15 +966,15 @@
float x = rect.left;
float y = rect.top;
- bool simpleTransform = mSnapshot->transform->isPureTranslate() &&
+ bool simpleTransform = currentTransform().isPureTranslate() &&
layer->getWidth() == (uint32_t) rect.getWidth() &&
layer->getHeight() == (uint32_t) rect.getHeight();
if (simpleTransform) {
// When we're swapping, the layer is already in screen coordinates
if (!swap) {
- x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f);
- y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f);
+ x = (int) floorf(rect.left + currentTransform().getTranslateX() + 0.5f);
+ y = (int) floorf(rect.top + currentTransform().getTranslateY() + 0.5f);
}
layer->setFilter(GL_NEAREST, true);
@@ -1041,9 +1041,9 @@
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms();
setupDrawTexture(layer->getTexture());
- if (mSnapshot->transform->isPureTranslate()) {
- const float x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f);
- const float y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f);
+ if (currentTransform().isPureTranslate()) {
+ const float x = (int) floorf(rect.left + currentTransform().getTranslateX() + 0.5f);
+ const float y = (int) floorf(rect.top + currentTransform().getTranslateY() + 0.5f);
layer->setFilter(GL_NEAREST);
setupDrawModelViewTranslate(x, y, x + rect.getWidth(), y + rect.getHeight(), true);
@@ -1241,7 +1241,7 @@
}
void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state) {
- mSnapshot->transform->load(state.mMatrix);
+ currentTransform().load(state.mMatrix);
// NOTE: a clip RECT will be saved and restored, but DeferredDisplayState doesn't support
// complex clips. In the future, we should add support for deferral of operations clipped by
@@ -1256,42 +1256,42 @@
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::translate(float dx, float dy) {
- mSnapshot->transform->translate(dx, dy, 0.0f);
+ currentTransform().translate(dx, dy, 0.0f);
}
void OpenGLRenderer::rotate(float degrees) {
- mSnapshot->transform->rotate(degrees, 0.0f, 0.0f, 1.0f);
+ currentTransform().rotate(degrees, 0.0f, 0.0f, 1.0f);
}
void OpenGLRenderer::scale(float sx, float sy) {
- mSnapshot->transform->scale(sx, sy, 1.0f);
+ currentTransform().scale(sx, sy, 1.0f);
}
void OpenGLRenderer::skew(float sx, float sy) {
- mSnapshot->transform->skew(sx, sy);
+ currentTransform().skew(sx, sy);
}
void OpenGLRenderer::setMatrix(SkMatrix* matrix) {
if (matrix) {
- mSnapshot->transform->load(*matrix);
+ currentTransform().load(*matrix);
} else {
- mSnapshot->transform->loadIdentity();
+ currentTransform().loadIdentity();
}
}
bool OpenGLRenderer::hasRectToRectTransform() {
- return CC_LIKELY(mSnapshot->transform->rectToRect());
+ return CC_LIKELY(currentTransform().rectToRect());
}
void OpenGLRenderer::getMatrix(SkMatrix* matrix) {
- mSnapshot->transform->copyTo(*matrix);
+ currentTransform().copyTo(*matrix);
}
void OpenGLRenderer::concatMatrix(SkMatrix* matrix) {
SkMatrix transform;
- mSnapshot->transform->copyTo(transform);
+ currentTransform().copyTo(transform);
transform.preConcat(*matrix);
- mSnapshot->transform->load(transform);
+ currentTransform().load(transform);
}
///////////////////////////////////////////////////////////////////////////////
@@ -1385,7 +1385,7 @@
}
Rect r(left, top, right, bottom);
- mSnapshot->transform->mapRect(r);
+ currentTransform().mapRect(r);
r.snapToPixelBoundaries();
Rect clipRect(*mSnapshot->clipRect);
@@ -1401,7 +1401,7 @@
}
transformed.set(left, top, right, bottom);
- mSnapshot->transform->mapRect(transformed);
+ currentTransform().mapRect(transformed);
transformed.snapToPixelBoundaries();
clip.set(*mSnapshot->clipRect);
@@ -1426,7 +1426,7 @@
}
Rect r(left, top, right, bottom);
- mSnapshot->transform->mapRect(r);
+ currentTransform().mapRect(r);
r.snapToPixelBoundaries();
Rect clipRect(*mSnapshot->clipRect);
@@ -1449,7 +1449,7 @@
}
bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
- if (CC_LIKELY(mSnapshot->transform->rectToRect())) {
+ if (CC_LIKELY(currentTransform().rectToRect())) {
bool clipped = mSnapshot->clip(left, top, right, bottom, op);
if (clipped) {
dirtyClip();
@@ -1465,7 +1465,7 @@
bool OpenGLRenderer::clipPath(SkPath* path, SkRegion::Op op) {
SkMatrix transform;
- mSnapshot->transform->copyTo(transform);
+ currentTransform().copyTo(transform);
SkPath transformed;
path->transform(transform, &transformed);
@@ -1642,8 +1642,8 @@
bool ignoreTransform) {
mModelView.loadTranslate(left, top, 0.0f);
if (!ignoreTransform) {
- mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
- if (mTrackDirtyRegions) dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+ mCaches.currentProgram->set(mOrthoMatrix, mModelView, currentTransform());
+ if (mTrackDirtyRegions) dirtyLayer(left, top, right, bottom, currentTransform());
} else {
mCaches.currentProgram->set(mOrthoMatrix, mModelView, mat4::identity());
if (mTrackDirtyRegions) dirtyLayer(left, top, right, bottom);
@@ -1651,7 +1651,7 @@
}
void OpenGLRenderer::setupDrawModelViewIdentity(bool offset) {
- mCaches.currentProgram->set(mOrthoMatrix, mat4::identity(), *mSnapshot->transform, offset);
+ mCaches.currentProgram->set(mOrthoMatrix, mat4::identity(), currentTransform(), offset);
}
void OpenGLRenderer::setupDrawModelView(float left, float top, float right, float bottom,
@@ -1664,9 +1664,9 @@
}
bool dirty = right - left > 0.0f && bottom - top > 0.0f;
if (!ignoreTransform) {
- mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
+ mCaches.currentProgram->set(mOrthoMatrix, mModelView, currentTransform());
if (mTrackDirtyRegions && dirty) {
- dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+ dirtyLayer(left, top, right, bottom, currentTransform());
}
} else {
mCaches.currentProgram->set(mOrthoMatrix, mModelView, mat4::identity());
@@ -1694,7 +1694,7 @@
void OpenGLRenderer::setupDrawShaderUniforms(bool ignoreTransform) {
if (mDrawModifiers.mShader) {
if (ignoreTransform) {
- mModelView.loadInverse(*mSnapshot->transform);
+ mModelView.loadInverse(currentTransform());
}
mDrawModifiers.mShader->setupProgram(mCaches.currentProgram,
mModelView, *mSnapshot, &mTextureUnit);
@@ -1833,9 +1833,9 @@
texture->setWrap(GL_CLAMP_TO_EDGE, true);
bool ignoreTransform = false;
- if (mSnapshot->transform->isPureTranslate()) {
- x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
- y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f);
+ if (currentTransform().isPureTranslate()) {
+ x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f);
+ y = (int) floorf(top + currentTransform().getTranslateY() + 0.5f);
ignoreTransform = true;
texture->setFilter(GL_NEAREST, true);
@@ -1999,7 +1999,7 @@
float a = alpha / 255.0f;
if (hasLayer()) {
- dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+ dirtyLayer(left, top, right, bottom, currentTransform());
}
setupDraw();
@@ -2069,9 +2069,9 @@
bool useScaleTransform = mDrawModifiers.mShader && scaled;
bool ignoreTransform = false;
- if (CC_LIKELY(mSnapshot->transform->isPureTranslate() && !useScaleTransform)) {
- float x = (int) floorf(dstLeft + mSnapshot->transform->getTranslateX() + 0.5f);
- float y = (int) floorf(dstTop + mSnapshot->transform->getTranslateY() + 0.5f);
+ if (CC_LIKELY(currentTransform().isPureTranslate() && !useScaleTransform)) {
+ float x = (int) floorf(dstLeft + currentTransform().getTranslateX() + 0.5f);
+ float y = (int) floorf(dstTop + currentTransform().getTranslateY() + 0.5f);
dstRight = x + (dstRight - dstLeft);
dstBottom = y + (dstBottom - dstTop);
@@ -2150,11 +2150,11 @@
texture->setWrap(GL_CLAMP_TO_EDGE, true);
texture->setFilter(GL_LINEAR, true);
- const bool pureTranslate = mSnapshot->transform->isPureTranslate();
+ const bool pureTranslate = currentTransform().isPureTranslate();
// Mark the current layer dirty where we are going to draw the patch
if (hasLayer() && mesh->hasEmptyQuads) {
- const float offsetX = left + mSnapshot->transform->getTranslateX();
- const float offsetY = top + mSnapshot->transform->getTranslateY();
+ const float offsetX = left + currentTransform().getTranslateX();
+ const float offsetY = top + currentTransform().getTranslateY();
const size_t count = mesh->quads.size();
for (size_t i = 0; i < count; i++) {
const Rect& bounds = mesh->quads.itemAt(i);
@@ -2164,14 +2164,14 @@
dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getHeight());
} else {
dirtyLayer(left + bounds.left, top + bounds.top,
- left + bounds.right, top + bounds.bottom, *mSnapshot->transform);
+ left + bounds.right, top + bounds.bottom, currentTransform());
}
}
}
if (CC_LIKELY(pureTranslate)) {
- const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
- const float y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f);
+ const float x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f);
+ const float y = (int) floorf(top + currentTransform().getTranslateY() + 0.5f);
drawTextureMesh(x, y, x + right - left, y + bottom - top, texture->id, alpha / 255.0f,
mode, texture->blend, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset,
@@ -2253,7 +2253,7 @@
SkRect bounds = path.getBounds();
PathTessellator::expandBoundsForStroke(bounds, paint, false);
- dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *mSnapshot->transform);
+ dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform());
return drawVertexBuffer(vertexBuffer, paint);
}
@@ -2282,7 +2282,7 @@
return DrawGlInfo::kStatusDone;
}
- dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *mSnapshot->transform);
+ dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform());
bool useOffset = !paint->isAntiAlias();
return drawVertexBuffer(buffer, paint, useOffset);
@@ -2342,7 +2342,7 @@
float top = points[i + 1] - halfWidth;
float bottom = points [i + 1] + halfWidth;
- dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+ dirtyLayer(left, top, right, bottom, currentTransform());
}
glDrawArrays(GL_POINTS, 0, generatedVerticesCount);
@@ -2502,7 +2502,7 @@
return drawConvexPath(path, p);
}
- if (p->isAntiAlias() && !mSnapshot->transform->isSimple()) {
+ if (p->isAntiAlias() && !currentTransform().isSimple()) {
SkPath path;
path.addRect(left, top, right, bottom);
return drawConvexPath(path, p);
@@ -2562,16 +2562,16 @@
}
// NOTE: Skia does not support perspective transform on drawPosText yet
- if (!mSnapshot->transform->isSimple()) {
+ if (!currentTransform().isSimple()) {
return DrawGlInfo::kStatusDone;
}
float x = 0.0f;
float y = 0.0f;
- const bool pureTranslate = mSnapshot->transform->isPureTranslate();
+ const bool pureTranslate = currentTransform().isPureTranslate();
if (pureTranslate) {
- x = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f);
- y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f);
+ x = (int) floorf(x + currentTransform().getTranslateX() + 0.5f);
+ y = (int) floorf(y + currentTransform().getTranslateY() + 0.5f);
}
FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
@@ -2587,7 +2587,7 @@
}
// Pick the appropriate texture filtering
- bool linearFilter = mSnapshot->transform->changesBounds();
+ bool linearFilter = currentTransform().changesBounds();
if (pureTranslate && !linearFilter) {
linearFilter = fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f;
}
@@ -2618,7 +2618,7 @@
positions, hasActiveLayer ? &bounds : NULL)) {
if (hasActiveLayer) {
if (!pureTranslate) {
- mSnapshot->transform->mapRect(bounds);
+ currentTransform().mapRect(bounds);
}
dirtyLayerUnchecked(bounds, getRegion());
}
@@ -2653,12 +2653,12 @@
const float oldX = x;
const float oldY = y;
- const bool pureTranslate = mSnapshot->transform->isPureTranslate();
- const bool isPerspective = mSnapshot->transform->isPerspective();
+ const bool pureTranslate = currentTransform().isPureTranslate();
+ const bool isPerspective = currentTransform().isPerspective();
if (CC_LIKELY(pureTranslate)) {
- x = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f);
- y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f);
+ x = (int) floorf(x + currentTransform().getTranslateX() + 0.5f);
+ y = (int) floorf(y + currentTransform().getTranslateY() + 0.5f);
}
int alpha;
@@ -2675,24 +2675,24 @@
const bool hasActiveLayer = hasLayer();
- const mat4* fontTransform;
+ mat4 fontTransform;
if (CC_LIKELY(pureTranslate)) {
- fontTransform = &mat4::identity();
+ fontTransform = mat4::identity();
} else {
if (CC_UNLIKELY(isPerspective)) {
// When the below condition is true, we are rendering text with a
// perspective transform inside a layer (either an inline layer
// created by Canvas.saveLayer() or a hardware layer.)
if (hasActiveLayer || getTargetFbo() != 0) {
- fontTransform = mSnapshot->transform;
+ fontTransform = currentTransform();
} else {
- fontTransform = &mat4::identity();
+ fontTransform = mat4::identity();
}
} else {
- fontTransform = mSnapshot->transform;
+ fontTransform = currentTransform();
}
}
- fontRenderer.setFont(paint, *fontTransform);
+ fontRenderer.setFont(paint, fontTransform);
// Pick the appropriate texture filtering
bool linearFilter = !pureTranslate || fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f;
@@ -2733,7 +2733,7 @@
if (status && hasActiveLayer) {
if (isPerspective) {
- mSnapshot->transform->mapRect(bounds);
+ currentTransform().mapRect(bounds);
}
dirtyLayerUnchecked(bounds, getRegion());
}
@@ -2781,7 +2781,7 @@
if (fontRenderer.renderTextOnPath(paint, clip, text, 0, bytesCount, count, path,
hOffset, vOffset, hasActiveLayer ? &bounds : NULL)) {
if (hasActiveLayer) {
- mSnapshot->transform->mapRect(bounds);
+ currentTransform().mapRect(bounds);
dirtyLayerUnchecked(bounds, getRegion());
}
}
@@ -2816,7 +2816,7 @@
transform = &layer->getTransform();
if (!transform->isIdentity()) {
save(0);
- mSnapshot->transform->multiply(*transform);
+ currentTransform().multiply(*transform);
}
}
@@ -2854,9 +2854,9 @@
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms();
setupDrawTexture(layer->getTexture());
- if (CC_LIKELY(mSnapshot->transform->isPureTranslate())) {
- int tx = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f);
- int ty = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f);
+ if (CC_LIKELY(currentTransform().isPureTranslate())) {
+ int tx = (int) floorf(x + currentTransform().getTranslateX() + 0.5f);
+ int ty = (int) floorf(y + currentTransform().getTranslateY() + 0.5f);
layer->setFilter(GL_NEAREST);
setupDrawModelViewTranslate(tx, ty,
@@ -3074,6 +3074,9 @@
status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color,
SkXfermode::Mode mode, bool ignoreTransform, bool dirty, bool clip) {
+ if (count == 0) {
+ return DrawGlInfo::kStatusDone;
+ }
float left = FLT_MAX;
float top = FLT_MAX;
@@ -3090,24 +3093,22 @@
float r = rects[index + 2];
float b = rects[index + 3];
- if (ignoreTransform || !quickRejectNoScissor(left, top, right, bottom)) {
- Vertex::set(vertex++, l, b);
- Vertex::set(vertex++, l, t);
- Vertex::set(vertex++, r, t);
- Vertex::set(vertex++, l, b);
- Vertex::set(vertex++, r, t);
- Vertex::set(vertex++, r, b);
+ Vertex::set(vertex++, l, b);
+ Vertex::set(vertex++, l, t);
+ Vertex::set(vertex++, r, t);
+ Vertex::set(vertex++, l, b);
+ Vertex::set(vertex++, r, t);
+ Vertex::set(vertex++, r, b);
- vertexCount += 6;
+ vertexCount += 6;
- left = fminf(left, l);
- top = fminf(top, t);
- right = fmaxf(right, r);
- bottom = fmaxf(bottom, b);
- }
+ left = fminf(left, l);
+ top = fminf(top, t);
+ right = fmaxf(right, r);
+ bottom = fmaxf(bottom, b);
}
- if (count == 0 || (clip && quickReject(left, top, right, bottom))) {
+ if (clip && quickReject(left, top, right, bottom)) {
return DrawGlInfo::kStatusDone;
}
@@ -3126,7 +3127,7 @@
setupDrawVertices((GLvoid*) &mesh[0].position[0]);
if (dirty && hasLayer()) {
- dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+ dirtyLayer(left, top, right, bottom, currentTransform());
}
glDrawArrays(GL_TRIANGLES, 0, vertexCount);
@@ -3165,9 +3166,9 @@
texture->setWrap(GL_CLAMP_TO_EDGE, true);
- if (CC_LIKELY(mSnapshot->transform->isPureTranslate())) {
- const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
- const float y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f);
+ if (CC_LIKELY(currentTransform().isPureTranslate())) {
+ const float x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f);
+ const float y = (int) floorf(top + currentTransform().getTranslateY() + 0.5f);
texture->setFilter(GL_NEAREST, true);
drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 1bfd3c0..d542315 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -903,6 +903,10 @@
mDirtyClip = true;
}
+ inline mat4& currentTransform() const {
+ return *mSnapshot->transform;
+ }
+
// Dimensions of the drawing surface
int mWidth, mHeight;