diff options
| -rw-r--r-- | libs/hwui/FloatColor.h | 9 | ||||
| -rw-r--r-- | libs/hwui/Glop.h | 10 | ||||
| -rw-r--r-- | libs/hwui/GlopBuilder.cpp | 15 | ||||
| -rw-r--r-- | libs/hwui/GlopBuilder.h | 4 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 28 | ||||
| -rw-r--r-- | libs/hwui/SkiaShader.cpp | 301 | ||||
| -rw-r--r-- | libs/hwui/SkiaShader.h | 66 | ||||
| -rw-r--r-- | libs/hwui/Vertex.h | 2 | ||||
| -rw-r--r-- | libs/hwui/renderstate/RenderState.cpp | 5 | ||||
| -rw-r--r-- | libs/hwui/utils/Macros.h | 2 |
10 files changed, 389 insertions, 53 deletions
diff --git a/libs/hwui/FloatColor.h b/libs/hwui/FloatColor.h index 803b9d420869..b3bd5fd428c9 100644 --- a/libs/hwui/FloatColor.h +++ b/libs/hwui/FloatColor.h @@ -18,10 +18,19 @@ #include "utils/Macros.h" +#include <stdint.h> + namespace android { namespace uirenderer { struct FloatColor { + void set(uint32_t color) { + a = ((color >> 24) & 0xff) / 255.0f; + r = a * ((color >> 16) & 0xff) / 255.0f; + g = a * ((color >> 8) & 0xff) / 255.0f; + b = a * ((color ) & 0xff) / 255.0f; + } + float r; float g; float b; diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h index 10dbd5c7353b..6eca468ded8a 100644 --- a/libs/hwui/Glop.h +++ b/libs/hwui/Glop.h @@ -19,7 +19,9 @@ #include "FloatColor.h" #include "Matrix.h" +#include "Program.h" #include "Rect.h" +#include "SkiaShader.h" #include "utils/Macros.h" #include <GLES2/gl2.h> @@ -31,6 +33,7 @@ namespace uirenderer { class Program; class RoundRectClipState; +class Texture; /* * Enumerates optional vertex attributes @@ -89,11 +92,6 @@ struct Glop { bool colorEnabled; FloatColor color; - /* TODO - union shader { - //... - }; TODO - */ ProgramDescription::ColorFilterMode filterMode; union Filter { struct Matrix { @@ -102,6 +100,8 @@ struct Glop { } matrix; FloatColor color; } filter; + + SkiaShaderData skiaShaderData; } fill; struct Transform { diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index 91e0f8916f6e..bdc5c5c27552 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -39,7 +39,7 @@ namespace uirenderer { LOG_ALWAYS_FATAL_IF((mStageFlags & (requiredFlags)) != (requiredFlags), \ "not prepared for current stage") -static void setUnitQuadTextureCoords(Rect uvs, TextureVertex* quadVertex) {; +static void setUnitQuadTextureCoords(Rect uvs, TextureVertex* quadVertex) { TextureVertex::setUV(quadVertex++, uvs.left, uvs.top); TextureVertex::setUV(quadVertex++, uvs.right, uvs.top); TextureVertex::setUV(quadVertex++, uvs.left, uvs.bottom); @@ -49,6 +49,7 @@ static void setUnitQuadTextureCoords(Rect uvs, TextureVertex* quadVertex) {; GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop) : mRenderState(renderState) , mCaches(caches) + , mShader(nullptr) , mOutGlop(outGlop) { mStageFlags = kInitialStage; } @@ -192,12 +193,7 @@ void GlopBuilder::setFill(int color, float alphaScale, SkXfermode::Mode mode, } } } - - if (shader) { - SkiaShader::describe(&mCaches, mDescription, mCaches.extensions(), *shader); - // TODO: store shader data - LOG_ALWAYS_FATAL("shaders not yet supported"); - } + mShader = shader; // shader resolved in ::build() if (colorFilter) { SkColor color; @@ -394,6 +390,11 @@ GlopBuilder& GlopBuilder::setRoundRectClipState(const RoundRectClipState* roundR void GlopBuilder::build() { REQUIRE_STAGES(kAllStages); + // serialize shader info into ShaderData + GLuint textureUnit = mOutGlop->fill.texture ? 1 : 0; + SkiaShader::store(mCaches, mShader, mOutGlop->transform.modelView, + &textureUnit, &mDescription, &(mOutGlop->fill.skiaShaderData)); + mOutGlop->fill.program = mCaches.programCache.get(mDescription); mOutGlop->transform.canvas.mapRect(mOutGlop->bounds); diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h index d724041c6635..657e6423fa75 100644 --- a/libs/hwui/GlopBuilder.h +++ b/libs/hwui/GlopBuilder.h @@ -21,16 +21,17 @@ #include "utils/Macros.h" class SkPaint; +class SkShader; namespace android { namespace uirenderer { class Caches; -struct Glop; class Matrix4; class RenderState; class Texture; class VertexBuffer; +struct Glop; class GlopBuilder { PREVENT_COPY_AND_ASSIGN(GlopBuilder); @@ -74,6 +75,7 @@ private: ProgramDescription mDescription; RenderState& mRenderState; Caches& mCaches; + const SkShader* mShader; Glop* mOutGlop; }; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index a00a2bc1ff47..4761ab4d475a 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -63,20 +63,6 @@ namespace android { namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// -// Globals -/////////////////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////////////////// -// Functions -/////////////////////////////////////////////////////////////////////////////// - -template<typename T> -static inline T min(T a, T b) { - return a < b ? a : b; -} - -/////////////////////////////////////////////////////////////////////////////// // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// @@ -1199,7 +1185,7 @@ void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) { void OpenGLRenderer::issueIndexedQuadDraw(Vertex* mesh, GLsizei quadsCount) { GLsizei elementsCount = quadsCount * 6; while (elementsCount > 0) { - GLsizei drawCount = min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6); + GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6); setupDrawIndexedVertices(&mesh[0].x); glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, nullptr); @@ -1970,7 +1956,7 @@ void OpenGLRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t } void OpenGLRenderer::drawAlphaBitmap(Texture* texture, const SkPaint* paint) { - if (USE_GLOPS && (!paint || !paint->getShader())) { + if (USE_GLOPS) { Glop glop; GlopBuilder aBuilder(mRenderState, mCaches, &glop); aBuilder.setMeshTexturedUnitQuad(texture->uvMapper, true) @@ -2358,7 +2344,7 @@ void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY, return; } - if (USE_GLOPS && !paint->getShader()) { + if (USE_GLOPS) { Glop glop; GlopBuilder aBuilder(mRenderState, mCaches, &glop); bool fudgeOffset = displayFlags & kVertexBuffer_Offset; @@ -3052,7 +3038,7 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y) { GLsizei elementsCount = layer->meshElementCount; while (elementsCount > 0) { - GLsizei drawCount = min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6); + GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6); setupDrawMeshIndices(&mesh[0].x, &mesh[0].u); DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, @@ -3113,7 +3099,7 @@ void OpenGLRenderer::drawPathTexture(PathTexture* texture, return; } - if (USE_GLOPS && !paint->getShader()) { + if (USE_GLOPS) { Glop glop; GlopBuilder aBuilder(mRenderState, mCaches, &glop); aBuilder.setMeshTexturedUnitQuad(nullptr, true) @@ -3274,7 +3260,7 @@ void OpenGLRenderer::drawColorRects(const float* rects, int count, const SkPaint return; } - if (USE_GLOPS && !paint->getShader()) { + if (USE_GLOPS) { const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform(); Glop glop; GlopBuilder aBuilder(mRenderState, mCaches, &glop); @@ -3320,7 +3306,7 @@ void OpenGLRenderer::drawColorRects(const float* rects, int count, const SkPaint void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, const SkPaint* paint, bool ignoreTransform) { - if (USE_GLOPS && !paint->getShader()) { + if (USE_GLOPS) { const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform(); Glop glop; GlopBuilder aBuilder(mRenderState, mCaches, &glop); diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index 9c929daf6400..81531e83ef77 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -16,17 +16,17 @@ #define LOG_TAG "OpenGLRenderer" -#include <utils/Log.h> - -#include <SkMatrix.h> +#include "SkiaShader.h" #include "Caches.h" #include "Extensions.h" #include "Layer.h" #include "Matrix.h" -#include "SkiaShader.h" #include "Texture.h" +#include <SkMatrix.h> +#include <utils/Log.h> + namespace android { namespace uirenderer { @@ -34,7 +34,7 @@ namespace uirenderer { // Support /////////////////////////////////////////////////////////////////////////////// -static const GLint gTileModes[] = { +static const GLenum gTileModes[] = { GL_CLAMP_TO_EDGE, // == SkShader::kClamp_TileMode GL_REPEAT, // == SkShader::kRepeat_Mode GL_MIRRORED_REPEAT // == SkShader::kMirror_TileMode @@ -56,6 +56,10 @@ static inline void bindUniformColor(int slot, uint32_t color) { a); } +static inline void bindUniformColor(int slot, FloatColor color) { + glUniform4fv(slot, 1, reinterpret_cast<const float*>(&color)); +} + static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) { caches->textureState().bindTexture(texture->id); texture->setWrapST(wrapS, wrapT); @@ -270,7 +274,7 @@ void SkiaBitmapShader::setupProgram(Caches* caches, const mat4& modelViewMatrix, } GLuint textureSlot = (*textureUnit)++; - Caches::getInstance().textureState().activateTexture(textureSlot); + caches->textureState().activateTexture(textureSlot); BitmapShaderInfo shaderInfo; if (!bitmapShaderHelper(caches, nullptr, &shaderInfo, extensions, bitmap, xy)) { @@ -470,5 +474,290 @@ void SkiaComposeShader::setupProgram(Caches* caches, const mat4& modelViewMatrix SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderB); } +/////////////////////////////////////////////////////////////////////////////// +// Store / apply +/////////////////////////////////////////////////////////////////////////////// + +bool tryStoreGradient(Caches& caches, const SkShader& shader, const Matrix4 modelViewMatrix, + GLuint* textureUnit, ProgramDescription* description, + SkiaShaderData::GradientShaderData* outData) { + SkShader::GradientInfo gradInfo; + gradInfo.fColorCount = 0; + gradInfo.fColors = nullptr; + gradInfo.fColorOffsets = nullptr; + + SkMatrix unitMatrix; + switch (shader.asAGradient(&gradInfo)) { + case SkShader::kLinear_GradientType: + description->gradientType = ProgramDescription::kGradientLinear; + + toUnitMatrix(gradInfo.fPoint, &unitMatrix); + break; + case SkShader::kRadial_GradientType: + description->gradientType = ProgramDescription::kGradientCircular; + + toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, + gradInfo.fRadius[0], &unitMatrix); + break; + case SkShader::kSweep_GradientType: + description->gradientType = ProgramDescription::kGradientSweep; + + toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix); + break; + default: + // Do nothing. This shader is unsupported. + return false; + } + description->hasGradient = true; + description->isSimpleGradient = isSimpleGradient(gradInfo); + + computeScreenSpaceMatrix(outData->screenSpace, unitMatrix, + shader.getLocalMatrix(), modelViewMatrix); + + // re-query shader to get full color / offset data + std::unique_ptr<SkColor[]> colorStorage(new SkColor[gradInfo.fColorCount]); + std::unique_ptr<SkScalar[]> colorOffsets(new SkScalar[gradInfo.fColorCount]); + gradInfo.fColors = &colorStorage[0]; + gradInfo.fColorOffsets = &colorOffsets[0]; + shader.asAGradient(&gradInfo); + + if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) { + outData->gradientSampler = (*textureUnit)++; + +#ifndef SK_SCALAR_IS_FLOAT + #error Need to convert gradInfo.fColorOffsets to float! +#endif + outData->gradientTexture = caches.gradientCache.get( + gradInfo.fColors, gradInfo.fColorOffsets, gradInfo.fColorCount); + outData->wrapST = gTileModes[gradInfo.fTileMode]; + } else { + outData->gradientSampler = 0; + outData->gradientTexture = nullptr; + + outData->startColor.set(gradInfo.fColors[0]); + outData->endColor.set(gradInfo.fColors[1]); + } + + outData->ditherSampler = (*textureUnit)++; + return true; +} + +void applyGradient(Caches& caches, const SkiaShaderData::GradientShaderData& data) { + if (CC_UNLIKELY(data.gradientTexture)) { + caches.textureState().activateTexture(data.gradientSampler); + bindTexture(&caches, data.gradientTexture, data.wrapST, data.wrapST); + glUniform1i(caches.program().getUniform("gradientSampler"), data.gradientSampler); + } else { + bindUniformColor(caches.program().getUniform("startColor"), data.startColor); + bindUniformColor(caches.program().getUniform("endColor"), data.endColor); + } + + // TODO: remove sampler slot incrementing from dither.setupProgram, + // since this assignment of slots is done at store, not apply time + GLuint ditherSampler = data.ditherSampler; + caches.dither.setupProgram(caches.program(), &ditherSampler); + glUniformMatrix4fv(caches.program().getUniform("screenSpace"), 1, + GL_FALSE, &data.screenSpace.data[0]); +} + +bool tryStoreBitmap(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix, + GLuint* textureUnit, ProgramDescription* description, + SkiaShaderData::BitmapShaderData* outData) { + SkBitmap bitmap; + SkShader::TileMode xy[2]; + if (shader.asABitmap(&bitmap, nullptr, xy) != SkShader::kDefault_BitmapType) { + return false; + } + + outData->bitmapTexture = caches.textureCache.get(&bitmap); + if (!outData->bitmapTexture) return false; + + outData->bitmapSampler = (*textureUnit)++; + + const float width = outData->bitmapTexture->width; + const float height = outData->bitmapTexture->height; + + description->hasBitmap = true; + if (!caches.extensions().hasNPot() + && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) + && (xy[0] != SkShader::kClamp_TileMode || xy[1] != SkShader::kClamp_TileMode)) { + description->isBitmapNpot = true; + description->bitmapWrapS = gTileModes[xy[0]]; + description->bitmapWrapT = gTileModes[xy[1]]; + + outData->wrapS = GL_CLAMP_TO_EDGE; + outData->wrapT = GL_CLAMP_TO_EDGE; + } else { + outData->wrapS = gTileModes[xy[0]]; + outData->wrapT = gTileModes[xy[1]]; + } + + computeScreenSpaceMatrix(outData->textureTransform, SkMatrix::I(), shader.getLocalMatrix(), + modelViewMatrix); + outData->textureDimension[0] = 1.0f / width; + outData->textureDimension[1] = 1.0f / height; + + return true; +} + +void applyBitmap(Caches& caches, const SkiaShaderData::BitmapShaderData& data) { + caches.textureState().activateTexture(data.bitmapSampler); + bindTexture(&caches, data.bitmapTexture, data.wrapS, data.wrapT); + data.bitmapTexture->setFilter(GL_LINEAR); + + glUniform1i(caches.program().getUniform("bitmapSampler"), data.bitmapSampler); + glUniformMatrix4fv(caches.program().getUniform("textureTransform"), 1, GL_FALSE, + &data.textureTransform.data[0]); + glUniform2fv(caches.program().getUniform("textureDimension"), 1, &data.textureDimension[0]); +} + +SkiaShaderType getComposeSubType(const SkShader& shader) { + // First check for a gradient shader. + switch (shader.asAGradient(nullptr)) { + 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(nullptr, nullptr, nullptr) == SkShader::kDefault_BitmapType) { + return kBitmap_SkiaShaderType; + } + return kNone_SkiaShaderType; +} + +void storeCompose(Caches& caches, const SkShader& bitmapShader, const SkShader& gradientShader, + const Matrix4& modelViewMatrix, GLuint* textureUnit, + ProgramDescription* description, SkiaShaderData* outData) { + LOG_ALWAYS_FATAL_IF(!tryStoreBitmap(caches, bitmapShader, modelViewMatrix, + textureUnit, description, &outData->bitmapData), + "failed storing bitmap shader data"); + LOG_ALWAYS_FATAL_IF(!tryStoreGradient(caches, gradientShader, modelViewMatrix, + textureUnit, description, &outData->gradientData), + "failing storing gradient shader data"); +} + +bool tryStoreCompose(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix, + GLuint* textureUnit, ProgramDescription* description, + SkiaShaderData* outData) { + + SkShader::ComposeRec rec; + if (!shader.asACompose(&rec)) return false; + + const SkiaShaderType shaderAType = getComposeSubType(*rec.fShaderA); + const SkiaShaderType shaderBType = getComposeSubType(*rec.fShaderB); + + // check that type enum values are the 2 flags that compose the kCompose value + if ((shaderAType & shaderBType) != 0) return false; + if ((shaderAType | shaderBType) != kCompose_SkiaShaderType) return false; + + mat4 transform; + computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(), modelViewMatrix); + if (shaderAType == kBitmap_SkiaShaderType) { + description->isBitmapFirst = true; + storeCompose(caches, *rec.fShaderA, *rec.fShaderB, + transform, textureUnit, description, outData); + } else { + description->isBitmapFirst = false; + storeCompose(caches, *rec.fShaderB, *rec.fShaderA, + transform, textureUnit, description, outData); + } + if (!SkXfermode::AsMode(rec.fMode, &description->shadersMode)) { + // TODO: Support other modes. + description->shadersMode = SkXfermode::kSrcOver_Mode; + } + return true; +} + +bool tryStoreLayer(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix, + GLuint* textureUnit, ProgramDescription* description, + SkiaShaderData::LayerShaderData* outData) { + Layer* layer; + if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) { + return false; + } + + description->hasBitmap = true; + + outData->bitmapSampler = (*textureUnit)++; + + const float width = layer->getWidth(); + const float height = layer->getHeight(); + + computeScreenSpaceMatrix(outData->textureTransform, SkMatrix::I(), shader.getLocalMatrix(), + modelViewMatrix); + + outData->textureDimension[0] = 1.0f / width; + outData->textureDimension[1] = 1.0f / height; + return true; +} + +void applyLayer(Caches& caches, const SkiaShaderData::LayerShaderData& data) { + caches.textureState().activateTexture(data.bitmapSampler); + + data.layer->bindTexture(); + data.layer->setWrap(GL_CLAMP_TO_EDGE); + data.layer->setFilter(GL_LINEAR); + + glUniform1i(caches.program().getUniform("bitmapSampler"), data.bitmapSampler); + glUniformMatrix4fv(caches.program().getUniform("textureTransform"), 1, + GL_FALSE, &data.textureTransform.data[0]); + glUniform2fv(caches.program().getUniform("textureDimension"), 1, &data.textureDimension[0]); +} + +void SkiaShader::store(Caches& caches, const SkShader* shader, const Matrix4& modelViewMatrix, + GLuint* textureUnit, ProgramDescription* description, + SkiaShaderData* outData) { + if (!shader) { + outData->skiaShaderType = kNone_SkiaShaderType; + return; + } + + if (tryStoreGradient(caches, *shader, modelViewMatrix, + textureUnit, description, &outData->gradientData)) { + outData->skiaShaderType = kGradient_SkiaShaderType; + return; + } + + if (tryStoreBitmap(caches, *shader, modelViewMatrix, + textureUnit, description, &outData->bitmapData)) { + outData->skiaShaderType = kBitmap_SkiaShaderType; + return; + } + + if (tryStoreCompose(caches, *shader, modelViewMatrix, + textureUnit, description, outData)) { + outData->skiaShaderType = kCompose_SkiaShaderType; + return; + } + + if (tryStoreLayer(caches, *shader, modelViewMatrix, + textureUnit, description, &outData->layerData)) { + outData->skiaShaderType = kLayer_SkiaShaderType; + } +} + +void SkiaShader::apply(Caches& caches, const SkiaShaderData& data) { + if (!data.skiaShaderType) return; + + if (data.skiaShaderType & kGradient_SkiaShaderType) { + applyGradient(caches, data.gradientData); + } + if (data.skiaShaderType & kBitmap_SkiaShaderType) { + applyBitmap(caches, data.bitmapData); + } + + if (data.skiaShaderType == kLayer_SkiaShaderType) { + applyLayer(caches, data.layerData); + } +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h index e110ca57d09b..2962441c6da2 100644 --- a/libs/hwui/SkiaShader.h +++ b/libs/hwui/SkiaShader.h @@ -17,32 +17,72 @@ #ifndef ANDROID_HWUI_SKIA_SHADER_H #define ANDROID_HWUI_SKIA_SHADER_H -#include <SkShader.h> -#include <SkXfermode.h> +#include "FloatColor.h" +#include "Matrix.h" #include <GLES2/gl2.h> - +#include <SkShader.h> +#include <SkXfermode.h> #include <cutils/compiler.h> -#include "Matrix.h" - namespace android { namespace uirenderer { class Caches; class Extensions; class Layer; +class Texture; struct ProgramDescription; /** * Type of Skia shader in use. + * + * Note that kBitmap | kGradient = kCompose, since Compose implies + * both its component types are in use simultaneously. No other + * composition of multiple types is supported. */ enum SkiaShaderType { - kNone_SkiaShaderType, - kBitmap_SkiaShaderType, - kGradient_SkiaShaderType, - kCompose_SkiaShaderType, - kLayer_SkiaShaderType + kNone_SkiaShaderType = 0, + kBitmap_SkiaShaderType = 1, + kGradient_SkiaShaderType = 2, + kCompose_SkiaShaderType = kBitmap_SkiaShaderType | kGradient_SkiaShaderType, + kLayer_SkiaShaderType = 4, +}; + +struct SkiaShaderData { + SkiaShaderType skiaShaderType; + struct BitmapShaderData { + Texture* bitmapTexture; + GLuint bitmapSampler; + GLenum wrapS; + GLenum wrapT; + + Matrix4 textureTransform; + float textureDimension[2]; + } bitmapData; + struct GradientShaderData { + Matrix4 screenSpace; + GLuint ditherSampler; + + // simple gradient + FloatColor startColor; + FloatColor endColor; + + // complex gradient + Texture* gradientTexture; + GLuint gradientSampler; + GLenum wrapST; + + } gradientData; + struct LayerShaderData { + Layer* layer; + GLuint bitmapSampler; + GLenum wrapS; + GLenum wrapT; + + Matrix4 textureTransform; + float textureDimension[2]; + } layerData; }; class SkiaShader { @@ -52,6 +92,12 @@ public: const Extensions& extensions, const SkShader& shader); static void setupProgram(Caches* caches, const mat4& modelViewMatrix, GLuint* textureUnit, const Extensions& extensions, const SkShader& shader); + + // new SkiaShader interaction model - store into ShaderData, and apply to Caches/Program/GL + static void store(Caches& caches, const SkShader* shader, const Matrix4& modelViewMatrix, + GLuint* textureUnit, ProgramDescription* description, + SkiaShaderData* outData); + static void apply(Caches& caches, const SkiaShaderData& data); }; class InvalidSkiaShader { diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h index fd3845da5efb..11d0c4bef84f 100644 --- a/libs/hwui/Vertex.h +++ b/libs/hwui/Vertex.h @@ -21,8 +21,6 @@ #include "utils/Macros.h" -#include <type_traits> - namespace android { namespace uirenderer { diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp index e35327b583c8..b64dbdc83943 100644 --- a/libs/hwui/renderstate/RenderState.cpp +++ b/libs/hwui/renderstate/RenderState.cpp @@ -266,7 +266,7 @@ void RenderState::render(const Glop& glop) { meshState().bindIndicesBufferInternal(mesh.indexBufferObject); if (mesh.vertexFlags & kTextureCoord_Attrib) { - // TODO: to support shaders, increment texture unit + // glop.fill.texture always takes slot 0, shader samplers increment from there mCaches->textureState().activateTexture(0); if (glop.fill.textureClamp != GL_INVALID_ENUM) { @@ -294,6 +294,9 @@ void RenderState::render(const Glop& glop) { glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, kAlphaVertexStride, alphaCoords); } + // Shader uniforms + SkiaShader::apply(*mCaches, glop.fill.skiaShaderData); + // ------------------------------------ // ---------- GL state setup ---------- // ------------------------------------ diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h index eae73a963ae6..5ca9083aab87 100644 --- a/libs/hwui/utils/Macros.h +++ b/libs/hwui/utils/Macros.h @@ -16,6 +16,8 @@ #ifndef MACROS_H #define MACROS_H +#include <type_traits> + #define PREVENT_COPY_AND_ASSIGN(Type) \ private: \ Type(const Type&) = delete; \ |