SkiaShader.cpp revision 24c00216687ac87fe531dc4d4168ac0c0ca04ea6
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
5024c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guyvoid SkiaShader::copyFrom(const SkiaShader& shader) {
5124c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mType = shader.mType;
5224c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mKey = shader.mKey;
5324c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mTileX = shader.mTileX;
5424c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mTileY = shader.mTileY;
5524c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mBlend = shader.mBlend;
5624c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mUnitMatrix = shader.mUnitMatrix;
5724c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mShaderMatrix = shader.mShaderMatrix;
5824c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mGenerationId = shader.mGenerationId;
5924c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy}
6024c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
6106f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaShader::SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
6206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
6314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy        mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend) {
6414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    setMatrix(matrix);
6524c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    mGenerationId = 0;
6606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
6706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
6806f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaShader::~SkiaShader() {
6906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
7006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
7106f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaShader::describe(ProgramDescription& description, const Extensions& extensions) {
7206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
7306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
7406f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaShader::setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
7506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        GLuint* textureUnit) {
7606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
7706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
7801d065795794fa56be660d6346e4830eb7e90a41Romain Guyvoid SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) {
798164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy    glBindTexture(GL_TEXTURE_2D, texture->id);
808164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy    if (wrapS != texture->wrapS) {
818164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
828164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy        texture->wrapS = wrapS;
838164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy    }
848164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy    if (wrapT != texture->wrapT) {
858164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
868164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy        texture->wrapT = wrapT;
878164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy    }
8806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
8906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
9014830948d02f768c41b97b7a8d15e1b3cab78267Romain Guyvoid SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) {
9114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix);
9214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    screenSpace.multiply(modelView);
9314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy}
9414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
9506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
9606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Bitmap shader
9706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
9806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
9906f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaBitmapShader::SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX,
10006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
1019cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy        SkiaShader(kBitmap, key, tileX, tileY, matrix, blend), mBitmap(bitmap), mTexture(NULL) {
10214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    updateLocalMatrix(matrix);
10306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
10406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
10524c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain GuySkiaShader* SkiaBitmapShader::copy() {
10624c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    SkiaBitmapShader* copy = new SkiaBitmapShader();
10724c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->copyFrom(*this);
10824c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mBitmap = mBitmap;
10924c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    return copy;
11024c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy}
11124c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
11206f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaBitmapShader::describe(ProgramDescription& description, const Extensions& extensions) {
1138164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy    Texture* texture = mTextureCache->get(mBitmap);
1149cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    if (!texture) return;
1159cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    mTexture = texture;
11606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
11706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float width = texture->width;
11806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float height = texture->height;
11906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
12006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    description.hasBitmap = true;
12106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // The driver does not support non-power of two mirrored/repeated
12206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // textures, so do it ourselves
12361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy    if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
12461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            (mTileX != SkShader::kClamp_TileMode || mTileY != SkShader::kClamp_TileMode)) {
12506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        description.isBitmapNpot = true;
12606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        description.bitmapWrapS = gTileModes[mTileX];
12706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        description.bitmapWrapT = gTileModes[mTileY];
12829d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy        mWrapS = GL_CLAMP_TO_EDGE;
12929d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy        mWrapT = GL_CLAMP_TO_EDGE;
13029d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy    } else {
13129d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy        mWrapS = gTileModes[mTileX];
13229d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy        mWrapT = gTileModes[mTileY];
13306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
13406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
13506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
13606f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView,
13706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        const Snapshot& snapshot, GLuint* textureUnit) {
13806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    GLuint textureSlot = (*textureUnit)++;
13906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glActiveTexture(gTextureUnitsMap[textureSlot]);
1409cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy
1418164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy    Texture* texture = mTexture;
1429cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    mTexture = NULL;
1439cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    if (!texture) return;
1449cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy    const AutoTexture autoCleanup(texture);
14506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
14606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float width = texture->width;
14706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const float height = texture->height;
14806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
14906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mat4 textureTransform;
15014830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    computeScreenSpaceMatrix(textureTransform, modelView);
15106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
15206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // Uniforms
15301d065795794fa56be660d6346e4830eb7e90a41Romain Guy    bindTexture(texture, mWrapS, mWrapT);
15406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
15506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
15606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy            GL_FALSE, &textureTransform.data[0]);
15706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height);
15806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
15906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
160759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guyvoid SkiaBitmapShader::updateTransforms(Program* program, const mat4& modelView,
161759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        const Snapshot& snapshot) {
162759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy    mat4 textureTransform;
16314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    computeScreenSpaceMatrix(textureTransform, modelView);
164759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy    glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
165759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy            GL_FALSE, &textureTransform.data[0]);
166759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy}
167759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy
16806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
16906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Linear gradient shader
17006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
17106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
172e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guystatic void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
173e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    SkVector vec = pts[1] - pts[0];
174e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    const float mag = vec.length();
175e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    const float inv = mag ? 1.0f / mag : 0;
176e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
177e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    vec.scale(inv);
178e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY);
179e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->postTranslate(-pts[0].fX, -pts[0].fY);
180e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    matrix->postScale(inv, inv);
181e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy}
182e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
18306f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaLinearGradientShader::SkiaLinearGradientShader(float* bounds, uint32_t* colors,
18406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
18506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkMatrix* matrix, bool blend):
18606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkiaShader(kLinearGradient, key, tileMode, tileMode, matrix, blend),
18706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        mBounds(bounds), mColors(colors), mPositions(positions), mCount(count) {
188e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    SkPoint points[2];
189e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    points[0].set(bounds[0], bounds[1]);
190e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    points[1].set(bounds[2], bounds[3]);
191e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
192e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    SkMatrix unitMatrix;
193e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    toUnitMatrix(points, &unitMatrix);
194e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    mUnitMatrix.load(unitMatrix);
195e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy
196e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    updateLocalMatrix(matrix);
19706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
19806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
19906f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaLinearGradientShader::~SkiaLinearGradientShader() {
20025ee037fee1607e8a77b1f2e259356e74dd6f645Romain Guy    delete[] mBounds;
20125ee037fee1607e8a77b1f2e259356e74dd6f645Romain Guy    delete[] mColors;
20225ee037fee1607e8a77b1f2e259356e74dd6f645Romain Guy    delete[] mPositions;
20306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
20406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
20524c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain GuySkiaShader* SkiaLinearGradientShader::copy() {
20624c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    SkiaLinearGradientShader* copy = new SkiaLinearGradientShader();
20724c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->copyFrom(*this);
20824c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mBounds = mBounds;
20924c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mColors = mColors;
21024c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mPositions = mPositions;
21124c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mCount = mCount;
21224c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    return copy;
21324c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy}
21424c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
21506f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaLinearGradientShader::describe(ProgramDescription& description,
21606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        const Extensions& extensions) {
21706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    description.hasGradient = true;
218ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    description.gradientType = ProgramDescription::kGradientLinear;
21906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
22006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
22106f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView,
22206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        const Snapshot& snapshot, GLuint* textureUnit) {
22306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    GLuint textureSlot = (*textureUnit)++;
22406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glActiveTexture(gTextureUnitsMap[textureSlot]);
22506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
22606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    Texture* texture = mGradientCache->get(mKey);
22706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    if (!texture) {
228ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount, mTileX);
22906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
23006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
231e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    mat4 screenSpace;
232e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    computeScreenSpaceMatrix(screenSpace, modelView);
23306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
23406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    // Uniforms
23501d065795794fa56be660d6346e4830eb7e90a41Romain Guy    bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
23606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniform1i(program->getUniform("gradientSampler"), textureSlot);
23706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
23806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
23906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
240759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guyvoid SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& modelView,
241759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        const Snapshot& snapshot) {
242e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    mat4 screenSpace;
243e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy    computeScreenSpaceMatrix(screenSpace, modelView);
244759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
245759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy}
246759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy
24706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
248ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy// Circular gradient shader
249ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy///////////////////////////////////////////////////////////////////////////////
250ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
25114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guystatic void toCircularUnitMatrix(const float x, const float y, const float radius,
25214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy        SkMatrix* matrix) {
25314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    const float inv = 1.0f / radius;
25414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    matrix->setTranslate(-x, -y);
25514830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    matrix->postScale(inv, inv);
25614830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy}
25714830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
258ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain GuySkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float radius,
259ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
260ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        SkMatrix* matrix, bool blend):
261ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        SkiaSweepGradientShader(kCircularGradient, x, y, colors, positions, count, key,
26214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy                tileMode, matrix, blend) {
26314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    SkMatrix unitMatrix;
26414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    toCircularUnitMatrix(x, y, radius, &unitMatrix);
26514830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    mUnitMatrix.load(unitMatrix);
26614830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
26714830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    updateLocalMatrix(matrix);
268ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy}
269ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
27024c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain GuySkiaShader* SkiaCircularGradientShader::copy() {
27124c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    SkiaCircularGradientShader* copy = new SkiaCircularGradientShader();
27224c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->copyFrom(*this);
27324c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mColors = mColors;
27424c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mPositions = mPositions;
27524c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mCount = mCount;
27624c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    return copy;
27724c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy}
27824c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
279ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guyvoid SkiaCircularGradientShader::describe(ProgramDescription& description,
280ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        const Extensions& extensions) {
281ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    description.hasGradient = true;
282ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    description.gradientType = ProgramDescription::kGradientCircular;
283ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy}
284ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
285ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy///////////////////////////////////////////////////////////////////////////////
286ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy// Sweep gradient shader
287ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy///////////////////////////////////////////////////////////////////////////////
288ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
28914830948d02f768c41b97b7a8d15e1b3cab78267Romain Guystatic void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) {
29014830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    matrix->setTranslate(-x, -y);
29114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy}
29214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
293ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain GuySkiaSweepGradientShader::SkiaSweepGradientShader(float x, float y, uint32_t* colors,
294ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        float* positions, int count, SkShader* key, SkMatrix* matrix, bool blend):
295ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        SkiaShader(kSweepGradient, key, SkShader::kClamp_TileMode,
296ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy                SkShader::kClamp_TileMode, matrix, blend),
29714830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy        mColors(colors), mPositions(positions), mCount(count) {
29814830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    SkMatrix unitMatrix;
29914830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    toSweepUnitMatrix(x, y, &unitMatrix);
30014830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    mUnitMatrix.load(unitMatrix);
30114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy
30214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    updateLocalMatrix(matrix);
303ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
304ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
305ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain GuySkiaSweepGradientShader::SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors,
306ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
307ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        SkMatrix* matrix, bool blend):
308ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        SkiaShader(type, key, tileMode, tileMode, matrix, blend),
30914830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy        mColors(colors), mPositions(positions), mCount(count) {
310ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy}
311ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
312ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain GuySkiaSweepGradientShader::~SkiaSweepGradientShader() {
313ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    delete[] mColors;
314ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    delete[] mPositions;
315ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
316ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
31724c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain GuySkiaShader* SkiaSweepGradientShader::copy() {
31824c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    SkiaSweepGradientShader* copy = new SkiaSweepGradientShader();
31924c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->copyFrom(*this);
32024c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mColors = mColors;
32124c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mPositions = mPositions;
32224c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mCount = mCount;
32324c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    return copy;
32424c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy}
32524c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
326ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyvoid SkiaSweepGradientShader::describe(ProgramDescription& description,
327ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        const Extensions& extensions) {
328ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    description.hasGradient = true;
329ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    description.gradientType = ProgramDescription::kGradientSweep;
330ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
331ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
332ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyvoid SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelView,
333ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        const Snapshot& snapshot, GLuint* textureUnit) {
334ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    GLuint textureSlot = (*textureUnit)++;
335ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    glActiveTexture(gTextureUnitsMap[textureSlot]);
336ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
337ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    Texture* texture = mGradientCache->get(mKey);
338ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    if (!texture) {
339ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount);
340ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    }
341ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
34214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    mat4 screenSpace;
34314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    computeScreenSpaceMatrix(screenSpace, modelView);
344ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
345ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    // Uniforms
34601d065795794fa56be660d6346e4830eb7e90a41Romain Guy    bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
347ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    glUniform1i(program->getUniform("gradientSampler"), textureSlot);
348ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
349ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
350ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
351ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyvoid SkiaSweepGradientShader::updateTransforms(Program* program, const mat4& modelView,
352ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        const Snapshot& snapshot) {
35314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    mat4 screenSpace;
35414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy    computeScreenSpaceMatrix(screenSpace, modelView);
355ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
356ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
357ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
358ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy///////////////////////////////////////////////////////////////////////////////
35906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Compose shader
36006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////
36106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
36206f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaComposeShader::SkiaComposeShader(SkiaShader* first, SkiaShader* second,
36306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkXfermode::Mode mode, SkShader* key):
36406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkiaShader(kCompose, key, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
36506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        NULL, first->blend() || second->blend()), mFirst(first), mSecond(second), mMode(mode) {
36606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
36706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
36824c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain GuySkiaShader* SkiaComposeShader::copy() {
36924c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    SkiaComposeShader* copy = new SkiaComposeShader();
37024c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->copyFrom(*this);
37124c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mFirst = mFirst;
37224c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mSecond = mSecond;
37324c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    copy->mMode = mMode;
37424c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    return copy;
37524c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy}
37624c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy
37706f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaComposeShader::set(TextureCache* textureCache, GradientCache* gradientCache) {
37806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    SkiaShader::set(textureCache, gradientCache);
37906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mFirst->set(textureCache, gradientCache);
38006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mSecond->set(textureCache, gradientCache);
38106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
38206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
38306f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaComposeShader::describe(ProgramDescription& description, const Extensions& extensions) {
38406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mFirst->describe(description, extensions);
38506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mSecond->describe(description, extensions);
38606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    if (mFirst->type() == kBitmap) {
38706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        description.isBitmapFirst = true;
38806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
38906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    description.shadersMode = mMode;
39006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
39106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
39206f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaComposeShader::setupProgram(Program* program, const mat4& modelView,
39306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        const Snapshot& snapshot, GLuint* textureUnit) {
39406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mFirst->setupProgram(program, modelView, snapshot, textureUnit);
39506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mSecond->setupProgram(program, modelView, snapshot, textureUnit);
39606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
39706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
39806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}; // namespace uirenderer
39906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}; // namespace android
400