SkiaShader.cpp revision e3095e0c1e2a4a4f34f741aa386eae56536ca5aa
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
2306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#include "SkiaShader.h"
2406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#include "Texture.h"
2506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#include "Matrix.h"
2606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
2706f96e2652e4855b6520ad9dd70583677605b79aRomain Guynamespace android {
2806f96e2652e4855b6520ad9dd70583677605b79aRomain Guynamespace uirenderer {
2906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
3006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
3106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Support
3206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
3306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
3406f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic const GLenum gTextureUnitsMap[] = {
3506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_TEXTURE0,
3606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_TEXTURE1,
3706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_TEXTURE2
3806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy};
3906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
4006f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic const GLint gTileModes[] = {
4106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_CLAMP_TO_EDGE,   // == SkShader::kClamp_TileMode
4206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_REPEAT,          // == SkShader::kRepeat_Mode
4306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_MIRRORED_REPEAT  // == SkShader::kMirror_TileMode
4406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy};
4506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
4606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
4706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Base shader
4806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
4906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
5006f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaShader::SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
5106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
5206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mMatrix(matrix), mBlend(blend) {
5306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
5406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
5506f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaShader::~SkiaShader() {
5606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
5706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
5806f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaShader::describe(ProgramDescription& description, const Extensions& extensions) {
5906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
6006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
6106f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaShader::setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
6206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GLuint* textureUnit) {
6306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
6406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
6506f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaShader::bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint textureUnit) {
6606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glActiveTexture(gTextureUnitsMap[textureUnit]);
6706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glBindTexture(GL_TEXTURE_2D, texture);
6806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
6906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
7006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
7106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
7206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
7306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Bitmap shader
7406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
7506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
7606f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaBitmapShader::SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX,
7706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
789cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy        SkiaShader(kBitmap, key, tileX, tileY, matrix, blend), mBitmap(bitmap), mTexture(NULL) {
7906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
8006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
8106f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaBitmapShader::describe(ProgramDescription& description, const Extensions& extensions) {
8206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const Texture* texture = mTextureCache->get(mBitmap);
839cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    if (!texture) return;
849cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    mTexture = texture;
8506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
8606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float width = texture->width;
8706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float height = texture->height;
8806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
8906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    description.hasBitmap = true;
9006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // The driver does not support non-power of two mirrored/repeated
9106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // textures, so do it ourselves
9261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy    if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
9361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            (mTileX != SkShader::kClamp_TileMode || mTileY != SkShader::kClamp_TileMode)) {
9406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        description.isBitmapNpot = true;
9506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        description.bitmapWrapS = gTileModes[mTileX];
9606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        description.bitmapWrapT = gTileModes[mTileY];
9729d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy        mWrapS = GL_CLAMP_TO_EDGE;
9829d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy        mWrapT = GL_CLAMP_TO_EDGE;
9929d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy    } else {
10029d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy        mWrapS = gTileModes[mTileX];
10129d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy        mWrapT = gTileModes[mTileY];
10206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
10306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
10406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
10506f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView,
10606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        const Snapshot& snapshot, GLuint* textureUnit) {
10706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    GLuint textureSlot = (*textureUnit)++;
10806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glActiveTexture(gTextureUnitsMap[textureSlot]);
1099cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy
1109cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    const Texture* texture = mTexture;
1119cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    mTexture = NULL;
1129cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    if (!texture) return;
1139cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    const AutoTexture autoCleanup(texture);
11406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
11506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float width = texture->width;
11606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float height = texture->height;
11706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
11806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mat4 textureTransform;
11906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    if (mMatrix) {
12006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkMatrix inverse;
12106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        mMatrix->invert(&inverse);
12206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        textureTransform.load(inverse);
12306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        textureTransform.multiply(modelView);
12406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    } else {
12506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        textureTransform.load(modelView);
12606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
12706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
12806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // Uniforms
12929d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy    bindTexture(texture->id, mWrapS, mWrapT, textureSlot);
13006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
13106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
13206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy            GL_FALSE, &textureTransform.data[0]);
13306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height);
13406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
13506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
136759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guyvoid SkiaBitmapShader::updateTransforms(Program* program, const mat4& modelView,
137759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        const Snapshot& snapshot) {
138759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy    mat4 textureTransform;
139759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy    if (mMatrix) {
140759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        SkMatrix inverse;
141759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        mMatrix->invert(&inverse);
142759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        textureTransform.load(inverse);
143759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        textureTransform.multiply(modelView);
144759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy    } else {
145759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        textureTransform.load(modelView);
146759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy    }
147759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy
148759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy    glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
149759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy            GL_FALSE, &textureTransform.data[0]);
150759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy}
151759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy
15206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
15306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Linear gradient shader
15406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
15506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
156e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guystatic void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
157e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    SkVector vec = pts[1] - pts[0];
158e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    const float mag = vec.length();
159e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    const float inv = mag ? 1.0f / mag : 0;
160e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
161e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    vec.scale(inv);
162e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY);
163e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->postTranslate(-pts[0].fX, -pts[0].fY);
164e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->postScale(inv, inv);
165e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy}
166e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
16706f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaLinearGradientShader::SkiaLinearGradientShader(float* bounds, uint32_t* colors,
16806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
16906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkMatrix* matrix, bool blend):
17006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkiaShader(kLinearGradient, key, tileMode, tileMode, matrix, blend),
17106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        mBounds(bounds), mColors(colors), mPositions(positions), mCount(count) {
172e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    SkPoint points[2];
173e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    points[0].set(bounds[0], bounds[1]);
174e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    points[1].set(bounds[2], bounds[3]);
175e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
176e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    SkMatrix unitMatrix;
177e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    toUnitMatrix(points, &unitMatrix);
178e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    mUnitMatrix.load(unitMatrix);
179e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
180e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    updateLocalMatrix(matrix);
18106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
18206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
18306f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaLinearGradientShader::~SkiaLinearGradientShader() {
18425ee037fee1607e8a77b1f2e259356e74dd6f645Romain Guy    delete[] mBounds;
18525ee037fee1607e8a77b1f2e259356e74dd6f645Romain Guy    delete[] mColors;
18625ee037fee1607e8a77b1f2e259356e74dd6f645Romain Guy    delete[] mPositions;
18706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
18806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
18906f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaLinearGradientShader::describe(ProgramDescription& description,
19006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        const Extensions& extensions) {
19106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    description.hasGradient = true;
192ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    description.gradientType = ProgramDescription::kGradientLinear;
19306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
19406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
195e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guyvoid SkiaLinearGradientShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) {
196e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix);
197e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    screenSpace.multiply(modelView);
198e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy}
199e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
200e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guyvoid SkiaLinearGradientShader::updateLocalMatrix(const SkMatrix* matrix) {
201e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    if (matrix) {
202e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy        mat4 localMatrix(*matrix);
203e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy        mShaderMatrix.loadInverse(localMatrix);
204e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    }
205e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy}
206e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
207e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guyvoid SkiaLinearGradientShader::setMatrix(SkMatrix* matrix) {
208e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    SkiaShader::setMatrix(matrix);
209e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    updateLocalMatrix(matrix);
210e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy}
211e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
21206f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView,
21306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        const Snapshot& snapshot, GLuint* textureUnit) {
21406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    GLuint textureSlot = (*textureUnit)++;
21506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glActiveTexture(gTextureUnitsMap[textureSlot]);
21606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
21706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    Texture* texture = mGradientCache->get(mKey);
21806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    if (!texture) {
219ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount, mTileX);
22006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
22106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
222e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    mat4 screenSpace;
223e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    computeScreenSpaceMatrix(screenSpace, modelView);
22406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
22506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // Uniforms
22606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    bindTexture(texture->id, gTileModes[mTileX], gTileModes[mTileY], textureSlot);
22706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniform1i(program->getUniform("gradientSampler"), textureSlot);
22806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
22906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
23006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
231759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guyvoid SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& modelView,
232759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        const Snapshot& snapshot) {
233e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    mat4 screenSpace;
234e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    computeScreenSpaceMatrix(screenSpace, modelView);
235759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
236759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy}
237759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy
23806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
239ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy// Circular gradient shader
240ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy///////////////////////////////////////////////////////////////////////////////
241ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
242ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain GuySkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float radius,
243ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
244ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        SkMatrix* matrix, bool blend):
245ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        SkiaSweepGradientShader(kCircularGradient, x, y, colors, positions, count, key,
246ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy                tileMode, matrix, blend),
247ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        mRadius(radius) {
248ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy}
249ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
250ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guyvoid SkiaCircularGradientShader::describe(ProgramDescription& description,
251ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        const Extensions& extensions) {
252ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    description.hasGradient = true;
253ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    description.gradientType = ProgramDescription::kGradientCircular;
254ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy}
255ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
256ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guyvoid SkiaCircularGradientShader::setupProgram(Program* program, const mat4& modelView,
257ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        const Snapshot& snapshot, GLuint* textureUnit) {
258ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    SkiaSweepGradientShader::setupProgram(program, modelView, snapshot, textureUnit);
259ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    glUniform1f(program->getUniform("gradientRadius"), 1.0f / mRadius);
260ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy}
261ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
262ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy///////////////////////////////////////////////////////////////////////////////
263ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy// Sweep gradient shader
264ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy///////////////////////////////////////////////////////////////////////////////
265ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
266ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain GuySkiaSweepGradientShader::SkiaSweepGradientShader(float x, float y, uint32_t* colors,
267ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        float* positions, int count, SkShader* key, SkMatrix* matrix, bool blend):
268ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        SkiaShader(kSweepGradient, key, SkShader::kClamp_TileMode,
269ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy                SkShader::kClamp_TileMode, matrix, blend),
270ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) {
271ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
272ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
273ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain GuySkiaSweepGradientShader::SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors,
274ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
275ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        SkMatrix* matrix, bool blend):
276ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        SkiaShader(type, key, tileMode, tileMode, matrix, blend),
277ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) {
278ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy}
279ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
280ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain GuySkiaSweepGradientShader::~SkiaSweepGradientShader() {
281ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    delete[] mColors;
282ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    delete[] mPositions;
283ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
284ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
285ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyvoid SkiaSweepGradientShader::describe(ProgramDescription& description,
286ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        const Extensions& extensions) {
287ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    description.hasGradient = true;
288ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    description.gradientType = ProgramDescription::kGradientSweep;
289ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
290ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
291ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyvoid SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelView,
292ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        const Snapshot& snapshot, GLuint* textureUnit) {
293ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    GLuint textureSlot = (*textureUnit)++;
294ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    glActiveTexture(gTextureUnitsMap[textureSlot]);
295ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
296ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    Texture* texture = mGradientCache->get(mKey);
297ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    if (!texture) {
298ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount);
299ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    }
300ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
301ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    float left = mX;
302ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    float top = mY;
303ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
304ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    mat4 shaderMatrix;
305ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    if (mMatrix) {
306ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        shaderMatrix.load(*mMatrix);
307ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        shaderMatrix.mapPoint(left, top);
308ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    }
309ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
310ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    mat4 copy(shaderMatrix);
311ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    shaderMatrix.loadInverse(copy);
312ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
313ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    snapshot.transform->mapPoint(left, top);
314ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
315ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    mat4 screenSpace(*snapshot.transform);
316ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    screenSpace.multiply(modelView);
317ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
318ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    // Uniforms
319ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    bindTexture(texture->id, gTileModes[mTileX], gTileModes[mTileY], textureSlot);
320ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    glUniform1i(program->getUniform("gradientSampler"), textureSlot);
321ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    glUniformMatrix4fv(program->getUniform("gradientMatrix"), 1, GL_FALSE, &shaderMatrix.data[0]);
322ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    glUniform2f(program->getUniform("gradientStart"), left, top);
323ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
324ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
325ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
326ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyvoid SkiaSweepGradientShader::updateTransforms(Program* program, const mat4& modelView,
327ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        const Snapshot& snapshot) {
328ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    mat4 screenSpace(*snapshot.transform);
329ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    screenSpace.multiply(modelView);
330ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
331ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
332ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
333ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy///////////////////////////////////////////////////////////////////////////////
33406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Compose shader
33506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
33606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
33706f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaComposeShader::SkiaComposeShader(SkiaShader* first, SkiaShader* second,
33806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkXfermode::Mode mode, SkShader* key):
33906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkiaShader(kCompose, key, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
34006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        NULL, first->blend() || second->blend()), mFirst(first), mSecond(second), mMode(mode) {
34106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
34206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
34306f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaComposeShader::set(TextureCache* textureCache, GradientCache* gradientCache) {
34406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    SkiaShader::set(textureCache, gradientCache);
34506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mFirst->set(textureCache, gradientCache);
34606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mSecond->set(textureCache, gradientCache);
34706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
34806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
34906f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaComposeShader::describe(ProgramDescription& description, const Extensions& extensions) {
35006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mFirst->describe(description, extensions);
35106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mSecond->describe(description, extensions);
35206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    if (mFirst->type() == kBitmap) {
35306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        description.isBitmapFirst = true;
35406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
35506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    description.shadersMode = mMode;
35606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
35706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
35806f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaComposeShader::setupProgram(Program* program, const mat4& modelView,
35906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        const Snapshot& snapshot, GLuint* textureUnit) {
36006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mFirst->setupProgram(program, modelView, snapshot, textureUnit);
36106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mSecond->setupProgram(program, modelView, snapshot, textureUnit);
36206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
36306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
36406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}; // namespace uirenderer
36506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}; // namespace android
366