summaryrefslogtreecommitdiffstats
path: root/libs/hwui
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui')
-rw-r--r--libs/hwui/DeferredDisplayList.cpp30
-rw-r--r--libs/hwui/DeferredDisplayList.h4
-rw-r--r--libs/hwui/DisplayList.cpp9
-rw-r--r--libs/hwui/DisplayListOp.h51
-rw-r--r--libs/hwui/DisplayListRenderer.cpp4
-rw-r--r--libs/hwui/DisplayListRenderer.h6
-rw-r--r--[-rwxr-xr-x]libs/hwui/Dither.cpp0
-rw-r--r--[-rwxr-xr-x]libs/hwui/Dither.h0
-rw-r--r--libs/hwui/Layer.cpp28
-rw-r--r--libs/hwui/Layer.h1
-rw-r--r--libs/hwui/LayerRenderer.cpp25
-rw-r--r--libs/hwui/OpenGLRenderer.cpp80
-rw-r--r--libs/hwui/OpenGLRenderer.h22
-rw-r--r--libs/hwui/PathTessellator.cpp1
14 files changed, 177 insertions, 84 deletions
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 020c1e9..fe51bf9 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -34,6 +34,9 @@
namespace android {
namespace uirenderer {
+// Depth of the save stack at the beginning of batch playback at flush time
+#define FLUSH_SAVE_STACK_DEPTH 2
+
/////////////////////////////////////////////////////////////////////////////////
// Operation Batches
/////////////////////////////////////////////////////////////////////////////////
@@ -75,7 +78,7 @@ public:
for (unsigned int i = 0; i < mOps.size(); i++) {
DrawOp* op = mOps[i];
- renderer.restoreDisplayState(op->state, kStateDeferFlag_Draw);
+ renderer.restoreDisplayState(op->state);
#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
renderer.eventMark(op->name());
@@ -106,7 +109,7 @@ public:
virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty) {
DEFER_LOGD("replaying state op batch %p", this);
- renderer.restoreDisplayState(mOp->state, 0);
+ renderer.restoreDisplayState(mOp->state);
// use invalid save count because it won't be used at flush time - RestoreToCountOp is the
// only one to use it, and we don't use that class at flush time, instead calling
@@ -117,12 +120,12 @@ public:
}
private:
- StateOp* mOp;
+ const StateOp* mOp;
};
class RestoreToCountBatch : public DrawOpBatch {
public:
- RestoreToCountBatch(int restoreCount) : mRestoreCount(restoreCount) {}
+ RestoreToCountBatch(StateOp* op, int restoreCount) : mOp(op), mRestoreCount(restoreCount) {}
bool intersects(Rect& rect) {
// if something checks for intersection, it's trying to go backwards across a state op,
@@ -133,11 +136,15 @@ public:
virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty) {
DEFER_LOGD("batch %p restoring to count %d", this, mRestoreCount);
+
+ renderer.restoreDisplayState(mOp->state);
renderer.restoreToCount(mRestoreCount);
return DrawGlInfo::kStatusDone;
}
private:
+ // we use the state storage for the RestoreToCountOp, but don't replay the op itself
+ const StateOp* mOp;
/*
* The count used here represents the flush() time saveCount. This is as opposed to the
* DisplayList record time, or defer() time values (which are RestoreToCountOp's mCount, and
@@ -251,7 +258,8 @@ void DeferredDisplayList::addSave(OpenGLRenderer& renderer, SaveOp* op, int newS
* Either will act as a barrier to draw operation reordering, as we want to play back layer
* save/restore and complex canvas modifications (including save/restore) in order.
*/
-void DeferredDisplayList::addRestoreToCount(OpenGLRenderer& renderer, int newSaveCount) {
+void DeferredDisplayList::addRestoreToCount(OpenGLRenderer& renderer, StateOp* op,
+ int newSaveCount) {
DEFER_LOGD("%p addRestoreToCount %d", this, newSaveCount);
if (recordingComplexClip() && newSaveCount <= mComplexClipStackStart) {
@@ -265,7 +273,7 @@ void DeferredDisplayList::addRestoreToCount(OpenGLRenderer& renderer, int newSav
while (!mSaveStack.isEmpty() && mSaveStack.top() >= newSaveCount) mSaveStack.pop();
- storeRestoreToCountBarrier(mSaveStack.size() + 1);
+ storeRestoreToCountBarrier(renderer, op, mSaveStack.size() + FLUSH_SAVE_STACK_DEPTH);
}
void DeferredDisplayList::addDrawOp(OpenGLRenderer& renderer, DrawOp* op) {
@@ -338,11 +346,15 @@ void DeferredDisplayList::storeStateOpBarrier(OpenGLRenderer& renderer, StateOp*
resetBatchingState();
}
-void DeferredDisplayList::storeRestoreToCountBarrier(int newSaveCount) {
+void DeferredDisplayList::storeRestoreToCountBarrier(OpenGLRenderer& renderer, StateOp* op,
+ int newSaveCount) {
DEFER_LOGD("%p adding restore to count %d barrier, pos %d",
this, newSaveCount, mBatches.size());
- mBatches.add(new RestoreToCountBatch(newSaveCount));
+ // store displayState for the restore operation, as it may be associated with a saveLayer that
+ // doesn't have kClip_SaveFlag set
+ renderer.storeDisplayState(op->state, getStateOpDeferFlags());
+ mBatches.add(new RestoreToCountBatch(op, newSaveCount));
resetBatchingState();
}
@@ -377,6 +389,8 @@ status_t DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty) {
DrawModifiers restoreDrawModifiers = renderer.getDrawModifiers();
renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ // NOTE: depth of the save stack at this point, before playback, should be reflected in
+ // FLUSH_SAVE_STACK_DEPTH, so that save/restores match up correctly
status |= replayBatchList(mBatches, renderer, dirty);
renderer.restoreToCount(1);
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
index 2afc8c1..3e450da 100644
--- a/libs/hwui/DeferredDisplayList.h
+++ b/libs/hwui/DeferredDisplayList.h
@@ -65,7 +65,7 @@ public:
void addClip(OpenGLRenderer& renderer, ClipOp* op);
void addSaveLayer(OpenGLRenderer& renderer, SaveLayerOp* op, int newSaveCount);
void addSave(OpenGLRenderer& renderer, SaveOp* op, int newSaveCount);
- void addRestoreToCount(OpenGLRenderer& renderer, int newSaveCount);
+ void addRestoreToCount(OpenGLRenderer& renderer, StateOp* op, int newSaveCount);
/**
* Add a draw op into the DeferredDisplayList, reordering as needed (for performance) if
@@ -81,7 +81,7 @@ private:
void resetBatchingState();
void storeStateOpBarrier(OpenGLRenderer& renderer, StateOp* op);
- void storeRestoreToCountBarrier(int newSaveCount);
+ void storeRestoreToCountBarrier(OpenGLRenderer& renderer, StateOp* op, int newSaveCount);
bool recordingComplexClip() const { return mComplexClipStackStart >= 0; }
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index d985ad0..36c95f9 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -352,7 +352,9 @@ void DisplayList::outputViewProperties(const int level) {
}
}
if (mAlpha < 1) {
- if (mCaching || !mHasOverlappingRendering) {
+ if (mCaching) {
+ ALOGD("%*sSetOverrideLayerAlpha %.2f", level * 2, "", mAlpha);
+ } else if (!mHasOverlappingRendering) {
ALOGD("%*sScaleAlpha %.2f", level * 2, "", mAlpha);
} else {
int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
@@ -400,7 +402,9 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, T& handler,
}
}
if (mAlpha < 1) {
- if (mCaching || !mHasOverlappingRendering) {
+ if (mCaching) {
+ renderer.setOverrideLayerAlpha(mAlpha);
+ } else if (!mHasOverlappingRendering) {
renderer.scaleAlpha(mAlpha);
} else {
// TODO: should be able to store the size of a DL at record time and not
@@ -513,6 +517,7 @@ void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level)
DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo);
handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT);
renderer.restoreToCount(restoreTo);
+ renderer.setOverrideLayerAlpha(1.0f);
}
}; // namespace uirenderer
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 4f2db69..a5dee9f 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -117,7 +117,7 @@ public:
applyState(replayStruct.mRenderer, saveCount);
}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) = 0;
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
};
class DrawOp : public DisplayListOp {
@@ -165,7 +165,11 @@ public:
return DeferredDisplayList::kOpBatch_None;
}
- float strokeWidthOutset() { return mPaint->getStrokeWidth() * 0.5f; }
+ float strokeWidthOutset() {
+ float width = mPaint->getStrokeWidth();
+ if (width == 0) return 0.5f; // account for hairline
+ return width * 0.5f;
+ }
protected:
SkPaint* getPaint(OpenGLRenderer& renderer) {
@@ -223,7 +227,7 @@ public:
deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.save(mFlags);
}
@@ -251,11 +255,12 @@ public:
: mCount(count) {}
virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
- deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer, saveCount + mCount);
+ deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
+ this, saveCount + mCount);
deferStruct.mRenderer.restoreToCount(saveCount + mCount);
}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.restoreToCount(saveCount + mCount);
}
@@ -293,7 +298,7 @@ public:
mAlpha, mMode, mFlags);
}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mAlpha, mMode, mFlags);
}
@@ -330,7 +335,7 @@ public:
TranslateOp(float dx, float dy)
: mDx(dx), mDy(dy) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.translate(mDx, mDy);
}
@@ -350,7 +355,7 @@ public:
RotateOp(float degrees)
: mDegrees(degrees) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.rotate(mDegrees);
}
@@ -369,7 +374,7 @@ public:
ScaleOp(float sx, float sy)
: mSx(sx), mSy(sy) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.scale(mSx, mSy);
}
@@ -389,7 +394,7 @@ public:
SkewOp(float sx, float sy)
: mSx(sx), mSy(sy) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.skew(mSx, mSy);
}
@@ -409,7 +414,7 @@ public:
SetMatrixOp(SkMatrix* matrix)
: mMatrix(matrix) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.setMatrix(mMatrix);
}
@@ -428,7 +433,7 @@ public:
ConcatMatrixOp(SkMatrix* matrix)
: mMatrix(matrix) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.concatMatrix(mMatrix);
}
@@ -471,7 +476,7 @@ public:
ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
: ClipOp(op), mArea(left, top, right, bottom) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
}
@@ -500,7 +505,7 @@ public:
ClipPathOp(SkPath* path, SkRegion::Op op)
: ClipOp(op), mPath(path) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.clipPath(mPath, mOp);
}
@@ -521,7 +526,7 @@ public:
ClipRegionOp(SkRegion* region, SkRegion::Op op)
: ClipOp(op), mRegion(region) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.clipRegion(mRegion, mOp);
}
@@ -540,7 +545,7 @@ private:
class ResetShaderOp : public StateOp {
public:
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.resetShader();
}
@@ -555,7 +560,7 @@ class SetupShaderOp : public StateOp {
public:
SetupShaderOp(SkiaShader* shader)
: mShader(shader) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.setupShader(mShader);
}
@@ -571,7 +576,7 @@ private:
class ResetColorFilterOp : public StateOp {
public:
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.resetColorFilter();
}
@@ -587,7 +592,7 @@ public:
SetupColorFilterOp(SkiaColorFilter* colorFilter)
: mColorFilter(colorFilter) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.setupColorFilter(mColorFilter);
}
@@ -603,7 +608,7 @@ private:
class ResetShadowOp : public StateOp {
public:
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.resetShadow();
}
@@ -619,7 +624,7 @@ public:
SetupShadowOp(float radius, float dx, float dy, int color)
: mRadius(radius), mDx(dx), mDy(dy), mColor(color) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.setupShadow(mRadius, mDx, mDy, mColor);
}
@@ -638,7 +643,7 @@ private:
class ResetPaintFilterOp : public StateOp {
public:
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.resetPaintFilter();
}
@@ -654,7 +659,7 @@ public:
SetupPaintFilterOp(int clearBits, int setBits)
: mClearBits(clearBits), mSetBits(setBits) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.setupPaintFilter(mClearBits, mSetBits);
}
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 07daa3b..0b8f7e6 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -248,9 +248,7 @@ status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList,
}
status_t DisplayListRenderer::drawLayer(Layer* layer, float x, float y) {
- mLayers.add(layer);
- mCaches.resourceCache.incrementRefcount(layer);
-
+ layer = refLayer(layer);
addDrawOp(new (alloc()) DrawLayerOp(layer, x, y));
return DrawGlInfo::kStatusDone;
}
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 50e552f..19f7eb6 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -271,6 +271,12 @@ private:
return copy;
}
+ inline Layer* refLayer(Layer* layer) {
+ mLayers.add(layer);
+ mCaches.resourceCache.incrementRefcount(layer);
+ return layer;
+ }
+
inline SkBitmap* refBitmap(SkBitmap* bitmap) {
// Note that this assumes the bitmap is immutable. There are cases this won't handle
// correctly, such as creating the bitmap from scratch, drawing with it, changing its
diff --git a/libs/hwui/Dither.cpp b/libs/hwui/Dither.cpp
index e80b325..e80b325 100755..100644
--- a/libs/hwui/Dither.cpp
+++ b/libs/hwui/Dither.cpp
diff --git a/libs/hwui/Dither.h b/libs/hwui/Dither.h
index 34cf9bf..34cf9bf 100755..100644
--- a/libs/hwui/Dither.h
+++ b/libs/hwui/Dither.h
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 2998535..63bb73f 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -75,6 +75,13 @@ bool Layer::resize(const uint32_t width, const uint32_t height) {
return true;
}
+ const uint32_t maxTextureSize = Caches::getInstance().maxTextureSize;
+ if (desiredWidth > maxTextureSize || desiredHeight > maxTextureSize) {
+ ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)",
+ desiredWidth, desiredHeight, maxTextureSize, maxTextureSize);
+ return false;
+ }
+
uint32_t oldWidth = getWidth();
uint32_t oldHeight = getHeight();
@@ -158,10 +165,13 @@ void Layer::defer() {
dirtyRect.right, dirtyRect.bottom, !isBlend());
displayList->defer(deferredState, 0);
+
+ deferredUpdateScheduled = false;
+ displayList = NULL;
}
void Layer::flush() {
- if (deferredList && !deferredList->isEmpty()) {
+ if (deferredList) {
renderer->setViewport(layer.getWidth(), layer.getHeight());
renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom,
!isBlend());
@@ -176,5 +186,21 @@ void Layer::flush() {
}
}
+void Layer::render() {
+ renderer->setViewport(layer.getWidth(), layer.getHeight());
+ renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom,
+ !isBlend());
+
+ renderer->drawDisplayList(displayList, dirtyRect, DisplayList::kReplayFlag_ClipChildren);
+
+ renderer->finish();
+ renderer = NULL;
+
+ dirtyRect.setEmpty();
+
+ deferredUpdateScheduled = false;
+ displayList = NULL;
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 0e00191..27e0cf1 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -275,6 +275,7 @@ struct Layer {
void defer();
void flush();
+ void render();
/**
* Bounds of the layer.
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index bb02286..8451048 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -222,6 +222,21 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque
return NULL;
}
+ // We first obtain a layer before comparing against the max texture size
+ // because layers are not allocated at the exact desired size. They are
+ // always created slighly larger to improve recycling
+ const uint32_t maxTextureSize = caches.maxTextureSize;
+ if (layer->getWidth() > maxTextureSize || layer->getHeight() > maxTextureSize) {
+ ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)",
+ width, height, maxTextureSize, maxTextureSize);
+
+ // Creating a new layer always increment its refcount by 1, this allows
+ // us to destroy the layer object if one was created for us
+ Caches::getInstance().resourceCache.decrementRefcount(layer);
+
+ return NULL;
+ }
+
layer->setFbo(fbo);
layer->layer.set(0.0f, 0.0f, width, height);
layer->texCoords.set(0.0f, height / float(layer->getHeight()),
@@ -243,14 +258,11 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque
layer->setEmpty(false);
layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
+ // This should only happen if we run out of memory
if (glGetError() != GL_NO_ERROR) {
- ALOGD("Could not allocate texture for layer (fbo=%d %dx%d)",
- fbo, width, height);
-
+ ALOGE("Could not allocate texture for layer (fbo=%d %dx%d)", fbo, width, height);
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-
- Caches::getInstance().resourceCache.decrementRefcount(layer);
-
+ caches.resourceCache.decrementRefcount(layer);
return NULL;
}
}
@@ -272,7 +284,6 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) {
layer->texCoords.set(0.0f, height / float(layer->getHeight()),
width / float(layer->getWidth()), 0.0f);
} else {
- Caches::getInstance().resourceCache.decrementRefcount(layer);
return false;
}
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 2903bcd..1138998 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -114,6 +114,7 @@ OpenGLRenderer::OpenGLRenderer():
mCaches(Caches::getInstance()), mExtensions(Extensions::getInstance()) {
mDrawModifiers.mShader = NULL;
mDrawModifiers.mColorFilter = NULL;
+ mDrawModifiers.mOverrideLayerAlpha = 1.0f;
mDrawModifiers.mHasShadow = false;
mDrawModifiers.mHasDrawFilter = false;
@@ -540,13 +541,7 @@ bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
}
if (CC_UNLIKELY(inFrame || mCaches.drawDeferDisabled)) {
- OpenGLRenderer* renderer = layer->renderer;
- renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight());
- renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom,
- !layer->isBlend());
- renderer->drawDisplayList(layer->displayList, dirty,
- DisplayList::kReplayFlag_ClipChildren);
- renderer->finish();
+ layer->render();
} else {
layer->defer();
}
@@ -556,13 +551,6 @@ bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
startTiling(mSnapshot);
}
- if (CC_UNLIKELY(inFrame || mCaches.drawDeferDisabled)) {
- dirty.setEmpty();
- layer->renderer = NULL;
- }
-
- layer->deferredUpdateScheduled = false;
- layer->displayList = NULL;
layer->debugDrawUpdate = mCaches.debugLayersUpdates;
return true;
@@ -609,11 +597,12 @@ void OpenGLRenderer::flushLayers() {
// Note: it is very important to update the layers in reverse order
for (int i = count - 1; i >= 0; i--) {
sprintf(layerName, "Layer #%d", i);
- startMark(layerName); {
- Layer* layer = mLayerUpdates.itemAt(i);
- layer->flush();
- mCaches.resourceCache.decrementRefcount(layer);
- }
+ startMark(layerName);
+
+ Layer* layer = mLayerUpdates.itemAt(i);
+ layer->flush();
+ mCaches.resourceCache.decrementRefcount(layer);
+
endMark();
}
@@ -626,6 +615,15 @@ void OpenGLRenderer::flushLayers() {
void OpenGLRenderer::pushLayerUpdate(Layer* layer) {
if (layer) {
+ // Make sure we don't introduce duplicates.
+ // SortedVector would do this automatically but we need to respect
+ // the insertion order. The linear search is not an issue since
+ // this list is usually very short (typically one item, at most a few)
+ for (int i = mLayerUpdates.size() - 1; i >= 0; i--) {
+ if (mLayerUpdates.itemAt(i) == layer) {
+ return;
+ }
+ }
mLayerUpdates.push_back(layer);
mCaches.resourceCache.incrementRefcount(layer);
}
@@ -696,7 +694,10 @@ bool OpenGLRenderer::restoreSnapshot() {
}
if (restoreLayer) {
+ endMark(); // Savelayer
+ startMark("ComposeLayer");
composeLayer(current, previous);
+ endMark();
}
return restoreClip;
@@ -874,6 +875,7 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto
mSnapshot->flags |= Snapshot::kFlagIsLayer;
mSnapshot->layer = layer;
+ startMark("SaveLayer");
if (fboLayer) {
return createFboLayer(layer, bounds, clip, previousFbo);
} else {
@@ -1073,7 +1075,7 @@ void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap)
layer->setFilter(GL_LINEAR, true);
}
- float alpha = layer->getAlpha() / 255.0f * mSnapshot->alpha;
+ float alpha = getLayerAlpha(layer);
bool blend = layer->isBlend() || alpha < 1.0f;
drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(),
layer->getTexture(), alpha, layer->getMode(), blend,
@@ -1111,7 +1113,7 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
rects = safeRegion.getArray(&count);
}
- const float alpha = layer->getAlpha() / 255.0f * mSnapshot->alpha;
+ const float alpha = getLayerAlpha(layer);
const float texX = 1.0f / float(layer->getWidth());
const float texY = 1.0f / float(layer->getHeight());
const float height = rect.getHeight();
@@ -1326,8 +1328,6 @@ bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDef
} else {
state.mBounds.set(currentClip);
}
- state.mDrawModifiers = mDrawModifiers;
- state.mAlpha = mSnapshot->alpha;
}
if (stateDeferFlags & kStateDeferFlag_Clip) {
@@ -1336,18 +1336,18 @@ bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDef
state.mClip.setEmpty();
}
- // transform always deferred
+ // 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.mDrawModifiers = mDrawModifiers;
+ state.mAlpha = mSnapshot->alpha;
return false;
}
-void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, int stateDeferFlags) {
+void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state) {
currentTransform().load(state.mMatrix);
-
- if (stateDeferFlags & kStateDeferFlag_Draw) {
- mDrawModifiers = state.mDrawModifiers;
- mSnapshot->alpha = state.mAlpha;
- }
+ mDrawModifiers = state.mDrawModifiers;
+ mSnapshot->alpha = state.mAlpha;
if (!state.mClip.isEmpty()) {
mSnapshot->setClip(state.mClip.left, state.mClip.top, state.mClip.right, state.mClip.bottom);
@@ -2238,7 +2238,7 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const
float left, float top, float right, float bottom, SkPaint* paint) {
int alpha;
SkXfermode::Mode mode;
- getAlphaAndModeDirect(paint, &alpha, &mode);
+ getAlphaAndMode(paint, &alpha, &mode);
return drawPatch(bitmap, xDivs, yDivs, colors, width, height, numColors,
left, top, right, bottom, alpha, mode);
@@ -2991,7 +2991,7 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
if (layer->region.isRect()) {
composeLayerRect(layer, layer->regionRect);
} else if (layer->mesh) {
- const float a = layer->getAlpha() / 255.0f * mSnapshot->alpha;
+ const float a = getLayerAlpha(layer);
setupDraw();
setupDrawWithTexture();
setupDrawColor(a, a, a, a);
@@ -3447,10 +3447,24 @@ void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, flo
TextureVertex::setUV(v++, u2, v2);
}
-void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
+void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) const {
getAlphaAndModeDirect(paint, alpha, mode);
+ if (mDrawModifiers.mOverrideLayerAlpha < 1.0f) {
+ // if drawing a layer, ignore the paint's alpha
+ *alpha = mDrawModifiers.mOverrideLayerAlpha;
+ }
*alpha *= mSnapshot->alpha;
}
+float OpenGLRenderer::getLayerAlpha(Layer* layer) const {
+ float alpha;
+ if (mDrawModifiers.mOverrideLayerAlpha < 1.0f) {
+ alpha = mDrawModifiers.mOverrideLayerAlpha;
+ } else {
+ alpha = layer->getAlpha() / 255.0f;
+ }
+ return alpha * mSnapshot->alpha;
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index b17bc3f..dd7a5a2 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -51,6 +51,7 @@ namespace uirenderer {
struct DrawModifiers {
SkiaShader* mShader;
SkiaColorFilter* mColorFilter;
+ float mOverrideLayerAlpha;
// Drop shadow
bool mHasShadow;
@@ -275,15 +276,17 @@ public:
virtual void resetPaintFilter();
virtual void setupPaintFilter(int clearBits, int setBits);
+ // If this value is set to < 1.0, it overrides alpha set on layer (see drawBitmap, drawLayer)
+ void setOverrideLayerAlpha(float alpha) { mDrawModifiers.mOverrideLayerAlpha = alpha; }
+
SkPaint* filterPaint(SkPaint* paint);
bool storeDisplayState(DeferredDisplayState& state, int stateDeferFlags);
- void restoreDisplayState(const DeferredDisplayState& state, int stateDeferFlags);
+ void restoreDisplayState(const DeferredDisplayState& state);
const DrawModifiers& getDrawModifiers() { return mDrawModifiers; }
void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; }
- // TODO: what does this mean? no perspective? no rotate?
ANDROID_API bool isCurrentTransformSimple() {
return mSnapshot->transform->isSimple();
}
@@ -325,7 +328,8 @@ public:
/**
* Gets the alpha and xfermode out of a paint object. If the paint is null
* alpha will be 255 and the xfermode will be SRC_OVER. This method does
- * not multiply the paint's alpha by the current snapshot's alpha.
+ * not multiply the paint's alpha by the current snapshot's alpha, and does
+ * not replace the alpha with the overrideLayerAlpha
*
* @param paint The paint to extract values from
* @param alpha Where to store the resulting alpha
@@ -450,13 +454,21 @@ protected:
/**
* Gets the alpha and xfermode out of a paint object. If the paint is null
- * alpha will be 255 and the xfermode will be SRC_OVER.
+ * alpha will be 255 and the xfermode will be SRC_OVER. Accounts for both
+ * snapshot alpha, and overrideLayerAlpha
*
* @param paint The paint to extract values from
* @param alpha Where to store the resulting alpha
* @param mode Where to store the resulting xfermode
*/
- inline void getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode);
+ inline void getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) const;
+
+ /**
+ * Gets the alpha from a layer, accounting for snapshot alpha and overrideLayerAlpha
+ *
+ * @param layer The layer from which the alpha is extracted
+ */
+ inline float getLayerAlpha(Layer* layer) const;
/**
* Safely retrieves the mode from the specified xfermode. If the specified
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index 395bbf6..0879b1b 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -61,6 +61,7 @@ void PathTessellator::expandBoundsForStroke(SkRect& bounds, const SkPaint* paint
bool forceExpand) {
if (forceExpand || paint->getStyle() != SkPaint::kFill_Style) {
float outset = paint->getStrokeWidth() * 0.5f;
+ if (outset == 0) outset = 0.5f; // account for hairline
bounds.outset(outset, outset);
}
}