diff options
author | Chris Craik <ccraik@google.com> | 2014-05-23 23:21:48 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-05-23 23:21:49 +0000 |
commit | cd3a8245489fa36c528b075efe99a147cf4f6785 (patch) | |
tree | 6631a48645caf9c8142fec9e1ad0fbac0ab9c371 /libs | |
parent | c1631fd8908c73b161797919c664edecc9d0c6c4 (diff) | |
parent | 0fa2bd699ab5539c0ce6b79eb6b4b681734b8bb5 (diff) | |
download | frameworks_base-cd3a8245489fa36c528b075efe99a147cf4f6785.zip frameworks_base-cd3a8245489fa36c528b075efe99a147cf4f6785.tar.gz frameworks_base-cd3a8245489fa36c528b075efe99a147cf4f6785.tar.bz2 |
Merge "DO NOT MERGE Inspect SkShader to determine hw shader." into lmp-preview-dev
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/Caches.h | 1 | ||||
-rw-r--r-- | libs/hwui/DeferredDisplayList.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/DisplayList.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/DisplayList.h | 2 | ||||
-rw-r--r-- | libs/hwui/DisplayListOp.h | 44 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 10 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.h | 19 | ||||
-rw-r--r-- | libs/hwui/FontRenderer.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 156 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 32 | ||||
-rw-r--r-- | libs/hwui/Renderer.h | 4 | ||||
-rw-r--r-- | libs/hwui/ResourceCache.cpp | 44 | ||||
-rw-r--r-- | libs/hwui/ResourceCache.h | 8 | ||||
-rw-r--r-- | libs/hwui/SkiaShader.cpp | 570 | ||||
-rw-r--r-- | libs/hwui/SkiaShader.h | 269 | ||||
-rw-r--r-- | libs/hwui/TextureCache.cpp | 16 | ||||
-rw-r--r-- | libs/hwui/TextureCache.h | 6 |
17 files changed, 488 insertions, 709 deletions
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 @@ public: 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 @@ public: */ 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 @@ void DisplayListData::cleanupResources() { 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 @@ void DisplayListData::cleanupResources() { 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 DisplayListRenderer; class OpenGLRenderer; class Rect; class Layer; -class SkiaShader; class ClipRectOp; class SaveLayerOp; @@ -127,7 +126,6 @@ public: 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 @@ protected: 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 @@ private: 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 @@ DisplayListRenderer::~DisplayListRenderer() { /////////////////////////////////////////////////////////////////////////////// DisplayListData* DisplayListRenderer::finishRecording() { - mShaderMap.clear(); mPaintMap.clear(); mRegionMap.clear(); mPathMap.clear(); @@ -394,15 +393,6 @@ status_t DisplayListRenderer::drawRects(const float* rects, int count, const SkP 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 @@ public: 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 @@ private: 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 @@ private: 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 @@ status_t TextSetupFunctor::operator ()(int what, void* data) { } } renderer->setupDrawColorFilter(paint->getColorFilter()); - renderer->setupDrawShader(); + renderer->setupDrawShader(paint->getShader()); renderer->setupDrawBlending(paint); renderer->setupDrawProgram(); renderer->setupDrawModelView(kModelViewMode_Translate, false, @@ -85,7 +85,7 @@ status_t TextSetupFunctor::operator ()(int what, void* data) { 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..71836dd 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 @@ void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) #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 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { 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 @@ void OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) { 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 @@ void OpenGLRenderer::accountForClear(SkXfermode::Mode mode) { } } +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 @@ void OpenGLRenderer::setupDrawBlending(const SkPaint* paint, bool blend, bool sw // 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::setupDrawModelView(ModelViewMode mode, bool offset, } } -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::setupDrawPureColorUniforms() { } } -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 @@ status_t OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, // 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 @@ status_t OpenGLRenderer::drawVertexBuffer(VertexBufferMode mode, 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 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text, 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 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text, 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 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text, 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 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) { } /////////////////////////////////////////////////////////////////////////////// -// 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 @@ void OpenGLRenderer::drawPathTexture(const PathTexture* texture, 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 @@ void OpenGLRenderer::drawPathTexture(const PathTexture* texture, 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 @@ status_t OpenGLRenderer::drawColorRects(const float* rects, int count, const SkP 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 @@ status_t OpenGLRenderer::drawColorRects(const float* rects, int count, const SkP 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 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot 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 @@ void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, f setupDrawAlpha8Color(color, alpha); } setupDrawColorFilter(getColorFilter(paint)); - setupDrawShader(); + setupDrawShader(getShader(paint)); setupDrawBlending(paint, true); setupDrawProgram(); if (!dirty) setupDrawDirtyRegionsDisabled(); @@ -3449,7 +3481,7 @@ void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, f 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 DeferredDisplayState; class RenderNode; class TextSetupFunctor; class VertexBuffer; -class SkiaShader; struct DrawModifiers { DrawModifiers() { @@ -70,7 +70,6 @@ struct DrawModifiers { memset(this, 0, sizeof(DrawModifiers)); } - SkiaShader* mShader; float mOverrideLayerAlpha; // Draw filters @@ -217,9 +216,6 @@ public: 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 @@ protected: } /** + * 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 @@ private: 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 @@ private: */ 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 RenderNode; class Layer; class Matrix4; class SkiaColorFilter; -class SkiaShader; class Patch; enum DrawOpMode { @@ -183,9 +182,6 @@ public: 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 @@ void ResourceCache::incrementRefcount(const SkPath* pathResource) { 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 @@ void ResourceCache::incrementRefcountLocked(const SkPath* pathResource) { 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 @@ void ResourceCache::decrementRefcount(const SkPath* pathResource) { 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 @@ void ResourceCache::decrementRefcountLocked(const SkPath* pathResource) { 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::destructorLocked(const SkBitmap* resource) { } } -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 @@ void ResourceCache::deleteResourceReferenceLocked(const void* resource, Resource } } 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 @@ namespace uirenderer { */ enum ResourceType { kBitmap, - kShader, kNinePatch, kPath, kLayer @@ -70,36 +68,30 @@ public: 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 @@ static inline void bindUniformColor(int slot, uint32_t color) { 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; +static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) { + caches->bindTexture(texture->id); + texture->setWrapST(wrapS, wrapT); } -SkiaShader::SkiaShader(): mCaches(NULL) { -} +/** + * 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; + } -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; -} + // The shader is not a gradient. Check for a bitmap shader. + if (shader.asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType) { + return kBitmap_SkiaShaderType; + } -SkiaShader::~SkiaShader() { -} + // 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; + } -void SkiaShader::describe(ProgramDescription& description, const Extensions& extensions) { -} + if (shader.asACustomShader(NULL)) { + return kLayer_SkiaShaderType; + } -void SkiaShader::setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, - GLuint* textureUnit) { + return kNone_SkiaShaderType; } -void SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) { - mCaches->bindTexture(texture->id); - texture->setWrapST(wrapS, wrapT); +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::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) { - screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix); - screenSpace.multiply(modelView); +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) { +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!"); + } + GLuint textureSlot = (*textureUnit)++; - Caches::getInstance().activeTexture(textureSlot); + caches->activeTexture(textureSlot); - const float width = mLayer->getWidth(); - const float height = mLayer->getHeight(); + 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 @@ void SkiaLayerShader::setupProgram(Program* program, const mat4& modelView, // 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); -} - -SkiaShader* SkiaBitmapShader::copy() { - SkiaBitmapShader* copy = new SkiaBitmapShader(); - copy->copyFrom(*this); - copy->mBitmap = mBitmap; - return copy; -} +struct BitmapShaderInfo { + float width; + float height; + GLenum wrapS; + GLenum wrapT; + Texture* texture; +}; -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; - const AutoTexture autoCleanup(texture); + BitmapShaderInfo shaderInfo; + if (!bitmapShaderHelper(caches, NULL, &shaderInfo, extensions, bitmap, xy)) { + return; + } - const float width = texture->width; - const float height = texture->height; + Program* program = caches->currentProgram; + Texture* texture = shaderInfo.texture; + + const AutoTexture autoCleanup(texture); 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 @@ static void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) { 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 @@ static void toCircularUnitMatrix(const float x, const float y, const float radiu 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 @@ static void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) { 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); - - updateLocalMatrix(matrix); - - mIsSimple = count == 2; -} - -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 - - 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; -} +/////////////////////////////////////////////////////////////////////////////// +// Common gradient code +/////////////////////////////////////////////////////////////////////////////// -void SkiaSweepGradientShader::describe(ProgramDescription& description, - const Extensions& extensions) { +static bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) { + return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode; +} + +void SkiaGradientShader::describe(Caches*, ProgramDescription& description, + const Extensions& extensions, const SkShader& shader) { + SkShader::GradientInfo gradInfo; + gradInfo.fColorCount = 0; + gradInfo.fColors = NULL; + gradInfo.fColorOffsets = NULL; + + 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; -} - -void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelView, - const Snapshot& snapshot, GLuint* textureUnit) { - if (CC_UNLIKELY(!mIsSimple)) { + description.isSimpleGradient = isSimpleGradient(gradInfo); +} + +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); + + 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::getInstance().activeTexture(textureSlot); + caches->activeTexture(textureSlot); - Texture* texture = mCaches->gradientCache.get(mColors, mPositions, mCount); +#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 @@ void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelVi // 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 - }; - - 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; - } - - 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++; + 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); +}; + +class InvalidSkiaShader { +public: + static void describe(Caches* caches, ProgramDescription& description, + const Extensions& extensions, const SkShader& shader) { + // This shader is unsupported. Skip it. } - - void updateLocalMatrix(const SkMatrix* matrix) { - if (matrix) { - mat4 localMatrix(*matrix); - mShaderMatrix.loadInverse(localMatrix); - } else { - mShaderMatrix.loadIdentity(); - } + static void setupProgram(Caches* caches, const mat4& modelViewMatrix, + GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) { + // This shader is unsupported. Skip it. } - 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(); - - 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 - -/** - * A shader that draws a linear gradient. - */ -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); +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); -private: - SkiaLinearGradientShader() { - } - bool mIsSimple; - float* mBounds; - uint32_t* mColors; - float* mPositions; - int mCount; -}; // struct SkiaLinearGradientShader +}; // class SkiaBitmapShader /** - * A shader that draws a sweep gradient. + * A shader that draws one of three types of gradient, depending on shader param. */ -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 @@ namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// 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(): } 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 @@ void TextureCache::setFlushRate(float flushRate) { // 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::operator()(const SkBitmap*&, Texture*& texture) { /////////////////////////////////////////////////////////////////////////////// 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 @@ bool TextureCache::canMakeTextureFromBitmap(const SkBitmap* bitmap) { // 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 @@ Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap) { 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 @@ Texture* TextureCache::getTransient(const SkBitmap* bitmap) { } void TextureCache::remove(const SkBitmap* bitmap) { - mCache.remove(bitmap); + mCache.remove(bitmap->pixelRef()); } void TextureCache::removeDeferred(const SkBitmap* bitmap) { @@ -231,7 +231,7 @@ void TextureCache::clearGarbage() { 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 @@ namespace uirenderer { * 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 @@ public: * 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 @@ private: void init(); - LruCache<const SkBitmap*, Texture*> mCache; + LruCache<const SkPixelRef*, Texture*> mCache; uint32_t mSize; uint32_t mMaxSize; |