Replace StatefulBaseRenderer inheritance with CanvasState member
Incrementally disentangles DisplayListRenderer and OpenGLRenderer. Introduces abstract CanvasStateClient class to share three functions between the two. Design doc at https://docs.google.com/a/google.com/document/d/1PY1JF7AfPEF2UOUAnETS5j_4_tnJShTAMExvpCJfP8o/edit?usp=sharing. BUG:15672762 R=djsollen@google.com,ccraik@google.com,jreck@google.com Change-Id: Ic9fdffe18808e7d921ad06d01ea1ca25b2ad6f23
This commit is contained in:
@@ -25,10 +25,9 @@ ifeq ($(USE_OPENGL_RENDERER),true)
|
||||
Animator.cpp \
|
||||
AnimatorManager.cpp \
|
||||
AssetAtlas.cpp \
|
||||
DamageAccumulator.cpp \
|
||||
FontRenderer.cpp \
|
||||
GammaFontRenderer.cpp \
|
||||
Caches.cpp \
|
||||
CanvasState.cpp \
|
||||
DamageAccumulator.cpp \
|
||||
DisplayList.cpp \
|
||||
DeferredDisplayList.cpp \
|
||||
DeferredLayerUpdater.cpp \
|
||||
@@ -38,6 +37,8 @@ ifeq ($(USE_OPENGL_RENDERER),true)
|
||||
DrawProfiler.cpp \
|
||||
Extensions.cpp \
|
||||
FboCache.cpp \
|
||||
FontRenderer.cpp \
|
||||
GammaFontRenderer.cpp \
|
||||
GradientCache.cpp \
|
||||
Image.cpp \
|
||||
Interpolator.cpp \
|
||||
@@ -62,7 +63,6 @@ ifeq ($(USE_OPENGL_RENDERER),true)
|
||||
SkiaShader.cpp \
|
||||
Snapshot.cpp \
|
||||
SpotShadow.cpp \
|
||||
StatefulBaseRenderer.cpp \
|
||||
Stencil.cpp \
|
||||
TessellationCache.cpp \
|
||||
Texture.cpp \
|
||||
|
||||
@@ -14,41 +14,45 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "OpenGLRenderer"
|
||||
|
||||
#include <SkCanvas.h>
|
||||
|
||||
#include "StatefulBaseRenderer.h"
|
||||
|
||||
#include "CanvasState.h"
|
||||
#include "utils/MathUtils.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
StatefulBaseRenderer::StatefulBaseRenderer()
|
||||
|
||||
CanvasState::CanvasState(CanvasStateClient& renderer)
|
||||
: mDirtyClip(false)
|
||||
, mWidth(-1)
|
||||
, mHeight(-1)
|
||||
, mSaveCount(1)
|
||||
, mFirstSnapshot(new Snapshot)
|
||||
, mCanvas(renderer)
|
||||
, mSnapshot(mFirstSnapshot) {
|
||||
|
||||
}
|
||||
|
||||
void StatefulBaseRenderer::initializeSaveStack(float clipLeft, float clipTop,
|
||||
CanvasState::~CanvasState() {
|
||||
|
||||
}
|
||||
|
||||
void CanvasState::initializeSaveStack(float clipLeft, float clipTop,
|
||||
float clipRight, float clipBottom, const Vector3& lightCenter) {
|
||||
mSnapshot = new Snapshot(mFirstSnapshot,
|
||||
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
|
||||
mSnapshot->setClip(clipLeft, clipTop, clipRight, clipBottom);
|
||||
mSnapshot->fbo = getTargetFbo();
|
||||
mSnapshot->fbo = mCanvas.onGetTargetFbo();
|
||||
mSnapshot->setRelativeLightCenter(lightCenter);
|
||||
mSaveCount = 1;
|
||||
}
|
||||
|
||||
void StatefulBaseRenderer::setViewport(int width, int height) {
|
||||
void CanvasState::setViewport(int width, int height) {
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
mFirstSnapshot->initializeViewport(width, height);
|
||||
onViewportInitialized();
|
||||
mCanvas.onViewportInitialized();
|
||||
|
||||
// create a temporary 1st snapshot, so old snapshots are released,
|
||||
// and viewport can be queried safely.
|
||||
@@ -63,24 +67,24 @@ void StatefulBaseRenderer::setViewport(int width, int height) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Non-virtual implementation of save, guaranteed to save without side-effects
|
||||
* Guaranteed to save without side-effects
|
||||
*
|
||||
* The approach here and in restoreSnapshot(), allows subclasses to directly manipulate the save
|
||||
* This approach, here and in restoreSnapshot(), allows subclasses to directly manipulate the save
|
||||
* stack, and ensures restoreToCount() doesn't call back into subclass overrides.
|
||||
*/
|
||||
int StatefulBaseRenderer::saveSnapshot(int flags) {
|
||||
int CanvasState::saveSnapshot(int flags) {
|
||||
mSnapshot = new Snapshot(mSnapshot, flags);
|
||||
return mSaveCount++;
|
||||
}
|
||||
|
||||
int StatefulBaseRenderer::save(int flags) {
|
||||
int CanvasState::save(int flags) {
|
||||
return saveSnapshot(flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-virtual implementation of restore, guaranteed to restore without side-effects.
|
||||
* Guaranteed to restore without side-effects.
|
||||
*/
|
||||
void StatefulBaseRenderer::restoreSnapshot() {
|
||||
void CanvasState::restoreSnapshot() {
|
||||
sp<Snapshot> toRemove = mSnapshot;
|
||||
sp<Snapshot> toRestore = mSnapshot->previous;
|
||||
|
||||
@@ -88,16 +92,16 @@ void StatefulBaseRenderer::restoreSnapshot() {
|
||||
mSnapshot = toRestore;
|
||||
|
||||
// subclass handles restore implementation
|
||||
onSnapshotRestored(*toRemove, *toRestore);
|
||||
mCanvas.onSnapshotRestored(*toRemove, *toRestore);
|
||||
}
|
||||
|
||||
void StatefulBaseRenderer::restore() {
|
||||
void CanvasState::restore() {
|
||||
if (mSaveCount > 1) {
|
||||
restoreSnapshot();
|
||||
}
|
||||
}
|
||||
|
||||
void StatefulBaseRenderer::restoreToCount(int saveCount) {
|
||||
void CanvasState::restoreToCount(int saveCount) {
|
||||
if (saveCount < 1) saveCount = 1;
|
||||
|
||||
while (mSaveCount > saveCount) {
|
||||
@@ -109,40 +113,40 @@ void StatefulBaseRenderer::restoreToCount(int saveCount) {
|
||||
// Matrix
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void StatefulBaseRenderer::getMatrix(SkMatrix* matrix) const {
|
||||
void CanvasState::getMatrix(SkMatrix* matrix) const {
|
||||
mSnapshot->transform->copyTo(*matrix);
|
||||
}
|
||||
|
||||
void StatefulBaseRenderer::translate(float dx, float dy, float dz) {
|
||||
void CanvasState::translate(float dx, float dy, float dz) {
|
||||
mSnapshot->transform->translate(dx, dy, dz);
|
||||
}
|
||||
|
||||
void StatefulBaseRenderer::rotate(float degrees) {
|
||||
void CanvasState::rotate(float degrees) {
|
||||
mSnapshot->transform->rotate(degrees, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void StatefulBaseRenderer::scale(float sx, float sy) {
|
||||
void CanvasState::scale(float sx, float sy) {
|
||||
mSnapshot->transform->scale(sx, sy, 1.0f);
|
||||
}
|
||||
|
||||
void StatefulBaseRenderer::skew(float sx, float sy) {
|
||||
void CanvasState::skew(float sx, float sy) {
|
||||
mSnapshot->transform->skew(sx, sy);
|
||||
}
|
||||
|
||||
void StatefulBaseRenderer::setMatrix(const SkMatrix& matrix) {
|
||||
void CanvasState::setMatrix(const SkMatrix& matrix) {
|
||||
mSnapshot->transform->load(matrix);
|
||||
}
|
||||
|
||||
void StatefulBaseRenderer::setMatrix(const Matrix4& matrix) {
|
||||
void CanvasState::setMatrix(const Matrix4& matrix) {
|
||||
mSnapshot->transform->load(matrix);
|
||||
}
|
||||
|
||||
void StatefulBaseRenderer::concatMatrix(const SkMatrix& matrix) {
|
||||
void CanvasState::concatMatrix(const SkMatrix& matrix) {
|
||||
mat4 transform(matrix);
|
||||
mSnapshot->transform->multiply(transform);
|
||||
}
|
||||
|
||||
void StatefulBaseRenderer::concatMatrix(const Matrix4& matrix) {
|
||||
void CanvasState::concatMatrix(const Matrix4& matrix) {
|
||||
mSnapshot->transform->multiply(matrix);
|
||||
}
|
||||
|
||||
@@ -150,7 +154,7 @@ void StatefulBaseRenderer::concatMatrix(const Matrix4& matrix) {
|
||||
// Clip
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool StatefulBaseRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
|
||||
bool CanvasState::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();
|
||||
@@ -159,10 +163,10 @@ bool StatefulBaseRenderer::clipRect(float left, float top, float right, float bo
|
||||
SkPath path;
|
||||
path.addRect(left, top, right, bottom);
|
||||
|
||||
return StatefulBaseRenderer::clipPath(&path, op);
|
||||
return CanvasState::clipPath(&path, op);
|
||||
}
|
||||
|
||||
bool StatefulBaseRenderer::clipPath(const SkPath* path, SkRegion::Op op) {
|
||||
bool CanvasState::clipPath(const SkPath* path, SkRegion::Op op) {
|
||||
SkMatrix transform;
|
||||
currentTransform()->copyTo(transform);
|
||||
|
||||
@@ -189,12 +193,12 @@ bool StatefulBaseRenderer::clipPath(const SkPath* path, SkRegion::Op op) {
|
||||
return !mSnapshot->clipRect->isEmpty();
|
||||
}
|
||||
|
||||
bool StatefulBaseRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) {
|
||||
bool CanvasState::clipRegion(const SkRegion* region, SkRegion::Op op) {
|
||||
mDirtyClip |= mSnapshot->clipRegionTransformed(*region, op);
|
||||
return !mSnapshot->clipRect->isEmpty();
|
||||
}
|
||||
|
||||
void StatefulBaseRenderer::setClippingOutline(LinearAllocator& allocator, const Outline* outline) {
|
||||
void CanvasState::setClippingOutline(LinearAllocator& allocator, const Outline* outline) {
|
||||
Rect bounds;
|
||||
float radius;
|
||||
if (!outline->getAsRoundRect(&bounds, &radius)) return; // only RR supported
|
||||
@@ -209,7 +213,7 @@ void StatefulBaseRenderer::setClippingOutline(LinearAllocator& allocator, const
|
||||
}
|
||||
}
|
||||
|
||||
void StatefulBaseRenderer::setClippingRoundRect(LinearAllocator& allocator,
|
||||
void CanvasState::setClippingRoundRect(LinearAllocator& allocator,
|
||||
const Rect& rect, float radius, bool highPriority) {
|
||||
mSnapshot->setClippingRoundRect(allocator, rect, radius, highPriority);
|
||||
}
|
||||
@@ -229,7 +233,7 @@ void StatefulBaseRenderer::setClippingRoundRect(LinearAllocator& allocator,
|
||||
* @param snapOut if set, the geometry will be treated as having an AA ramp.
|
||||
* See Rect::snapGeometryToPixelBoundaries()
|
||||
*/
|
||||
bool StatefulBaseRenderer::calculateQuickRejectForScissor(float left, float top,
|
||||
bool CanvasState::calculateQuickRejectForScissor(float left, float top,
|
||||
float right, float bottom,
|
||||
bool* clipRequired, bool* roundRectClipRequired,
|
||||
bool snapOut) const {
|
||||
@@ -259,18 +263,7 @@ bool StatefulBaseRenderer::calculateQuickRejectForScissor(float left, float top,
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false if drawing won't be clipped out.
|
||||
*
|
||||
* Makes the decision conservatively, by rounding out the mapped rect before comparing with the
|
||||
* clipRect. To be used when perfect, pixel accuracy is not possible (esp. with tessellation) but
|
||||
* rejection is still desired.
|
||||
*
|
||||
* This function, unlike quickRejectSetupScissor, should be used where precise geometry information
|
||||
* isn't known (esp. when geometry adjusts based on scale). Generally, this will be first pass
|
||||
* rejection where precise rejection isn't important, or precise information isn't available.
|
||||
*/
|
||||
bool StatefulBaseRenderer::quickRejectConservative(float left, float top,
|
||||
bool CanvasState::quickRejectConservative(float left, float top,
|
||||
float right, float bottom) const {
|
||||
if (mSnapshot->isIgnored() || bottom <= top || right <= left) {
|
||||
return true;
|
||||
@@ -288,5 +281,5 @@ bool StatefulBaseRenderer::quickRejectConservative(float left, float top,
|
||||
return false;
|
||||
}
|
||||
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
} // namespace uirenderer
|
||||
} // namespace android
|
||||
196
libs/hwui/CanvasState.h
Normal file
196
libs/hwui/CanvasState.h
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_HWUI_CANVAS_STATE_H
|
||||
#define ANDROID_HWUI_CANVAS_STATE_H
|
||||
|
||||
#include <SkMatrix.h>
|
||||
#include <SkPath.h>
|
||||
#include <SkRegion.h>
|
||||
|
||||
#include "Snapshot.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
/**
|
||||
* Abstract base class for any class containing CanvasState.
|
||||
* Defines three mandatory callbacks.
|
||||
*/
|
||||
class CanvasStateClient {
|
||||
public:
|
||||
CanvasStateClient() { }
|
||||
virtual ~CanvasStateClient() { }
|
||||
|
||||
/**
|
||||
* Callback allowing embedder to take actions in the middle of a
|
||||
* setViewport() call.
|
||||
*/
|
||||
virtual void onViewportInitialized() = 0;
|
||||
|
||||
/**
|
||||
* Callback allowing embedder to take actions in the middle of a
|
||||
* restore() call. May be called several times sequentially.
|
||||
*/
|
||||
virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) = 0;
|
||||
|
||||
/**
|
||||
* Allows subclasses to control what value is stored in snapshot's
|
||||
* fbo field in * initializeSaveStack.
|
||||
*/
|
||||
virtual GLuint onGetTargetFbo() const = 0;
|
||||
|
||||
}; // class CanvasStateClient
|
||||
|
||||
/**
|
||||
* Implements Canvas state methods on behalf of Renderers.
|
||||
*
|
||||
* Manages the Snapshot stack, implementing matrix, save/restore, and clipping methods in the
|
||||
* Renderer interface. Drawing and recording classes that include a CanvasState 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 CanvasState, so that not only will querying operations work (getClip/Matrix), but so
|
||||
* that quickRejection can also be used.
|
||||
*/
|
||||
|
||||
class CanvasState {
|
||||
public:
|
||||
CanvasState(CanvasStateClient& renderer);
|
||||
~CanvasState();
|
||||
|
||||
/**
|
||||
* Initializes the first snapshot, computing the projection matrix,
|
||||
* and stores the dimensions of the render target.
|
||||
*/
|
||||
void initializeSaveStack(float clipLeft, float clipTop, float clipRight, float clipBottom,
|
||||
const Vector3& lightCenter);
|
||||
|
||||
void setViewport(int width, int height);
|
||||
|
||||
bool hasRectToRectTransform() const {
|
||||
return CC_LIKELY(currentTransform()->rectToRect());
|
||||
}
|
||||
|
||||
// Save (layer)
|
||||
int getSaveCount() const { return mSaveCount; }
|
||||
int save(int flags);
|
||||
void restore();
|
||||
void restoreToCount(int saveCount);
|
||||
|
||||
// Save/Restore without side-effects
|
||||
int saveSnapshot(int flags);
|
||||
void restoreSnapshot();
|
||||
|
||||
// Matrix
|
||||
void getMatrix(SkMatrix* outMatrix) const;
|
||||
void translate(float dx, float dy, float dz = 0.0f);
|
||||
void rotate(float degrees);
|
||||
void scale(float sx, float sy);
|
||||
void skew(float sx, float sy);
|
||||
|
||||
void setMatrix(const SkMatrix& matrix);
|
||||
void setMatrix(const Matrix4& matrix); // internal only convenience method
|
||||
void concatMatrix(const SkMatrix& matrix);
|
||||
void concatMatrix(const Matrix4& matrix); // internal only convenience method
|
||||
|
||||
// Clip
|
||||
const Rect& getLocalClipBounds() const { return mSnapshot->getLocalClip(); }
|
||||
const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); }
|
||||
|
||||
bool quickRejectConservative(float left, float top, float right, float bottom) const;
|
||||
|
||||
bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
|
||||
bool clipPath(const SkPath* path, SkRegion::Op op);
|
||||
bool clipRegion(const SkRegion* region, SkRegion::Op op);
|
||||
|
||||
bool isCurrentClipSimple() const {
|
||||
return currentSnapshot()->clipRegion->isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a "clipping outline", which is independent from the regular clip.
|
||||
* Currently only supports rectangles or rounded rectangles; passing in a
|
||||
* more complicated outline fails silently. Replaces any previous clipping
|
||||
* outline.
|
||||
*/
|
||||
void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
|
||||
void setClippingRoundRect(LinearAllocator& allocator,
|
||||
const Rect& rect, float radius, bool highPriority = true);
|
||||
|
||||
/**
|
||||
* Returns true if drawing in the rectangle (left, top, right, bottom)
|
||||
* will be clipped out. Is conservative: might return false when subpixel-
|
||||
* perfect tests would return true.
|
||||
*/
|
||||
bool calculateQuickRejectForScissor(float left, float top, float right, float bottom,
|
||||
bool* clipRequired, bool* roundRectClipRequired, bool snapOut) const;
|
||||
|
||||
void setDirtyClip(bool opaque) { mDirtyClip = opaque; }
|
||||
bool getDirtyClip() const { return mDirtyClip; }
|
||||
|
||||
void scaleAlpha(float alpha) { mSnapshot->alpha *= alpha; }
|
||||
void setEmpty(bool value) { mSnapshot->empty = value; }
|
||||
void setInvisible(bool value) { mSnapshot->invisible = value; }
|
||||
|
||||
inline const mat4* currentTransform() const { return currentSnapshot()->transform; }
|
||||
inline const Rect* currentClipRect() const { return currentSnapshot()->clipRect; }
|
||||
inline Region* currentRegion() const { return currentSnapshot()->region; }
|
||||
inline int currentFlags() const { return currentSnapshot()->flags; }
|
||||
const Vector3& currentLightCenter() const { return currentSnapshot()->getRelativeLightCenter(); }
|
||||
inline bool currentlyIgnored() const { return currentSnapshot()->isIgnored(); }
|
||||
int getViewportWidth() const { return currentSnapshot()->getViewportWidth(); }
|
||||
int getViewportHeight() const { return currentSnapshot()->getViewportHeight(); }
|
||||
int getWidth() { return mWidth; }
|
||||
int getHeight() { return mHeight; }
|
||||
|
||||
inline const Snapshot* currentSnapshot() const {
|
||||
return mSnapshot != NULL ? mSnapshot.get() : mFirstSnapshot.get();
|
||||
}
|
||||
inline Snapshot* writableSnapshot() { return mSnapshot.get(); }
|
||||
inline const Snapshot* firstSnapshot() const { return mFirstSnapshot.get(); }
|
||||
|
||||
private:
|
||||
/// No default constructor - must supply a CanvasStateClient (mCanvas).
|
||||
CanvasState();
|
||||
|
||||
/// indicates that the clip has been changed since the last time it was consumed
|
||||
bool mDirtyClip;
|
||||
|
||||
/// Dimensions of the drawing surface
|
||||
int mWidth, mHeight;
|
||||
|
||||
/// Number of saved states
|
||||
int mSaveCount;
|
||||
|
||||
/// Base state
|
||||
sp<Snapshot> mFirstSnapshot;
|
||||
|
||||
/// Host providing callbacks
|
||||
CanvasStateClient& mCanvas;
|
||||
|
||||
/// Current state
|
||||
sp<Snapshot> mSnapshot;
|
||||
|
||||
}; // class CanvasState
|
||||
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_HWUI_CANVAS_STATE_H
|
||||
@@ -32,7 +32,8 @@ namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
DisplayListRenderer::DisplayListRenderer()
|
||||
: mCaches(Caches::getInstance())
|
||||
: mState(*this)
|
||||
, mCaches(Caches::getInstance())
|
||||
, mDisplayListData(NULL)
|
||||
, mTranslateX(0.0f)
|
||||
, mTranslateY(0.0f)
|
||||
@@ -66,10 +67,10 @@ void DisplayListRenderer::prepareDirty(float left, float top,
|
||||
"prepareDirty called a second time during a recording!");
|
||||
mDisplayListData = new DisplayListData();
|
||||
|
||||
initializeSaveStack(0, 0, getWidth(), getHeight(), Vector3());
|
||||
mState.initializeSaveStack(0, 0, mState.getWidth(), mState.getHeight(), Vector3());
|
||||
|
||||
mDeferredBarrierType = kBarrier_InOrder;
|
||||
mDirtyClip = opaque;
|
||||
mState.setDirtyClip(opaque);
|
||||
mRestoreSaveCount = -1;
|
||||
}
|
||||
|
||||
@@ -93,7 +94,7 @@ void DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
|
||||
|
||||
int DisplayListRenderer::save(int flags) {
|
||||
addStateOp(new (alloc()) SaveOp(flags));
|
||||
return StatefulBaseRenderer::save(flags);
|
||||
return mState.save(flags);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::restore() {
|
||||
@@ -104,13 +105,13 @@ void DisplayListRenderer::restore() {
|
||||
|
||||
mRestoreSaveCount--;
|
||||
flushTranslate();
|
||||
StatefulBaseRenderer::restore();
|
||||
mState.restore();
|
||||
}
|
||||
|
||||
void DisplayListRenderer::restoreToCount(int saveCount) {
|
||||
mRestoreSaveCount = saveCount;
|
||||
flushTranslate();
|
||||
StatefulBaseRenderer::restoreToCount(saveCount);
|
||||
mState.restoreToCount(saveCount);
|
||||
}
|
||||
|
||||
int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
|
||||
@@ -120,7 +121,7 @@ int DisplayListRenderer::saveLayer(float left, float top, float right, float bot
|
||||
|
||||
paint = refPaint(paint);
|
||||
addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, paint, flags));
|
||||
return StatefulBaseRenderer::save(flags);
|
||||
return mState.save(flags);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::translate(float dx, float dy, float dz) {
|
||||
@@ -129,50 +130,50 @@ void DisplayListRenderer::translate(float dx, float dy, float dz) {
|
||||
mTranslateX += dx;
|
||||
mTranslateY += dy;
|
||||
flushRestoreToCount();
|
||||
StatefulBaseRenderer::translate(dx, dy, dz);
|
||||
mState.translate(dx, dy, dz);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::rotate(float degrees) {
|
||||
addStateOp(new (alloc()) RotateOp(degrees));
|
||||
StatefulBaseRenderer::rotate(degrees);
|
||||
mState.rotate(degrees);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::scale(float sx, float sy) {
|
||||
addStateOp(new (alloc()) ScaleOp(sx, sy));
|
||||
StatefulBaseRenderer::scale(sx, sy);
|
||||
mState.scale(sx, sy);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::skew(float sx, float sy) {
|
||||
addStateOp(new (alloc()) SkewOp(sx, sy));
|
||||
StatefulBaseRenderer::skew(sx, sy);
|
||||
mState.skew(sx, sy);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::setMatrix(const SkMatrix& matrix) {
|
||||
addStateOp(new (alloc()) SetMatrixOp(matrix));
|
||||
StatefulBaseRenderer::setMatrix(matrix);
|
||||
mState.setMatrix(matrix);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::concatMatrix(const SkMatrix& matrix) {
|
||||
addStateOp(new (alloc()) ConcatMatrixOp(matrix));
|
||||
StatefulBaseRenderer::concatMatrix(matrix);
|
||||
mState.concatMatrix(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 StatefulBaseRenderer::clipRect(left, top, right, bottom, op);
|
||||
return mState.clipRect(left, top, right, bottom, op);
|
||||
}
|
||||
|
||||
bool DisplayListRenderer::clipPath(const SkPath* path, SkRegion::Op op) {
|
||||
path = refPath(path);
|
||||
addStateOp(new (alloc()) ClipPathOp(path, op));
|
||||
return StatefulBaseRenderer::clipPath(path, op);
|
||||
return mState.clipPath(path, op);
|
||||
}
|
||||
|
||||
bool DisplayListRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) {
|
||||
region = refRegion(region);
|
||||
addStateOp(new (alloc()) ClipRegionOp(region, op));
|
||||
return StatefulBaseRenderer::clipRegion(region, op);
|
||||
return mState.clipRegion(region, op);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t flags) {
|
||||
@@ -180,7 +181,7 @@ void DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, in
|
||||
|
||||
// dirty is an out parameter and should not be recorded,
|
||||
// it matters only when replaying the display list
|
||||
DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
|
||||
DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *mState.currentTransform());
|
||||
addRenderNodeOp(op);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,11 @@
|
||||
#include <SkTLazy.h>
|
||||
#include <cutils/compiler.h>
|
||||
|
||||
#include "CanvasState.h"
|
||||
#include "DisplayList.h"
|
||||
#include "DisplayListLogBuffer.h"
|
||||
#include "StatefulBaseRenderer.h"
|
||||
#include "RenderNode.h"
|
||||
#include "Renderer.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
@@ -57,7 +59,7 @@ class StateOp;
|
||||
/**
|
||||
* Records drawing commands in a display list for later playback into an OpenGLRenderer.
|
||||
*/
|
||||
class ANDROID_API DisplayListRenderer: public StatefulBaseRenderer {
|
||||
class ANDROID_API DisplayListRenderer: public Renderer, public CanvasStateClient {
|
||||
public:
|
||||
DisplayListRenderer();
|
||||
virtual ~DisplayListRenderer();
|
||||
@@ -70,6 +72,9 @@ public:
|
||||
// Frame state operations
|
||||
// ----------------------------------------------------------------------------
|
||||
virtual void prepareDirty(float left, float top, float right, float bottom, bool opaque);
|
||||
virtual void prepare(bool opaque) {
|
||||
prepareDirty(0.0f, 0.0f, mState.getWidth(), mState.getHeight(), opaque);
|
||||
}
|
||||
virtual bool finish();
|
||||
virtual void interrupt();
|
||||
virtual void resume();
|
||||
@@ -77,7 +82,10 @@ public:
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas state operations
|
||||
// ----------------------------------------------------------------------------
|
||||
virtual void setViewport(int width, int height) { mState.setViewport(width, height); }
|
||||
|
||||
// Save (layer)
|
||||
virtual int getSaveCount() const { return mState.getSaveCount(); }
|
||||
virtual int save(int flags);
|
||||
virtual void restore();
|
||||
virtual void restoreToCount(int saveCount);
|
||||
@@ -85,6 +93,8 @@ public:
|
||||
const SkPaint* paint, int flags);
|
||||
|
||||
// Matrix
|
||||
virtual void getMatrix(SkMatrix* outMatrix) const { mState.getMatrix(outMatrix); }
|
||||
|
||||
virtual void translate(float dx, float dy, float dz = 0.0f);
|
||||
virtual void rotate(float degrees);
|
||||
virtual void scale(float sx, float sy);
|
||||
@@ -100,9 +110,14 @@ public:
|
||||
|
||||
// Misc
|
||||
virtual void setDrawFilter(SkDrawFilter* filter);
|
||||
virtual const Rect& getLocalClipBounds() const { return mState.getLocalClipBounds(); }
|
||||
const Rect& getRenderTargetClipBounds() const { return mState.getRenderTargetClipBounds(); }
|
||||
virtual bool quickRejectConservative(float left, float top, float right, float bottom) const {
|
||||
return mState.quickRejectConservative(left, top, right, bottom);
|
||||
}
|
||||
|
||||
bool isCurrentTransformSimple() {
|
||||
return currentTransform()->isSimple();
|
||||
return mState.currentTransform()->isSimple();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -163,7 +178,18 @@ public:
|
||||
void setHighContrastText(bool highContrastText) {
|
||||
mHighContrastText = highContrastText;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CanvasState callbacks
|
||||
// ----------------------------------------------------------------------------
|
||||
virtual void onViewportInitialized() { }
|
||||
virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) { }
|
||||
virtual GLuint onGetTargetFbo() const { return -1; }
|
||||
|
||||
private:
|
||||
|
||||
CanvasState mState;
|
||||
|
||||
enum DeferredBarrierType {
|
||||
kBarrier_None,
|
||||
kBarrier_InOrder,
|
||||
|
||||
@@ -91,7 +91,7 @@ bool LayerRenderer::finish() {
|
||||
return retval;
|
||||
}
|
||||
|
||||
GLuint LayerRenderer::getTargetFbo() const {
|
||||
GLuint LayerRenderer::onGetTargetFbo() const {
|
||||
return mLayer->getFbo();
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ void LayerRenderer::ensureStencilBuffer() {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Region* LayerRenderer::getRegion() const {
|
||||
if (currentSnapshot()->flags & Snapshot::kFlagFboTarget) {
|
||||
if (mState.currentFlags() & Snapshot::kFlagFboTarget) {
|
||||
return OpenGLRenderer::getRegion();
|
||||
}
|
||||
return &mLayer->region;
|
||||
|
||||
@@ -68,7 +68,7 @@ protected:
|
||||
virtual void ensureStencilBuffer();
|
||||
virtual bool hasLayer() const;
|
||||
virtual Region* getRegion() const;
|
||||
virtual GLuint getTargetFbo() const;
|
||||
virtual GLuint onGetTargetFbo() const;
|
||||
virtual bool suppressErrorChecks() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -147,7 +147,8 @@ static inline T min(T a, T b) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OpenGLRenderer::OpenGLRenderer(RenderState& renderState)
|
||||
: mFrameStarted(false)
|
||||
: mState(*this)
|
||||
, mFrameStarted(false)
|
||||
, mCaches(Caches::getInstance())
|
||||
, mExtensions(Extensions::getInstance())
|
||||
, mRenderState(renderState)
|
||||
@@ -205,7 +206,7 @@ void OpenGLRenderer::onViewportInitialized() {
|
||||
void OpenGLRenderer::setupFrameState(float left, float top,
|
||||
float right, float bottom, bool opaque) {
|
||||
mCaches.clearGarbage();
|
||||
initializeSaveStack(left, top, right, bottom, mLightCenter);
|
||||
mState.initializeSaveStack(left, top, right, bottom, mLightCenter);
|
||||
mOpaque = opaque;
|
||||
mTilingClip.set(left, top, right, bottom);
|
||||
}
|
||||
@@ -214,11 +215,11 @@ void OpenGLRenderer::startFrame() {
|
||||
if (mFrameStarted) return;
|
||||
mFrameStarted = true;
|
||||
|
||||
mDirtyClip = true;
|
||||
mState.setDirtyClip(true);
|
||||
|
||||
discardFramebuffer(mTilingClip.left, mTilingClip.top, mTilingClip.right, mTilingClip.bottom);
|
||||
|
||||
mRenderState.setViewport(getWidth(), getHeight());
|
||||
mRenderState.setViewport(mState.getWidth(), mState.getHeight());
|
||||
|
||||
// Functors break the tiling extension in pretty spectacular ways
|
||||
// This ensures we don't use tiling when a functor is going to be
|
||||
@@ -257,8 +258,8 @@ void OpenGLRenderer::discardFramebuffer(float left, float top, float right, floa
|
||||
// perform a discard to let the driver know we don't need to preserve
|
||||
// the back buffer for this frame.
|
||||
if (mExtensions.hasDiscardFramebuffer() &&
|
||||
left <= 0.0f && top <= 0.0f && right >= getWidth() && bottom >= getHeight()) {
|
||||
const bool isFbo = getTargetFbo() == 0;
|
||||
left <= 0.0f && top <= 0.0f && right >= mState.getWidth() && bottom >= mState.getHeight()) {
|
||||
const bool isFbo = onGetTargetFbo() == 0;
|
||||
const GLenum attachments[] = {
|
||||
isFbo ? (const GLenum) GL_COLOR_EXT : (const GLenum) GL_COLOR_ATTACHMENT0,
|
||||
isFbo ? (const GLenum) GL_STENCIL_EXT : (const GLenum) GL_STENCIL_ATTACHMENT };
|
||||
@@ -329,7 +330,7 @@ bool OpenGLRenderer::finish() {
|
||||
|
||||
// When finish() is invoked on FBO 0 we've reached the end
|
||||
// of the current frame
|
||||
if (getTargetFbo() == 0) {
|
||||
if (onGetTargetFbo() == 0) {
|
||||
mCaches.pathCache.trim();
|
||||
mCaches.tessellationCache.trim();
|
||||
}
|
||||
@@ -363,9 +364,9 @@ void OpenGLRenderer::resumeAfterLayer() {
|
||||
}
|
||||
|
||||
void OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
|
||||
if (currentSnapshot()->isIgnored()) return;
|
||||
if (mState.currentlyIgnored()) return;
|
||||
|
||||
Rect clip(*currentClipRect());
|
||||
Rect clip(*mState.currentClipRect());
|
||||
clip.snapToPixelBoundaries();
|
||||
|
||||
// Since we don't know what the functor will draw, let's dirty
|
||||
@@ -384,9 +385,9 @@ void OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
|
||||
info.height = getViewportHeight();
|
||||
currentTransform()->copyTo(&info.transform[0]);
|
||||
|
||||
bool prevDirtyClip = mDirtyClip;
|
||||
bool prevDirtyClip = mState.getDirtyClip();
|
||||
// setup GL state for functor
|
||||
if (mDirtyClip) {
|
||||
if (mState.getDirtyClip()) {
|
||||
setStencilFromClip(); // can issue draws, so must precede enableScissor()/interrupt()
|
||||
}
|
||||
if (mCaches.enableScissor() || prevDirtyClip) {
|
||||
@@ -436,11 +437,11 @@ void OpenGLRenderer::debugOverdraw(bool enable, bool clear) {
|
||||
}
|
||||
|
||||
void OpenGLRenderer::renderOverdraw() {
|
||||
if (mCaches.debugOverdraw && getTargetFbo() == 0) {
|
||||
if (mCaches.debugOverdraw && onGetTargetFbo() == 0) {
|
||||
const Rect* clip = &mTilingClip;
|
||||
|
||||
mCaches.enableScissor();
|
||||
mCaches.setScissor(clip->left, firstSnapshot()->getViewportHeight() - clip->bottom,
|
||||
mCaches.setScissor(clip->left, mState.firstSnapshot()->getViewportHeight() - clip->bottom,
|
||||
clip->right - clip->left, clip->bottom - clip->top);
|
||||
|
||||
// 1x overdraw
|
||||
@@ -519,7 +520,7 @@ void OpenGLRenderer::updateLayers() {
|
||||
|
||||
if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
|
||||
mLayerUpdates.clear();
|
||||
mRenderState.bindFramebuffer(getTargetFbo());
|
||||
mRenderState.bindFramebuffer(onGetTargetFbo());
|
||||
}
|
||||
endMark();
|
||||
}
|
||||
@@ -546,7 +547,7 @@ void OpenGLRenderer::flushLayers() {
|
||||
}
|
||||
|
||||
mLayerUpdates.clear();
|
||||
mRenderState.bindFramebuffer(getTargetFbo());
|
||||
mRenderState.bindFramebuffer(onGetTargetFbo());
|
||||
|
||||
endMark();
|
||||
}
|
||||
@@ -628,9 +629,9 @@ int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
|
||||
// force matrix/clip isolation for layer
|
||||
flags |= SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag;
|
||||
|
||||
const int count = saveSnapshot(flags);
|
||||
const int count = mState.saveSnapshot(flags);
|
||||
|
||||
if (!currentSnapshot()->isIgnored()) {
|
||||
if (!mState.currentlyIgnored()) {
|
||||
createLayer(left, top, right, bottom, paint, flags, convexMask);
|
||||
}
|
||||
|
||||
@@ -643,7 +644,7 @@ void OpenGLRenderer::calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool
|
||||
currentTransform()->mapRect(bounds);
|
||||
|
||||
// Layers only make sense if they are in the framebuffer's bounds
|
||||
if (bounds.intersect(*currentClipRect())) {
|
||||
if (bounds.intersect(*mState.currentClipRect())) {
|
||||
// We cannot work with sub-pixels in this case
|
||||
bounds.snapToPixelBoundaries();
|
||||
|
||||
@@ -677,17 +678,17 @@ void OpenGLRenderer::updateSnapshotIgnoreForLayer(const Rect& bounds, const Rect
|
||||
if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
|
||||
bounds.getHeight() > mCaches.maxTextureSize ||
|
||||
(fboLayer && clip.isEmpty())) {
|
||||
mSnapshot->empty = fboLayer;
|
||||
writableSnapshot()->empty = fboLayer;
|
||||
} else {
|
||||
mSnapshot->invisible = mSnapshot->invisible || (alpha <= 0 && fboLayer);
|
||||
writableSnapshot()->invisible = writableSnapshot()->invisible || (alpha <= 0 && fboLayer);
|
||||
}
|
||||
}
|
||||
|
||||
int OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float bottom,
|
||||
const SkPaint* paint, int flags) {
|
||||
const int count = saveSnapshot(flags);
|
||||
const int count = mState.saveSnapshot(flags);
|
||||
|
||||
if (!currentSnapshot()->isIgnored() && (flags & SkCanvas::kClipToLayer_SaveFlag)) {
|
||||
if (!mState.currentlyIgnored() && (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)
|
||||
@@ -697,11 +698,11 @@ int OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float
|
||||
calculateLayerBoundsAndClip(bounds, clip, true);
|
||||
updateSnapshotIgnoreForLayer(bounds, clip, true, getAlphaDirect(paint));
|
||||
|
||||
if (!currentSnapshot()->isIgnored()) {
|
||||
mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
|
||||
mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
|
||||
mSnapshot->initializeViewport(bounds.getWidth(), bounds.getHeight());
|
||||
mSnapshot->roundRectClipState = NULL;
|
||||
if (!mState.currentlyIgnored()) {
|
||||
writableSnapshot()->resetTransform(-bounds.left, -bounds.top, 0.0f);
|
||||
writableSnapshot()->resetClip(clip.left, clip.top, clip.right, clip.bottom);
|
||||
writableSnapshot()->initializeViewport(bounds.getWidth(), bounds.getHeight());
|
||||
writableSnapshot()->roundRectClipState = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -773,7 +774,7 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto
|
||||
updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, getAlphaDirect(paint));
|
||||
|
||||
// Bail out if we won't draw in this snapshot
|
||||
if (currentSnapshot()->isIgnored()) {
|
||||
if (mState.currentlyIgnored()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -793,8 +794,8 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto
|
||||
layer->setConvexMask(convexMask); // note: the mask must be cleared before returning to the cache
|
||||
|
||||
// Save the layer in the snapshot
|
||||
mSnapshot->flags |= Snapshot::kFlagIsLayer;
|
||||
mSnapshot->layer = layer;
|
||||
writableSnapshot()->flags |= Snapshot::kFlagIsLayer;
|
||||
writableSnapshot()->layer = layer;
|
||||
|
||||
ATRACE_FORMAT_BEGIN("%ssaveLayer %ux%u",
|
||||
fboLayer ? "" : "unclipped ",
|
||||
@@ -832,13 +833,13 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip) {
|
||||
layer->clipRect.set(clip);
|
||||
layer->setFbo(mCaches.fboCache.get());
|
||||
|
||||
mSnapshot->region = &mSnapshot->layer->region;
|
||||
mSnapshot->flags |= Snapshot::kFlagFboTarget | Snapshot::kFlagIsFboLayer;
|
||||
mSnapshot->fbo = layer->getFbo();
|
||||
mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
|
||||
mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
|
||||
mSnapshot->initializeViewport(bounds.getWidth(), bounds.getHeight());
|
||||
mSnapshot->roundRectClipState = NULL;
|
||||
writableSnapshot()->region = &writableSnapshot()->layer->region;
|
||||
writableSnapshot()->flags |= Snapshot::kFlagFboTarget | Snapshot::kFlagIsFboLayer;
|
||||
writableSnapshot()->fbo = layer->getFbo();
|
||||
writableSnapshot()->resetTransform(-bounds.left, -bounds.top, 0.0f);
|
||||
writableSnapshot()->resetClip(clip.left, clip.top, clip.right, clip.bottom);
|
||||
writableSnapshot()->initializeViewport(bounds.getWidth(), bounds.getHeight());
|
||||
writableSnapshot()->roundRectClipState = NULL;
|
||||
|
||||
endTiling();
|
||||
debugOverdraw(false, false);
|
||||
@@ -885,7 +886,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto
|
||||
const bool fboLayer = removed.flags & Snapshot::kFlagIsFboLayer;
|
||||
|
||||
bool clipRequired = false;
|
||||
calculateQuickRejectForScissor(rect.left, rect.top, rect.right, rect.bottom,
|
||||
mState.calculateQuickRejectForScissor(rect.left, rect.top, rect.right, rect.bottom,
|
||||
&clipRequired, NULL, false); // safely ignore return, should never be rejected
|
||||
mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired);
|
||||
|
||||
@@ -930,7 +931,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto
|
||||
save(0);
|
||||
// the layer contains screen buffer content that shouldn't be alpha modulated
|
||||
// (and any necessary alpha modulation was handled drawing into the layer)
|
||||
mSnapshot->alpha = 1.0f;
|
||||
writableSnapshot()->alpha = 1.0f;
|
||||
composeLayerRect(layer, rect, true);
|
||||
restore();
|
||||
}
|
||||
@@ -1038,13 +1039,13 @@ void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap)
|
||||
* operations are correctly counted twice for overdraw. NOTE: assumes composeLayerRegion only used
|
||||
* by saveLayer's restore
|
||||
*/
|
||||
#define DRAW_DOUBLE_STENCIL_IF(COND, DRAW_COMMAND) { \
|
||||
DRAW_COMMAND; \
|
||||
if (CC_UNLIKELY(mCaches.debugOverdraw && getTargetFbo() == 0 && COND)) { \
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); \
|
||||
DRAW_COMMAND; \
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \
|
||||
} \
|
||||
#define DRAW_DOUBLE_STENCIL_IF(COND, DRAW_COMMAND) { \
|
||||
DRAW_COMMAND; \
|
||||
if (CC_UNLIKELY(mCaches.debugOverdraw && onGetTargetFbo() == 0 && COND)) { \
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); \
|
||||
DRAW_COMMAND; \
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DRAW_DOUBLE_STENCIL(DRAW_COMMAND) DRAW_DOUBLE_STENCIL_IF(true, DRAW_COMMAND)
|
||||
@@ -1273,7 +1274,7 @@ void OpenGLRenderer::dirtyLayer(const float left, const float top,
|
||||
}
|
||||
|
||||
void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) {
|
||||
if (bounds.intersect(*currentClipRect())) {
|
||||
if (bounds.intersect(*mState.currentClipRect())) {
|
||||
bounds.snapToPixelBoundaries();
|
||||
android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
|
||||
if (!dirty.isEmpty()) {
|
||||
@@ -1301,7 +1302,7 @@ void OpenGLRenderer::clearLayerRegions() {
|
||||
const size_t count = mLayers.size();
|
||||
if (count == 0) return;
|
||||
|
||||
if (!currentSnapshot()->isIgnored()) {
|
||||
if (!mState.currentlyIgnored()) {
|
||||
EVENT_LOGD("clearLayerRegions");
|
||||
// Doing several glScissor/glClear here can negatively impact
|
||||
// GPUs with a tiler architecture, instead we draw quads with
|
||||
@@ -1357,7 +1358,7 @@ void OpenGLRenderer::clearLayerRegions() {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDeferFlags) {
|
||||
const Rect* currentClip = currentClipRect();
|
||||
const Rect* currentClip = mState.currentClipRect();
|
||||
const mat4* currentMatrix = currentTransform();
|
||||
|
||||
if (stateDeferFlags & kStateDeferFlag_Draw) {
|
||||
@@ -1410,12 +1411,12 @@ bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDef
|
||||
|
||||
void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, bool skipClipRestore) {
|
||||
setMatrix(state.mMatrix);
|
||||
mSnapshot->alpha = state.mAlpha;
|
||||
writableSnapshot()->alpha = state.mAlpha;
|
||||
mDrawModifiers = state.mDrawModifiers;
|
||||
mSnapshot->roundRectClipState = state.mRoundRectClipState;
|
||||
writableSnapshot()->roundRectClipState = state.mRoundRectClipState;
|
||||
|
||||
if (state.mClipValid && !skipClipRestore) {
|
||||
mSnapshot->setClip(state.mClip.left, state.mClip.top,
|
||||
writableSnapshot()->setClip(state.mClip.left, state.mClip.top,
|
||||
state.mClip.right, state.mClip.bottom);
|
||||
dirtyClip();
|
||||
}
|
||||
@@ -1430,9 +1431,9 @@ void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, bool
|
||||
*/
|
||||
void OpenGLRenderer::setupMergedMultiDraw(const Rect* clipRect) {
|
||||
if (clipRect != NULL) {
|
||||
mSnapshot->setClip(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
|
||||
writableSnapshot()->setClip(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
|
||||
} else {
|
||||
mSnapshot->setClip(0, 0, getWidth(), getHeight());
|
||||
writableSnapshot()->setClip(0, 0, mState.getWidth(), mState.getHeight());
|
||||
}
|
||||
dirtyClip();
|
||||
mCaches.setScissorEnabled(clipRect != NULL || mScissorOptimizationDisabled);
|
||||
@@ -1443,12 +1444,12 @@ void OpenGLRenderer::setupMergedMultiDraw(const Rect* clipRect) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void OpenGLRenderer::setScissorFromClip() {
|
||||
Rect clip(*currentClipRect());
|
||||
Rect clip(*mState.currentClipRect());
|
||||
clip.snapToPixelBoundaries();
|
||||
|
||||
if (mCaches.setScissor(clip.left, getViewportHeight() - clip.bottom,
|
||||
clip.getWidth(), clip.getHeight())) {
|
||||
mDirtyClip = false;
|
||||
mState.setDirtyClip(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1484,7 +1485,7 @@ void OpenGLRenderer::setStencilFromClip() {
|
||||
|
||||
// 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;
|
||||
mState.setDirtyClip(false);
|
||||
|
||||
ensureStencilBuffer();
|
||||
|
||||
@@ -1553,7 +1554,7 @@ bool OpenGLRenderer::quickRejectSetupScissor(float left, float top, float right,
|
||||
|
||||
bool clipRequired = false;
|
||||
bool roundRectClipRequired = false;
|
||||
if (calculateQuickRejectForScissor(left, top, right, bottom,
|
||||
if (mState.calculateQuickRejectForScissor(left, top, right, bottom,
|
||||
&clipRequired, &roundRectClipRequired, snapOut)) {
|
||||
return true;
|
||||
}
|
||||
@@ -1585,7 +1586,7 @@ void OpenGLRenderer::setupDraw(bool clearLayer) {
|
||||
if (clearLayer) clearLayerRegions();
|
||||
// Make sure setScissor & setStencil happen at the beginning of
|
||||
// this method
|
||||
if (mDirtyClip) {
|
||||
if (mState.getDirtyClip()) {
|
||||
if (mCaches.scissorEnabled) {
|
||||
setScissorFromClip();
|
||||
}
|
||||
@@ -1723,7 +1724,7 @@ void OpenGLRenderer::setupDrawProgram() {
|
||||
useProgram(mCaches.programCache.get(mDescription));
|
||||
if (mDescription.hasRoundRectClip) {
|
||||
// TODO: avoid doing this repeatedly, stashing state pointer in program
|
||||
const RoundRectClipState* state = mSnapshot->roundRectClipState;
|
||||
const RoundRectClipState* state = writableSnapshot()->roundRectClipState;
|
||||
const Rect& innerRect = state->innerRect;
|
||||
glUniform4f(mCaches.currentProgram->getUniform("roundRectInnerRectLTRB"),
|
||||
innerRect.left, innerRect.top,
|
||||
@@ -1751,7 +1752,7 @@ void OpenGLRenderer::setupDrawModelView(ModelViewMode mode, bool offset,
|
||||
|
||||
bool dirty = right - left > 0.0f && bottom - top > 0.0f;
|
||||
const Matrix4& transformMatrix = ignoreTransform ? Matrix4::identity() : *currentTransform();
|
||||
mCaches.currentProgram->set(mSnapshot->getOrthoMatrix(), mModelViewMatrix, transformMatrix, offset);
|
||||
mCaches.currentProgram->set(writableSnapshot()->getOrthoMatrix(), mModelViewMatrix, transformMatrix, offset);
|
||||
if (dirty && mTrackDirtyRegions) {
|
||||
if (!ignoreTransform) {
|
||||
dirtyLayer(left, top, right, bottom, *currentTransform());
|
||||
@@ -1942,7 +1943,7 @@ void OpenGLRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t
|
||||
return;
|
||||
}
|
||||
|
||||
DeferredDisplayList deferredList(*currentClipRect());
|
||||
DeferredDisplayList deferredList(*mState.currentClipRect());
|
||||
DeferStateStruct deferStruct(deferredList, *this, replayFlags);
|
||||
renderNode->defer(deferStruct, 0);
|
||||
|
||||
@@ -2056,7 +2057,7 @@ void OpenGLRenderer::drawBitmapData(const SkBitmap* bitmap, const SkPaint* paint
|
||||
|
||||
void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
|
||||
const float* vertices, const int* colors, const SkPaint* paint) {
|
||||
if (!vertices || currentSnapshot()->isIgnored()) {
|
||||
if (!vertices || mState.currentlyIgnored()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2369,7 +2370,7 @@ void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY,
|
||||
setupDraw();
|
||||
setupDrawNoTexture();
|
||||
if (isAA) setupDrawVertexAlpha((displayFlags & kVertexBuffer_ShadowInterp));
|
||||
setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
|
||||
setupDrawColor(color, ((color >> 24) & 0xFF) * writableSnapshot()->alpha);
|
||||
setupDrawColorFilter(getColorFilter(paint));
|
||||
setupDrawShader(getShader(paint));
|
||||
setupDrawBlending(paint, isAA);
|
||||
@@ -2445,7 +2446,7 @@ void OpenGLRenderer::drawConvexPath(const SkPath& path, const SkPaint* paint) {
|
||||
* memory transfer by removing need for degenerate vertices.
|
||||
*/
|
||||
void OpenGLRenderer::drawLines(const float* points, int count, const SkPaint* paint) {
|
||||
if (currentSnapshot()->isIgnored() || count < 4) return;
|
||||
if (mState.currentlyIgnored() || count < 4) return;
|
||||
|
||||
count &= ~0x3; // round down to nearest four
|
||||
|
||||
@@ -2462,7 +2463,7 @@ void OpenGLRenderer::drawLines(const float* points, int count, const SkPaint* pa
|
||||
}
|
||||
|
||||
void OpenGLRenderer::drawPoints(const float* points, int count, const SkPaint* paint) {
|
||||
if (currentSnapshot()->isIgnored() || count < 2) return;
|
||||
if (mState.currentlyIgnored() || count < 2) return;
|
||||
|
||||
count &= ~0x1; // round down to nearest two
|
||||
|
||||
@@ -2482,9 +2483,9 @@ void OpenGLRenderer::drawPoints(const float* points, int count, const SkPaint* p
|
||||
|
||||
void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
|
||||
// No need to check against the clip, we fill the clip region
|
||||
if (currentSnapshot()->isIgnored()) return;
|
||||
if (mState.currentlyIgnored()) return;
|
||||
|
||||
Rect clip(*currentClipRect());
|
||||
Rect clip(*mState.currentClipRect());
|
||||
clip.snapToPixelBoundaries();
|
||||
|
||||
SkPaint paint;
|
||||
@@ -2511,7 +2512,7 @@ void OpenGLRenderer::drawShape(float left, float top, const PathTexture* texture
|
||||
|
||||
void OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom,
|
||||
float rx, float ry, const SkPaint* p) {
|
||||
if (currentSnapshot()->isIgnored()
|
||||
if (mState.currentlyIgnored()
|
||||
|| quickRejectSetupScissor(left, top, right, bottom, p)
|
||||
|| paintWillNotDraw(*p)) {
|
||||
return;
|
||||
@@ -2530,7 +2531,7 @@ void OpenGLRenderer::drawRoundRect(float left, float top, float right, float bot
|
||||
}
|
||||
|
||||
void OpenGLRenderer::drawCircle(float x, float y, float radius, const SkPaint* p) {
|
||||
if (currentSnapshot()->isIgnored()
|
||||
if (mState.currentlyIgnored()
|
||||
|| quickRejectSetupScissor(x - radius, y - radius, x + radius, y + radius, p)
|
||||
|| paintWillNotDraw(*p)) {
|
||||
return;
|
||||
@@ -2552,7 +2553,7 @@ void OpenGLRenderer::drawCircle(float x, float y, float radius, const SkPaint* p
|
||||
|
||||
void OpenGLRenderer::drawOval(float left, float top, float right, float bottom,
|
||||
const SkPaint* p) {
|
||||
if (currentSnapshot()->isIgnored()
|
||||
if (mState.currentlyIgnored()
|
||||
|| quickRejectSetupScissor(left, top, right, bottom, p)
|
||||
|| paintWillNotDraw(*p)) {
|
||||
return;
|
||||
@@ -2575,7 +2576,7 @@ void OpenGLRenderer::drawOval(float left, float top, float right, float bottom,
|
||||
|
||||
void OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
|
||||
float startAngle, float sweepAngle, bool useCenter, const SkPaint* p) {
|
||||
if (currentSnapshot()->isIgnored()
|
||||
if (mState.currentlyIgnored()
|
||||
|| quickRejectSetupScissor(left, top, right, bottom, p)
|
||||
|| paintWillNotDraw(*p)) {
|
||||
return;
|
||||
@@ -2610,7 +2611,7 @@ void OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
|
||||
|
||||
void OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
|
||||
const SkPaint* p) {
|
||||
if (currentSnapshot()->isIgnored()
|
||||
if (mState.currentlyIgnored()
|
||||
|| quickRejectSetupScissor(left, top, right, bottom, p)
|
||||
|| paintWillNotDraw(*p)) {
|
||||
return;
|
||||
@@ -2669,7 +2670,7 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text,
|
||||
const float sx = x - shadow->left + textShadow.dx;
|
||||
const float sy = y - shadow->top + textShadow.dy;
|
||||
|
||||
const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * mSnapshot->alpha;
|
||||
const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * writableSnapshot()->alpha;
|
||||
if (getShader(paint)) {
|
||||
textShadow.color = SK_ColorWHITE;
|
||||
}
|
||||
@@ -2693,13 +2694,13 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text,
|
||||
}
|
||||
|
||||
bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
|
||||
float alpha = (hasTextShadow(paint) ? 1.0f : paint->getAlpha()) * mSnapshot->alpha;
|
||||
float alpha = (hasTextShadow(paint) ? 1.0f : paint->getAlpha()) * currentSnapshot()->alpha;
|
||||
return alpha == 0.0f && getXfermode(paint->getXfermode()) == SkXfermode::kSrcOver_Mode;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count,
|
||||
const float* positions, const SkPaint* paint) {
|
||||
if (text == NULL || count == 0 || currentSnapshot()->isIgnored() || canSkipText(paint)) {
|
||||
if (text == NULL || count == 0 || mState.currentlyIgnored() || canSkipText(paint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2737,7 +2738,7 @@ void OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count,
|
||||
}
|
||||
fontRenderer.setTextureFiltering(linearFilter);
|
||||
|
||||
const Rect* clip = pureTranslate ? mSnapshot->clipRect : &mSnapshot->getLocalClip();
|
||||
const Rect* clip = pureTranslate ? writableSnapshot()->clipRect : &writableSnapshot()->getLocalClip();
|
||||
Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
|
||||
|
||||
const bool hasActiveLayer = hasLayer();
|
||||
@@ -2777,6 +2778,69 @@ bool OpenGLRenderer::findBestFontTransform(const mat4& transform, SkMatrix* outM
|
||||
return true;
|
||||
}
|
||||
|
||||
int OpenGLRenderer::getSaveCount() const {
|
||||
return mState.getSaveCount();
|
||||
}
|
||||
|
||||
int OpenGLRenderer::save(int flags) {
|
||||
return mState.save(flags);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::restore() {
|
||||
return mState.restore();
|
||||
}
|
||||
|
||||
void OpenGLRenderer::restoreToCount(int saveCount) {
|
||||
return mState.restoreToCount(saveCount);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::translate(float dx, float dy, float dz) {
|
||||
return mState.translate(dx, dy, dz);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::rotate(float degrees) {
|
||||
return mState.rotate(degrees);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::scale(float sx, float sy) {
|
||||
return mState.scale(sx, sy);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::skew(float sx, float sy) {
|
||||
return mState.skew(sx, sy);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setMatrix(const Matrix4& matrix) {
|
||||
mState.setMatrix(matrix);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::concatMatrix(const Matrix4& matrix) {
|
||||
mState.concatMatrix(matrix);
|
||||
}
|
||||
|
||||
bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
|
||||
return mState.clipRect(left, top, right, bottom, op);
|
||||
}
|
||||
|
||||
bool OpenGLRenderer::clipPath(const SkPath* path, SkRegion::Op op) {
|
||||
return mState.clipPath(path, op);
|
||||
}
|
||||
|
||||
bool OpenGLRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) {
|
||||
return mState.clipRegion(region, op);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setClippingOutline(LinearAllocator& allocator, const Outline* outline) {
|
||||
mState.setClippingOutline(allocator, outline);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setClippingRoundRect(LinearAllocator& allocator,
|
||||
const Rect& rect, float radius, bool highPriority) {
|
||||
mState.setClippingRoundRect(allocator, rect, radius, highPriority);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float x, float y,
|
||||
const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds,
|
||||
DrawOpMode drawOpMode) {
|
||||
@@ -2784,7 +2848,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float
|
||||
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 || currentSnapshot()->isIgnored() || canSkipText(paint) ||
|
||||
if (text == NULL || count == 0 || mState.currentlyIgnored() || canSkipText(paint) ||
|
||||
quickRejectSetupScissor(bounds)) {
|
||||
return;
|
||||
}
|
||||
@@ -2834,7 +2898,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float
|
||||
fontRenderer.setTextureFiltering(linearFilter);
|
||||
|
||||
// TODO: Implement better clipping for scaled/rotated text
|
||||
const Rect* clip = !pureTranslate ? NULL : currentClipRect();
|
||||
const Rect* clip = !pureTranslate ? NULL : mState.currentClipRect();
|
||||
Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
|
||||
|
||||
bool status;
|
||||
@@ -2866,7 +2930,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float
|
||||
|
||||
void OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
|
||||
const SkPath* path, float hOffset, float vOffset, const SkPaint* paint) {
|
||||
if (text == NULL || count == 0 || currentSnapshot()->isIgnored() || canSkipText(paint)) {
|
||||
if (text == NULL || count == 0 || mState.currentlyIgnored() || canSkipText(paint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2882,7 +2946,7 @@ void OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
|
||||
getAlphaAndMode(paint, &alpha, &mode);
|
||||
TextSetupFunctor functor(this, 0.0f, 0.0f, false, alpha, mode, paint);
|
||||
|
||||
const Rect* clip = &mSnapshot->getLocalClip();
|
||||
const Rect* clip = &writableSnapshot()->getLocalClip();
|
||||
Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
|
||||
|
||||
const bool hasActiveLayer = hasLayer();
|
||||
@@ -2899,7 +2963,7 @@ void OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
|
||||
}
|
||||
|
||||
void OpenGLRenderer::drawPath(const SkPath* path, const SkPaint* paint) {
|
||||
if (currentSnapshot()->isIgnored()) return;
|
||||
if (mState.currentlyIgnored()) return;
|
||||
|
||||
mCaches.activeTexture(0);
|
||||
|
||||
@@ -2929,7 +2993,7 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
|
||||
}
|
||||
|
||||
bool clipRequired = false;
|
||||
const bool rejected = calculateQuickRejectForScissor(x, y,
|
||||
const bool rejected = mState.calculateQuickRejectForScissor(x, y,
|
||||
x + layer->layer.getWidth(), y + layer->layer.getHeight(), &clipRequired, NULL, false);
|
||||
|
||||
if (rejected) {
|
||||
@@ -3114,7 +3178,7 @@ void OpenGLRenderer::drawTextDecorations(float underlineWidth, float x, float y,
|
||||
}
|
||||
|
||||
void OpenGLRenderer::drawRects(const float* rects, int count, const SkPaint* paint) {
|
||||
if (currentSnapshot()->isIgnored()) {
|
||||
if (mState.currentlyIgnored()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3131,7 +3195,7 @@ static void mapPointFakeZ(Vector3& point, const mat4& transformXY, const mat4& t
|
||||
|
||||
void OpenGLRenderer::drawShadow(float casterAlpha,
|
||||
const VertexBuffer* ambientShadowVertexBuffer, const VertexBuffer* spotShadowVertexBuffer) {
|
||||
if (currentSnapshot()->isIgnored()) return;
|
||||
if (mState.currentlyIgnored()) return;
|
||||
|
||||
// TODO: use quickRejectWithScissor. For now, always force enable scissor.
|
||||
mCaches.enableScissor();
|
||||
@@ -3373,7 +3437,7 @@ void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, f
|
||||
void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
|
||||
ProgramDescription& description, bool swapSrcDst) {
|
||||
|
||||
if (mSnapshot->roundRectClipState != NULL /*&& !mSkipOutlineClip*/) {
|
||||
if (writableSnapshot()->roundRectClipState != NULL /*&& !mSkipOutlineClip*/) {
|
||||
blend = true;
|
||||
mDescription.hasRoundRectClip = true;
|
||||
}
|
||||
|
||||
@@ -38,13 +38,14 @@
|
||||
|
||||
#include <androidfw/ResourceTypes.h>
|
||||
|
||||
#include "CanvasState.h"
|
||||
#include "Debug.h"
|
||||
#include "Extensions.h"
|
||||
#include "Matrix.h"
|
||||
#include "Program.h"
|
||||
#include "Rect.h"
|
||||
#include "Renderer.h"
|
||||
#include "Snapshot.h"
|
||||
#include "StatefulBaseRenderer.h"
|
||||
#include "UvMapper.h"
|
||||
#include "Vertex.h"
|
||||
#include "Caches.h"
|
||||
@@ -116,7 +117,7 @@ enum ModelViewMode {
|
||||
/**
|
||||
* OpenGL Renderer implementation.
|
||||
*/
|
||||
class OpenGLRenderer : public StatefulBaseRenderer {
|
||||
class OpenGLRenderer : public Renderer, public CanvasStateClient {
|
||||
public:
|
||||
OpenGLRenderer(RenderState& renderState);
|
||||
virtual ~OpenGLRenderer();
|
||||
@@ -125,8 +126,10 @@ public:
|
||||
void initLight(const Vector3& lightCenter, float lightRadius,
|
||||
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
|
||||
|
||||
virtual void onViewportInitialized();
|
||||
virtual void prepareDirty(float left, float top, float right, float bottom, bool opaque);
|
||||
virtual void prepare(bool opaque) {
|
||||
prepareDirty(0.0f, 0.0f, mState.getWidth(), mState.getHeight(), opaque);
|
||||
}
|
||||
virtual bool finish();
|
||||
|
||||
virtual void callDrawGLFunction(Functor* functor, Rect& dirty);
|
||||
@@ -218,20 +221,16 @@ public:
|
||||
}
|
||||
|
||||
// simple rect clip
|
||||
bool isCurrentClipSimple() {
|
||||
return mSnapshot->clipRegion->isEmpty();
|
||||
}
|
||||
bool isCurrentClipSimple() { return mState.isCurrentClipSimple(); }
|
||||
|
||||
int getViewportWidth() { return currentSnapshot()->getViewportWidth(); }
|
||||
int getViewportHeight() { return currentSnapshot()->getViewportHeight(); }
|
||||
int getViewportWidth() { return mState.getViewportWidth(); }
|
||||
int getViewportHeight() { return mState.getViewportHeight(); }
|
||||
|
||||
/**
|
||||
* Scales the alpha on the current snapshot. This alpha value will be modulated
|
||||
* with other alpha values when drawing primitives.
|
||||
*/
|
||||
void scaleAlpha(float alpha) {
|
||||
mSnapshot->alpha *= alpha;
|
||||
}
|
||||
void scaleAlpha(float alpha) { mState.scaleAlpha(alpha); }
|
||||
|
||||
/**
|
||||
* Inserts a named event marker in the stream of GL commands.
|
||||
@@ -328,11 +327,63 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
const Vector3& getLightCenter() const { return currentSnapshot()->getRelativeLightCenter(); }
|
||||
const Vector3& getLightCenter() const { return mState.currentLightCenter(); }
|
||||
float getLightRadius() const { return mLightRadius; }
|
||||
uint8_t getAmbientShadowAlpha() const { return mAmbientShadowAlpha; }
|
||||
uint8_t getSpotShadowAlpha() const { return mSpotShadowAlpha; }
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
/// State manipulation
|
||||
|
||||
virtual void setViewport(int width, int height) { mState.setViewport(width, height); }
|
||||
|
||||
virtual int getSaveCount() const;
|
||||
virtual int save(int flags);
|
||||
virtual void restore();
|
||||
virtual void restoreToCount(int saveCount);
|
||||
|
||||
virtual void getMatrix(SkMatrix* outMatrix) const { mState.getMatrix(outMatrix); }
|
||||
virtual void setMatrix(const SkMatrix& matrix) { mState.setMatrix(matrix); }
|
||||
virtual void concatMatrix(const SkMatrix& matrix) { mState.concatMatrix(matrix); }
|
||||
|
||||
virtual void translate(float dx, float dy, float dz = 0.0f);
|
||||
virtual void rotate(float degrees);
|
||||
virtual void scale(float sx, float sy);
|
||||
virtual void skew(float sx, float sy);
|
||||
|
||||
void setMatrix(const Matrix4& matrix); // internal only convenience method
|
||||
void concatMatrix(const Matrix4& matrix); // internal only convenience method
|
||||
|
||||
virtual const Rect& getLocalClipBounds() const { return mState.getLocalClipBounds(); }
|
||||
const Rect& getRenderTargetClipBounds() const { return mState.getRenderTargetClipBounds(); }
|
||||
virtual bool quickRejectConservative(float left, float top, float right, float bottom) const {
|
||||
return mState.quickRejectConservative(left, top, right, bottom);
|
||||
}
|
||||
|
||||
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
|
||||
virtual bool clipPath(const SkPath* path, SkRegion::Op op);
|
||||
virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
|
||||
|
||||
/**
|
||||
* Does not support different clipping Ops (that is, every call to setClippingOutline is
|
||||
* effectively using SkRegion::kReplaceOp)
|
||||
*
|
||||
* The clipping outline is independent from the regular clip.
|
||||
*/
|
||||
void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
|
||||
void setClippingRoundRect(LinearAllocator& allocator,
|
||||
const Rect& rect, float radius, bool highPriority = true);
|
||||
|
||||
inline bool hasRectToRectTransform() const { return mState.hasRectToRectTransform(); }
|
||||
inline const mat4* currentTransform() const { return mState.currentTransform(); }
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
/// CanvasStateClient interface
|
||||
|
||||
virtual void onViewportInitialized();
|
||||
virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored);
|
||||
virtual GLuint onGetTargetFbo() const { return 0; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Perform the setup specific to a frame. This method does not
|
||||
@@ -396,22 +447,16 @@ protected:
|
||||
* Returns the region of the current layer.
|
||||
*/
|
||||
virtual Region* getRegion() const {
|
||||
return mSnapshot->region;
|
||||
return mState.currentRegion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether rendering is currently targeted at a layer.
|
||||
*/
|
||||
virtual bool hasLayer() const {
|
||||
return (mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region;
|
||||
return (mState.currentFlags() & Snapshot::kFlagFboTarget) && mState.currentRegion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the FBO this renderer is rendering into.
|
||||
*/
|
||||
virtual GLuint getTargetFbo() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the specified layer as a textured quad.
|
||||
@@ -464,6 +509,8 @@ protected:
|
||||
|
||||
inline RenderState& renderState() { return mRenderState; }
|
||||
|
||||
CanvasState mState;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Discards the content of the framebuffer if supported by the driver.
|
||||
@@ -499,8 +546,6 @@ private:
|
||||
*/
|
||||
void endTiling();
|
||||
|
||||
void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored);
|
||||
|
||||
/**
|
||||
* Sets the clipping rectangle using glScissor. The clip is defined by
|
||||
* the current snapshot's clipRect member.
|
||||
@@ -916,9 +961,7 @@ private:
|
||||
/**
|
||||
* Should be invoked every time the glScissor is modified.
|
||||
*/
|
||||
inline void dirtyClip() {
|
||||
mDirtyClip = true;
|
||||
}
|
||||
inline void dirtyClip() { mState.setDirtyClip(true); }
|
||||
|
||||
inline const UvMapper& getMapper(const Texture* texture) {
|
||||
return texture && texture->uvMapper ? *texture->uvMapper : mUvMapper;
|
||||
@@ -932,6 +975,8 @@ private:
|
||||
Texture* getTexture(const SkBitmap* bitmap);
|
||||
|
||||
bool reportAndClearDirty() { bool ret = mDirty; mDirty = false; return ret; }
|
||||
inline Snapshot* writableSnapshot() { return mState.writableSnapshot(); }
|
||||
inline const Snapshot* currentSnapshot() const { return mState.currentSnapshot(); }
|
||||
|
||||
/**
|
||||
* Model-view matrix used to position/size objects
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_HWUI_STATEFUL_BASE_RENDERER_H
|
||||
#define ANDROID_HWUI_STATEFUL_BASE_RENDERER_H
|
||||
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
#include "Renderer.h"
|
||||
#include "Snapshot.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
/**
|
||||
* Abstract Renderer subclass, which implements Canvas state methods.
|
||||
*
|
||||
* 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:
|
||||
StatefulBaseRenderer();
|
||||
|
||||
virtual void prepare(bool opaque) {
|
||||
prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the first snapshot, computing the projection matrix, and stores the dimensions of
|
||||
* the render target.
|
||||
*/
|
||||
virtual void setViewport(int width, int height);
|
||||
void initializeSaveStack(float clipLeft, float clipTop, float clipRight, float clipBottom,
|
||||
const Vector3& lightCenter);
|
||||
|
||||
// getters
|
||||
bool hasRectToRectTransform() const {
|
||||
return CC_LIKELY(currentTransform()->rectToRect());
|
||||
}
|
||||
|
||||
// Save (layer)
|
||||
virtual int getSaveCount() const { return mSaveCount; }
|
||||
virtual int save(int flags);
|
||||
virtual void restore();
|
||||
virtual void restoreToCount(int saveCount);
|
||||
//virtual int saveLayer(float left, float top, float right, float bottom,
|
||||
// int alpha, SkXfermode::Mode mode, int flags);
|
||||
|
||||
// Matrix
|
||||
virtual void getMatrix(SkMatrix* outMatrix) const;
|
||||
virtual void translate(float dx, float dy, float dz = 0.0f);
|
||||
virtual void rotate(float degrees);
|
||||
virtual void scale(float sx, float sy);
|
||||
virtual void skew(float sx, float sy);
|
||||
|
||||
virtual void setMatrix(const SkMatrix& matrix);
|
||||
void setMatrix(const Matrix4& matrix); // internal only convenience method
|
||||
virtual void concatMatrix(const SkMatrix& matrix);
|
||||
void concatMatrix(const Matrix4& matrix); // internal only convenience method
|
||||
|
||||
// Clip
|
||||
virtual const Rect& getLocalClipBounds() const { return mSnapshot->getLocalClip(); }
|
||||
|
||||
virtual bool quickRejectConservative(float left, float top, float right, float bottom) const;
|
||||
|
||||
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
|
||||
virtual bool clipPath(const SkPath* path, SkRegion::Op op);
|
||||
virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
|
||||
|
||||
/**
|
||||
* Does not support different clipping Ops (that is, every call to setClippingOutline is
|
||||
* effectively using SkRegion::kReplaceOp)
|
||||
*
|
||||
* The clipping outline is independent from the regular clip.
|
||||
*/
|
||||
void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
|
||||
void setClippingRoundRect(LinearAllocator& allocator,
|
||||
const Rect& rect, float radius, bool highPriority = true);
|
||||
|
||||
inline const mat4* currentTransform() const {
|
||||
return mSnapshot->transform;
|
||||
}
|
||||
|
||||
protected:
|
||||
const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); }
|
||||
|
||||
int getWidth() { return mWidth; }
|
||||
int getHeight() { return mHeight; }
|
||||
|
||||
// Save
|
||||
int saveSnapshot(int flags);
|
||||
void restoreSnapshot();
|
||||
|
||||
// allows subclasses to control what value is stored in snapshot's fbo field in
|
||||
// initializeSaveStack
|
||||
virtual GLuint getTargetFbo() const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Clip
|
||||
bool calculateQuickRejectForScissor(float left, float top, float right, float bottom,
|
||||
bool* clipRequired, bool* roundRectClipRequired, bool snapOut) const;
|
||||
|
||||
/**
|
||||
* Called just after a restore has occurred. The 'removed' snapshot popped from the stack,
|
||||
* 'restored' snapshot has become the top/current.
|
||||
*
|
||||
* Subclasses can override this method to handle layer restoration
|
||||
*/
|
||||
virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {};
|
||||
|
||||
virtual void onViewportInitialized() {};
|
||||
|
||||
inline const Rect* currentClipRect() const {
|
||||
return mSnapshot->clipRect;
|
||||
}
|
||||
|
||||
inline const Snapshot* currentSnapshot() const {
|
||||
return mSnapshot != NULL ? mSnapshot.get() : mFirstSnapshot.get();
|
||||
}
|
||||
|
||||
inline const Snapshot* firstSnapshot() const {
|
||||
return mFirstSnapshot.get();
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// Base state
|
||||
sp<Snapshot> mFirstSnapshot;
|
||||
|
||||
protected:
|
||||
// Current state
|
||||
// TODO: should become private, once hooks needed by OpenGLRenderer are added
|
||||
sp<Snapshot> mSnapshot;
|
||||
}; // class StatefulBaseRenderer
|
||||
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_HWUI_STATEFUL_BASE_RENDERER_H
|
||||
Reference in New Issue
Block a user