Glop SkiaShader support
Change-Id: I894a0b62701bd02367ab970813e4c332147351a2
diff --git a/libs/hwui/FloatColor.h b/libs/hwui/FloatColor.h
index 803b9d4..b3bd5fd 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 10dbd5c..6eca468 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 @@
class Program;
class RoundRectClipState;
+class Texture;
/*
* Enumerates optional vertex attributes
@@ -89,11 +92,6 @@
bool colorEnabled;
FloatColor color;
- /* TODO
- union shader {
- //...
- }; TODO
- */
ProgramDescription::ColorFilterMode filterMode;
union Filter {
struct Matrix {
@@ -102,6 +100,8 @@
} matrix;
FloatColor color;
} filter;
+
+ SkiaShaderData skiaShaderData;
} fill;
struct Transform {
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 91e0f89..bdc5c5c2 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -39,7 +39,7 @@
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 @@
GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop)
: mRenderState(renderState)
, mCaches(caches)
+ , mShader(nullptr)
, mOutGlop(outGlop) {
mStageFlags = kInitialStage;
}
@@ -192,12 +193,7 @@
}
}
}
-
- 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 @@
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 d724041..657e642 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 @@
ProgramDescription mDescription;
RenderState& mRenderState;
Caches& mCaches;
+ const SkShader* mShader;
Glop* mOutGlop;
};
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index a00a2bc..4761ab4 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -63,20 +63,6 @@
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::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::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 @@
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 @@
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 @@
return;
}
- if (USE_GLOPS && !paint->getShader()) {
+ if (USE_GLOPS) {
Glop glop;
GlopBuilder aBuilder(mRenderState, mCaches, &glop);
aBuilder.setMeshTexturedUnitQuad(nullptr, true)
@@ -3274,7 +3260,7 @@
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::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 9c929da..81531e8 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 @@
// 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 @@
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 @@
}
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 @@
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 e110ca5..2962441c 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 @@
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 fd3845d..11d0c4b 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 e35327b..b64dbdc 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -266,7 +266,7 @@
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 @@
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 eae73a9..5ca9083 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; \