SkiaShader.cpp revision 211efea7376371ee755edd2ad03e83ef6eea464e
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"
2406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#include "SkiaShader.h"
2506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#include "Texture.h"
2606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#include "Matrix.h"
2706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
2806f96e2652e4855b6520ad9dd70583677605b79aRomain Guynamespace android {
2906f96e2652e4855b6520ad9dd70583677605b79aRomain Guynamespace uirenderer {
3006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
3106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
3206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Support
3306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
3406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
3506f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic const GLint gTileModes[] = {
3606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_CLAMP_TO_EDGE,   // == SkShader::kClamp_TileMode
3706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_REPEAT,          // == SkShader::kRepeat_Mode
3806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GL_MIRRORED_REPEAT  // == SkShader::kMirror_TileMode
3906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy};
4006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
4142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy/**
4242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy * This function does not work for n == 0.
4342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy */
4442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guystatic inline bool isPowerOfTwo(unsigned int n) {
4542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    return !(n & (n - 1));
4642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy}
4742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
4842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guystatic inline void bindUniformColor(int slot, uint32_t color) {
4942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    glUniform4f(slot,
5042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            ((color >> 16) & 0xff) / 255.0f,
5142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            ((color >>  8) & 0xff) / 255.0f,
5242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            ((color      ) & 0xff) / 255.0f,
5342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            ((color >> 24) & 0xff) / 255.0f);
5442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy}
5542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
5606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
5706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Base shader
5806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
5906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
6024c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guyvoid SkiaShader::copyFrom(const SkiaShader& shader) {
6124c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mType = shader.mType;
6224c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mKey = shader.mKey;
6324c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mTileX = shader.mTileX;
6424c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mTileY = shader.mTileY;
6524c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mBlend = shader.mBlend;
6624c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mUnitMatrix = shader.mUnitMatrix;
6724c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mShaderMatrix = shader.mShaderMatrix;
6824c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mGenerationId = shader.mGenerationId;
6924c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy}
7024c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
7106f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaShader::SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
7206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
7314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy        mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend) {
7414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    setMatrix(matrix);
7524c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mGenerationId = 0;
7606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
7706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
7806f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaShader::~SkiaShader() {
7906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
8006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
8106f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaShader::describe(ProgramDescription& description, const Extensions& extensions) {
8206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
8306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
8406f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaShader::setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
8506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GLuint* textureUnit) {
8606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
8706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
8801d065795794fa56be660d6346e4830eb7e90a41Romain Guyvoid SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) {
898164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy    glBindTexture(GL_TEXTURE_2D, texture->id);
90d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy    texture->setWrapST(wrapS, wrapT);
9106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
9206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
9314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guyvoid SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) {
9414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix);
9514830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    screenSpace.multiply(modelView);
9614830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy}
9714830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
9806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
9906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Bitmap shader
10006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
10106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
10206f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaBitmapShader::SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX,
10306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
1049cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy        SkiaShader(kBitmap, key, tileX, tileY, matrix, blend), mBitmap(bitmap), mTexture(NULL) {
10514830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    updateLocalMatrix(matrix);
10606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
10706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
10824c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain GuySkiaShader* SkiaBitmapShader::copy() {
10924c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    SkiaBitmapShader* copy = new SkiaBitmapShader();
11024c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->copyFrom(*this);
11124c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mBitmap = mBitmap;
11224c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    return copy;
11324c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy}
11424c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
11506f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaBitmapShader::describe(ProgramDescription& description, const Extensions& extensions) {
1168164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy    Texture* texture = mTextureCache->get(mBitmap);
1179cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    if (!texture) return;
1189cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    mTexture = texture;
11906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
12006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float width = texture->width;
12106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float height = texture->height;
12206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
12306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    description.hasBitmap = true;
12406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // The driver does not support non-power of two mirrored/repeated
12506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // textures, so do it ourselves
12661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy    if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
12761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            (mTileX != SkShader::kClamp_TileMode || mTileY != SkShader::kClamp_TileMode)) {
12806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        description.isBitmapNpot = true;
12906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        description.bitmapWrapS = gTileModes[mTileX];
13006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        description.bitmapWrapT = gTileModes[mTileY];
13129d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy        mWrapS = GL_CLAMP_TO_EDGE;
13229d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy        mWrapT = GL_CLAMP_TO_EDGE;
13329d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy    } else {
13429d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy        mWrapS = gTileModes[mTileX];
13529d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy        mWrapT = gTileModes[mTileY];
13606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
13706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
13806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
13906f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView,
14006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        const Snapshot& snapshot, GLuint* textureUnit) {
14106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    GLuint textureSlot = (*textureUnit)++;
142a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy    Caches::getInstance().activeTexture(textureSlot);
1439cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy
1448164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy    Texture* texture = mTexture;
1459cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    mTexture = NULL;
1469cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    if (!texture) return;
1479cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    const AutoTexture autoCleanup(texture);
14806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
14906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float width = texture->width;
15006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float height = texture->height;
15106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
15206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mat4 textureTransform;
15314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    computeScreenSpaceMatrix(textureTransform, modelView);
15406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
15506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // Uniforms
15601d065795794fa56be660d6346e4830eb7e90a41Romain Guy    bindTexture(texture, mWrapS, mWrapT);
157b50149825fae95b2918bcf67b2ddb773b9797068Romain Guy    // Assume linear here; we should really check the transform in
158b50149825fae95b2918bcf67b2ddb773b9797068Romain Guy    // ::updateTransforms() but we don't have the texture object
159b50149825fae95b2918bcf67b2ddb773b9797068Romain Guy    // available at that point. The optimization is not worth the
160b50149825fae95b2918bcf67b2ddb773b9797068Romain Guy    // effort for now.
161d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy    texture->setFilter(GL_LINEAR);
162e3c26851dc315b730ea0fe5ef35bb1db81f6d675Romain Guy
16306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
16406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
16506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy            GL_FALSE, &textureTransform.data[0]);
16606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height);
16706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
16806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
169759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guyvoid SkiaBitmapShader::updateTransforms(Program* program, const mat4& modelView,
170759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        const Snapshot& snapshot) {
171759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy    mat4 textureTransform;
17214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    computeScreenSpaceMatrix(textureTransform, modelView);
173759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy    glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
174759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy            GL_FALSE, &textureTransform.data[0]);
175759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy}
176759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy
17706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
17806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Linear gradient shader
17906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
18006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
181e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guystatic void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
182e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    SkVector vec = pts[1] - pts[0];
183e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    const float mag = vec.length();
184e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    const float inv = mag ? 1.0f / mag : 0;
185e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
186e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    vec.scale(inv);
187e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY);
188e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->postTranslate(-pts[0].fX, -pts[0].fY);
189e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->postScale(inv, inv);
190e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy}
191e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
19206f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaLinearGradientShader::SkiaLinearGradientShader(float* bounds, uint32_t* colors,
19306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
19406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkMatrix* matrix, bool blend):
19506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkiaShader(kLinearGradient, key, tileMode, tileMode, matrix, blend),
19606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        mBounds(bounds), mColors(colors), mPositions(positions), mCount(count) {
197e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    SkPoint points[2];
198e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    points[0].set(bounds[0], bounds[1]);
199e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    points[1].set(bounds[2], bounds[3]);
200e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
201e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    SkMatrix unitMatrix;
202e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    toUnitMatrix(points, &unitMatrix);
203e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    mUnitMatrix.load(unitMatrix);
204e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
205e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    updateLocalMatrix(matrix);
20642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
20742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    mIsSimple = count == 2 && tileMode == SkShader::kClamp_TileMode;
20806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
20906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
21006f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaLinearGradientShader::~SkiaLinearGradientShader() {
21125ee037fee1607e8a77b1f2e259356e74dd6f645Romain Guy    delete[] mBounds;
21225ee037fee1607e8a77b1f2e259356e74dd6f645Romain Guy    delete[] mColors;
21325ee037fee1607e8a77b1f2e259356e74dd6f645Romain Guy    delete[] mPositions;
21406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
21506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
21624c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain GuySkiaShader* SkiaLinearGradientShader::copy() {
21724c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    SkiaLinearGradientShader* copy = new SkiaLinearGradientShader();
21824c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->copyFrom(*this);
21943ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    copy->mBounds = new float[4];
22043ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    memcpy(copy->mBounds, mBounds, sizeof(float) * 4);
22143ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    copy->mColors = new uint32_t[mCount];
22243ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
22343ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    copy->mPositions = new float[mCount];
22443ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
22524c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mCount = mCount;
22642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    copy->mIsSimple = mIsSimple;
22724c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    return copy;
22824c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy}
22924c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
23006f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaLinearGradientShader::describe(ProgramDescription& description,
23106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        const Extensions& extensions) {
23206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    description.hasGradient = true;
233ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    description.gradientType = ProgramDescription::kGradientLinear;
23442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    description.isSimpleGradient = mIsSimple;
23506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
23606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
23706f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView,
23806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        const Snapshot& snapshot, GLuint* textureUnit) {
23942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    if (CC_UNLIKELY(!mIsSimple)) {
24042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        GLuint textureSlot = (*textureUnit)++;
24142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        Caches::getInstance().activeTexture(textureSlot);
24242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
24342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        Texture* texture = mGradientCache->get(mColors, mPositions, mCount);
24406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
24542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        // Uniforms
24642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
24742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        glUniform1i(program->getUniform("gradientSampler"), textureSlot);
24842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    } else {
24942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        bindUniformColor(program->getUniform("startColor"), mColors[0]);
25042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        bindUniformColor(program->getUniform("endColor"), mColors[1]);
25142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    }
25206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
253211efea7376371ee755edd2ad03e83ef6eea464eRomain Guy    Caches::getInstance().dither.setupProgram(program, textureUnit);
254211efea7376371ee755edd2ad03e83ef6eea464eRomain Guy
255e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    mat4 screenSpace;
256e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    computeScreenSpaceMatrix(screenSpace, modelView);
25706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
25806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
25906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
260759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guyvoid SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& modelView,
261759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        const Snapshot& snapshot) {
262e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    mat4 screenSpace;
263e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    computeScreenSpaceMatrix(screenSpace, modelView);
264759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
265759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy}
266759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy
26706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
268ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy// Circular gradient shader
269ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy///////////////////////////////////////////////////////////////////////////////
270ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
27114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guystatic void toCircularUnitMatrix(const float x, const float y, const float radius,
27214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy        SkMatrix* matrix) {
27314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    const float inv = 1.0f / radius;
27414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    matrix->setTranslate(-x, -y);
27514830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    matrix->postScale(inv, inv);
27614830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy}
27714830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
278ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain GuySkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float radius,
279ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
280ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        SkMatrix* matrix, bool blend):
281ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        SkiaSweepGradientShader(kCircularGradient, x, y, colors, positions, count, key,
28214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy                tileMode, matrix, blend) {
28314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    SkMatrix unitMatrix;
28414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    toCircularUnitMatrix(x, y, radius, &unitMatrix);
28514830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    mUnitMatrix.load(unitMatrix);
28614830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
28714830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    updateLocalMatrix(matrix);
288ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy}
289ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
29024c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain GuySkiaShader* SkiaCircularGradientShader::copy() {
29124c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    SkiaCircularGradientShader* copy = new SkiaCircularGradientShader();
29224c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->copyFrom(*this);
29343ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    copy->mColors = new uint32_t[mCount];
29443ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
29543ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    copy->mPositions = new float[mCount];
29643ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
29724c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mCount = mCount;
29842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    copy->mIsSimple = mIsSimple;
29924c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    return copy;
30024c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy}
30124c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
302ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guyvoid SkiaCircularGradientShader::describe(ProgramDescription& description,
303ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        const Extensions& extensions) {
304ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    description.hasGradient = true;
305ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    description.gradientType = ProgramDescription::kGradientCircular;
30642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    description.isSimpleGradient = mIsSimple;
307ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy}
308ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
309ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy///////////////////////////////////////////////////////////////////////////////
310ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy// Sweep gradient shader
311ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy///////////////////////////////////////////////////////////////////////////////
312ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
31314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guystatic void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) {
31414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    matrix->setTranslate(-x, -y);
31514830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy}
31614830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
317ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain GuySkiaSweepGradientShader::SkiaSweepGradientShader(float x, float y, uint32_t* colors,
318ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        float* positions, int count, SkShader* key, SkMatrix* matrix, bool blend):
319ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        SkiaShader(kSweepGradient, key, SkShader::kClamp_TileMode,
320ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy                SkShader::kClamp_TileMode, matrix, blend),
32114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy        mColors(colors), mPositions(positions), mCount(count) {
32214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    SkMatrix unitMatrix;
32314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    toSweepUnitMatrix(x, y, &unitMatrix);
32414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    mUnitMatrix.load(unitMatrix);
32514830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
32614830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    updateLocalMatrix(matrix);
32742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
32842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    mIsSimple = count == 2;
329ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
330ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
331ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain GuySkiaSweepGradientShader::SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors,
332ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
333ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        SkMatrix* matrix, bool blend):
334ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        SkiaShader(type, key, tileMode, tileMode, matrix, blend),
33514830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy        mColors(colors), mPositions(positions), mCount(count) {
33642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
33742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    mIsSimple = count == 2 && tileMode == SkShader::kClamp_TileMode;
338ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy}
339ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
340ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain GuySkiaSweepGradientShader::~SkiaSweepGradientShader() {
341ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    delete[] mColors;
342ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    delete[] mPositions;
343ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
344ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
34524c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain GuySkiaShader* SkiaSweepGradientShader::copy() {
34624c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    SkiaSweepGradientShader* copy = new SkiaSweepGradientShader();
34724c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->copyFrom(*this);
34843ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    copy->mColors = new uint32_t[mCount];
34943ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
35043ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    copy->mPositions = new float[mCount];
35143ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
35224c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mCount = mCount;
35342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    copy->mIsSimple = mIsSimple;
35424c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    return copy;
35524c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy}
35624c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
357ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyvoid SkiaSweepGradientShader::describe(ProgramDescription& description,
358ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        const Extensions& extensions) {
359ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    description.hasGradient = true;
360ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    description.gradientType = ProgramDescription::kGradientSweep;
36142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    description.isSimpleGradient = mIsSimple;
362ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
363ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
364ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyvoid SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelView,
365ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        const Snapshot& snapshot, GLuint* textureUnit) {
36642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    if (CC_UNLIKELY(!mIsSimple)) {
36742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        GLuint textureSlot = (*textureUnit)++;
36842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        Caches::getInstance().activeTexture(textureSlot);
369ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
37042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        Texture* texture = mGradientCache->get(mColors, mPositions, mCount);
37142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
37242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        // Uniforms
37342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
37442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        glUniform1i(program->getUniform("gradientSampler"), textureSlot);
37542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    } else {
37642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy       bindUniformColor(program->getUniform("startColor"), mColors[0]);
37742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy       bindUniformColor(program->getUniform("endColor"), mColors[1]);
37842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    }
379ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
380211efea7376371ee755edd2ad03e83ef6eea464eRomain Guy    Caches::getInstance().dither.setupProgram(program, textureUnit);
381211efea7376371ee755edd2ad03e83ef6eea464eRomain Guy
38214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    mat4 screenSpace;
38314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    computeScreenSpaceMatrix(screenSpace, modelView);
384ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
385ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
386ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
387ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyvoid SkiaSweepGradientShader::updateTransforms(Program* program, const mat4& modelView,
388ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        const Snapshot& snapshot) {
38914830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    mat4 screenSpace;
39014830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    computeScreenSpaceMatrix(screenSpace, modelView);
391ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
392ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
393ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
394ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy///////////////////////////////////////////////////////////////////////////////
39506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Compose shader
39606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
39706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
39806f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaComposeShader::SkiaComposeShader(SkiaShader* first, SkiaShader* second,
39906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkXfermode::Mode mode, SkShader* key):
40006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkiaShader(kCompose, key, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
40143ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy        NULL, first->blend() || second->blend()),
40243ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy        mFirst(first), mSecond(second), mMode(mode), mCleanup(false) {
40343ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy}
40443ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy
40543ccf4663c822ddd435b7683cc05221f6169c6c3Romain GuySkiaComposeShader::~SkiaComposeShader() {
40643ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    if (mCleanup) {
40743ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy        delete mFirst;
40843ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy        delete mSecond;
40943ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    }
41006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
41106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
41224c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain GuySkiaShader* SkiaComposeShader::copy() {
41324c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    SkiaComposeShader* copy = new SkiaComposeShader();
41424c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->copyFrom(*this);
41543ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    copy->mFirst = mFirst->copy();
41643ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    copy->mSecond = mSecond->copy();
41724c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mMode = mMode;
41843ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    copy->cleanup();
41924c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    return copy;
42024c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy}
42124c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
42206f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaComposeShader::set(TextureCache* textureCache, GradientCache* gradientCache) {
42306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    SkiaShader::set(textureCache, gradientCache);
42406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mFirst->set(textureCache, gradientCache);
42506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mSecond->set(textureCache, gradientCache);
42606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
42706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
42806f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaComposeShader::describe(ProgramDescription& description, const Extensions& extensions) {
42906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mFirst->describe(description, extensions);
43006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mSecond->describe(description, extensions);
43106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    if (mFirst->type() == kBitmap) {
43206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        description.isBitmapFirst = true;
43306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
43406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    description.shadersMode = mMode;
43506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
43606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
43706f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaComposeShader::setupProgram(Program* program, const mat4& modelView,
43806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        const Snapshot& snapshot, GLuint* textureUnit) {
43906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mFirst->setupProgram(program, modelView, snapshot, textureUnit);
44006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mSecond->setupProgram(program, modelView, snapshot, textureUnit);
44106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
44206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
44306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}; // namespace uirenderer
44406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}; // namespace android
445