SkiaShader.cpp revision d1ad5e62fda248c6d185cde3cb6d9f01a223066c
106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy/*
206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy * Copyright (C) 2010 The Android Open Source Project
306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy *
406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy * you may not use this file except in compliance with the License.
606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy * You may obtain a copy of the License at
706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy *
806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy *
1006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy * Unless required by applicable law or agreed to in writing, software
1106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
1206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy * See the License for the specific language governing permissions and
1406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy * limitations under the License.
1506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy */
1606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
1706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#define LOG_TAG "OpenGLRenderer"
1806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
1906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#include <utils/Log.h>
2006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
2106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#include <SkMatrix.h>
2206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
23a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy#include "Caches.h"
24d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III#include "Layer.h"
25d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III#include "Matrix.h"
2606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#include "SkiaShader.h"
2706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#include "Texture.h"
2806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
2906f96e2652e4855b6520ad9dd70583677605b79aRomain Guynamespace android {
3006f96e2652e4855b6520ad9dd70583677605b79aRomain Guynamespace uirenderer {
3106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
3206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
3306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Support
3406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
3506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
3606f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic const GLint gTileModes[] = {
3706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_CLAMP_TO_EDGE,   // == SkShader::kClamp_TileMode
3806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_REPEAT,          // == SkShader::kRepeat_Mode
3906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_MIRRORED_REPEAT  // == SkShader::kMirror_TileMode
4006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy};
4106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
4242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy/**
4342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy * This function does not work for n == 0.
4442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy */
4542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guystatic inline bool isPowerOfTwo(unsigned int n) {
4642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    return !(n & (n - 1));
4742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy}
4842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
4942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guystatic inline void bindUniformColor(int slot, uint32_t color) {
50d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy    const float a = ((color >> 24) & 0xff) / 255.0f;
5142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    glUniform4f(slot,
52d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy            a * ((color >> 16) & 0xff) / 255.0f,
53d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy            a * ((color >>  8) & 0xff) / 255.0f,
54d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy            a * ((color      ) & 0xff) / 255.0f,
55d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy            a);
5642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy}
5742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
58d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIstatic inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) {
59d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    caches->bindTexture(texture->id);
60d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    texture->setWrapST(wrapS, wrapT);
6124c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy}
6224c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
63d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III/**
64d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III * Compute the matrix to transform to screen space.
65d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III * @param screenSpace Output param for the computed matrix.
66d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III * @param unitMatrix The unit matrix for gradient shaders, as returned by SkShader::asAGradient,
67d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III *      or identity.
68d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III * @param localMatrix Local matrix, as returned by SkShader::getLocalMatrix().
69d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III * @param modelViewMatrix Model view matrix, as supplied by the OpenGLRenderer.
70d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III */
71d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIstatic void computeScreenSpaceMatrix(mat4& screenSpace, const SkMatrix& unitMatrix,
72d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const SkMatrix& localMatrix, const mat4& modelViewMatrix) {
73d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    mat4 shaderMatrix;
74d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // uses implicit construction
75d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    shaderMatrix.loadInverse(localMatrix);
76d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // again, uses implicit construction
77d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    screenSpace.loadMultiply(unitMatrix, shaderMatrix);
78d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    screenSpace.multiply(modelViewMatrix);
79d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III}
80d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
81d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III// Returns true if one is a bitmap and the other is a gradient
82d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIstatic bool bitmapAndGradient(SkiaShaderType type1, SkiaShaderType type2) {
83d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    return (type1 == kBitmap_SkiaShaderType && type2 == kGradient_SkiaShaderType)
84d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            || (type2 == kBitmap_SkiaShaderType && type1 == kGradient_SkiaShaderType);
85d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III}
86d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
87d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIISkiaShaderType SkiaShader::getType(const SkShader& shader) {
88d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // First check for a gradient shader.
89d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    switch (shader.asAGradient(NULL)) {
90d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kNone_GradientType:
91d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            // Not a gradient shader. Fall through to check for other types.
92d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            break;
93d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kLinear_GradientType:
94d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kRadial_GradientType:
95d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kSweep_GradientType:
96d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            return kGradient_SkiaShaderType;
97d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        default:
98d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            // This is a Skia gradient that has no SkiaShader equivalent. Return None to skip.
99d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            return kNone_SkiaShaderType;
100d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
1018aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy
102d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // The shader is not a gradient. Check for a bitmap shader.
103d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (shader.asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType) {
104d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        return kBitmap_SkiaShaderType;
105d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
10606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
107d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // Check for a ComposeShader.
108d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::ComposeRec rec;
109d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (shader.asACompose(&rec)) {
110d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const SkiaShaderType shaderAType = getType(*rec.fShaderA);
111d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const SkiaShaderType shaderBType = getType(*rec.fShaderB);
112d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
113d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        // Compose is only supported if one is a bitmap and the other is a
114d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        // gradient. Otherwise, return None to skip.
115d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (!bitmapAndGradient(shaderAType, shaderBType)) {
116d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            return kNone_SkiaShaderType;
117d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        }
118d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        return kCompose_SkiaShaderType;
119d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
12006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
121d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (shader.asACustomShader(NULL)) {
122d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        return kLayer_SkiaShaderType;
123d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
12406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
125d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    return kNone_SkiaShaderType;
12606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
12706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
128d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIItypedef void (*describeProc)(Caches* caches, ProgramDescription& description,
129d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const Extensions& extensions, const SkShader& shader);
130d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
131d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIdescribeProc gDescribeProc[] = {
132d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    InvalidSkiaShader::describe,
133d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaBitmapShader::describe,
134d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaGradientShader::describe,
135d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaComposeShader::describe,
136d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaLayerShader::describe,
137d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III};
138d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
139d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIItypedef void (*setupProgramProc)(Caches* caches, const mat4& modelViewMatrix,
140d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
141d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
142d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIsetupProgramProc gSetupProgramProc[] = {
143d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    InvalidSkiaShader::setupProgram,
144d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaBitmapShader::setupProgram,
145d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaGradientShader::setupProgram,
146d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaComposeShader::setupProgram,
147d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaLayerShader::setupProgram,
148d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III};
149d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
150d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaShader::describe(Caches* caches, ProgramDescription& description,
151d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const Extensions& extensions, const SkShader& shader) {
152d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gDescribeProc[getType(shader)](caches, description, extensions, shader);
15306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
15406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
155d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
156d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
157d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
158d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gSetupProgramProc[getType(shader)](caches, modelViewMatrix, textureUnit, extensions, shader);
15914830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy}
16014830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
16106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
1623f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik// Layer shader
1633f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik///////////////////////////////////////////////////////////////////////////////
1643f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik
165d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaLayerShader::describe(Caches*, ProgramDescription& description,
166d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const Extensions&, const SkShader& shader) {
1673f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    description.hasBitmap = true;
1683f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik}
1693f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik
170d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaLayerShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
171d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        GLuint* textureUnit, const Extensions&, const SkShader& shader) {
172d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    Layer* layer;
173d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) {
174d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        LOG_ALWAYS_FATAL("SkiaLayerShader::setupProgram called on the wrong type of shader!");
175d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
176d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
1773f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    GLuint textureSlot = (*textureUnit)++;
178d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    caches->activeTexture(textureSlot);
1793f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik
180d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    const float width = layer->getWidth();
181d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    const float height = layer->getHeight();
1823f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik
1833f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    mat4 textureTransform;
184d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
185d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            modelViewMatrix);
186d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
1873f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik
1883f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    // Uniforms
189d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    layer->bindTexture();
190d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    layer->setWrap(GL_CLAMP_TO_EDGE);
191d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    layer->setFilter(GL_LINEAR);
1923f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik
193d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    Program* program = caches->currentProgram;
1943f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
1953f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
1963f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik            GL_FALSE, &textureTransform.data[0]);
1973f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height);
1983f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik}
1993f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik
2003f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik///////////////////////////////////////////////////////////////////////////////
20106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Bitmap shader
20206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
20306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
204d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIstruct BitmapShaderInfo {
205d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    float width;
206d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    float height;
207d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    GLenum wrapS;
208d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    GLenum wrapT;
209d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    Texture* texture;
210d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III};
21124c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
212d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIstatic bool bitmapShaderHelper(Caches* caches, ProgramDescription* description,
213d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        BitmapShaderInfo* shaderInfo,
214d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const Extensions& extensions,
215d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const SkBitmap& bitmap, SkShader::TileMode tileModes[2]) {
216d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    Texture* texture = caches->textureCache.get(&bitmap);
217d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (!texture) return false;
21806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
21906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float width = texture->width;
22006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float height = texture->height;
221d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    GLenum wrapS, wrapT;
22206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
223d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (description) {
224d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        description->hasBitmap = true;
225d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
22606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // The driver does not support non-power of two mirrored/repeated
22706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // textures, so do it ourselves
22861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy    if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
229d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            (tileModes[0] != SkShader::kClamp_TileMode ||
230d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III             tileModes[1] != SkShader::kClamp_TileMode)) {
231d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (description) {
232d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            description->isBitmapNpot = true;
233d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            description->bitmapWrapS = gTileModes[tileModes[0]];
234d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            description->bitmapWrapT = gTileModes[tileModes[1]];
235d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        }
236d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        wrapS = GL_CLAMP_TO_EDGE;
237d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        wrapT = GL_CLAMP_TO_EDGE;
23829d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy    } else {
239d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        wrapS = gTileModes[tileModes[0]];
240d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        wrapT = gTileModes[tileModes[1]];
241d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
242d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
243d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (shaderInfo) {
244d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        shaderInfo->width = width;
245d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        shaderInfo->height = height;
246d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        shaderInfo->wrapS = wrapS;
247d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        shaderInfo->wrapT = wrapT;
248d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        shaderInfo->texture = texture;
24906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
250d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    return true;
25106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
25206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
253d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaBitmapShader::describe(Caches* caches, ProgramDescription& description,
254d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const Extensions& extensions, const SkShader& shader) {
255d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkBitmap bitmap;
256d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::TileMode xy[2];
257d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (shader.asABitmap(&bitmap, NULL, xy) != SkShader::kDefault_BitmapType) {
258d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        LOG_ALWAYS_FATAL("SkiaBitmapShader::describe called with a different kind of shader!");
259d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
260d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    bitmapShaderHelper(caches, &description, NULL, extensions, bitmap, xy);
261d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III}
262d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
263d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaBitmapShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
264d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
265d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkBitmap bitmap;
266d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::TileMode xy[2];
267d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (shader.asABitmap(&bitmap, NULL, xy) != SkShader::kDefault_BitmapType) {
268d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        LOG_ALWAYS_FATAL("SkiaBitmapShader::setupProgram called with a different kind of shader!");
269d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
270d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
27106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    GLuint textureSlot = (*textureUnit)++;
272a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy    Caches::getInstance().activeTexture(textureSlot);
2739cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy
274d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    BitmapShaderInfo shaderInfo;
275d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (!bitmapShaderHelper(caches, NULL, &shaderInfo, extensions, bitmap, xy)) {
276d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        return;
277d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
27806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
279d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    Program* program = caches->currentProgram;
280d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    Texture* texture = shaderInfo.texture;
281d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
282d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    const AutoTexture autoCleanup(texture);
28306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
28406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mat4 textureTransform;
285d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
286d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            modelViewMatrix);
28706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
28806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // Uniforms
289d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    bindTexture(caches, texture, shaderInfo.wrapS, shaderInfo.wrapT);
290d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy    texture->setFilter(GL_LINEAR);
291e3c26851dc315b730ea0fe5ef35bb1db81f6d675Romain Guy
29206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
29306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
29406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy            GL_FALSE, &textureTransform.data[0]);
295d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    glUniform2f(program->getUniform("textureDimension"), 1.0f / shaderInfo.width,
296d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            1.0f / shaderInfo.height);
29706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
29806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
29906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
30006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Linear gradient shader
30106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
30206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
303e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guystatic void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
304e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    SkVector vec = pts[1] - pts[0];
305e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    const float mag = vec.length();
306e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    const float inv = mag ? 1.0f / mag : 0;
307e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
308e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    vec.scale(inv);
309e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY);
310e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->postTranslate(-pts[0].fX, -pts[0].fY);
311e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->postScale(inv, inv);
312e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy}
313e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
31406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
315ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy// Circular gradient shader
316ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy///////////////////////////////////////////////////////////////////////////////
317ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
31814830948d02f768c41b97b7a8d15e1b3cab78267Romain Guystatic void toCircularUnitMatrix(const float x, const float y, const float radius,
31914830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy        SkMatrix* matrix) {
32014830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    const float inv = 1.0f / radius;
32114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    matrix->setTranslate(-x, -y);
32214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    matrix->postScale(inv, inv);
32314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy}
32414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
325ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy///////////////////////////////////////////////////////////////////////////////
326ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy// Sweep gradient shader
327ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy///////////////////////////////////////////////////////////////////////////////
328ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
32914830948d02f768c41b97b7a8d15e1b3cab78267Romain Guystatic void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) {
33014830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    matrix->setTranslate(-x, -y);
33114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy}
33214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
333d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III///////////////////////////////////////////////////////////////////////////////
334d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III// Common gradient code
335d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III///////////////////////////////////////////////////////////////////////////////
33624c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
337d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIstatic bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) {
338d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode;
339d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III}
340d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
341d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaGradientShader::describe(Caches*, ProgramDescription& description,
342d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const Extensions& extensions, const SkShader& shader) {
343d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::GradientInfo gradInfo;
344d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gradInfo.fColorCount = 0;
345d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gradInfo.fColors = NULL;
346d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gradInfo.fColorOffsets = NULL;
347d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
348d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    switch (shader.asAGradient(&gradInfo)) {
349d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kLinear_GradientType:
350d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            description.gradientType = ProgramDescription::kGradientLinear;
351d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            break;
352d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kRadial_GradientType:
353d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            description.gradientType = ProgramDescription::kGradientCircular;
354d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            break;
355d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kSweep_GradientType:
356d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            description.gradientType = ProgramDescription::kGradientSweep;
357d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            break;
358d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        default:
359d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            // Do nothing. This shader is unsupported.
360d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            return;
361d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
362ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    description.hasGradient = true;
363d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    description.isSimpleGradient = isSimpleGradient(gradInfo);
364d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III}
365d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
366d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaGradientShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
367d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        GLuint* textureUnit, const Extensions&, const SkShader& shader) {
368d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // SkShader::GradientInfo.fColorCount is an in/out parameter. As input, it tells asAGradient
369d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // how much space has been allocated for fColors and fColorOffsets.  10 was chosen
370d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // arbitrarily, but should be >= 2.
371d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // As output, it tells the number of actual colors/offsets in the gradient.
372d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    const int COLOR_COUNT = 10;
373d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkAutoSTMalloc<COLOR_COUNT, SkColor> colorStorage(COLOR_COUNT);
374d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkAutoSTMalloc<COLOR_COUNT, SkScalar> positionStorage(COLOR_COUNT);
375d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
376d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::GradientInfo gradInfo;
377d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gradInfo.fColorCount = COLOR_COUNT;
378d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gradInfo.fColors = colorStorage.get();
379d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gradInfo.fColorOffsets = positionStorage.get();
380d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
381d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::GradientType gradType = shader.asAGradient(&gradInfo);
382d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
383d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    Program* program = caches->currentProgram;
384d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) {
385d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (gradInfo.fColorCount > COLOR_COUNT) {
386d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            // There was not enough room in our arrays for all the colors and offsets. Try again,
387d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            // now that we know the true number of colors.
388d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            gradInfo.fColors = colorStorage.reset(gradInfo.fColorCount);
389d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            gradInfo.fColorOffsets = positionStorage.reset(gradInfo.fColorCount);
390d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
391d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            shader.asAGradient(&gradInfo);
392d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        }
39342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        GLuint textureSlot = (*textureUnit)++;
394d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        caches->activeTexture(textureSlot);
395ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
396d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III#ifndef SK_SCALAR_IS_FLOAT
397d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    #error Need to convert gradInfo.fColorOffsets to float!
398d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III#endif
399d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        Texture* texture = caches->gradientCache.get(gradInfo.fColors, gradInfo.fColorOffsets,
400d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                gradInfo.fColorCount);
40142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
40242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        // Uniforms
403d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        bindTexture(caches, texture, gTileModes[gradInfo.fTileMode], gTileModes[gradInfo.fTileMode]);
40442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        glUniform1i(program->getUniform("gradientSampler"), textureSlot);
40542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    } else {
406d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        bindUniformColor(program->getUniform("startColor"), gradInfo.fColors[0]);
407d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        bindUniformColor(program->getUniform("endColor"), gradInfo.fColors[1]);
40842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    }
409ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
410d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    caches->dither.setupProgram(program, textureUnit);
411d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
412d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkMatrix unitMatrix;
413d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    switch (gradType) {
414d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kLinear_GradientType:
415d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            toUnitMatrix(gradInfo.fPoint, &unitMatrix);
416d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            break;
417d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kRadial_GradientType:
418d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY,
419d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                    gradInfo.fRadius[0], &unitMatrix);
420d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            break;
421d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kSweep_GradientType:
422d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix);
423d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            break;
424d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        default:
425d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            LOG_ALWAYS_FATAL("Invalid SkShader gradient type %d", gradType);
426d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
427211efea7376371ee755edd2ad03e83ef6eea464eRomain Guy
42814830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    mat4 screenSpace;
429d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    computeScreenSpaceMatrix(screenSpace, unitMatrix, shader.getLocalMatrix(), modelViewMatrix);
430ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
431ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
432ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
433ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy///////////////////////////////////////////////////////////////////////////////
43406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Compose shader
43506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
43606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
437d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaComposeShader::describe(Caches* caches, ProgramDescription& description,
438d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const Extensions& extensions, const SkShader& shader) {
439d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::ComposeRec rec;
440d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (!shader.asACompose(&rec)) {
441d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        LOG_ALWAYS_FATAL("SkiaComposeShader::describe called on the wrong shader type!");
44243ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    }
443d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaShader::describe(caches, description, extensions, *rec.fShaderA);
444d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaShader::describe(caches, description, extensions, *rec.fShaderB);
445d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (SkiaShader::getType(*rec.fShaderA) == kBitmap_SkiaShaderType) {
44606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        description.isBitmapFirst = true;
44706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
448d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (!SkXfermode::AsMode(rec.fMode, &description.shadersMode)) {
449d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        // TODO: Support other modes.
450d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        description.shadersMode = SkXfermode::kSrcOver_Mode;
451d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
45206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
45306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
454d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaComposeShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
455d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
456d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::ComposeRec rec;
457d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (!shader.asACompose(&rec)) {
458d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        LOG_ALWAYS_FATAL("SkiaComposeShader::setupProgram called on the wrong shader type!");
459d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
460d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
461d4289922ce772ed8e170a27d1c9521672b315698Romain Guy    // Apply this compose shader's local transform and pass it down to
462d4289922ce772ed8e170a27d1c9521672b315698Romain Guy    // the child shaders. They will in turn apply their local transform
463d4289922ce772ed8e170a27d1c9521672b315698Romain Guy    // to this matrix.
464d4289922ce772ed8e170a27d1c9521672b315698Romain Guy    mat4 transform;
465d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(),
466d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            modelViewMatrix);
467d4289922ce772ed8e170a27d1c9521672b315698Romain Guy
468d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderA);
469d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderB);
47006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
47106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
47206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}; // namespace uirenderer
47306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}; // namespace android
474