summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2014-01-02 21:04:27 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-01-02 21:04:27 +0000
commite459367a3a49cbe94dfe38c50369431614dddc9c (patch)
tree11cdca93a3677220bb5094a2c18fde4d90908864 /libs
parent23ab74de5eda745e2ef88bd156cde83fbcd4b5da (diff)
parentd6b65f67717025b1162f86f04e2caa5723566cac (diff)
downloadframeworks_base-e459367a3a49cbe94dfe38c50369431614dddc9c.zip
frameworks_base-e459367a3a49cbe94dfe38c50369431614dddc9c.tar.gz
frameworks_base-e459367a3a49cbe94dfe38c50369431614dddc9c.tar.bz2
Merge "Use const access to snapshot from OpenGLRenderer"
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/DisplayListRenderer.cpp9
-rw-r--r--libs/hwui/DisplayListRenderer.h2
-rw-r--r--libs/hwui/LayerRenderer.cpp2
-rw-r--r--libs/hwui/OpenGLRenderer.cpp304
-rw-r--r--libs/hwui/OpenGLRenderer.h22
-rw-r--r--libs/hwui/PathTessellator.cpp18
-rw-r--r--libs/hwui/PathTessellator.h6
-rw-r--r--libs/hwui/StatefulBaseRenderer.cpp51
-rw-r--r--libs/hwui/StatefulBaseRenderer.h53
9 files changed, 231 insertions, 236 deletions
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 9c5db6e..0376db7 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -218,19 +218,19 @@ void DisplayListRenderer::concatMatrix(SkMatrix* matrix) {
bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
SkRegion::Op op) {
addStateOp(new (alloc()) ClipRectOp(left, top, right, bottom, op));
- return OpenGLRenderer::clipRect(left, top, right, bottom, op);
+ return StatefulBaseRenderer::clipRect(left, top, right, bottom, op);
}
bool DisplayListRenderer::clipPath(SkPath* path, SkRegion::Op op) {
path = refPath(path);
addStateOp(new (alloc()) ClipPathOp(path, op));
- return OpenGLRenderer::clipPath(path, op);
+ return StatefulBaseRenderer::clipPath(path, op);
}
bool DisplayListRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
region = refRegion(region);
addStateOp(new (alloc()) ClipRegionOp(region, op));
- return OpenGLRenderer::clipRegion(region, op);
+ return StatefulBaseRenderer::clipRegion(region, op);
}
status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList,
@@ -242,7 +242,8 @@ status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList,
// resources cache, but we rely on the caller (UI toolkit) to
// do the right thing for now
- DrawDisplayListOp* op = new (alloc()) DrawDisplayListOp(displayList, flags, currentTransform());
+ DrawDisplayListOp* op = new (alloc()) DrawDisplayListOp(displayList,
+ flags, *currentTransform());
addDrawOp(op);
mDisplayListData->children.push(op);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index b5d9924..2c3f7c0 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -54,7 +54,7 @@ class DrawOp;
class StateOp;
/**
- * Records drawing commands in a display list for latter playback.
+ * Records drawing commands in a display list for later playback into an OpenGLRenderer.
*/
class DisplayListRenderer: public OpenGLRenderer {
public:
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 35fd46e..0b38c4d 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -117,7 +117,7 @@ void LayerRenderer::ensureStencilBuffer() {
///////////////////////////////////////////////////////////////////////////////
Region* LayerRenderer::getRegion() const {
- if (getSnapshot()->flags & Snapshot::kFlagFboTarget) {
+ if (currentSnapshot()->flags & Snapshot::kFlagFboTarget) {
return OpenGLRenderer::getRegion();
}
return &mLayer->region;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index a3a4432..ac4e71d 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -208,7 +208,7 @@ status_t OpenGLRenderer::startFrame() {
// invoked during the frame
mSuppressTiling = mCaches.hasRegisteredFunctors();
- startTiling(*mSnapshot, true);
+ startTilingCurrentClip(true);
debugOverdraw(true, true);
@@ -225,7 +225,7 @@ status_t OpenGLRenderer::prepareDirty(float left, float top,
// The framebuffer renderer will first defer the display list
// for each layer and wait until the first drawing command
// to start the frame
- if (currentSnapshot().fbo == 0) {
+ if (currentSnapshot()->fbo == 0) {
syncState();
updateLayers();
} else {
@@ -252,7 +252,7 @@ void OpenGLRenderer::discardFramebuffer(float left, float top, float right, floa
status_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
if (!opaque || mCountOverdraw) {
mCaches.enableScissor();
- mCaches.setScissor(left, currentSnapshot().height - bottom, right - left, bottom - top);
+ mCaches.setScissor(left, currentSnapshot()->height - bottom, right - left, bottom - top);
glClear(GL_COLOR_BUFFER_BIT);
return DrawGlInfo::kStatusDrew;
}
@@ -269,14 +269,16 @@ void OpenGLRenderer::syncState() {
}
}
-void OpenGLRenderer::startTiling(const Snapshot& s, bool opaque) {
+void OpenGLRenderer::startTilingCurrentClip(bool opaque) {
if (!mSuppressTiling) {
+ const Snapshot* snapshot = currentSnapshot();
+
const Rect* clip = &mTilingClip;
- if (s.flags & Snapshot::kFlagFboTarget) {
- clip = &(s.layer->clipRect);
+ if (snapshot->flags & Snapshot::kFlagFboTarget) {
+ clip = &(snapshot->layer->clipRect);
}
- startTiling(*clip, s.height, opaque);
+ startTiling(*clip, snapshot->height, opaque);
}
}
@@ -355,9 +357,9 @@ void OpenGLRenderer::interrupt() {
}
void OpenGLRenderer::resume() {
- const Snapshot& snapshot = currentSnapshot();
- glViewport(0, 0, snapshot.viewport.getWidth(), snapshot.viewport.getHeight());
- glBindFramebuffer(GL_FRAMEBUFFER, snapshot.fbo);
+ const Snapshot* snapshot = currentSnapshot();
+ glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
+ glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
debugOverdraw(true, false);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -377,9 +379,9 @@ void OpenGLRenderer::resume() {
}
void OpenGLRenderer::resumeAfterLayer() {
- const Snapshot& snapshot = currentSnapshot();
- glViewport(0, 0, snapshot.viewport.getWidth(), snapshot.viewport.getHeight());
- glBindFramebuffer(GL_FRAMEBUFFER, snapshot.fbo);
+ const Snapshot* snapshot = currentSnapshot();
+ glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
+ glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
debugOverdraw(true, false);
mCaches.resetScissor();
@@ -433,16 +435,16 @@ status_t OpenGLRenderer::invokeFunctors(Rect& dirty) {
}
status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
- if (currentSnapshot().isIgnored()) return DrawGlInfo::kStatusDone;
+ if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
detachFunctor(functor);
- Rect clip(currentClipRect());
+ Rect clip(*currentClipRect());
clip.snapToPixelBoundaries();
// Since we don't know what the functor will draw, let's dirty
- // tne entire clip region
+ // the entire clip region
if (hasLayer()) {
dirtyLayerUnchecked(clip, getRegion());
}
@@ -453,9 +455,9 @@ status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
info.clipRight = clip.right;
info.clipBottom = clip.bottom;
info.isLayer = hasLayer();
- info.width = getSnapshot()->viewport.getWidth();
- info.height = getSnapshot()->height;
- getSnapshot()->transform->copyTo(&info.transform[0]);
+ info.width = currentSnapshot()->viewport.getWidth();
+ info.height = currentSnapshot()->height;
+ currentTransform()->copyTo(&info.transform[0]);
bool dirtyClip = mDirtyClip;
// setup GL state for functor
@@ -518,7 +520,7 @@ void OpenGLRenderer::renderOverdraw() {
const Rect* clip = &mTilingClip;
mCaches.enableScissor();
- mCaches.setScissor(clip->left, mFirstSnapshot->height - clip->bottom,
+ mCaches.setScissor(clip->left, firstSnapshot()->height - clip->bottom,
clip->right - clip->left, clip->bottom - clip->top);
// 1x overdraw
@@ -580,7 +582,7 @@ bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
if (inFrame) {
resumeAfterLayer();
- startTiling(*mSnapshot);
+ startTilingCurrentClip();
}
layer->debugDrawUpdate = mCaches.debugLayersUpdates;
@@ -709,7 +711,7 @@ void OpenGLRenderer::onSnapshotRestored(const Snapshot& removed, const Snapshot&
if (restoreOrtho) {
const Rect& r = restored.viewport;
glViewport(r.left, r.top, r.right, r.bottom);
- mViewProjMatrix.load(removed.orthoMatrix); // todo: should ortho be stored in 'restored'?
+ mViewProjMatrix.load(removed.orthoMatrix); // TODO: should ortho be stored in 'restored'?
}
if (restoreClip) {
@@ -732,7 +734,7 @@ int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
int alpha, SkXfermode::Mode mode, int flags) {
const int count = saveSnapshot(flags);
- if (!currentSnapshot().isIgnored()) {
+ if (!currentSnapshot()->isIgnored()) {
createLayer(left, top, right, bottom, alpha, mode, flags);
}
@@ -742,22 +744,22 @@ int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
void OpenGLRenderer::calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool fboLayer) {
const Rect untransformedBounds(bounds);
- currentTransform().mapRect(bounds);
+ currentTransform()->mapRect(bounds);
// Layers only make sense if they are in the framebuffer's bounds
- if (bounds.intersect(currentClipRect())) {
+ if (bounds.intersect(*currentClipRect())) {
// We cannot work with sub-pixels in this case
bounds.snapToPixelBoundaries();
// When the layer is not an FBO, we may use glCopyTexImage so we
// need to make sure the layer does not extend outside the bounds
// of the framebuffer
- if (!bounds.intersect(currentSnapshot().previous->viewport)) {
+ if (!bounds.intersect(currentSnapshot()->previous->viewport)) {
bounds.setEmpty();
} else if (fboLayer) {
clip.set(bounds);
mat4 inverse;
- inverse.loadInverse(currentTransform());
+ inverse.loadInverse(*currentTransform());
inverse.mapRect(clip);
clip.snapToPixelBoundaries();
if (clip.intersect(untransformedBounds)) {
@@ -787,7 +789,7 @@ int OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float
int alpha, SkXfermode::Mode mode, int flags) {
const int count = saveSnapshot(flags);
- if (!currentSnapshot().isIgnored() && (flags & SkCanvas::kClipToLayer_SaveFlag)) {
+ if (!currentSnapshot()->isIgnored() && (flags & SkCanvas::kClipToLayer_SaveFlag)) {
// initialize the snapshot as though it almost represents an FBO layer so deferred draw
// operations will be able to store and restore the current clip and transform info, and
// quick rejection will be correct (for display lists)
@@ -797,7 +799,7 @@ int OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float
calculateLayerBoundsAndClip(bounds, clip, true);
updateSnapshotIgnoreForLayer(bounds, clip, true, alpha);
- if (!currentSnapshot().isIgnored()) {
+ if (!currentSnapshot()->isIgnored()) {
mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
mSnapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
@@ -873,7 +875,7 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto
updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, alpha);
// Bail out if we won't draw in this snapshot
- if (currentSnapshot().isIgnored()) {
+ if (currentSnapshot()->isIgnored()) {
return false;
}
@@ -952,7 +954,7 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
layer->getTexture(), 0);
- startTiling(*mSnapshot, true);
+ startTilingCurrentClip(true);
// Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
mCaches.enableScissor();
@@ -1001,7 +1003,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto
glBindFramebuffer(GL_FRAMEBUFFER, restored.fbo);
debugOverdraw(true, false);
- startTiling(restored);
+ startTilingCurrentClip();
}
if (!fboLayer && layer->getAlpha() < 255) {
@@ -1067,11 +1069,11 @@ void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
} else {
setupDrawExternalTexture(layer->getTexture());
}
- if (currentTransform().isPureTranslate() &&
+ if (currentTransform()->isPureTranslate() &&
layer->getWidth() == (uint32_t) rect.getWidth() &&
layer->getHeight() == (uint32_t) rect.getHeight()) {
- const float x = (int) floorf(rect.left + currentTransform().getTranslateX() + 0.5f);
- const float y = (int) floorf(rect.top + currentTransform().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(kModelViewMode_TranslateAndScale, false,
@@ -1095,15 +1097,15 @@ void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap)
float x = rect.left;
float y = rect.top;
- bool simpleTransform = currentTransform().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 + currentTransform().getTranslateX() + 0.5f);
- y = (int) floorf(rect.top + currentTransform().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);
@@ -1186,9 +1188,9 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms();
setupDrawTexture(layer->getTexture());
- 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);
+ 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);
setupDrawModelView(kModelViewMode_Translate, false,
@@ -1298,7 +1300,7 @@ void OpenGLRenderer::dirtyLayer(const float left, const float top,
}
void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) {
- if (bounds.intersect(currentClipRect())) {
+ if (bounds.intersect(*currentClipRect())) {
bounds.snapToPixelBoundaries();
android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
if (!dirty.isEmpty()) {
@@ -1326,7 +1328,7 @@ void OpenGLRenderer::clearLayerRegions() {
const size_t count = mLayers.size();
if (count == 0) return;
- if (!currentSnapshot().isIgnored()) {
+ if (!currentSnapshot()->isIgnored()) {
// Doing several glScissor/glClear here can negatively impact
// GPUs with a tiler architecture, instead we draw quads with
// the Clear blending mode
@@ -1378,51 +1380,51 @@ void OpenGLRenderer::clearLayerRegions() {
///////////////////////////////////////////////////////////////////////////////
bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDeferFlags) {
- const Rect& currentClip = currentClipRect();
- const mat4& currentMatrix = currentTransform();
+ const Rect* currentClip = currentClipRect();
+ const mat4* currentMatrix = currentTransform();
if (stateDeferFlags & kStateDeferFlag_Draw) {
// state has bounds initialized in local coordinates
if (!state.mBounds.isEmpty()) {
- currentMatrix.mapRect(state.mBounds);
+ currentMatrix->mapRect(state.mBounds);
Rect clippedBounds(state.mBounds);
// NOTE: if we ever want to use this clipping info to drive whether the scissor
// is used, it should more closely duplicate the quickReject logic (in how it uses
// snapToPixelBoundaries)
- if(!clippedBounds.intersect(currentClip)) {
+ if(!clippedBounds.intersect(*currentClip)) {
// quick rejected
return true;
}
state.mClipSideFlags = kClipSide_None;
- if (!currentClip.contains(state.mBounds)) {
+ if (!currentClip->contains(state.mBounds)) {
int& flags = state.mClipSideFlags;
// op partially clipped, so record which sides are clipped for clip-aware merging
- if (currentClip.left > state.mBounds.left) flags |= kClipSide_Left;
- if (currentClip.top > state.mBounds.top) flags |= kClipSide_Top;
- if (currentClip.right < state.mBounds.right) flags |= kClipSide_Right;
- if (currentClip.bottom < state.mBounds.bottom) flags |= kClipSide_Bottom;
+ if (currentClip->left > state.mBounds.left) flags |= kClipSide_Left;
+ if (currentClip->top > state.mBounds.top) flags |= kClipSide_Top;
+ if (currentClip->right < state.mBounds.right) flags |= kClipSide_Right;
+ if (currentClip->bottom < state.mBounds.bottom) flags |= kClipSide_Bottom;
}
state.mBounds.set(clippedBounds);
} else {
// Empty bounds implies size unknown. Label op as conservatively clipped to disable
// overdraw avoidance (since we don't know what it overlaps)
state.mClipSideFlags = kClipSide_ConservativeFull;
- state.mBounds.set(currentClip);
+ state.mBounds.set(*currentClip);
}
}
state.mClipValid = (stateDeferFlags & kStateDeferFlag_Clip);
if (state.mClipValid) {
- state.mClip.set(currentClip);
+ state.mClip.set(*currentClip);
}
// Transform, drawModifiers, and alpha always deferred, since they are used by state operations
// (Note: saveLayer/restore use colorFilter and alpha, so we just save restore everything)
- state.mMatrix.load(currentMatrix);
+ state.mMatrix.load(*currentMatrix);
state.mDrawModifiers = mDrawModifiers;
- state.mAlpha = currentSnapshot().alpha;
+ state.mAlpha = currentSnapshot()->alpha;
return false;
}
@@ -1460,10 +1462,10 @@ void OpenGLRenderer::setupMergedMultiDraw(const Rect* clipRect) {
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::setScissorFromClip() {
- Rect clip(currentClipRect());
+ Rect clip(*currentClipRect());
clip.snapToPixelBoundaries();
- if (mCaches.setScissor(clip.left, currentSnapshot().height - clip.bottom,
+ if (mCaches.setScissor(clip.left, currentSnapshot()->height - clip.bottom,
clip.getWidth(), clip.getHeight())) {
mDirtyClip = false;
}
@@ -1474,7 +1476,7 @@ void OpenGLRenderer::ensureStencilBuffer() {
// cannot attach a stencil buffer to fbo0 dynamically. Let's
// just hope we have one when hasLayer() returns false.
if (hasLayer()) {
- attachStencilBufferToLayer(currentSnapshot().layer);
+ attachStencilBufferToLayer(currentSnapshot()->layer);
}
}
@@ -1496,7 +1498,7 @@ void OpenGLRenderer::attachStencilBufferToLayer(Layer* layer) {
void OpenGLRenderer::setStencilFromClip() {
if (!mCaches.debugOverdraw) {
- if (!currentSnapshot().clipRegion->isEmpty()) {
+ if (!currentSnapshot()->clipRegion->isEmpty()) {
// NOTE: The order here is important, we must set dirtyClip to false
// before any draw call to avoid calling back into this method
mDirtyClip = false;
@@ -1521,7 +1523,7 @@ void OpenGLRenderer::setStencilFromClip() {
// The last parameter is important: we are not drawing in the color buffer
// so we don't want to dirty the current layer, if any
- drawRegionRects(*(currentSnapshot().clipRegion),
+ drawRegionRects(*(currentSnapshot()->clipRegion),
0xff000000, SkXfermode::kSrc_Mode, false);
mCaches.stencil.enableTest();
@@ -1529,7 +1531,7 @@ void OpenGLRenderer::setStencilFromClip() {
// Draw the region used to generate the stencil if the appropriate debug
// mode is enabled
if (mCaches.debugStencilClip == Caches::kStencilShowRegion) {
- drawRegionRects(*(currentSnapshot().clipRegion),
+ drawRegionRects(*(currentSnapshot()->clipRegion),
0x7f0000ff, SkXfermode::kSrcOver_Mode);
}
} else {
@@ -1570,64 +1572,12 @@ bool OpenGLRenderer::quickRejectSetupScissor(float left, float top, float right,
void OpenGLRenderer::debugClip() {
#if DEBUG_CLIP_REGIONS
- if (!isRecording() && !currentSnapshot().clipRegion->isEmpty()) {
- drawRegionRects(*(currentSnapshot().clipRegion), 0x7f00ff00, SkXfermode::kSrcOver_Mode);
+ if (!isRecording() && !currentSnapshot()->clipRegion->isEmpty()) {
+ drawRegionRects(*(currentSnapshot()->clipRegion), 0x7f00ff00, SkXfermode::kSrcOver_Mode);
}
#endif
}
-bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
- if (CC_LIKELY(currentTransform().rectToRect())) {
- bool clipped = mSnapshot->clip(left, top, right, bottom, op);
- if (clipped) {
- dirtyClip();
- }
- return !mSnapshot->clipRect->isEmpty();
- }
-
- SkPath path;
- path.addRect(left, top, right, bottom);
-
- return OpenGLRenderer::clipPath(&path, op);
-}
-
-bool OpenGLRenderer::clipPath(SkPath* path, SkRegion::Op op) {
- SkMatrix transform;
- currentTransform().copyTo(transform);
-
- SkPath transformed;
- path->transform(transform, &transformed);
-
- SkRegion clip;
- if (!mSnapshot->previous->clipRegion->isEmpty()) {
- clip.setRegion(*mSnapshot->previous->clipRegion);
- } else {
- if (mSnapshot->previous == mFirstSnapshot) {
- clip.setRect(0, 0, getWidth(), getHeight());
- } else {
- Rect* bounds = mSnapshot->previous->clipRect;
- clip.setRect(bounds->left, bounds->top, bounds->right, bounds->bottom);
- }
- }
-
- SkRegion region;
- region.setPath(transformed, clip);
-
- bool clipped = mSnapshot->clipRegionTransformed(region, op);
- if (clipped) {
- dirtyClip();
- }
- return !mSnapshot->clipRect->isEmpty();
-}
-
-bool OpenGLRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
- bool clipped = mSnapshot->clipRegionTransformed(*region, op);
- if (clipped) {
- dirtyClip();
- }
- return !mSnapshot->clipRect->isEmpty();
-}
-
///////////////////////////////////////////////////////////////////////////////
// Drawing commands
///////////////////////////////////////////////////////////////////////////////
@@ -1772,8 +1722,8 @@ void OpenGLRenderer::setupDrawModelView(ModelViewMode mode, bool offset,
bool dirty = right - left > 0.0f && bottom - top > 0.0f;
if (!ignoreTransform) {
- mCaches.currentProgram->set(mViewProjMatrix, mModelView, currentTransform(), offset);
- if (dirty && mTrackDirtyRegions) dirtyLayer(left, top, right, bottom, currentTransform());
+ mCaches.currentProgram->set(mViewProjMatrix, mModelView, *currentTransform(), offset);
+ if (dirty && mTrackDirtyRegions) dirtyLayer(left, top, right, bottom, *currentTransform());
} else {
mCaches.currentProgram->set(mViewProjMatrix, mModelView, mat4::identity(), offset);
if (dirty && mTrackDirtyRegions) dirtyLayer(left, top, right, bottom);
@@ -1799,7 +1749,7 @@ void OpenGLRenderer::setupDrawShaderUniforms(bool ignoreTransform) {
// because it was built into modelView / the geometry, and the SkiaShader needs to
// compensate.
mat4 modelViewWithoutTransform;
- modelViewWithoutTransform.loadInverse(currentTransform());
+ modelViewWithoutTransform.loadInverse(*currentTransform());
modelViewWithoutTransform.multiply(mModelView);
mModelView.load(modelViewWithoutTransform);
}
@@ -1929,7 +1879,7 @@ status_t OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty,
}
bool avoidOverdraw = !mCaches.debugOverdraw && !mCountOverdraw; // shh, don't tell devs!
- DeferredDisplayList deferredList(*(mSnapshot->clipRect), avoidOverdraw);
+ DeferredDisplayList deferredList(*currentClipRect(), avoidOverdraw);
DeferStateStruct deferStruct(deferredList, *this, replayFlags);
displayList->defer(deferStruct, 0);
@@ -1955,9 +1905,9 @@ void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, Sk
texture->setWrap(GL_CLAMP_TO_EDGE, true);
bool ignoreTransform = false;
- if (currentTransform().isPureTranslate()) {
- x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f);
- y = (int) floorf(top + currentTransform().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);
@@ -2085,7 +2035,7 @@ status_t OpenGLRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top,
status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
float* vertices, int* colors, SkPaint* paint) {
- if (!vertices || mSnapshot->isIgnored()) {
+ if (!vertices || currentSnapshot()->isIgnored()) {
return DrawGlInfo::kStatusDone;
}
@@ -2173,7 +2123,7 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes
float a = alpha / 255.0f;
if (hasLayer()) {
- dirtyLayer(left, top, right, bottom, currentTransform());
+ dirtyLayer(left, top, right, bottom, *currentTransform());
}
setupDraw();
@@ -2243,9 +2193,9 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
bool useScaleTransform = mDrawModifiers.mShader && scaled;
bool ignoreTransform = false;
- if (CC_LIKELY(currentTransform().isPureTranslate() && !useScaleTransform)) {
- float x = (int) floorf(dstLeft + currentTransform().getTranslateX() + 0.5f);
- float y = (int) floorf(dstTop + currentTransform().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);
@@ -2325,11 +2275,11 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtl
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
- const bool pureTranslate = currentTransform().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 + currentTransform().getTranslateX();
- const float offsetY = top + currentTransform().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);
@@ -2339,15 +2289,15 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtl
dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getHeight());
} else {
dirtyLayer(left + bounds.left, top + bounds.top,
- left + bounds.right, top + bounds.bottom, currentTransform());
+ left + bounds.right, top + bounds.bottom, *currentTransform());
}
}
}
bool ignoreTransform = false;
if (CC_LIKELY(pureTranslate)) {
- const float x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f);
- const float y = (int) floorf(top + currentTransform().getTranslateY() + 0.5f);
+ const float x = (int) floorf(left + currentTransform()->getTranslateX() + 0.5f);
+ const float y = (int) floorf(top + currentTransform()->getTranslateY() + 0.5f);
right = x + right - left;
bottom = y + bottom - top;
@@ -2453,12 +2403,12 @@ status_t OpenGLRenderer::drawVertexBuffer(const VertexBuffer& vertexBuffer, SkPa
status_t OpenGLRenderer::drawConvexPath(const SkPath& path, SkPaint* paint) {
VertexBuffer vertexBuffer;
// TODO: try clipping large paths to viewport
- PathTessellator::tessellatePath(path, paint, mSnapshot->transform, vertexBuffer);
+ PathTessellator::tessellatePath(path, paint, *currentTransform(), vertexBuffer);
if (hasLayer()) {
SkRect bounds = path.getBounds();
PathTessellator::expandBoundsForStroke(bounds, paint);
- dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform());
+ dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *currentTransform());
}
return drawVertexBuffer(vertexBuffer, paint);
@@ -2476,40 +2426,40 @@ status_t OpenGLRenderer::drawConvexPath(const SkPath& path, SkPaint* paint) {
* memory transfer by removing need for degenerate vertices.
*/
status_t OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
- if (mSnapshot->isIgnored() || count < 4) return DrawGlInfo::kStatusDone;
+ if (currentSnapshot()->isIgnored() || count < 4) return DrawGlInfo::kStatusDone;
count &= ~0x3; // round down to nearest four
VertexBuffer buffer;
SkRect bounds;
- PathTessellator::tessellateLines(points, count, paint, mSnapshot->transform, bounds, buffer);
+ PathTessellator::tessellateLines(points, count, paint, *currentTransform(), bounds, buffer);
// can't pass paint, since style would be checked for outset. outset done by tessellation.
if (quickRejectSetupScissor(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom)) {
return DrawGlInfo::kStatusDone;
}
- dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform());
+ dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *currentTransform());
bool useOffset = !paint->isAntiAlias();
return drawVertexBuffer(buffer, paint, useOffset);
}
status_t OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) {
- if (mSnapshot->isIgnored() || count < 2) return DrawGlInfo::kStatusDone;
+ if (currentSnapshot()->isIgnored() || count < 2) return DrawGlInfo::kStatusDone;
count &= ~0x1; // round down to nearest two
VertexBuffer buffer;
SkRect bounds;
- PathTessellator::tessellatePoints(points, count, paint, mSnapshot->transform, bounds, buffer);
+ PathTessellator::tessellatePoints(points, count, paint, *currentTransform(), bounds, buffer);
// can't pass paint, since style would be checked for outset. outset done by tessellation.
if (quickRejectSetupScissor(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom)) {
return DrawGlInfo::kStatusDone;
}
- dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform());
+ dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *currentTransform());
bool useOffset = !paint->isAntiAlias();
return drawVertexBuffer(buffer, paint, useOffset);
@@ -2517,9 +2467,9 @@ status_t OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) {
status_t OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
// No need to check against the clip, we fill the clip region
- if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone;
+ if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
- Rect& clip(*mSnapshot->clipRect);
+ Rect clip(*currentClipRect());
clip.snapToPixelBoundaries();
drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true);
@@ -2542,7 +2492,7 @@ status_t OpenGLRenderer::drawShape(float left, float top, const PathTexture* tex
status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom,
float rx, float ry, SkPaint* p) {
- if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
+ if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
(p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
return DrawGlInfo::kStatusDone;
}
@@ -2567,7 +2517,7 @@ status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float
}
status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p) {
- if (mSnapshot->isIgnored() || quickRejectSetupScissor(x - radius, y - radius,
+ if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(x - radius, y - radius,
x + radius, y + radius, p) ||
(p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
return DrawGlInfo::kStatusDone;
@@ -2589,7 +2539,7 @@ status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p)
status_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom,
SkPaint* p) {
- if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
+ if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
(p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
return DrawGlInfo::kStatusDone;
}
@@ -2611,7 +2561,7 @@ status_t OpenGLRenderer::drawOval(float left, float top, float right, float bott
status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
float startAngle, float sweepAngle, bool useCenter, SkPaint* p) {
- if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
+ if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
(p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
return DrawGlInfo::kStatusDone;
}
@@ -2648,7 +2598,7 @@ status_t OpenGLRenderer::drawArc(float left, float top, float right, float botto
#define SkPaintDefaults_MiterLimit SkIntToScalar(4)
status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* p) {
- if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
+ if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
(p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
return DrawGlInfo::kStatusDone;
}
@@ -2672,7 +2622,7 @@ status_t OpenGLRenderer::drawRect(float left, float top, float right, float bott
return drawConvexPath(path, p);
}
- if (p->isAntiAlias() && !currentTransform().isSimple()) {
+ if (p->isAntiAlias() && !currentTransform()->isSimple()) {
SkPath path;
path.addRect(left, top, right, bottom);
return drawConvexPath(path, p);
@@ -2731,12 +2681,12 @@ bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count,
const float* positions, SkPaint* paint) {
- if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint)) {
+ if (text == NULL || count == 0 || currentSnapshot()->isIgnored() || canSkipText(paint)) {
return DrawGlInfo::kStatusDone;
}
// NOTE: Skia does not support perspective transform on drawPosText yet
- if (!currentTransform().isSimple()) {
+ if (!currentTransform()->isSimple()) {
return DrawGlInfo::kStatusDone;
}
@@ -2744,10 +2694,10 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count
float x = 0.0f;
float y = 0.0f;
- const bool pureTranslate = currentTransform().isPureTranslate();
+ const bool pureTranslate = currentTransform()->isPureTranslate();
if (pureTranslate) {
- x = (int) floorf(x + currentTransform().getTranslateX() + 0.5f);
- y = (int) floorf(y + currentTransform().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);
@@ -2763,7 +2713,7 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count
}
// Pick the appropriate texture filtering
- bool linearFilter = currentTransform().changesBounds();
+ bool linearFilter = currentTransform()->changesBounds();
if (pureTranslate && !linearFilter) {
linearFilter = fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f;
}
@@ -2779,7 +2729,7 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count
positions, hasActiveLayer ? &bounds : NULL, &functor)) {
if (hasActiveLayer) {
if (!pureTranslate) {
- currentTransform().mapRect(bounds);
+ currentTransform()->mapRect(bounds);
}
dirtyLayerUnchecked(bounds, getRegion());
}
@@ -2797,7 +2747,7 @@ mat4 OpenGLRenderer::findBestFontTransform(const mat4& transform) const {
fontTransform = mat4::identity();
} else {
float sx, sy;
- currentTransform().decomposeScale(sx, sy);
+ currentTransform()->decomposeScale(sx, sy);
fontTransform.loadScale(sx, sy, 1.0f);
}
}
@@ -2811,7 +2761,7 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, f
if (drawOpMode == kDrawOpMode_Immediate) {
// The checks for corner-case ignorable text and quick rejection is only done for immediate
// drawing as ops from DeferredDisplayList are already filtered for these
- if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint) ||
+ if (text == NULL || count == 0 || currentSnapshot()->isIgnored() || canSkipText(paint) ||
quickRejectSetupScissor(bounds)) {
return DrawGlInfo::kStatusDone;
}
@@ -2820,7 +2770,7 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, f
const float oldX = x;
const float oldY = y;
- const mat4& transform = currentTransform();
+ const mat4& transform = *currentTransform();
const bool pureTranslate = transform.isPureTranslate();
if (CC_LIKELY(pureTranslate)) {
@@ -2861,7 +2811,7 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, f
fontRenderer.setTextureFiltering(linearFilter);
// TODO: Implement better clipping for scaled/rotated text
- const Rect* clip = !pureTranslate ? NULL : mSnapshot->clipRect;
+ const Rect* clip = !pureTranslate ? NULL : currentClipRect();
Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
bool status;
@@ -2893,7 +2843,7 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, f
status_t OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
float hOffset, float vOffset, SkPaint* paint) {
- if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint)) {
+ if (text == NULL || count == 0 || currentSnapshot()->isIgnored() || canSkipText(paint)) {
return DrawGlInfo::kStatusDone;
}
@@ -2917,7 +2867,7 @@ status_t OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int co
if (fontRenderer.renderTextOnPath(paint, clip, text, 0, bytesCount, count, path,
hOffset, vOffset, hasActiveLayer ? &bounds : NULL, &functor)) {
if (hasActiveLayer) {
- currentTransform().mapRect(bounds);
+ currentTransform()->mapRect(bounds);
dirtyLayerUnchecked(bounds, getRegion());
}
}
@@ -2926,7 +2876,7 @@ status_t OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int co
}
status_t OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
- if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone;
+ if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
mCaches.activeTexture(0);
@@ -2990,9 +2940,9 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms();
setupDrawTexture(layer->getTexture());
- if (CC_LIKELY(currentTransform().isPureTranslate())) {
- int tx = (int) floorf(x + currentTransform().getTranslateX() + 0.5f);
- int ty = (int) floorf(y + currentTransform().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);
setupDrawModelView(kModelViewMode_Translate, false, tx, ty,
@@ -3206,7 +3156,7 @@ void OpenGLRenderer::drawTextDecorations(float underlineWidth, float x, float y,
}
status_t OpenGLRenderer::drawRects(const float* rects, int count, SkPaint* paint) {
- if (mSnapshot->isIgnored()) {
+ if (currentSnapshot()->isIgnored()) {
return DrawGlInfo::kStatusDone;
}
@@ -3222,7 +3172,7 @@ status_t OpenGLRenderer::drawRects(const float* rects, int count, SkPaint* paint
status_t OpenGLRenderer::drawShadow(const mat4& casterTransform, float casterAlpha,
float width, float height) {
- if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone;
+ if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
// For now, always and scissor
// TODO: use quickReject
@@ -3275,7 +3225,7 @@ status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color
setupDraw();
setupDrawNoTexture();
- setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
+ setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
setupDrawShader();
setupDrawColorFilter();
setupDrawBlending(mode);
@@ -3288,7 +3238,7 @@ status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color
setupDrawColorFilterUniforms();
if (dirty && hasLayer()) {
- dirtyLayer(left, top, right, bottom, currentTransform());
+ dirtyLayer(left, top, right, bottom, *currentTransform());
}
issueIndexedQuadDraw(&mesh[0], count / 4);
@@ -3305,7 +3255,7 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
setupDraw();
setupDrawNoTexture();
- setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
+ setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
setupDrawShader();
setupDrawColorFilter();
setupDrawBlending(mode);
@@ -3341,9 +3291,9 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b
resetDrawTextureTexCoords(uvs.left, uvs.top, uvs.right, uvs.bottom);
}
- 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);
+ 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,
@@ -3516,7 +3466,7 @@ void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mod
// if drawing a layer, ignore the paint's alpha
*alpha = mDrawModifiers.mOverrideLayerAlpha * 255;
}
- *alpha *= mSnapshot->alpha;
+ *alpha *= currentSnapshot()->alpha;
}
float OpenGLRenderer::getLayerAlpha(Layer* layer) const {
@@ -3526,7 +3476,7 @@ float OpenGLRenderer::getLayerAlpha(Layer* layer) const {
} else {
alpha = layer->getAlpha() / 255.0f;
}
- return alpha * mSnapshot->alpha;
+ return alpha * currentSnapshot()->alpha;
}
}; // namespace uirenderer
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 1325bf7..b4725d4 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -170,10 +170,6 @@ public:
int saveLayerDeferred(float left, float top, float right, float bottom,
int alpha, SkXfermode::Mode mode, int flags);
- virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
- virtual bool clipPath(SkPath* path, SkRegion::Op op);
- virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
-
virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t replayFlags);
virtual status_t drawLayer(Layer* layer, float x, float y);
virtual status_t drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
@@ -246,7 +242,7 @@ public:
void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; }
ANDROID_API bool isCurrentTransformSimple() {
- return currentTransform().isSimple();
+ return currentTransform()->isSimple();
}
Caches& getCaches() {
@@ -258,8 +254,8 @@ public:
return mSnapshot->clipRegion->isEmpty();
}
- int getViewportWidth() { return getSnapshot()->viewport.getWidth(); }
- int getViewportHeight() { return getSnapshot()->viewport.getHeight(); }
+ int getViewportWidth() { return currentSnapshot()->viewport.getWidth(); }
+ int getViewportHeight() { return currentSnapshot()->viewport.getHeight(); }
/**
* Scales the alpha on the current snapshot. This alpha value will be modulated
@@ -396,10 +392,6 @@ protected:
*/
void dirtyLayerUnchecked(Rect& bounds, Region* region);
- sp<Snapshot> getSnapshot() const {
- return mSnapshot;
- }
-
/**
* Returns the region of the current layer.
*/
@@ -482,12 +474,11 @@ private:
/**
* Tells the GPU what part of the screen is about to be redrawn.
- * This method will use the clip rect that we started drawing the
- * frame with.
+ * This method will use the current layer space clip rect.
* This method needs to be invoked every time getTargetFbo() is
* bound again.
*/
- void startTiling(const Snapshot& snapshot, bool opaque = false);
+ void startTilingCurrentClip(bool opaque = false);
/**
* Tells the GPU what part of the screen is about to be redrawn.
@@ -988,9 +979,6 @@ private:
// List of layers to update at the beginning of a frame
Vector<Layer*> mLayerUpdates;
- // Indicates whether the clip must be restored
- bool mDirtyClip;
-
// The following fields are used to setup drawing
// Used to describe the shaders to generate
ProgramDescription mDescription;
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index 7a86dfc..fd2f636 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -88,16 +88,16 @@ inline static vec2 totalOffsetFromNormals(const vec2& normalA, const vec2& norma
*/
struct PaintInfo {
public:
- PaintInfo(const SkPaint* paint, const mat4 *transform) :
+ PaintInfo(const SkPaint* paint, const mat4& transform) :
style(paint->getStyle()), cap(paint->getStrokeCap()), isAA(paint->isAntiAlias()),
inverseScaleX(1.0f), inverseScaleY(1.0f),
halfStrokeWidth(paint->getStrokeWidth() * 0.5f), maxAlpha(1.0f) {
// compute inverse scales
- if (CC_UNLIKELY(!transform->isPureTranslate())) {
- float m00 = transform->data[Matrix4::kScaleX];
- float m01 = transform->data[Matrix4::kSkewY];
- float m10 = transform->data[Matrix4::kSkewX];
- float m11 = transform->data[Matrix4::kScaleY];
+ if (CC_UNLIKELY(!transform.isPureTranslate())) {
+ float m00 = transform.data[Matrix4::kScaleX];
+ float m01 = transform.data[Matrix4::kSkewY];
+ float m10 = transform.data[Matrix4::kSkewX];
+ float m11 = transform.data[Matrix4::kScaleY];
float scaleX = sqrt(m00 * m00 + m01 * m01);
float scaleY = sqrt(m10 * m10 + m11 * m11);
inverseScaleX = (scaleX != 0) ? (1.0f / scaleX) : 1.0f;
@@ -718,7 +718,7 @@ void getStrokeVerticesFromPerimeterAA(const PaintInfo& paintInfo, const Vector<V
}
void PathTessellator::tessellatePath(const SkPath &path, const SkPaint* paint,
- const mat4 *transform, VertexBuffer& vertexBuffer) {
+ const mat4& transform, VertexBuffer& vertexBuffer) {
ATRACE_CALL();
const PaintInfo paintInfo(paint, transform);
@@ -806,7 +806,7 @@ static void instanceVertices(VertexBuffer& srcBuffer, VertexBuffer& dstBuffer,
}
void PathTessellator::tessellatePoints(const float* points, int count, SkPaint* paint,
- const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer) {
+ const mat4& transform, SkRect& bounds, VertexBuffer& vertexBuffer) {
const PaintInfo paintInfo(paint, transform);
// determine point shape
@@ -846,7 +846,7 @@ void PathTessellator::tessellatePoints(const float* points, int count, SkPaint*
}
void PathTessellator::tessellateLines(const float* points, int count, SkPaint* paint,
- const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer) {
+ const mat4& transform, SkRect& bounds, VertexBuffer& vertexBuffer) {
ATRACE_CALL();
const PaintInfo paintInfo(paint, transform);
diff --git a/libs/hwui/PathTessellator.h b/libs/hwui/PathTessellator.h
index 236658d..24f20bc 100644
--- a/libs/hwui/PathTessellator.h
+++ b/libs/hwui/PathTessellator.h
@@ -32,13 +32,13 @@ public:
static void expandBoundsForStroke(SkRect& bounds, const SkPaint* paint);
static void tessellatePath(const SkPath& path, const SkPaint* paint,
- const mat4 *transform, VertexBuffer& vertexBuffer);
+ const mat4& transform, VertexBuffer& vertexBuffer);
static void tessellatePoints(const float* points, int count, SkPaint* paint,
- const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer);
+ const mat4& transform, SkRect& bounds, VertexBuffer& vertexBuffer);
static void tessellateLines(const float* points, int count, SkPaint* paint,
- const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer);
+ const mat4& transform, SkRect& bounds, VertexBuffer& vertexBuffer);
private:
static bool approximatePathOutlineVertices(const SkPath &path, bool forceClose,
diff --git a/libs/hwui/StatefulBaseRenderer.cpp b/libs/hwui/StatefulBaseRenderer.cpp
index cc8b14f..2932037 100644
--- a/libs/hwui/StatefulBaseRenderer.cpp
+++ b/libs/hwui/StatefulBaseRenderer.cpp
@@ -22,6 +22,7 @@ namespace android {
namespace uirenderer {
StatefulBaseRenderer::StatefulBaseRenderer() :
+ mDirtyClip(false), mWidth(-1), mHeight(-1),
mSaveCount(1), mFirstSnapshot(new Snapshot), mSnapshot(mFirstSnapshot) {
}
@@ -138,6 +139,48 @@ void StatefulBaseRenderer::concatMatrix(const Matrix4& matrix) {
// Clip
///////////////////////////////////////////////////////////////////////////////
+bool StatefulBaseRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
+ if (CC_LIKELY(currentTransform()->rectToRect())) {
+ mDirtyClip |= mSnapshot->clip(left, top, right, bottom, op);
+ return !mSnapshot->clipRect->isEmpty();
+ }
+
+ SkPath path;
+ path.addRect(left, top, right, bottom);
+
+ return StatefulBaseRenderer::clipPath(&path, op);
+}
+
+bool StatefulBaseRenderer::clipPath(SkPath* path, SkRegion::Op op) {
+ SkMatrix transform;
+ currentTransform()->copyTo(transform);
+
+ SkPath transformed;
+ path->transform(transform, &transformed);
+
+ SkRegion clip;
+ if (!mSnapshot->previous->clipRegion->isEmpty()) {
+ clip.setRegion(*mSnapshot->previous->clipRegion);
+ } else {
+ if (mSnapshot->previous == firstSnapshot()) {
+ clip.setRect(0, 0, getWidth(), getHeight());
+ } else {
+ Rect* bounds = mSnapshot->previous->clipRect;
+ clip.setRect(bounds->left, bounds->top, bounds->right, bounds->bottom);
+ }
+ }
+
+ SkRegion region;
+ region.setPath(transformed, clip);
+
+ mDirtyClip |= mSnapshot->clipRegionTransformed(region, op);
+ return !mSnapshot->clipRect->isEmpty();
+}
+
+bool StatefulBaseRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
+ mDirtyClip |= mSnapshot->clipRegionTransformed(*region, op);
+ return !mSnapshot->clipRect->isEmpty();
+}
///////////////////////////////////////////////////////////////////////////////
// Quick Rejection
@@ -160,10 +203,10 @@ bool StatefulBaseRenderer::calculateQuickRejectForScissor(float left, float top,
}
Rect r(left, top, right, bottom);
- currentTransform().mapRect(r);
+ currentTransform()->mapRect(r);
r.snapGeometryToPixelBoundaries(snapOut);
- Rect clipRect(currentClipRect());
+ Rect clipRect(*currentClipRect());
clipRect.snapToPixelBoundaries();
if (!clipRect.intersects(r)) return true;
@@ -191,10 +234,10 @@ bool StatefulBaseRenderer::quickRejectConservative(float left, float top,
}
Rect r(left, top, right, bottom);
- currentTransform().mapRect(r);
+ currentTransform()->mapRect(r);
r.roundOut(); // rounded out to be conservative
- Rect clipRect(currentClipRect());
+ Rect clipRect(*currentClipRect());
clipRect.snapToPixelBoundaries();
if (!clipRect.intersects(r)) return true;
diff --git a/libs/hwui/StatefulBaseRenderer.h b/libs/hwui/StatefulBaseRenderer.h
index 2bd196e..20eca22 100644
--- a/libs/hwui/StatefulBaseRenderer.h
+++ b/libs/hwui/StatefulBaseRenderer.h
@@ -26,10 +26,18 @@ namespace android {
namespace uirenderer {
/**
- * Implementation for Renderer state methods
+ * Abstract Renderer subclass, which implements Canvas state methods.
*
- * Eventually, this class should have abstract protected methods
- * for allowing subclasses to hook into save/saveLayer and restore
+ * Manages the Snapshot stack, implementing matrix, save/restore, and clipping methods in the
+ * Renderer interface. Drawing and recording classes that extend StatefulBaseRenderer will have
+ * different use cases:
+ *
+ * Drawing subclasses (i.e. OpenGLRenderer) can query attributes (such as transform) or hook into
+ * changes (e.g. save/restore) with minimal surface area for manipulating the stack itself.
+ *
+ * Recording subclasses (i.e. DisplayListRenderer) can both record and pass through state operations
+ * to StatefulBaseRenderer, so that not only will querying operations work (getClip/Matrix), but so
+ * that quickRejection can also be used.
*/
class StatefulBaseRenderer : public Renderer {
public:
@@ -43,7 +51,7 @@ public:
// getters
bool hasRectToRectTransform() const {
- return CC_LIKELY(currentTransform().rectToRect());
+ return CC_LIKELY(currentTransform()->rectToRect());
}
// Save (layer)
@@ -70,10 +78,9 @@ public:
const Rect& getClipBounds() const { return mSnapshot->getLocalClip(); }
virtual bool quickRejectConservative(float left, float top, float right, float bottom) const;
- // TODO: implement these with hooks to enable scissor/stencil usage in OpenGLRenderer
- // virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
- // virtual bool clipPath(SkPath* path, SkRegion::Op op);
- // virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
+ virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
+ virtual bool clipPath(SkPath* path, SkRegion::Op op);
+ virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
protected:
int getWidth() { return mWidth; }
@@ -101,20 +108,28 @@ protected:
*/
virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {};
- inline const Rect& currentClipRect() const {
- return *(mSnapshot->clipRect);
+ inline const Rect* currentClipRect() const {
+ return mSnapshot->clipRect;
+ }
+
+ inline const mat4* currentTransform() const {
+ return mSnapshot->transform;
}
- inline const mat4& currentTransform() const {
- return *(mSnapshot->transform);
+ inline const Snapshot* currentSnapshot() const {
+ return mSnapshot != NULL ? mSnapshot.get() : mFirstSnapshot.get();
}
- inline const Snapshot& currentSnapshot() const {
- return mSnapshot != NULL ? *mSnapshot : *mFirstSnapshot;
+ inline const Snapshot* firstSnapshot() const {
+ return mFirstSnapshot.get();
}
- // TODO: below should be private so that snapshot stack manipulation
- // goes though (mostly) public methods
+ // indicites that the clip has been changed since the last time it was consumed
+ bool mDirtyClip;
+
+private:
+ // Dimensions of the drawing surface
+ int mWidth, mHeight;
// Number of saved states
int mSaveCount;
@@ -122,13 +137,11 @@ protected:
// Base state
sp<Snapshot> mFirstSnapshot;
+protected:
// Current state
+ // TODO: should become private, once hooks needed by OpenGLRenderer are added
sp<Snapshot> mSnapshot;
-private:
- // Dimensions of the drawing surface
- int mWidth, mHeight;
-
}; // class StatefulBaseRenderer
}; // namespace uirenderer