SkiaShader.cpp revision 2dc236b2bae13b9a0ed9b3f7320502aecd7983b3
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"
242dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include "Extensions.h"
25d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III#include "Layer.h"
26d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III#include "Matrix.h"
2706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#include "SkiaShader.h"
2806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#include "Texture.h"
2906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
3006f96e2652e4855b6520ad9dd70583677605b79aRomain Guynamespace android {
3106f96e2652e4855b6520ad9dd70583677605b79aRomain Guynamespace uirenderer {
3206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
3306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
3406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Support
3506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
3606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
3706f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic const GLint gTileModes[] = {
3806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_CLAMP_TO_EDGE,   // == SkShader::kClamp_TileMode
3906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_REPEAT,          // == SkShader::kRepeat_Mode
4006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_MIRRORED_REPEAT  // == SkShader::kMirror_TileMode
4106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy};
4206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
4342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy/**
4442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy * This function does not work for n == 0.
4542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy */
4642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guystatic inline bool isPowerOfTwo(unsigned int n) {
4742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    return !(n & (n - 1));
4842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy}
4942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
5042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guystatic inline void bindUniformColor(int slot, uint32_t color) {
51d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy    const float a = ((color >> 24) & 0xff) / 255.0f;
5242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    glUniform4f(slot,
53d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy            a * ((color >> 16) & 0xff) / 255.0f,
54d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy            a * ((color >>  8) & 0xff) / 255.0f,
55d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy            a * ((color      ) & 0xff) / 255.0f,
56d679b57ef279239cf11bb6c9bd14fb99b07971c9Romain Guy            a);
5742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy}
5842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
59d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIstatic inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) {
60d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    caches->bindTexture(texture->id);
61d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    texture->setWrapST(wrapS, wrapT);
6224c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy}
6324c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
64d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III/**
65d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III * Compute the matrix to transform to screen space.
66d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III * @param screenSpace Output param for the computed matrix.
67d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III * @param unitMatrix The unit matrix for gradient shaders, as returned by SkShader::asAGradient,
68d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III *      or identity.
69d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III * @param localMatrix Local matrix, as returned by SkShader::getLocalMatrix().
70d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III * @param modelViewMatrix Model view matrix, as supplied by the OpenGLRenderer.
71d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III */
72d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIstatic void computeScreenSpaceMatrix(mat4& screenSpace, const SkMatrix& unitMatrix,
73d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const SkMatrix& localMatrix, const mat4& modelViewMatrix) {
74d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    mat4 shaderMatrix;
75d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // uses implicit construction
76d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    shaderMatrix.loadInverse(localMatrix);
77d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // again, uses implicit construction
78d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    screenSpace.loadMultiply(unitMatrix, shaderMatrix);
79d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    screenSpace.multiply(modelViewMatrix);
80d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III}
81d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
82d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III// Returns true if one is a bitmap and the other is a gradient
83d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIstatic bool bitmapAndGradient(SkiaShaderType type1, SkiaShaderType type2) {
84d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    return (type1 == kBitmap_SkiaShaderType && type2 == kGradient_SkiaShaderType)
85d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            || (type2 == kBitmap_SkiaShaderType && type1 == kGradient_SkiaShaderType);
86d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III}
87d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
88d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIISkiaShaderType SkiaShader::getType(const SkShader& shader) {
89d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // First check for a gradient shader.
90d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    switch (shader.asAGradient(NULL)) {
91d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kNone_GradientType:
92d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            // Not a gradient shader. Fall through to check for other types.
93d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            break;
94d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kLinear_GradientType:
95d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kRadial_GradientType:
96d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kSweep_GradientType:
97d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            return kGradient_SkiaShaderType;
98d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        default:
99d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            // This is a Skia gradient that has no SkiaShader equivalent. Return None to skip.
100d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            return kNone_SkiaShaderType;
101d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
1028aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy
103d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // The shader is not a gradient. Check for a bitmap shader.
104d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (shader.asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType) {
105d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        return kBitmap_SkiaShaderType;
106d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
10706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
108d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // Check for a ComposeShader.
109d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::ComposeRec rec;
110d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (shader.asACompose(&rec)) {
111d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const SkiaShaderType shaderAType = getType(*rec.fShaderA);
112d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const SkiaShaderType shaderBType = getType(*rec.fShaderB);
113d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
114d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        // Compose is only supported if one is a bitmap and the other is a
115d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        // gradient. Otherwise, return None to skip.
116d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (!bitmapAndGradient(shaderAType, shaderBType)) {
117d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            return kNone_SkiaShaderType;
118d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        }
119d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        return kCompose_SkiaShaderType;
120d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
12106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
122d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (shader.asACustomShader(NULL)) {
123d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        return kLayer_SkiaShaderType;
124d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
12506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
126d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    return kNone_SkiaShaderType;
12706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
12806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
129d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIItypedef void (*describeProc)(Caches* caches, ProgramDescription& description,
130d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const Extensions& extensions, const SkShader& shader);
131d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
132d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIdescribeProc gDescribeProc[] = {
133d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    InvalidSkiaShader::describe,
134d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaBitmapShader::describe,
135d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaGradientShader::describe,
136d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaComposeShader::describe,
137d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaLayerShader::describe,
138d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III};
139d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
140d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIItypedef void (*setupProgramProc)(Caches* caches, const mat4& modelViewMatrix,
141d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
142d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
143d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIsetupProgramProc gSetupProgramProc[] = {
144d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    InvalidSkiaShader::setupProgram,
145d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaBitmapShader::setupProgram,
146d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaGradientShader::setupProgram,
147d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaComposeShader::setupProgram,
148d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaLayerShader::setupProgram,
149d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III};
150d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
151d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaShader::describe(Caches* caches, ProgramDescription& description,
152d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const Extensions& extensions, const SkShader& shader) {
153d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gDescribeProc[getType(shader)](caches, description, extensions, shader);
15406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
15506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
156d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
157d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
158d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
159d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gSetupProgramProc[getType(shader)](caches, modelViewMatrix, textureUnit, extensions, shader);
16014830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy}
16114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
16206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
1633f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik// Layer shader
1643f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik///////////////////////////////////////////////////////////////////////////////
1653f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik
166d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaLayerShader::describe(Caches*, ProgramDescription& description,
167d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const Extensions&, const SkShader& shader) {
1683f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    description.hasBitmap = true;
1693f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik}
1703f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik
171d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaLayerShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
172d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        GLuint* textureUnit, const Extensions&, const SkShader& shader) {
173d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    Layer* layer;
174d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) {
175d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        LOG_ALWAYS_FATAL("SkiaLayerShader::setupProgram called on the wrong type of shader!");
176d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
177d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
1783f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    GLuint textureSlot = (*textureUnit)++;
179d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    caches->activeTexture(textureSlot);
1803f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik
181d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    const float width = layer->getWidth();
182d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    const float height = layer->getHeight();
1833f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik
1843f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    mat4 textureTransform;
185d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
186d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            modelViewMatrix);
187d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
1883f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik
1893f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    // Uniforms
190d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    layer->bindTexture();
191d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    layer->setWrap(GL_CLAMP_TO_EDGE);
192d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    layer->setFilter(GL_LINEAR);
1933f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik
194d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    Program* program = caches->currentProgram;
1953f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
1963f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
1973f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik            GL_FALSE, &textureTransform.data[0]);
1983f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height);
1993f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik}
2003f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik
2013f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik///////////////////////////////////////////////////////////////////////////////
20206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Bitmap shader
20306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
20406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
205d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIstruct BitmapShaderInfo {
206d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    float width;
207d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    float height;
208d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    GLenum wrapS;
209d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    GLenum wrapT;
210d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    Texture* texture;
211d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III};
21224c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
213d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIstatic bool bitmapShaderHelper(Caches* caches, ProgramDescription* description,
214d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        BitmapShaderInfo* shaderInfo,
215d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const Extensions& extensions,
216d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const SkBitmap& bitmap, SkShader::TileMode tileModes[2]) {
217d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    Texture* texture = caches->textureCache.get(&bitmap);
218d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (!texture) return false;
21906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
22006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float width = texture->width;
22106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float height = texture->height;
222d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    GLenum wrapS, wrapT;
22306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
224d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (description) {
225d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        description->hasBitmap = true;
226d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
22706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // The driver does not support non-power of two mirrored/repeated
22806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // textures, so do it ourselves
22961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy    if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
230d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            (tileModes[0] != SkShader::kClamp_TileMode ||
231d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III             tileModes[1] != SkShader::kClamp_TileMode)) {
232d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (description) {
233d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            description->isBitmapNpot = true;
234d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            description->bitmapWrapS = gTileModes[tileModes[0]];
235d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            description->bitmapWrapT = gTileModes[tileModes[1]];
236d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        }
237d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        wrapS = GL_CLAMP_TO_EDGE;
238d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        wrapT = GL_CLAMP_TO_EDGE;
23929d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy    } else {
240d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        wrapS = gTileModes[tileModes[0]];
241d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        wrapT = gTileModes[tileModes[1]];
242d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
243d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
244d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (shaderInfo) {
245d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        shaderInfo->width = width;
246d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        shaderInfo->height = height;
247d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        shaderInfo->wrapS = wrapS;
248d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        shaderInfo->wrapT = wrapT;
249d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        shaderInfo->texture = texture;
25006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
251d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    return true;
25206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
25306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
254d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaBitmapShader::describe(Caches* caches, ProgramDescription& description,
255d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const Extensions& extensions, const SkShader& shader) {
256d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkBitmap bitmap;
257d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::TileMode xy[2];
258d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (shader.asABitmap(&bitmap, NULL, xy) != SkShader::kDefault_BitmapType) {
259d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        LOG_ALWAYS_FATAL("SkiaBitmapShader::describe called with a different kind of shader!");
260d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
261d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    bitmapShaderHelper(caches, &description, NULL, extensions, bitmap, xy);
262d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III}
263d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
264d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaBitmapShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
265d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
266d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkBitmap bitmap;
267d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::TileMode xy[2];
268d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (shader.asABitmap(&bitmap, NULL, xy) != SkShader::kDefault_BitmapType) {
269d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        LOG_ALWAYS_FATAL("SkiaBitmapShader::setupProgram called with a different kind of shader!");
270d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
271d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
27206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    GLuint textureSlot = (*textureUnit)++;
273a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy    Caches::getInstance().activeTexture(textureSlot);
2749cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy
275d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    BitmapShaderInfo shaderInfo;
276d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (!bitmapShaderHelper(caches, NULL, &shaderInfo, extensions, bitmap, xy)) {
277d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        return;
278d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
27906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
280d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    Program* program = caches->currentProgram;
281d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    Texture* texture = shaderInfo.texture;
282d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
283d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    const AutoTexture autoCleanup(texture);
28406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
28506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mat4 textureTransform;
286d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
287d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            modelViewMatrix);
28806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
28906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // Uniforms
290d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    bindTexture(caches, texture, shaderInfo.wrapS, shaderInfo.wrapT);
291d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy    texture->setFilter(GL_LINEAR);
292e3c26851dc315b730ea0fe5ef35bb1db81f6d675Romain Guy
29306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
29406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
29506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy            GL_FALSE, &textureTransform.data[0]);
296d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    glUniform2f(program->getUniform("textureDimension"), 1.0f / shaderInfo.width,
297d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            1.0f / shaderInfo.height);
29806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
29906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
30006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
30106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Linear gradient shader
30206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
30306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
304e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guystatic void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
305e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    SkVector vec = pts[1] - pts[0];
306e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    const float mag = vec.length();
307e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    const float inv = mag ? 1.0f / mag : 0;
308e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
309e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    vec.scale(inv);
310e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY);
311e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->postTranslate(-pts[0].fX, -pts[0].fY);
312e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->postScale(inv, inv);
313e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy}
314e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
31506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
316ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy// Circular gradient shader
317ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy///////////////////////////////////////////////////////////////////////////////
318ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
31914830948d02f768c41b97b7a8d15e1b3cab78267Romain Guystatic void toCircularUnitMatrix(const float x, const float y, const float radius,
32014830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy        SkMatrix* matrix) {
32114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    const float inv = 1.0f / radius;
32214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    matrix->setTranslate(-x, -y);
32314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    matrix->postScale(inv, inv);
32414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy}
32514830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
326ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy///////////////////////////////////////////////////////////////////////////////
327ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy// Sweep gradient shader
328ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy///////////////////////////////////////////////////////////////////////////////
329ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
33014830948d02f768c41b97b7a8d15e1b3cab78267Romain Guystatic void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) {
33114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    matrix->setTranslate(-x, -y);
33214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy}
33314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
334d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III///////////////////////////////////////////////////////////////////////////////
335d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III// Common gradient code
336d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III///////////////////////////////////////////////////////////////////////////////
33724c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
338d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIstatic bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) {
339d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode;
340d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III}
341d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
342d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaGradientShader::describe(Caches*, ProgramDescription& description,
343d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const Extensions& extensions, const SkShader& shader) {
344d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::GradientInfo gradInfo;
345d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gradInfo.fColorCount = 0;
346d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gradInfo.fColors = NULL;
347d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gradInfo.fColorOffsets = NULL;
348d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
349d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    switch (shader.asAGradient(&gradInfo)) {
350d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kLinear_GradientType:
351d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            description.gradientType = ProgramDescription::kGradientLinear;
352d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            break;
353d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kRadial_GradientType:
354d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            description.gradientType = ProgramDescription::kGradientCircular;
355d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            break;
356d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kSweep_GradientType:
357d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            description.gradientType = ProgramDescription::kGradientSweep;
358d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            break;
359d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        default:
360d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            // Do nothing. This shader is unsupported.
361d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            return;
362d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
363ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    description.hasGradient = true;
364d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    description.isSimpleGradient = isSimpleGradient(gradInfo);
365d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III}
366d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
367d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaGradientShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
368d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        GLuint* textureUnit, const Extensions&, const SkShader& shader) {
369d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // SkShader::GradientInfo.fColorCount is an in/out parameter. As input, it tells asAGradient
370d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // how much space has been allocated for fColors and fColorOffsets.  10 was chosen
371d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // arbitrarily, but should be >= 2.
372d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    // As output, it tells the number of actual colors/offsets in the gradient.
373d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    const int COLOR_COUNT = 10;
374d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkAutoSTMalloc<COLOR_COUNT, SkColor> colorStorage(COLOR_COUNT);
375d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkAutoSTMalloc<COLOR_COUNT, SkScalar> positionStorage(COLOR_COUNT);
376d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
377d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::GradientInfo gradInfo;
378d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gradInfo.fColorCount = COLOR_COUNT;
379d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gradInfo.fColors = colorStorage.get();
380d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    gradInfo.fColorOffsets = positionStorage.get();
381d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
382d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::GradientType gradType = shader.asAGradient(&gradInfo);
383d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
384d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    Program* program = caches->currentProgram;
385d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) {
386d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (gradInfo.fColorCount > COLOR_COUNT) {
387d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            // There was not enough room in our arrays for all the colors and offsets. Try again,
388d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            // now that we know the true number of colors.
389d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            gradInfo.fColors = colorStorage.reset(gradInfo.fColorCount);
390d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            gradInfo.fColorOffsets = positionStorage.reset(gradInfo.fColorCount);
391d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
392d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            shader.asAGradient(&gradInfo);
393d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        }
39442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        GLuint textureSlot = (*textureUnit)++;
395d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        caches->activeTexture(textureSlot);
396ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
397d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III#ifndef SK_SCALAR_IS_FLOAT
398d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    #error Need to convert gradInfo.fColorOffsets to float!
399d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III#endif
400d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        Texture* texture = caches->gradientCache.get(gradInfo.fColors, gradInfo.fColorOffsets,
401d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                gradInfo.fColorCount);
40242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
40342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        // Uniforms
404d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        bindTexture(caches, texture, gTileModes[gradInfo.fTileMode], gTileModes[gradInfo.fTileMode]);
40542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        glUniform1i(program->getUniform("gradientSampler"), textureSlot);
40642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    } else {
407d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        bindUniformColor(program->getUniform("startColor"), gradInfo.fColors[0]);
408d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        bindUniformColor(program->getUniform("endColor"), gradInfo.fColors[1]);
40942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    }
410ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
411d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    caches->dither.setupProgram(program, textureUnit);
412d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
413d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkMatrix unitMatrix;
414d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    switch (gradType) {
415d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kLinear_GradientType:
416d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            toUnitMatrix(gradInfo.fPoint, &unitMatrix);
417d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            break;
418d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kRadial_GradientType:
419d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY,
420d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                    gradInfo.fRadius[0], &unitMatrix);
421d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            break;
422d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        case SkShader::kSweep_GradientType:
423d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix);
424d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            break;
425d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        default:
426d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            LOG_ALWAYS_FATAL("Invalid SkShader gradient type %d", gradType);
427d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
428211efea7376371ee755edd2ad03e83ef6eea464eRomain Guy
42914830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    mat4 screenSpace;
430d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    computeScreenSpaceMatrix(screenSpace, unitMatrix, shader.getLocalMatrix(), modelViewMatrix);
431ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
432ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
433ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
434ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy///////////////////////////////////////////////////////////////////////////////
43506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Compose shader
43606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
43706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
438d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaComposeShader::describe(Caches* caches, ProgramDescription& description,
439d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        const Extensions& extensions, const SkShader& shader) {
440d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::ComposeRec rec;
441d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (!shader.asACompose(&rec)) {
442d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        LOG_ALWAYS_FATAL("SkiaComposeShader::describe called on the wrong shader type!");
44343ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    }
444d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaShader::describe(caches, description, extensions, *rec.fShaderA);
445d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaShader::describe(caches, description, extensions, *rec.fShaderB);
446d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (SkiaShader::getType(*rec.fShaderA) == kBitmap_SkiaShaderType) {
44706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        description.isBitmapFirst = true;
44806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
449d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (!SkXfermode::AsMode(rec.fMode, &description.shadersMode)) {
450d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        // TODO: Support other modes.
451d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        description.shadersMode = SkXfermode::kSrcOver_Mode;
452d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
45306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
45406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
455d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins IIIvoid SkiaComposeShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
456d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
457d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkShader::ComposeRec rec;
458d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    if (!shader.asACompose(&rec)) {
459d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        LOG_ALWAYS_FATAL("SkiaComposeShader::setupProgram called on the wrong shader type!");
460d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    }
461d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
462d4289922ce772ed8e170a27d1c9521672b315698Romain Guy    // Apply this compose shader's local transform and pass it down to
463d4289922ce772ed8e170a27d1c9521672b315698Romain Guy    // the child shaders. They will in turn apply their local transform
464d4289922ce772ed8e170a27d1c9521672b315698Romain Guy    // to this matrix.
465d4289922ce772ed8e170a27d1c9521672b315698Romain Guy    mat4 transform;
466d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(),
467d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            modelViewMatrix);
468d4289922ce772ed8e170a27d1c9521672b315698Romain Guy
469d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderA);
470d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III    SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderB);
47106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
47206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
47306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}; // namespace uirenderer
47406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}; // namespace android
475