DO NOT MERGE Inspect SkShader to determine hw shader.
cherry-pick of Iaa7189178bda1c55f96da044d2a9fa602ba36034
Instead of duplicating internal info about SkShader, inspect the
SkShader installed on the SkPaint.
core/java/android/view/GLES20Canvas.java:
Remove setupModifiers, nResetModifiers, and nSetupShader.
core/jni/android/graphics/Shader.cpp:
Remove calls to create/destroy the (previously) attached SkiaShader.
core/jni/android_view_GLES20Canvas.cpp:
Remove native code for setupShader and resetModifiers.
graphics/java/android/graphics/BitmapShader.java:
graphics/java/android/graphics/ComposeShader.java:
graphics/java/android/graphics/LinearGradient.java:
graphics/java/android/graphics/RadialGradient.java:
graphics/java/android/graphics/Shader.java:
graphics/java/android/graphics/SweepGradient.java:
Remove code keeping track of native SkiaShader.
libs/hwui/Caches.h:
Include Extensions.h.
libs/hwui/DeferredDisplayList.cpp:
Compare shaders on the paint, instead of on DrawModifiers.
libs/hwui/DisplayList.cpp:
libs/hwui/DisplayList.h:
Remove vector of SkiaShaders.
libs/hwui/DisplayListOp.h:
Access the SkShader on mPaint.
Remove SetupShaderOp and ResetShaderOp.
libs/hwui/DisplayListRenderer.cpp:
libs/hwui/DisplayListRenderer.h:
Remove resetShader, setupShader, refShader, and mShaderMap.
libs/hwui/FontRenderer.cpp:
Pass SkShader to setupDrawShader and setupDrawShaderUniforms.
libs/hwui/OpenGLRenderer.cpp:
libs/hwui/OpenGLRenderer.h:
Add LayerShader, a class inheriting from SkShader, to mimic the
behavior of SkiaLayerShader. Unlike SkiaLayerShader, it can be set on
the SkPaint so it can be inspected later.
Set a LayerShader instead of a SkiaLayerShader.
setupDrawShader and setupDrawShaderUniforms now inspect an SkShader
passed in.
Inspect SkShader instead of mDrawModifiers.mShader.
Remove resetShader and setupShader.
setupDrawColorUniforms now takes a boolean indicating whether there is
a shader.
Add an inline function for accessing the SkShader on an SkPaint.
In setupDrawBlending(Layer*, bool), do not check the shader (which will
never be set), but do check whether the color filter may change the
alpha (newly fixed behavior).
In setupDrawBlending(SkPaint, ...), check the SkShader and whether the
color filter affects alpha (the latter is new behavior).
libs/hwui/Renderer.h:
Remove pure virtual functions setupShader and resetShader.
libs/hwui/ResourceCache.cpp:
libs/hwui/ResourceCache.h:
Remove functions for refing/unrefing shaders.
libs/hwui/SkiaShader.cpp:
libs/hwui/SkiaShader.h:
Much of this code was redundant and has been removed.
Convert structs into class with nothing but static functions for
calling describe/setupProgram.
libs/hwui/TextureCache.cpp:
libs/hwui/TextureCache.h:
Use the SkPixelRef as the key to the bitmap Lru cache, since shader
inspection will provide a different SkBitmap pointer (though it will
hold the correct SkPixelRef with the correct generation ID).
tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java:
tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java:
Update manual test to have more shaders: radial, sweep, compose,
invalid compose.
BUG:10650594
Change-Id: I2e7182b3fc28268e7ca82fac6780540b6b45365c
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 2e2ee15..5367663 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -33,6 +33,7 @@
#include "thread/TaskManager.h"
#include "AssetAtlas.h"
+#include "Extensions.h"
#include "FontRenderer.h"
#include "GammaFontRenderer.h"
#include "TextureCache.h"
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 3016814..937bf8d 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -230,6 +230,11 @@
return false;
}
+ if (op->mPaint && mOps[0].op->mPaint &&
+ op->mPaint->getShader() != mOps[0].op->mPaint->getShader()) {
+ return false;
+ }
+
/* Draw Modifiers compatibility check
*
* Shadows are ignored, as only text uses them, and in that case they are drawn
@@ -244,7 +249,6 @@
*/
const DrawModifiers& lhsMod = lhs->mDrawModifiers;
const DrawModifiers& rhsMod = rhs->mDrawModifiers;
- if (lhsMod.mShader != rhsMod.mShader) return false;
// Draw filter testing expects bit fields to be clear if filter not set.
if (lhsMod.mHasDrawFilter != rhsMod.mHasDrawFilter) return false;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index dac86cb..96c6292 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -58,11 +58,6 @@
caches.resourceCache.decrementRefcountLocked(patchResources.itemAt(i));
}
- for (size_t i = 0; i < shaders.size(); i++) {
- caches.resourceCache.decrementRefcountLocked(shaders.itemAt(i));
- caches.resourceCache.destructorLocked(shaders.itemAt(i));
- }
-
for (size_t i = 0; i < sourcePaths.size(); i++) {
caches.resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i));
}
@@ -92,7 +87,6 @@
bitmapResources.clear();
ownedBitmapResources.clear();
patchResources.clear();
- shaders.clear();
sourcePaths.clear();
paints.clear();
regions.clear();
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index b2ead5b..11e78b0 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -56,7 +56,6 @@
class OpenGLRenderer;
class Rect;
class Layer;
-class SkiaShader;
class ClipRectOp;
class SaveLayerOp;
@@ -127,7 +126,6 @@
SortedVector<const SkPath*> sourcePaths;
Vector<const SkRegion*> regions;
Vector<const SkMatrix*> matrices;
- Vector<SkiaShader*> shaders;
Vector<Layer*> layers;
uint32_t functorCount;
bool hasDrawOps;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index e4867220..ea3e7a8 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -208,9 +208,16 @@
if (!state.mMatrix.isSimple()) return false;
// check state/paint for transparency
- if (state.mDrawModifiers.mShader ||
- state.mAlpha != 1.0f ||
- (mPaint && mPaint->getAlpha() != 0xFF)) return false;
+ if (mPaint) {
+ if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
+ return false;
+ }
+ if (mPaint->getAlpha() != 0xFF) {
+ return false;
+ }
+ }
+
+ if (state.mAlpha != 1.0f) return false;
SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
return (mode == SkXfermode::kSrcOver_Mode ||
@@ -592,37 +599,6 @@
const SkRegion* mRegion;
};
-class ResetShaderOp : public StateOp {
-public:
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
- renderer.resetShader();
- }
-
- virtual void output(int level, uint32_t logFlags) const {
- OP_LOGS("ResetShader");
- }
-
- virtual const char* name() { return "ResetShader"; }
-};
-
-class SetupShaderOp : public StateOp {
-public:
- SetupShaderOp(SkiaShader* shader)
- : mShader(shader) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
- renderer.setupShader(mShader);
- }
-
- virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("SetupShader, shader %p", mShader);
- }
-
- virtual const char* name() { return "SetupShader"; }
-
-private:
- SkiaShader* mShader;
-};
-
class ResetPaintFilterOp : public StateOp {
public:
virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 606c67e..229afdf 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -47,7 +47,6 @@
///////////////////////////////////////////////////////////////////////////////
DisplayListData* DisplayListRenderer::finishRecording() {
- mShaderMap.clear();
mPaintMap.clear();
mRegionMap.clear();
mPathMap.clear();
@@ -394,15 +393,6 @@
return DrawGlInfo::kStatusDone;
}
-void DisplayListRenderer::resetShader() {
- addStateOp(new (alloc()) ResetShaderOp());
-}
-
-void DisplayListRenderer::setupShader(SkiaShader* shader) {
- shader = refShader(shader);
- addStateOp(new (alloc()) SetupShaderOp(shader));
-}
-
void DisplayListRenderer::resetPaintFilter() {
addStateOp(new (alloc()) ResetPaintFilterOp());
}
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index d814111..f0ae00f 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -95,9 +95,6 @@
virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
// Misc - should be implemented with SkPaint inspection
- virtual void resetShader();
- virtual void setupShader(SkiaShader* shader);
-
virtual void resetPaintFilter();
virtual void setupPaintFilter(int clearBits, int setBits);
@@ -269,21 +266,6 @@
return bitmap;
}
- inline SkiaShader* refShader(SkiaShader* shader) {
- if (!shader) return NULL;
-
- SkiaShader* shaderCopy = mShaderMap.valueFor(shader);
- // TODO: We also need to handle generation ID changes in compose shaders
- if (shaderCopy == NULL || shaderCopy->getGenerationId() != shader->getGenerationId()) {
- shaderCopy = shader->copy();
- // replaceValueFor() performs an add if the entry doesn't exist
- mShaderMap.replaceValueFor(shader, shaderCopy);
- mDisplayListData->shaders.add(shaderCopy);
- mCaches.resourceCache.incrementRefcount(shaderCopy);
- }
- return shaderCopy;
- }
-
inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
mDisplayListData->patchResources.add(patch);
mCaches.resourceCache.incrementRefcount(patch);
@@ -293,7 +275,6 @@
DefaultKeyedVector<const SkPaint*, const SkPaint*> mPaintMap;
DefaultKeyedVector<const SkPath*, const SkPath*> mPathMap;
DefaultKeyedVector<const SkRegion*, const SkRegion*> mRegionMap;
- DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
Caches& mCaches;
DisplayListData* mDisplayListData;
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 647c281..4407ab0 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -73,7 +73,7 @@
}
}
renderer->setupDrawColorFilter(paint->getColorFilter());
- renderer->setupDrawShader();
+ renderer->setupDrawShader(paint->getShader());
renderer->setupDrawBlending(paint);
renderer->setupDrawProgram();
renderer->setupDrawModelView(kModelViewMode_Translate, false,
@@ -85,7 +85,7 @@
renderer->setupDrawTexture(0);
renderer->setupDrawPureColorUniforms();
renderer->setupDrawColorFilterUniforms(paint->getColorFilter());
- renderer->setupDrawShaderUniforms(pureTranslate);
+ renderer->setupDrawShaderUniforms(paint->getShader(), pureTranslate);
renderer->setupDrawTextGammaUniforms();
return NO_ERROR;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 691f1c9..71836dd5 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <SkCanvas.h>
+#include <SkShader.h>
#include <SkTypeface.h>
#include <utils/Log.h>
@@ -37,6 +38,7 @@
#include "PathTessellator.h"
#include "Properties.h"
#include "ShadowTessellator.h"
+#include "SkiaShader.h"
#include "utils/GLUtils.h"
#include "Vector.h"
#include "VertexBuffer.h"
@@ -1053,6 +1055,45 @@
#define DRAW_DOUBLE_STENCIL(DRAW_COMMAND) DRAW_DOUBLE_STENCIL_IF(true, DRAW_COMMAND)
+// This class is purely for inspection. It inherits from SkShader, but Skia does not know how to
+// use it. The OpenGLRenderer will look at it to find its Layer and whether it is opaque.
+class LayerShader : public SkShader {
+public:
+ LayerShader(Layer* layer, const SkMatrix* localMatrix)
+ : INHERITED(localMatrix)
+ , mLayer(layer) {
+ }
+
+ virtual bool asACustomShader(void** data) const {
+ if (data) {
+ *data = static_cast<void*>(mLayer);
+ }
+ return true;
+ }
+
+ virtual bool isOpaque() const {
+ return !mLayer->isBlend();
+ }
+
+protected:
+ virtual void shadeSpan(int x, int y, SkPMColor[], int count) {
+ LOG_ALWAYS_FATAL("LayerShader should never be drawn with raster backend.");
+ }
+
+ virtual void flatten(SkWriteBuffer&) const {
+ LOG_ALWAYS_FATAL("LayerShader should never be flattened.");
+ }
+
+ virtual Factory getFactory() const {
+ LOG_ALWAYS_FATAL("LayerShader should never be created from a stream.");
+ return NULL;
+ }
+private:
+ // Unowned.
+ Layer* mLayer;
+ typedef SkShader INHERITED;
+};
+
void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
if (CC_UNLIKELY(layer->region.isEmpty())) return; // nothing to draw
@@ -1066,21 +1107,19 @@
paint.setAntiAlias(true);
paint.setColor(SkColorSetARGB(int(getLayerAlpha(layer) * 255), 0, 0, 0));
- SkiaShader* oldShader = mDrawModifiers.mShader;
-
// create LayerShader to map SaveLayer content into subsequent draw
SkMatrix shaderMatrix;
shaderMatrix.setTranslate(rect.left, rect.bottom);
shaderMatrix.preScale(1, -1);
- SkiaLayerShader layerShader(layer, &shaderMatrix);
- mDrawModifiers.mShader = &layerShader;
+ LayerShader layerShader(layer, &shaderMatrix);
+ paint.setShader(&layerShader);
// Since the drawing primitive is defined in local drawing space,
// we don't need to modify the draw matrix
const SkPath* maskPath = layer->getConvexMask();
DRAW_DOUBLE_STENCIL(drawConvexPath(*maskPath, &paint));
- mDrawModifiers.mShader = oldShader;
+ paint.setShader(NULL);
restore();
return;
@@ -1627,9 +1666,9 @@
mSetShaderColor = mDescription.setColorModulate(a);
}
-void OpenGLRenderer::setupDrawShader() {
- if (mDrawModifiers.mShader) {
- mDrawModifiers.mShader->describe(mDescription, mExtensions);
+void OpenGLRenderer::setupDrawShader(const SkShader* shader) {
+ if (shader != NULL) {
+ SkiaShader::describe(&mCaches, mDescription, mExtensions, *shader);
}
}
@@ -1655,15 +1694,21 @@
}
}
+static bool isBlendedColorFilter(const SkColorFilter* filter) {
+ if (filter == NULL) {
+ return false;
+ }
+ return (filter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) == 0;
+}
+
void OpenGLRenderer::setupDrawBlending(const Layer* layer, bool swapSrcDst) {
SkXfermode::Mode mode = layer->getMode();
// When the blending mode is kClear_Mode, we need to use a modulate color
// argb=1,0,0,0
accountForClear(mode);
+ // TODO: check shader blending, once we have shader drawing support for layers.
bool blend = layer->isBlend() || getLayerAlpha(layer) < 1.0f ||
- (mColorSet && mColorA < 1.0f) ||
- (mDrawModifiers.mShader && mDrawModifiers.mShader->blend()) ||
- layer->getColorFilter();
+ (mColorSet && mColorA < 1.0f) || isBlendedColorFilter(layer->getColorFilter());
chooseBlending(blend, mode, mDescription, swapSrcDst);
}
@@ -1673,8 +1718,8 @@
// argb=1,0,0,0
accountForClear(mode);
blend |= (mColorSet && mColorA < 1.0f) ||
- (mDrawModifiers.mShader && mDrawModifiers.mShader->blend()) ||
- (paint && paint->getColorFilter());
+ (getShader(paint) && !getShader(paint)->isOpaque()) ||
+ isBlendedColorFilter(getColorFilter(paint));
chooseBlending(blend, mode, mDescription, swapSrcDst);
}
@@ -1717,8 +1762,8 @@
}
}
-void OpenGLRenderer::setupDrawColorUniforms() {
- if ((mColorSet && !mDrawModifiers.mShader) || (mDrawModifiers.mShader && mSetShaderColor)) {
+void OpenGLRenderer::setupDrawColorUniforms(bool hasShader) {
+ if ((mColorSet && !hasShader) || (hasShader && mSetShaderColor)) {
mCaches.currentProgram->setColor(mColorR, mColorG, mColorB, mColorA);
}
}
@@ -1729,20 +1774,22 @@
}
}
-void OpenGLRenderer::setupDrawShaderUniforms(bool ignoreTransform) {
- if (mDrawModifiers.mShader) {
- if (ignoreTransform) {
- // if ignoreTransform=true was passed to setupDrawModelView, undo currentTransform()
- // because it was built into modelView / the geometry, and the SkiaShader needs to
- // compensate.
- mat4 modelViewWithoutTransform;
- modelViewWithoutTransform.loadInverse(*currentTransform());
- modelViewWithoutTransform.multiply(mModelViewMatrix);
- mModelViewMatrix.load(modelViewWithoutTransform);
- }
- mDrawModifiers.mShader->setupProgram(mCaches.currentProgram,
- mModelViewMatrix, *mSnapshot, &mTextureUnit);
+void OpenGLRenderer::setupDrawShaderUniforms(const SkShader* shader, bool ignoreTransform) {
+ if (shader == NULL) {
+ return;
}
+
+ if (ignoreTransform) {
+ // if ignoreTransform=true was passed to setupDrawModelView, undo currentTransform()
+ // because it was built into modelView / the geometry, and the description needs to
+ // compensate.
+ mat4 modelViewWithoutTransform;
+ modelViewWithoutTransform.loadInverse(*currentTransform());
+ modelViewWithoutTransform.multiply(mModelViewMatrix);
+ mModelViewMatrix.load(modelViewWithoutTransform);
+ }
+
+ SkiaShader::setupProgram(&mCaches, mModelViewMatrix, &mTextureUnit, mExtensions, *shader);
}
void OpenGLRenderer::setupDrawColorFilterUniforms(const SkColorFilter* filter) {
@@ -2201,7 +2248,7 @@
// Apply a scale transform on the canvas only when a shader is in use
// Skia handles the ratio between the dst and src rects as a scale factor
// when a shader is set
- bool useScaleTransform = mDrawModifiers.mShader && scaled;
+ bool useScaleTransform = getShader(paint) && scaled;
bool ignoreTransform = false;
if (CC_LIKELY(currentTransform()->isPureTranslate() && !useScaleTransform)) {
@@ -2359,13 +2406,13 @@
if (isAA) setupDrawAA();
setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
setupDrawColorFilter(getColorFilter(paint));
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawBlending(paint, isAA);
setupDrawProgram();
setupDrawModelView(kModelViewMode_Translate, useOffset, 0, 0, 0, 0);
- setupDrawColorUniforms();
+ setupDrawColorUniforms(getShader(paint));
setupDrawColorFilterUniforms(getColorFilter(paint));
- setupDrawShaderUniforms();
+ setupDrawShaderUniforms(getShader(paint));
const void* vertices = vertexBuffer.getBuffer();
bool force = mCaches.unbindMeshBuffer();
@@ -2670,7 +2717,7 @@
const float sy = y - shadow->top + textShadow.dy;
const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * mSnapshot->alpha;
- if (mDrawModifiers.mShader) {
+ if (getShader(paint)) {
textShadow.color = SK_ColorWHITE;
}
@@ -2678,7 +2725,7 @@
setupDrawWithTexture(true);
setupDrawAlpha8Color(textShadow.color, shadowAlpha < 255 ? shadowAlpha : alpha);
setupDrawColorFilter(getColorFilter(paint));
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawBlending(paint, true);
setupDrawProgram();
setupDrawModelView(kModelViewMode_TranslateAndScale, false,
@@ -2686,7 +2733,7 @@
setupDrawTexture(shadow->id);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(getColorFilter(paint));
- setupDrawShaderUniforms();
+ setupDrawShaderUniforms(getShader(paint));
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
@@ -3008,21 +3055,6 @@
}
///////////////////////////////////////////////////////////////////////////////
-// Shaders
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::resetShader() {
- mDrawModifiers.mShader = NULL;
-}
-
-void OpenGLRenderer::setupShader(SkiaShader* shader) {
- mDrawModifiers.mShader = shader;
- if (mDrawModifiers.mShader) {
- mDrawModifiers.mShader->setCaches(mCaches);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
// Draw filters
///////////////////////////////////////////////////////////////////////////////
@@ -3080,7 +3112,7 @@
setupDrawWithTexture(true);
setupDrawAlpha8Color(paint->getColor(), alpha);
setupDrawColorFilter(getColorFilter(paint));
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawBlending(paint, true);
setupDrawProgram();
setupDrawModelView(kModelViewMode_TranslateAndScale, false,
@@ -3088,7 +3120,7 @@
setupDrawTexture(texture->id);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(getColorFilter(paint));
- setupDrawShaderUniforms();
+ setupDrawShaderUniforms(getShader(paint));
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
@@ -3254,7 +3286,7 @@
int color = paint->getColor();
// If a shader is set, preserve only the alpha
- if (mDrawModifiers.mShader) {
+ if (getShader(paint)) {
color |= 0x00ffffff;
}
@@ -3290,15 +3322,15 @@
setupDraw();
setupDrawNoTexture();
setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawColorFilter(getColorFilter(paint));
setupDrawBlending(paint);
setupDrawProgram();
setupDrawDirtyRegionsDisabled();
setupDrawModelView(kModelViewMode_Translate, false,
0.0f, 0.0f, 0.0f, 0.0f, ignoreTransform);
- setupDrawColorUniforms();
- setupDrawShaderUniforms();
+ setupDrawColorUniforms(getShader(paint));
+ setupDrawShaderUniforms(getShader(paint));
setupDrawColorFilterUniforms(getColorFilter(paint));
if (dirty && hasLayer()) {
@@ -3314,21 +3346,21 @@
const SkPaint* paint, bool ignoreTransform) {
int color = paint->getColor();
// If a shader is set, preserve only the alpha
- if (mDrawModifiers.mShader) {
+ if (getShader(paint)) {
color |= 0x00ffffff;
}
setupDraw();
setupDrawNoTexture();
setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawColorFilter(getColorFilter(paint));
setupDrawBlending(paint);
setupDrawProgram();
setupDrawModelView(kModelViewMode_TranslateAndScale, false,
left, top, right, bottom, ignoreTransform);
- setupDrawColorUniforms();
- setupDrawShaderUniforms(ignoreTransform);
+ setupDrawColorUniforms(getShader(paint));
+ setupDrawShaderUniforms(getShader(paint), ignoreTransform);
setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawSimpleMesh();
@@ -3441,7 +3473,7 @@
setupDrawAlpha8Color(color, alpha);
}
setupDrawColorFilter(getColorFilter(paint));
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawBlending(paint, true);
setupDrawProgram();
if (!dirty) setupDrawDirtyRegionsDisabled();
@@ -3449,7 +3481,7 @@
setupDrawTexture(texture);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(getColorFilter(paint));
- setupDrawShaderUniforms(ignoreTransform);
+ setupDrawShaderUniforms(getShader(paint), ignoreTransform);
setupDrawMesh(vertices, texCoords);
glDrawArrays(drawMode, 0, elementsCount);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index c6d9071..fc27947 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -26,7 +26,6 @@
#include <SkMatrix.h>
#include <SkPaint.h>
#include <SkRegion.h>
-#include <SkShader.h>
#include <SkXfermode.h>
#include <utils/Blur.h>
@@ -45,13 +44,15 @@
#include "Program.h"
#include "Rect.h"
#include "Renderer.h"
-#include "StatefulBaseRenderer.h"
#include "Snapshot.h"
+#include "StatefulBaseRenderer.h"
#include "UvMapper.h"
#include "Vertex.h"
#include "Caches.h"
#include "CanvasProperty.h"
+class SkShader;
+
namespace android {
namespace uirenderer {
@@ -59,7 +60,6 @@
class RenderNode;
class TextSetupFunctor;
class VertexBuffer;
-class SkiaShader;
struct DrawModifiers {
DrawModifiers() {
@@ -70,7 +70,6 @@
memset(this, 0, sizeof(DrawModifiers));
}
- SkiaShader* mShader;
float mOverrideLayerAlpha;
// Draw filters
@@ -217,9 +216,6 @@
status_t drawShadow(const mat4& casterTransformXY, const mat4& casterTransformZ,
float casterAlpha, bool casterUnclipped, const SkPath* casterPerimeter);
- virtual void resetShader();
- virtual void setupShader(SkiaShader* shader);
-
virtual void resetPaintFilter();
virtual void setupPaintFilter(int clearBits, int setBits);
@@ -467,6 +463,14 @@
}
/**
+ * Safely retrieves the Shader from the given Paint. If the paint is
+ * null then null is returned.
+ */
+ static inline const SkShader* getShader(const SkPaint* paint) {
+ return paint ? paint->getShader() : NULL;
+ }
+
+ /**
* Set to true to suppress error checks at the end of a frame.
*/
virtual bool suppressErrorChecks() const {
@@ -838,7 +842,7 @@
void setupDrawColor(float r, float g, float b, float a);
void setupDrawAlpha8Color(int color, int alpha);
void setupDrawTextGamma(const SkPaint* paint);
- void setupDrawShader();
+ void setupDrawShader(const SkShader* shader);
void setupDrawColorFilter(const SkColorFilter* filter);
void setupDrawBlending(const Layer* layer, bool swapSrcDst = false);
void setupDrawBlending(const SkPaint* paint, bool blend = true, bool swapSrcDst = false);
@@ -862,9 +866,17 @@
*/
void setupDrawModelView(ModelViewMode mode, bool offset,
float left, float top, float right, float bottom, bool ignoreTransform = false);
- void setupDrawColorUniforms();
+ void setupDrawColorUniforms(bool hasShader);
void setupDrawPureColorUniforms();
- void setupDrawShaderUniforms(bool ignoreTransform = false);
+
+ /**
+ * Setup uniforms for the current shader.
+ *
+ * @param shader SkShader on the current paint.
+ *
+ * @param ignoreTransform Set to true to ignore the transform in shader.
+ */
+ void setupDrawShaderUniforms(const SkShader* shader, bool ignoreTransform = false);
void setupDrawColorFilterUniforms(const SkColorFilter* paint);
void setupDrawSimpleMesh();
void setupDrawTexture(GLuint texture);
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index e191a26..23cab0e 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -35,7 +35,6 @@
class Layer;
class Matrix4;
class SkiaColorFilter;
-class SkiaShader;
class Patch;
enum DrawOpMode {
@@ -183,9 +182,6 @@
virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) = 0;
// Misc - should be implemented with SkPaint inspection
- virtual void resetShader() = 0;
- virtual void setupShader(SkiaShader* shader) = 0;
-
virtual void resetPaintFilter() = 0;
virtual void setupPaintFilter(int clearBits, int setBits) = 0;
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 13a3e8e..8b553d1 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -71,11 +71,6 @@
incrementRefcount((void*) pathResource, kPath);
}
-void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
- SkSafeRef(shaderResource->getSkShader());
- incrementRefcount((void*) shaderResource, kShader);
-}
-
void ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) {
incrementRefcount((void*) patchResource, kNinePatch);
}
@@ -104,11 +99,6 @@
incrementRefcountLocked((void*) pathResource, kPath);
}
-void ResourceCache::incrementRefcountLocked(SkiaShader* shaderResource) {
- SkSafeRef(shaderResource->getSkShader());
- incrementRefcountLocked((void*) shaderResource, kShader);
-}
-
void ResourceCache::incrementRefcountLocked(const Res_png_9patch* patchResource) {
incrementRefcountLocked((void*) patchResource, kNinePatch);
}
@@ -132,11 +122,6 @@
decrementRefcount((void*) pathResource);
}
-void ResourceCache::decrementRefcount(SkiaShader* shaderResource) {
- SkSafeUnref(shaderResource->getSkShader());
- decrementRefcount((void*) shaderResource);
-}
-
void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) {
decrementRefcount((void*) patchResource);
}
@@ -168,11 +153,6 @@
decrementRefcountLocked((void*) pathResource);
}
-void ResourceCache::decrementRefcountLocked(SkiaShader* shaderResource) {
- SkSafeUnref(shaderResource->getSkShader());
- decrementRefcountLocked((void*) shaderResource);
-}
-
void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) {
decrementRefcountLocked((void*) patchResource);
}
@@ -227,25 +207,6 @@
}
}
-void ResourceCache::destructor(SkiaShader* resource) {
- Mutex::Autolock _l(mLock);
- destructorLocked(resource);
-}
-
-void ResourceCache::destructorLocked(SkiaShader* resource) {
- ssize_t index = mCache->indexOfKey(resource);
- ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
- if (ref == NULL) {
- // If we're not tracking this resource, just delete it
- delete resource;
- return;
- }
- ref->destroyed = true;
- if (ref->refCount == 0) {
- deleteResourceReferenceLocked(resource, ref);
- }
-}
-
void ResourceCache::destructor(Res_png_9patch* resource) {
Mutex::Autolock _l(mLock);
destructorLocked(resource);
@@ -333,11 +294,6 @@
}
}
break;
- case kShader: {
- SkiaShader* shader = (SkiaShader*) resource;
- delete shader;
- }
- break;
case kNinePatch: {
if (Caches::hasInstance()) {
Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*) resource);
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 4097ba4..3864d4b 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -20,7 +20,6 @@
#include <cutils/compiler.h>
#include <SkBitmap.h>
-#include <SkiaShader.h>
#include <utils/KeyedVector.h>
@@ -36,7 +35,6 @@
*/
enum ResourceType {
kBitmap,
- kShader,
kNinePatch,
kPath,
kLayer
@@ -70,36 +68,30 @@
void incrementRefcount(const SkPath* resource);
void incrementRefcount(const SkBitmap* resource);
- void incrementRefcount(SkiaShader* resource);
void incrementRefcount(const Res_png_9patch* resource);
void incrementRefcount(Layer* resource);
void incrementRefcountLocked(const SkPath* resource);
void incrementRefcountLocked(const SkBitmap* resource);
- void incrementRefcountLocked(SkiaShader* resource);
void incrementRefcountLocked(const Res_png_9patch* resource);
void incrementRefcountLocked(Layer* resource);
void decrementRefcount(const SkBitmap* resource);
void decrementRefcount(const SkPath* resource);
- void decrementRefcount(SkiaShader* resource);
void decrementRefcount(const Res_png_9patch* resource);
void decrementRefcount(Layer* resource);
void decrementRefcountLocked(const SkBitmap* resource);
void decrementRefcountLocked(const SkPath* resource);
- void decrementRefcountLocked(SkiaShader* resource);
void decrementRefcountLocked(const Res_png_9patch* resource);
void decrementRefcountLocked(Layer* resource);
void destructor(SkPath* resource);
void destructor(const SkBitmap* resource);
- void destructor(SkiaShader* resource);
void destructor(Res_png_9patch* resource);
void destructorLocked(SkPath* resource);
void destructorLocked(const SkBitmap* resource);
- void destructorLocked(SkiaShader* resource);
void destructorLocked(Res_png_9patch* resource);
bool recycle(SkBitmap* resource);
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 6a4a0c8..c672bc4 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -21,9 +21,10 @@
#include <SkMatrix.h>
#include "Caches.h"
+#include "Layer.h"
+#include "Matrix.h"
#include "SkiaShader.h"
#include "Texture.h"
-#include "Matrix.h"
namespace android {
namespace uirenderer {
@@ -54,89 +55,142 @@
a);
}
-///////////////////////////////////////////////////////////////////////////////
-// Base shader
-///////////////////////////////////////////////////////////////////////////////
-
-void SkiaShader::copyFrom(const SkiaShader& shader) {
- mType = shader.mType;
- mKey = shader.mKey;
- mTileX = shader.mTileX;
- mTileY = shader.mTileY;
- mBlend = shader.mBlend;
- mUnitMatrix = shader.mUnitMatrix;
- mShaderMatrix = shader.mShaderMatrix;
- mGenerationId = shader.mGenerationId;
-}
-
-SkiaShader::SkiaShader(): mCaches(NULL) {
-}
-
-SkiaShader::SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
- SkShader::TileMode tileY, const SkMatrix* matrix, bool blend):
- mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend),
- mCaches(NULL) {
- setMatrix(matrix);
- mGenerationId = 0;
-}
-
-SkiaShader::~SkiaShader() {
-}
-
-void SkiaShader::describe(ProgramDescription& description, const Extensions& extensions) {
-}
-
-void SkiaShader::setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit) {
-}
-
-void SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) {
- mCaches->bindTexture(texture->id);
+static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) {
+ caches->bindTexture(texture->id);
texture->setWrapST(wrapS, wrapT);
}
-void SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) {
- screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix);
- screenSpace.multiply(modelView);
+/**
+ * Compute the matrix to transform to screen space.
+ * @param screenSpace Output param for the computed matrix.
+ * @param unitMatrix The unit matrix for gradient shaders, as returned by SkShader::asAGradient,
+ * or identity.
+ * @param localMatrix Local matrix, as returned by SkShader::getLocalMatrix().
+ * @param modelViewMatrix Model view matrix, as supplied by the OpenGLRenderer.
+ */
+static void computeScreenSpaceMatrix(mat4& screenSpace, const SkMatrix& unitMatrix,
+ const SkMatrix& localMatrix, const mat4& modelViewMatrix) {
+ mat4 shaderMatrix;
+ // uses implicit construction
+ shaderMatrix.loadInverse(localMatrix);
+ // again, uses implicit construction
+ screenSpace.loadMultiply(unitMatrix, shaderMatrix);
+ screenSpace.multiply(modelViewMatrix);
+}
+
+// Returns true if one is a bitmap and the other is a gradient
+static bool bitmapAndGradient(SkiaShaderType type1, SkiaShaderType type2) {
+ return (type1 == kBitmap_SkiaShaderType && type2 == kGradient_SkiaShaderType)
+ || (type2 == kBitmap_SkiaShaderType && type1 == kGradient_SkiaShaderType);
+}
+
+SkiaShaderType SkiaShader::getType(const SkShader& shader) {
+ // First check for a gradient shader.
+ switch (shader.asAGradient(NULL)) {
+ case SkShader::kNone_GradientType:
+ // Not a gradient shader. Fall through to check for other types.
+ break;
+ case SkShader::kLinear_GradientType:
+ case SkShader::kRadial_GradientType:
+ case SkShader::kSweep_GradientType:
+ return kGradient_SkiaShaderType;
+ default:
+ // This is a Skia gradient that has no SkiaShader equivalent. Return None to skip.
+ return kNone_SkiaShaderType;
+ }
+
+ // The shader is not a gradient. Check for a bitmap shader.
+ if (shader.asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType) {
+ return kBitmap_SkiaShaderType;
+ }
+
+ // Check for a ComposeShader.
+ SkShader::ComposeRec rec;
+ if (shader.asACompose(&rec)) {
+ const SkiaShaderType shaderAType = getType(*rec.fShaderA);
+ const SkiaShaderType shaderBType = getType(*rec.fShaderB);
+
+ // Compose is only supported if one is a bitmap and the other is a
+ // gradient. Otherwise, return None to skip.
+ if (!bitmapAndGradient(shaderAType, shaderBType)) {
+ return kNone_SkiaShaderType;
+ }
+ return kCompose_SkiaShaderType;
+ }
+
+ if (shader.asACustomShader(NULL)) {
+ return kLayer_SkiaShaderType;
+ }
+
+ return kNone_SkiaShaderType;
+}
+
+typedef void (*describeProc)(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+
+describeProc gDescribeProc[] = {
+ InvalidSkiaShader::describe,
+ SkiaBitmapShader::describe,
+ SkiaGradientShader::describe,
+ SkiaComposeShader::describe,
+ SkiaLayerShader::describe,
+};
+
+typedef void (*setupProgramProc)(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+
+setupProgramProc gSetupProgramProc[] = {
+ InvalidSkiaShader::setupProgram,
+ SkiaBitmapShader::setupProgram,
+ SkiaGradientShader::setupProgram,
+ SkiaComposeShader::setupProgram,
+ SkiaLayerShader::setupProgram,
+};
+
+void SkiaShader::describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ gDescribeProc[getType(shader)](caches, description, extensions, shader);
+}
+
+void SkiaShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
+
+ gSetupProgramProc[getType(shader)](caches, modelViewMatrix, textureUnit, extensions, shader);
}
///////////////////////////////////////////////////////////////////////////////
// Layer shader
///////////////////////////////////////////////////////////////////////////////
-SkiaLayerShader::SkiaLayerShader(Layer* layer, const SkMatrix* matrix):
- SkiaShader(kBitmap, NULL, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
- matrix, layer->isBlend()), mLayer(layer) {
- updateLocalMatrix(matrix);
-}
-
-SkiaShader* SkiaLayerShader::copy() {
- SkiaLayerShader* copy = new SkiaLayerShader();
- copy->copyFrom(*this);
- copy->mLayer = mLayer;
- return copy;
-}
-
-void SkiaLayerShader::describe(ProgramDescription& description, const Extensions& extensions) {
+void SkiaLayerShader::describe(Caches*, ProgramDescription& description,
+ const Extensions&, const SkShader& shader) {
description.hasBitmap = true;
}
-void SkiaLayerShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot& snapshot, GLuint* textureUnit) {
- GLuint textureSlot = (*textureUnit)++;
- Caches::getInstance().activeTexture(textureSlot);
+void SkiaLayerShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions&, const SkShader& shader) {
+ Layer* layer;
+ if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) {
+ LOG_ALWAYS_FATAL("SkiaLayerShader::setupProgram called on the wrong type of shader!");
+ }
- const float width = mLayer->getWidth();
- const float height = mLayer->getHeight();
+ GLuint textureSlot = (*textureUnit)++;
+ caches->activeTexture(textureSlot);
+
+ const float width = layer->getWidth();
+ const float height = layer->getHeight();
mat4 textureTransform;
- computeScreenSpaceMatrix(textureTransform, modelView);
+ computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
+ modelViewMatrix);
+
// Uniforms
- mLayer->bindTexture();
- mLayer->setWrap(GL_CLAMP_TO_EDGE);
- mLayer->setFilter(GL_LINEAR);
+ layer->bindTexture();
+ layer->setWrap(GL_CLAMP_TO_EDGE);
+ layer->setFilter(GL_LINEAR);
+ Program* program = caches->currentProgram;
glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
GL_FALSE, &textureTransform.data[0]);
@@ -147,67 +201,99 @@
// Bitmap shader
///////////////////////////////////////////////////////////////////////////////
-SkiaBitmapShader::SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX,
- SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
- SkiaShader(kBitmap, key, tileX, tileY, matrix, blend), mBitmap(bitmap), mTexture(NULL) {
- updateLocalMatrix(matrix);
-}
+struct BitmapShaderInfo {
+ float width;
+ float height;
+ GLenum wrapS;
+ GLenum wrapT;
+ Texture* texture;
+};
-SkiaShader* SkiaBitmapShader::copy() {
- SkiaBitmapShader* copy = new SkiaBitmapShader();
- copy->copyFrom(*this);
- copy->mBitmap = mBitmap;
- return copy;
-}
-
-void SkiaBitmapShader::describe(ProgramDescription& description, const Extensions& extensions) {
- Texture* texture = mCaches->textureCache.get(mBitmap);
- if (!texture) return;
- mTexture = texture;
+static bool bitmapShaderHelper(Caches* caches, ProgramDescription* description,
+ BitmapShaderInfo* shaderInfo,
+ const Extensions& extensions,
+ const SkBitmap& bitmap, SkShader::TileMode tileModes[2]) {
+ Texture* texture = caches->textureCache.get(&bitmap);
+ if (!texture) return false;
const float width = texture->width;
const float height = texture->height;
+ GLenum wrapS, wrapT;
- description.hasBitmap = true;
+ if (description) {
+ description->hasBitmap = true;
+ }
// The driver does not support non-power of two mirrored/repeated
// textures, so do it ourselves
if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
- (mTileX != SkShader::kClamp_TileMode || mTileY != SkShader::kClamp_TileMode)) {
- description.isBitmapNpot = true;
- description.bitmapWrapS = gTileModes[mTileX];
- description.bitmapWrapT = gTileModes[mTileY];
- mWrapS = GL_CLAMP_TO_EDGE;
- mWrapT = GL_CLAMP_TO_EDGE;
+ (tileModes[0] != SkShader::kClamp_TileMode ||
+ tileModes[1] != SkShader::kClamp_TileMode)) {
+ if (description) {
+ description->isBitmapNpot = true;
+ description->bitmapWrapS = gTileModes[tileModes[0]];
+ description->bitmapWrapT = gTileModes[tileModes[1]];
+ }
+ wrapS = GL_CLAMP_TO_EDGE;
+ wrapT = GL_CLAMP_TO_EDGE;
} else {
- mWrapS = gTileModes[mTileX];
- mWrapT = gTileModes[mTileY];
+ wrapS = gTileModes[tileModes[0]];
+ wrapT = gTileModes[tileModes[1]];
}
+
+ if (shaderInfo) {
+ shaderInfo->width = width;
+ shaderInfo->height = height;
+ shaderInfo->wrapS = wrapS;
+ shaderInfo->wrapT = wrapT;
+ shaderInfo->texture = texture;
+ }
+ return true;
}
-void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot&, GLuint* textureUnit) {
+void SkiaBitmapShader::describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ SkBitmap bitmap;
+ SkShader::TileMode xy[2];
+ if (shader.asABitmap(&bitmap, NULL, xy) != SkShader::kDefault_BitmapType) {
+ LOG_ALWAYS_FATAL("SkiaBitmapShader::describe called with a different kind of shader!");
+ }
+ bitmapShaderHelper(caches, &description, NULL, extensions, bitmap, xy);
+}
+
+void SkiaBitmapShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
+ SkBitmap bitmap;
+ SkShader::TileMode xy[2];
+ if (shader.asABitmap(&bitmap, NULL, xy) != SkShader::kDefault_BitmapType) {
+ LOG_ALWAYS_FATAL("SkiaBitmapShader::setupProgram called with a different kind of shader!");
+ }
+
GLuint textureSlot = (*textureUnit)++;
Caches::getInstance().activeTexture(textureSlot);
- Texture* texture = mTexture;
- mTexture = NULL;
- if (!texture) return;
+ BitmapShaderInfo shaderInfo;
+ if (!bitmapShaderHelper(caches, NULL, &shaderInfo, extensions, bitmap, xy)) {
+ return;
+ }
+
+ Program* program = caches->currentProgram;
+ Texture* texture = shaderInfo.texture;
+
const AutoTexture autoCleanup(texture);
- const float width = texture->width;
- const float height = texture->height;
-
mat4 textureTransform;
- computeScreenSpaceMatrix(textureTransform, modelView);
+ computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
+ modelViewMatrix);
// Uniforms
- bindTexture(texture, mWrapS, mWrapT);
+ bindTexture(caches, texture, shaderInfo.wrapS, shaderInfo.wrapT);
texture->setFilter(GL_LINEAR);
glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
GL_FALSE, &textureTransform.data[0]);
- glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height);
+ glUniform2f(program->getUniform("textureDimension"), 1.0f / shaderInfo.width,
+ 1.0f / shaderInfo.height);
}
///////////////////////////////////////////////////////////////////////////////
@@ -225,74 +311,6 @@
matrix->postScale(inv, inv);
}
-SkiaLinearGradientShader::SkiaLinearGradientShader(float* bounds, uint32_t* colors,
- float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
- SkMatrix* matrix, bool blend):
- SkiaShader(kLinearGradient, key, tileMode, tileMode, matrix, blend),
- mBounds(bounds), mColors(colors), mPositions(positions), mCount(count) {
- SkPoint points[2];
- points[0].set(bounds[0], bounds[1]);
- points[1].set(bounds[2], bounds[3]);
-
- SkMatrix unitMatrix;
- toUnitMatrix(points, &unitMatrix);
- mUnitMatrix.load(unitMatrix);
-
- updateLocalMatrix(matrix);
-
- mIsSimple = count == 2 && tileMode == SkShader::kClamp_TileMode;
-}
-
-SkiaLinearGradientShader::~SkiaLinearGradientShader() {
- delete[] mBounds;
- delete[] mColors;
- delete[] mPositions;
-}
-
-SkiaShader* SkiaLinearGradientShader::copy() {
- SkiaLinearGradientShader* copy = new SkiaLinearGradientShader();
- copy->copyFrom(*this);
- copy->mBounds = new float[4];
- memcpy(copy->mBounds, mBounds, sizeof(float) * 4);
- copy->mColors = new uint32_t[mCount];
- memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
- copy->mPositions = new float[mCount];
- memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
- copy->mCount = mCount;
- copy->mIsSimple = mIsSimple;
- return copy;
-}
-
-void SkiaLinearGradientShader::describe(ProgramDescription& description,
- const Extensions& extensions) {
- description.hasGradient = true;
- description.gradientType = ProgramDescription::kGradientLinear;
- description.isSimpleGradient = mIsSimple;
-}
-
-void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot&, GLuint* textureUnit) {
- if (CC_UNLIKELY(!mIsSimple)) {
- GLuint textureSlot = (*textureUnit)++;
- Caches::getInstance().activeTexture(textureSlot);
-
- Texture* texture = mCaches->gradientCache.get(mColors, mPositions, mCount);
-
- // Uniforms
- bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
- glUniform1i(program->getUniform("gradientSampler"), textureSlot);
- } else {
- bindUniformColor(program->getUniform("startColor"), mColors[0]);
- bindUniformColor(program->getUniform("endColor"), mColors[1]);
- }
-
- Caches::getInstance().dither.setupProgram(program, textureUnit);
-
- mat4 screenSpace;
- computeScreenSpaceMatrix(screenSpace, modelView);
- glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
-}
-
///////////////////////////////////////////////////////////////////////////////
// Circular gradient shader
///////////////////////////////////////////////////////////////////////////////
@@ -304,37 +322,6 @@
matrix->postScale(inv, inv);
}
-SkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float radius,
- uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
- SkMatrix* matrix, bool blend):
- SkiaSweepGradientShader(kCircularGradient, colors, positions, count, key,
- tileMode, matrix, blend) {
- SkMatrix unitMatrix;
- toCircularUnitMatrix(x, y, radius, &unitMatrix);
- mUnitMatrix.load(unitMatrix);
-
- updateLocalMatrix(matrix);
-}
-
-SkiaShader* SkiaCircularGradientShader::copy() {
- SkiaCircularGradientShader* copy = new SkiaCircularGradientShader();
- copy->copyFrom(*this);
- copy->mColors = new uint32_t[mCount];
- memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
- copy->mPositions = new float[mCount];
- memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
- copy->mCount = mCount;
- copy->mIsSimple = mIsSimple;
- return copy;
-}
-
-void SkiaCircularGradientShader::describe(ProgramDescription& description,
- const Extensions& extensions) {
- description.hasGradient = true;
- description.gradientType = ProgramDescription::kGradientCircular;
- description.isSimpleGradient = mIsSimple;
-}
-
///////////////////////////////////////////////////////////////////////////////
// Sweep gradient shader
///////////////////////////////////////////////////////////////////////////////
@@ -343,74 +330,103 @@
matrix->setTranslate(-x, -y);
}
-SkiaSweepGradientShader::SkiaSweepGradientShader(float x, float y, uint32_t* colors,
- float* positions, int count, SkShader* key, SkMatrix* matrix, bool blend):
- SkiaShader(kSweepGradient, key, SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode, matrix, blend),
- mColors(colors), mPositions(positions), mCount(count) {
- SkMatrix unitMatrix;
- toSweepUnitMatrix(x, y, &unitMatrix);
- mUnitMatrix.load(unitMatrix);
+///////////////////////////////////////////////////////////////////////////////
+// Common gradient code
+///////////////////////////////////////////////////////////////////////////////
- updateLocalMatrix(matrix);
-
- mIsSimple = count == 2;
+static bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) {
+ return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode;
}
-SkiaSweepGradientShader::SkiaSweepGradientShader(Type type, uint32_t* colors,
- float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
- SkMatrix* matrix, bool blend):
- SkiaShader(type, key, tileMode, tileMode, matrix, blend),
- mColors(colors), mPositions(positions), mCount(count) {
- // protected method, that doesn't setup mUnitMatrix - should be handled by subclass
+void SkiaGradientShader::describe(Caches*, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ SkShader::GradientInfo gradInfo;
+ gradInfo.fColorCount = 0;
+ gradInfo.fColors = NULL;
+ gradInfo.fColorOffsets = NULL;
- mIsSimple = count == 2 && tileMode == SkShader::kClamp_TileMode;
-}
-
-SkiaSweepGradientShader::~SkiaSweepGradientShader() {
- delete[] mColors;
- delete[] mPositions;
-}
-
-SkiaShader* SkiaSweepGradientShader::copy() {
- SkiaSweepGradientShader* copy = new SkiaSweepGradientShader();
- copy->copyFrom(*this);
- copy->mColors = new uint32_t[mCount];
- memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
- copy->mPositions = new float[mCount];
- memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
- copy->mCount = mCount;
- copy->mIsSimple = mIsSimple;
- return copy;
-}
-
-void SkiaSweepGradientShader::describe(ProgramDescription& description,
- const Extensions& extensions) {
+ switch (shader.asAGradient(&gradInfo)) {
+ case SkShader::kLinear_GradientType:
+ description.gradientType = ProgramDescription::kGradientLinear;
+ break;
+ case SkShader::kRadial_GradientType:
+ description.gradientType = ProgramDescription::kGradientCircular;
+ break;
+ case SkShader::kSweep_GradientType:
+ description.gradientType = ProgramDescription::kGradientSweep;
+ break;
+ default:
+ // Do nothing. This shader is unsupported.
+ return;
+ }
description.hasGradient = true;
- description.gradientType = ProgramDescription::kGradientSweep;
- description.isSimpleGradient = mIsSimple;
+ description.isSimpleGradient = isSimpleGradient(gradInfo);
}
-void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot& snapshot, GLuint* textureUnit) {
- if (CC_UNLIKELY(!mIsSimple)) {
- GLuint textureSlot = (*textureUnit)++;
- Caches::getInstance().activeTexture(textureSlot);
+void SkiaGradientShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions&, const SkShader& shader) {
+ // SkShader::GradientInfo.fColorCount is an in/out parameter. As input, it tells asAGradient
+ // how much space has been allocated for fColors and fColorOffsets. 10 was chosen
+ // arbitrarily, but should be >= 2.
+ // As output, it tells the number of actual colors/offsets in the gradient.
+ const int COLOR_COUNT = 10;
+ SkAutoSTMalloc<COLOR_COUNT, SkColor> colorStorage(COLOR_COUNT);
+ SkAutoSTMalloc<COLOR_COUNT, SkScalar> positionStorage(COLOR_COUNT);
- Texture* texture = mCaches->gradientCache.get(mColors, mPositions, mCount);
+ SkShader::GradientInfo gradInfo;
+ gradInfo.fColorCount = COLOR_COUNT;
+ gradInfo.fColors = colorStorage.get();
+ gradInfo.fColorOffsets = positionStorage.get();
+
+ SkShader::GradientType gradType = shader.asAGradient(&gradInfo);
+
+ Program* program = caches->currentProgram;
+ if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) {
+ if (gradInfo.fColorCount > COLOR_COUNT) {
+ // There was not enough room in our arrays for all the colors and offsets. Try again,
+ // now that we know the true number of colors.
+ gradInfo.fColors = colorStorage.reset(gradInfo.fColorCount);
+ gradInfo.fColorOffsets = positionStorage.reset(gradInfo.fColorCount);
+
+ shader.asAGradient(&gradInfo);
+ }
+ GLuint textureSlot = (*textureUnit)++;
+ caches->activeTexture(textureSlot);
+
+#ifndef SK_SCALAR_IS_FLOAT
+ #error Need to convert gradInfo.fColorOffsets to float!
+#endif
+ Texture* texture = caches->gradientCache.get(gradInfo.fColors, gradInfo.fColorOffsets,
+ gradInfo.fColorCount);
// Uniforms
- bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
+ bindTexture(caches, texture, gTileModes[gradInfo.fTileMode], gTileModes[gradInfo.fTileMode]);
glUniform1i(program->getUniform("gradientSampler"), textureSlot);
} else {
- bindUniformColor(program->getUniform("startColor"), mColors[0]);
- bindUniformColor(program->getUniform("endColor"), mColors[1]);
+ bindUniformColor(program->getUniform("startColor"), gradInfo.fColors[0]);
+ bindUniformColor(program->getUniform("endColor"), gradInfo.fColors[1]);
}
- mCaches->dither.setupProgram(program, textureUnit);
+ caches->dither.setupProgram(program, textureUnit);
+
+ SkMatrix unitMatrix;
+ switch (gradType) {
+ case SkShader::kLinear_GradientType:
+ toUnitMatrix(gradInfo.fPoint, &unitMatrix);
+ break;
+ case SkShader::kRadial_GradientType:
+ toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY,
+ gradInfo.fRadius[0], &unitMatrix);
+ break;
+ case SkShader::kSweep_GradientType:
+ toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix);
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Invalid SkShader gradient type %d", gradType);
+ }
mat4 screenSpace;
- computeScreenSpaceMatrix(screenSpace, modelView);
+ computeScreenSpaceMatrix(screenSpace, unitMatrix, shader.getLocalMatrix(), modelViewMatrix);
glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
}
@@ -418,49 +434,39 @@
// Compose shader
///////////////////////////////////////////////////////////////////////////////
-SkiaComposeShader::SkiaComposeShader(SkiaShader* first, SkiaShader* second,
- SkXfermode::Mode mode, SkShader* key):
- SkiaShader(kCompose, key, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
- NULL, first->blend() || second->blend()),
- mFirst(first), mSecond(second), mMode(mode), mCleanup(false) {
-}
-
-SkiaComposeShader::~SkiaComposeShader() {
- if (mCleanup) {
- delete mFirst;
- delete mSecond;
+void SkiaComposeShader::describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ SkShader::ComposeRec rec;
+ if (!shader.asACompose(&rec)) {
+ LOG_ALWAYS_FATAL("SkiaComposeShader::describe called on the wrong shader type!");
}
-}
-
-SkiaShader* SkiaComposeShader::copy() {
- SkiaComposeShader* copy = new SkiaComposeShader();
- copy->copyFrom(*this);
- copy->mFirst = mFirst->copy();
- copy->mSecond = mSecond->copy();
- copy->mMode = mMode;
- copy->cleanup();
- return copy;
-}
-
-void SkiaComposeShader::describe(ProgramDescription& description, const Extensions& extensions) {
- mFirst->describe(description, extensions);
- mSecond->describe(description, extensions);
- if (mFirst->type() == kBitmap) {
+ SkiaShader::describe(caches, description, extensions, *rec.fShaderA);
+ SkiaShader::describe(caches, description, extensions, *rec.fShaderB);
+ if (SkiaShader::getType(*rec.fShaderA) == kBitmap_SkiaShaderType) {
description.isBitmapFirst = true;
}
- description.shadersMode = mMode;
+ if (!SkXfermode::AsMode(rec.fMode, &description.shadersMode)) {
+ // TODO: Support other modes.
+ description.shadersMode = SkXfermode::kSrcOver_Mode;
+ }
}
-void SkiaComposeShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot& snapshot, GLuint* textureUnit) {
+void SkiaComposeShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
+ SkShader::ComposeRec rec;
+ if (!shader.asACompose(&rec)) {
+ LOG_ALWAYS_FATAL("SkiaComposeShader::setupProgram called on the wrong shader type!");
+ }
+
// Apply this compose shader's local transform and pass it down to
// the child shaders. They will in turn apply their local transform
// to this matrix.
mat4 transform;
- computeScreenSpaceMatrix(transform, modelView);
+ computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(),
+ modelViewMatrix);
- mFirst->setupProgram(program, transform, snapshot, textureUnit);
- mSecond->setupProgram(program, transform, snapshot, textureUnit);
+ SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderA);
+ SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderB);
}
}; // namespace uirenderer
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 9f30257..034c3f6 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -28,249 +28,90 @@
#include "ProgramCache.h"
#include "TextureCache.h"
#include "GradientCache.h"
-#include "Snapshot.h"
namespace android {
namespace uirenderer {
class Caches;
-
-///////////////////////////////////////////////////////////////////////////////
-// Base shader
-///////////////////////////////////////////////////////////////////////////////
+class Layer;
/**
- * Represents a Skia shader. A shader will modify the GL context and active
- * program to recreate the original effect.
+ * Type of Skia shader in use.
*/
+enum SkiaShaderType {
+ kNone_SkiaShaderType,
+ kBitmap_SkiaShaderType,
+ kGradient_SkiaShaderType,
+ kCompose_SkiaShaderType,
+ kLayer_SkiaShaderType
+};
+
class SkiaShader {
public:
- /**
- * Type of Skia shader in use.
- */
- enum Type {
- kNone,
- kBitmap,
- kLinearGradient,
- kCircularGradient,
- kSweepGradient,
- kCompose
- };
+ static SkiaShaderType getType(const SkShader& shader);
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+};
- ANDROID_API SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
- SkShader::TileMode tileY, const SkMatrix* matrix, bool blend);
- virtual ~SkiaShader();
-
- virtual SkiaShader* copy() = 0;
- void copyFrom(const SkiaShader& shader);
-
- virtual void describe(ProgramDescription& description, const Extensions& extensions);
- virtual void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit);
-
- inline SkShader* getSkShader() {
- return mKey;
+class InvalidSkiaShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ // This shader is unsupported. Skip it.
+ }
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
+ // This shader is unsupported. Skip it.
}
- inline bool blend() const {
- return mBlend;
- }
-
- Type type() const {
- return mType;
- }
-
- virtual void setCaches(Caches& caches) {
- mCaches = &caches;
- }
-
- uint32_t getGenerationId() {
- return mGenerationId;
- }
-
- void setMatrix(const SkMatrix* matrix) {
- updateLocalMatrix(matrix);
- mGenerationId++;
- }
-
- void updateLocalMatrix(const SkMatrix* matrix) {
- if (matrix) {
- mat4 localMatrix(*matrix);
- mShaderMatrix.loadInverse(localMatrix);
- } else {
- mShaderMatrix.loadIdentity();
- }
- }
-
- void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView);
-
-protected:
- SkiaShader();
-
- /**
- * The appropriate texture unit must have been activated prior to invoking
- * this method.
- */
- inline void bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT);
-
- Type mType;
- SkShader* mKey;
- SkShader::TileMode mTileX;
- SkShader::TileMode mTileY;
- bool mBlend;
-
- Caches* mCaches;
-
- mat4 mUnitMatrix;
- mat4 mShaderMatrix;
-
-private:
- uint32_t mGenerationId;
-}; // struct SkiaShader
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Implementations
-///////////////////////////////////////////////////////////////////////////////
-
+};
/**
* A shader that draws a layer.
*/
-struct SkiaLayerShader: public SkiaShader {
- SkiaLayerShader(Layer* layer, const SkMatrix* matrix);
- SkiaShader* copy();
-
- void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit);
-
-private:
- SkiaLayerShader() {
- }
-
- Layer* mLayer;
-}; // struct SkiaLayerShader
+class SkiaLayerShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+}; // class SkiaLayerShader
/**
* A shader that draws a bitmap.
*/
-struct SkiaBitmapShader: public SkiaShader {
- ANDROID_API SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX,
- SkShader::TileMode tileY, SkMatrix* matrix, bool blend);
- SkiaShader* copy();
+class SkiaBitmapShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
- void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit);
-private:
- SkiaBitmapShader() : mBitmap(NULL), mTexture(NULL) {
- }
-
- SkBitmap* mBitmap;
- Texture* mTexture;
- GLenum mWrapS;
- GLenum mWrapT;
-}; // struct SkiaBitmapShader
+}; // class SkiaBitmapShader
/**
- * A shader that draws a linear gradient.
+ * A shader that draws one of three types of gradient, depending on shader param.
*/
-struct SkiaLinearGradientShader: public SkiaShader {
- ANDROID_API SkiaLinearGradientShader(float* bounds, uint32_t* colors, float* positions,
- int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
- ~SkiaLinearGradientShader();
- SkiaShader* copy();
-
- void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit);
-
-private:
- SkiaLinearGradientShader() {
- }
-
- bool mIsSimple;
- float* mBounds;
- uint32_t* mColors;
- float* mPositions;
- int mCount;
-}; // struct SkiaLinearGradientShader
-
-/**
- * A shader that draws a sweep gradient.
- */
-struct SkiaSweepGradientShader: public SkiaShader {
- ANDROID_API SkiaSweepGradientShader(float x, float y, uint32_t* colors, float* positions,
- int count, SkShader* key, SkMatrix* matrix, bool blend);
- ~SkiaSweepGradientShader();
- SkiaShader* copy();
-
- virtual void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit);
-
-protected:
- SkiaSweepGradientShader(Type type, uint32_t* colors, float* positions,
- int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
- SkiaSweepGradientShader() {
- }
-
- bool mIsSimple;
- uint32_t* mColors;
- float* mPositions;
- int mCount;
-}; // struct SkiaSweepGradientShader
-
-/**
- * A shader that draws a circular gradient.
- */
-struct SkiaCircularGradientShader: public SkiaSweepGradientShader {
- ANDROID_API SkiaCircularGradientShader(float x, float y, float radius, uint32_t* colors,
- float* positions, int count, SkShader* key,SkShader::TileMode tileMode,
- SkMatrix* matrix, bool blend);
- SkiaShader* copy();
-
- void describe(ProgramDescription& description, const Extensions& extensions);
-
-private:
- SkiaCircularGradientShader() {
- }
-}; // struct SkiaCircularGradientShader
+class SkiaGradientShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+};
/**
* A shader that draws two shaders, composited with an xfermode.
*/
-struct SkiaComposeShader: public SkiaShader {
- ANDROID_API SkiaComposeShader(SkiaShader* first, SkiaShader* second, SkXfermode::Mode mode,
- SkShader* key);
- ~SkiaComposeShader();
- SkiaShader* copy();
-
- void setCaches(Caches& caches) {
- SkiaShader::setCaches(caches);
- mFirst->setCaches(caches);
- mSecond->setCaches(caches);
- }
-
- void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit);
-
-private:
- SkiaComposeShader(): mCleanup(false) {
- }
-
- void cleanup() {
- mCleanup = true;
- }
-
- SkiaShader* mFirst;
- SkiaShader* mSecond;
- SkXfermode::Mode mMode;
-
- bool mCleanup;
-}; // struct SkiaComposeShader
+class SkiaComposeShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+}; // class SkiaComposeShader
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 34e2265..60b4b96 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -34,7 +34,7 @@
///////////////////////////////////////////////////////////////////////////////
TextureCache::TextureCache():
- mCache(LruCache<const SkBitmap*, Texture*>::kUnlimitedCapacity),
+ mCache(LruCache<const SkPixelRef*, Texture*>::kUnlimitedCapacity),
mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)),
mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE) {
char property[PROPERTY_VALUE_MAX];
@@ -58,7 +58,7 @@
}
TextureCache::TextureCache(uint32_t maxByteSize):
- mCache(LruCache<const SkBitmap*, Texture*>::kUnlimitedCapacity),
+ mCache(LruCache<const SkPixelRef*, Texture*>::kUnlimitedCapacity),
mSize(0), mMaxSize(maxByteSize) {
init();
}
@@ -103,7 +103,7 @@
// Callbacks
///////////////////////////////////////////////////////////////////////////////
-void TextureCache::operator()(const SkBitmap*&, Texture*& texture) {
+void TextureCache::operator()(const SkPixelRef*&, Texture*& texture) {
// This will be called already locked
if (texture) {
mSize -= texture->bitmapSize;
@@ -122,7 +122,7 @@
///////////////////////////////////////////////////////////////////////////////
void TextureCache::resetMarkInUse() {
- LruCache<const SkBitmap*, Texture*>::Iterator iter(mCache);
+ LruCache<const SkPixelRef*, Texture*>::Iterator iter(mCache);
while (iter.next()) {
iter.value()->isInUse = false;
}
@@ -140,7 +140,7 @@
// Returns a prepared Texture* that either is already in the cache or can fit
// in the cache (and is thus added to the cache)
Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap) {
- Texture* texture = mCache.get(bitmap);
+ Texture* texture = mCache.get(bitmap->pixelRef());
if (!texture) {
if (!canMakeTextureFromBitmap(bitmap)) {
@@ -170,7 +170,7 @@
if (mDebugEnabled) {
ALOGD("Texture created, size = %d", size);
}
- mCache.put(bitmap, texture);
+ mCache.put(bitmap->pixelRef(), texture);
}
} else if (!texture->isInUse && bitmap->getGenerationID() != texture->generation) {
// Texture was in the cache but is dirty, re-upload
@@ -218,7 +218,7 @@
}
void TextureCache::remove(const SkBitmap* bitmap) {
- mCache.remove(bitmap);
+ mCache.remove(bitmap->pixelRef());
}
void TextureCache::removeDeferred(const SkBitmap* bitmap) {
@@ -231,7 +231,7 @@
size_t count = mGarbage.size();
for (size_t i = 0; i < count; i++) {
const SkBitmap* bitmap = mGarbage.itemAt(i);
- mCache.remove(bitmap);
+ mCache.remove(bitmap->pixelRef());
delete bitmap;
}
mGarbage.clear();
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 48a10c2..e5b5c1a 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -49,7 +49,7 @@
* Any texture added to the cache causing the cache to grow beyond the maximum
* allowed size will also cause the oldest texture to be kicked out.
*/
-class TextureCache: public OnEntryRemoved<const SkBitmap*, Texture*> {
+class TextureCache: public OnEntryRemoved<const SkPixelRef*, Texture*> {
public:
TextureCache();
TextureCache(uint32_t maxByteSize);
@@ -59,7 +59,7 @@
* Used as a callback when an entry is removed from the cache.
* Do not invoke directly.
*/
- void operator()(const SkBitmap*& bitmap, Texture*& texture);
+ void operator()(const SkPixelRef*& pixelRef, Texture*& texture);
/**
* Resets all Textures to not be marked as in use
@@ -147,7 +147,7 @@
void init();
- LruCache<const SkBitmap*, Texture*> mCache;
+ LruCache<const SkPixelRef*, Texture*> mCache;
uint32_t mSize;
uint32_t mMaxSize;