Add support for Canvas flags on save.
This is required for the rewrite of layers support. Change-Id: I5c0867dcf5aeb0392c8d0fbab05febb0eaff70d9
This commit is contained in:
@@ -320,7 +320,7 @@ class GLES20Canvas extends Canvas {
|
||||
|
||||
@Override
|
||||
public int save() {
|
||||
return nSave(mRenderer, 0);
|
||||
return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -127,7 +127,8 @@ void OpenGLRenderer::setViewport(int width, int height) {
|
||||
}
|
||||
|
||||
void OpenGLRenderer::prepare() {
|
||||
mSnapshot = new Snapshot(mFirstSnapshot);
|
||||
mSnapshot = new Snapshot(mFirstSnapshot,
|
||||
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
|
||||
mSaveCount = 1;
|
||||
|
||||
glViewport(0, 0, mWidth, mHeight);
|
||||
@@ -175,7 +176,7 @@ int OpenGLRenderer::getSaveCount() const {
|
||||
}
|
||||
|
||||
int OpenGLRenderer::save(int flags) {
|
||||
return saveSnapshot();
|
||||
return saveSnapshot(flags);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::restore() {
|
||||
@@ -192,8 +193,8 @@ void OpenGLRenderer::restoreToCount(int saveCount) {
|
||||
}
|
||||
}
|
||||
|
||||
int OpenGLRenderer::saveSnapshot() {
|
||||
mSnapshot = new Snapshot(mSnapshot);
|
||||
int OpenGLRenderer::saveSnapshot(int flags) {
|
||||
mSnapshot = new Snapshot(mSnapshot, flags);
|
||||
return mSaveCount++;
|
||||
}
|
||||
|
||||
@@ -231,7 +232,7 @@ bool OpenGLRenderer::restoreSnapshot() {
|
||||
|
||||
int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
|
||||
const SkPaint* p, int flags) {
|
||||
int count = saveSnapshot();
|
||||
int count = saveSnapshot(flags);
|
||||
|
||||
int alpha = 255;
|
||||
SkXfermode::Mode mode;
|
||||
@@ -258,13 +259,13 @@ 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) {
|
||||
int count = saveSnapshot();
|
||||
if (alpha > 0 && !mSnapshot->invisible) {
|
||||
createLayer(mSnapshot, left, top, right, bottom, alpha, SkXfermode::kSrcOver_Mode, flags);
|
||||
if (alpha == 0xff) {
|
||||
return saveLayer(left, top, right, bottom, NULL, flags);
|
||||
} else {
|
||||
mSnapshot->invisible = true;
|
||||
SkPaint paint;
|
||||
paint.setAlpha(alpha);
|
||||
return saveLayer(left, top, right, bottom, &paint, flags);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
|
||||
@@ -272,8 +273,12 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
|
||||
LAYER_LOGD("Requesting layer %fx%f", right - left, bottom - top);
|
||||
LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize());
|
||||
|
||||
Rect bounds(left, top, right, bottom);
|
||||
// TODO: Apply transformations and treat layers in screen coordinates
|
||||
// mSnapshot->transform->mapRect(bounds);
|
||||
|
||||
GLuint previousFbo = snapshot->previous.get() ? snapshot->previous->fbo : 0;
|
||||
LayerSize size(right - left, bottom - top);
|
||||
LayerSize size(bounds.getWidth(), bounds.getHeight());
|
||||
|
||||
Layer* layer = mCaches.layerCache.get(size, previousFbo);
|
||||
if (!layer) {
|
||||
@@ -290,24 +295,26 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
|
||||
|
||||
layer->mode = mode;
|
||||
layer->alpha = alpha / 255.0f;
|
||||
layer->layer.set(left, top, right, bottom);
|
||||
layer->layer.set(bounds);
|
||||
|
||||
// Save the layer in the snapshot
|
||||
snapshot->flags |= Snapshot::kFlagIsLayer;
|
||||
snapshot->layer = layer;
|
||||
snapshot->fbo = layer->fbo;
|
||||
snapshot->transform.loadTranslate(-left, -top, 0.0f);
|
||||
snapshot->setClip(0.0f, 0.0f, right - left, bottom - top);
|
||||
snapshot->viewport.set(0.0f, 0.0f, right - left, bottom - top);
|
||||
snapshot->height = bottom - top;
|
||||
// TODO: Temporary until real layer support is implemented
|
||||
snapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
|
||||
// TODO: Temporary until real layer support is implemented
|
||||
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);
|
||||
|
||||
setScissorFromClip();
|
||||
|
||||
// Change the ortho projection
|
||||
glViewport(0, 0, right - left, bottom - top);
|
||||
mOrthoMatrix.loadOrtho(0.0f, right - left, bottom - top, 0.0f, -1.0f, 1.0f);
|
||||
glViewport(0, 0, bounds.getWidth(), bounds.getHeight());
|
||||
mOrthoMatrix.loadOrtho(0.0f, bounds.getWidth(), bounds.getHeight(), 0.0f, -1.0f, 1.0f);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -323,8 +330,8 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo);
|
||||
|
||||
// Restore the clip from the previous snapshot
|
||||
const Rect& clip = previous->clipRect;
|
||||
glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight());
|
||||
const Rect& clip = *previous->clipRect;
|
||||
glScissor(clip.left, previous->height - clip.bottom, clip.getWidth(), clip.getHeight());
|
||||
|
||||
Layer* layer = current->layer;
|
||||
const Rect& rect = layer->layer;
|
||||
@@ -355,28 +362,28 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void OpenGLRenderer::translate(float dx, float dy) {
|
||||
mSnapshot->transform.translate(dx, dy, 0.0f);
|
||||
mSnapshot->transform->translate(dx, dy, 0.0f);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::rotate(float degrees) {
|
||||
mSnapshot->transform.rotate(degrees, 0.0f, 0.0f, 1.0f);
|
||||
mSnapshot->transform->rotate(degrees, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::scale(float sx, float sy) {
|
||||
mSnapshot->transform.scale(sx, sy, 1.0f);
|
||||
mSnapshot->transform->scale(sx, sy, 1.0f);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setMatrix(SkMatrix* matrix) {
|
||||
mSnapshot->transform.load(*matrix);
|
||||
mSnapshot->transform->load(*matrix);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::getMatrix(SkMatrix* matrix) {
|
||||
mSnapshot->transform.copyTo(*matrix);
|
||||
mSnapshot->transform->copyTo(*matrix);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::concatMatrix(SkMatrix* matrix) {
|
||||
mat4 m(*matrix);
|
||||
mSnapshot->transform.multiply(m);
|
||||
mSnapshot->transform->multiply(m);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -384,7 +391,7 @@ void OpenGLRenderer::concatMatrix(SkMatrix* matrix) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void OpenGLRenderer::setScissorFromClip() {
|
||||
const Rect& clip = mSnapshot->clipRect;
|
||||
const Rect& clip = *mSnapshot->clipRect;
|
||||
glScissor(clip.left, mSnapshot->height - clip.bottom, clip.getWidth(), clip.getHeight());
|
||||
}
|
||||
|
||||
@@ -396,8 +403,8 @@ bool OpenGLRenderer::quickReject(float left, float top, float right, float botto
|
||||
if (mSnapshot->invisible) return true;
|
||||
|
||||
Rect r(left, top, right, bottom);
|
||||
mSnapshot->transform.mapRect(r);
|
||||
return !mSnapshot->clipRect.intersects(r);
|
||||
mSnapshot->transform->mapRect(r);
|
||||
return !mSnapshot->clipRect->intersects(r);
|
||||
}
|
||||
|
||||
bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
|
||||
@@ -405,7 +412,7 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom,
|
||||
if (clipped) {
|
||||
setScissorFromClip();
|
||||
}
|
||||
return !mSnapshot->clipRect.isEmpty();
|
||||
return !mSnapshot->clipRect->isEmpty();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -501,7 +508,7 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
|
||||
|
||||
void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
|
||||
if (mSnapshot->invisible) return;
|
||||
const Rect& clip = mSnapshot->clipRect;
|
||||
const Rect& clip = *mSnapshot->clipRect;
|
||||
drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true);
|
||||
}
|
||||
|
||||
@@ -538,7 +545,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
|
||||
float scaleX = paint->getTextScaleX();
|
||||
bool applyScaleX = scaleX < 0.9999f || scaleX > 1.0001f;
|
||||
if (applyScaleX) {
|
||||
save(0);
|
||||
save(SkCanvas::kMatrix_SaveFlag);
|
||||
translate(x - (x * scaleX), 0.0f);
|
||||
scale(scaleX, 1.0f);
|
||||
}
|
||||
@@ -747,7 +754,7 @@ void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t
|
||||
} else {
|
||||
mModelView.loadIdentity();
|
||||
}
|
||||
mCaches.currentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);
|
||||
mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
|
||||
glUniform4f(mCaches.currentProgram->color, r, g, b, a);
|
||||
|
||||
textureUnit++;
|
||||
@@ -852,7 +859,7 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
|
||||
mModelView.loadTranslate(left, top, 0.0f);
|
||||
mModelView.scale(right - left, bottom - top, 1.0f);
|
||||
if (!ignoreTransform) {
|
||||
mCaches.currentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);
|
||||
mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
|
||||
} else {
|
||||
mat4 identity;
|
||||
mCaches.currentProgram->set(mOrthoMatrix, mModelView, identity);
|
||||
@@ -900,7 +907,7 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
|
||||
mModelView.scale(right - left, bottom - top, 1.0f);
|
||||
|
||||
useProgram(mCaches.programCache.get(description));
|
||||
mCaches.currentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);
|
||||
mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
|
||||
|
||||
chooseBlending(blend || alpha < 1.0f, mode);
|
||||
|
||||
|
||||
@@ -108,9 +108,11 @@ private:
|
||||
* The new snapshot is saved in mSnapshot and the previous snapshot
|
||||
* is linked from mSnapshot->previous.
|
||||
*
|
||||
* @param flags The save flags; see SkCanvas for more information
|
||||
*
|
||||
* @return The new save count. This value can be passed to #restoreToCount()
|
||||
*/
|
||||
int saveSnapshot();
|
||||
int saveSnapshot(int flags);
|
||||
|
||||
/**
|
||||
* Restores the current snapshot; mSnapshot becomes mSnapshot->previous.
|
||||
|
||||
@@ -91,11 +91,11 @@ struct Rect {
|
||||
set(r.left, r.top, r.right, r.bottom);
|
||||
}
|
||||
|
||||
float getWidth() const {
|
||||
inline float getWidth() const {
|
||||
return right - left;
|
||||
}
|
||||
|
||||
float getHeight() const {
|
||||
inline float getHeight() const {
|
||||
return bottom - top;
|
||||
}
|
||||
|
||||
|
||||
@@ -167,12 +167,12 @@ void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelV
|
||||
shaderMatrix.mapPoint(start.left, start.top);
|
||||
shaderMatrix.mapPoint(start.right, start.bottom);
|
||||
}
|
||||
snapshot.transform.mapRect(start);
|
||||
snapshot.transform->mapRect(start);
|
||||
|
||||
const float gradientX = start.right - start.left;
|
||||
const float gradientY = start.bottom - start.top;
|
||||
|
||||
mat4 screenSpace(snapshot.transform);
|
||||
mat4 screenSpace(*snapshot.transform);
|
||||
screenSpace.multiply(modelView);
|
||||
|
||||
// Uniforms
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
#include <SkCanvas.h>
|
||||
#include <SkRegion.h>
|
||||
|
||||
#include "Layer.h"
|
||||
@@ -42,27 +43,40 @@ namespace uirenderer {
|
||||
*/
|
||||
class Snapshot: public LightRefBase<Snapshot> {
|
||||
public:
|
||||
Snapshot(): invisible(false), flags(0), previous(NULL), layer(NULL), fbo(0) { }
|
||||
Snapshot(): invisible(false), flags(0), previous(NULL), layer(NULL), fbo(0) {
|
||||
transform = &mTransformRoot;
|
||||
clipRect = &mClipRectRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the specified snapshot. Only the transform and clip rectangle
|
||||
* are copied. The layer information is set to 0 and the transform is
|
||||
* assumed to be dirty. The specified snapshot is stored as the previous
|
||||
* snapshot.
|
||||
* Copies the specified snapshot/ The specified snapshot is stored as
|
||||
* the previous snapshot.
|
||||
*/
|
||||
Snapshot(const sp<Snapshot>& s):
|
||||
Snapshot(const sp<Snapshot>& s, int saveFlags):
|
||||
height(s->height),
|
||||
transform(s->transform),
|
||||
clipRect(s->clipRect),
|
||||
invisible(s->invisible),
|
||||
flags(0),
|
||||
previous(s),
|
||||
layer(NULL),
|
||||
fbo(s->fbo),
|
||||
viewport(s->viewport) {
|
||||
if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
|
||||
mTransformRoot.load(*s->transform);
|
||||
transform = &mTransformRoot;
|
||||
} else {
|
||||
transform = s->transform;
|
||||
}
|
||||
|
||||
if (saveFlags & SkCanvas::kClip_SaveFlag) {
|
||||
mClipRectRoot.set(*s->clipRect);
|
||||
clipRect = &mClipRectRoot;
|
||||
} else {
|
||||
clipRect = s->clipRect;
|
||||
}
|
||||
|
||||
if ((s->flags & Snapshot::kFlagClipSet) &&
|
||||
!(s->flags & Snapshot::kFlagDirtyLocalClip)) {
|
||||
localClip.set(s->localClip);
|
||||
mLocalClip.set(s->mLocalClip);
|
||||
} else {
|
||||
flags |= Snapshot::kFlagDirtyLocalClip;
|
||||
}
|
||||
@@ -99,23 +113,23 @@ public:
|
||||
bool clipped = false;
|
||||
|
||||
Rect r(left, top, right, bottom);
|
||||
transform.mapRect(r);
|
||||
transform->mapRect(r);
|
||||
|
||||
switch (op) {
|
||||
case SkRegion::kDifference_Op:
|
||||
break;
|
||||
case SkRegion::kIntersect_Op:
|
||||
clipped = clipRect.intersect(r);
|
||||
clipped = clipRect->intersect(r);
|
||||
break;
|
||||
case SkRegion::kUnion_Op:
|
||||
clipped = clipRect.unionWith(r);
|
||||
clipped = clipRect->unionWith(r);
|
||||
break;
|
||||
case SkRegion::kXOR_Op:
|
||||
break;
|
||||
case SkRegion::kReverseDifference_Op:
|
||||
break;
|
||||
case SkRegion::kReplace_Op:
|
||||
clipRect.set(r);
|
||||
clipRect->set(r);
|
||||
clipped = true;
|
||||
break;
|
||||
}
|
||||
@@ -131,21 +145,34 @@ public:
|
||||
* Sets the current clip.
|
||||
*/
|
||||
void setClip(float left, float top, float right, float bottom) {
|
||||
clipRect.set(left, top, right, bottom);
|
||||
clipRect->set(left, top, right, bottom);
|
||||
flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip;
|
||||
}
|
||||
|
||||
const Rect& getLocalClip() {
|
||||
if (flags & Snapshot::kFlagDirtyLocalClip) {
|
||||
mat4 inverse;
|
||||
inverse.loadInverse(transform);
|
||||
inverse.loadInverse(*transform);
|
||||
|
||||
localClip.set(clipRect);
|
||||
inverse.mapRect(localClip);
|
||||
mLocalClip.set(*clipRect);
|
||||
inverse.mapRect(mLocalClip);
|
||||
|
||||
flags &= ~Snapshot::kFlagDirtyLocalClip;
|
||||
}
|
||||
return localClip;
|
||||
return mLocalClip;
|
||||
}
|
||||
|
||||
// TODO: Temporary
|
||||
void resetTransform(float x, float y, float z) {
|
||||
transform = &mTransformRoot;
|
||||
transform->loadTranslate(x, y, z);
|
||||
}
|
||||
|
||||
// TODO: Temporary
|
||||
void resetClip(float left, float top, float right, float bottom) {
|
||||
clipRect = &mClipRectRoot;
|
||||
clipRect->set(left, top, right, bottom);
|
||||
flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,18 +180,6 @@ public:
|
||||
*/
|
||||
int height;
|
||||
|
||||
/**
|
||||
* Local transformation. Holds the current translation, scale and
|
||||
* rotation values.
|
||||
*/
|
||||
mat4 transform;
|
||||
|
||||
/**
|
||||
* Current clip region. The clip is stored in canvas-space coordinates,
|
||||
* (screen-space coordinates in the regular case.)
|
||||
*/
|
||||
Rect clipRect;
|
||||
|
||||
/**
|
||||
* If true, the layer won't be rendered.
|
||||
*/
|
||||
@@ -196,8 +211,22 @@ public:
|
||||
*/
|
||||
mat4 orthoMatrix;
|
||||
|
||||
/**
|
||||
* Local transformation. Holds the current translation, scale and
|
||||
* rotation values.
|
||||
*/
|
||||
mat4* transform;
|
||||
|
||||
/**
|
||||
* Current clip region. The clip is stored in canvas-space coordinates,
|
||||
* (screen-space coordinates in the regular case.)
|
||||
*/
|
||||
Rect* clipRect;
|
||||
|
||||
private:
|
||||
Rect localClip;
|
||||
mat4 mTransformRoot;
|
||||
Rect mClipRectRoot;
|
||||
Rect mLocalClip;
|
||||
|
||||
}; // class Snapshot
|
||||
|
||||
|
||||
Reference in New Issue
Block a user