SkiaShader.cpp revision 14830948d02f768c41b97b7a8d15e1b3cab78267
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): 5214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend) { 5314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy setMatrix(matrix); 5406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 5506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 5606f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaShader::~SkiaShader() { 5706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 5806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 5906f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaShader::describe(ProgramDescription& description, const Extensions& extensions) { 6006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 6106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 6206f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaShader::setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, 6306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy GLuint* textureUnit) { 6406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 6506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 6606f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaShader::bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint textureUnit) { 6706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy glActiveTexture(gTextureUnitsMap[textureUnit]); 6806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy glBindTexture(GL_TEXTURE_2D, texture); 6906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); 7006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); 7106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 7206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 7314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guyvoid SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) { 7414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix); 7514830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy screenSpace.multiply(modelView); 7614830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy} 7714830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy 7806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy/////////////////////////////////////////////////////////////////////////////// 7906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Bitmap shader 8006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy/////////////////////////////////////////////////////////////////////////////// 8106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 8206f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaBitmapShader::SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX, 8306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy SkShader::TileMode tileY, SkMatrix* matrix, bool blend): 849cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy SkiaShader(kBitmap, key, tileX, tileY, matrix, blend), mBitmap(bitmap), mTexture(NULL) { 8514830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy updateLocalMatrix(matrix); 8606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 8706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 8806f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaBitmapShader::describe(ProgramDescription& description, const Extensions& extensions) { 8906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy const Texture* texture = mTextureCache->get(mBitmap); 909cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy if (!texture) return; 919cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy mTexture = texture; 9206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 9306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy const float width = texture->width; 9406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy const float height = texture->height; 9506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 9606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy description.hasBitmap = true; 9706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy // The driver does not support non-power of two mirrored/repeated 9806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy // textures, so do it ourselves 9961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) && 10061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy (mTileX != SkShader::kClamp_TileMode || mTileY != SkShader::kClamp_TileMode)) { 10106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy description.isBitmapNpot = true; 10206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy description.bitmapWrapS = gTileModes[mTileX]; 10306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy description.bitmapWrapT = gTileModes[mTileY]; 10429d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy mWrapS = GL_CLAMP_TO_EDGE; 10529d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy mWrapT = GL_CLAMP_TO_EDGE; 10629d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy } else { 10729d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy mWrapS = gTileModes[mTileX]; 10829d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy mWrapT = gTileModes[mTileY]; 10906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy } 11006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 11106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 11206f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView, 11306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy const Snapshot& snapshot, GLuint* textureUnit) { 11406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy GLuint textureSlot = (*textureUnit)++; 11506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy glActiveTexture(gTextureUnitsMap[textureSlot]); 1169cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy 1179cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy const Texture* texture = mTexture; 1189cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy mTexture = NULL; 1199cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy if (!texture) return; 1209cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy const AutoTexture autoCleanup(texture); 12106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 12206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy const float width = texture->width; 12306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy const float height = texture->height; 12406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 12506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mat4 textureTransform; 12614830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy computeScreenSpaceMatrix(textureTransform, modelView); 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; 13914830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy computeScreenSpaceMatrix(textureTransform, modelView); 140759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy glUniformMatrix4fv(program->getUniform("textureTransform"), 1, 141759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy GL_FALSE, &textureTransform.data[0]); 142759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy} 143759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy 14406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy/////////////////////////////////////////////////////////////////////////////// 14506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Linear gradient shader 14606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy/////////////////////////////////////////////////////////////////////////////// 14706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 148e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guystatic void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) { 149e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy SkVector vec = pts[1] - pts[0]; 150e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy const float mag = vec.length(); 151e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy const float inv = mag ? 1.0f / mag : 0; 152e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy 153e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy vec.scale(inv); 154e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY); 155e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy matrix->postTranslate(-pts[0].fX, -pts[0].fY); 156e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy matrix->postScale(inv, inv); 157e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy} 158e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy 15906f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaLinearGradientShader::SkiaLinearGradientShader(float* bounds, uint32_t* colors, 16006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy float* positions, int count, SkShader* key, SkShader::TileMode tileMode, 16106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy SkMatrix* matrix, bool blend): 16206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy SkiaShader(kLinearGradient, key, tileMode, tileMode, matrix, blend), 16306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mBounds(bounds), mColors(colors), mPositions(positions), mCount(count) { 164e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy SkPoint points[2]; 165e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy points[0].set(bounds[0], bounds[1]); 166e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy points[1].set(bounds[2], bounds[3]); 167e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy 168e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy SkMatrix unitMatrix; 169e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy toUnitMatrix(points, &unitMatrix); 170e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy mUnitMatrix.load(unitMatrix); 171e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy 172e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy updateLocalMatrix(matrix); 17306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 17406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 17506f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaLinearGradientShader::~SkiaLinearGradientShader() { 17625ee037fee1607e8a77b1f2e259356e74dd6f645Romain Guy delete[] mBounds; 17725ee037fee1607e8a77b1f2e259356e74dd6f645Romain Guy delete[] mColors; 17825ee037fee1607e8a77b1f2e259356e74dd6f645Romain Guy delete[] mPositions; 17906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 18006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 18106f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaLinearGradientShader::describe(ProgramDescription& description, 18206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy const Extensions& extensions) { 18306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy description.hasGradient = true; 184ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy description.gradientType = ProgramDescription::kGradientLinear; 18506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 18606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 18706f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView, 18806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy const Snapshot& snapshot, GLuint* textureUnit) { 18906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy GLuint textureSlot = (*textureUnit)++; 19006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy glActiveTexture(gTextureUnitsMap[textureSlot]); 19106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 19206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy Texture* texture = mGradientCache->get(mKey); 19306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy if (!texture) { 194ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount, mTileX); 19506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy } 19606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 197e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy mat4 screenSpace; 198e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy computeScreenSpaceMatrix(screenSpace, modelView); 19906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 20006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy // Uniforms 20106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy bindTexture(texture->id, gTileModes[mTileX], gTileModes[mTileY], textureSlot); 20206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy glUniform1i(program->getUniform("gradientSampler"), textureSlot); 20306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); 20406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 20506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 206759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guyvoid SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& modelView, 207759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy const Snapshot& snapshot) { 208e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy mat4 screenSpace; 209e3095e0c1e2a4a4f34f741aa386eae56536ca5aaRomain Guy computeScreenSpaceMatrix(screenSpace, modelView); 210759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); 211759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy} 212759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy 21306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy/////////////////////////////////////////////////////////////////////////////// 214ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy// Circular gradient shader 215ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy/////////////////////////////////////////////////////////////////////////////// 216ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy 21714830948d02f768c41b97b7a8d15e1b3cab78267Romain Guystatic void toCircularUnitMatrix(const float x, const float y, const float radius, 21814830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy SkMatrix* matrix) { 21914830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy const float inv = 1.0f / radius; 22014830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy matrix->setTranslate(-x, -y); 22114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy matrix->postScale(inv, inv); 22214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy} 22314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy 224ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain GuySkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float radius, 225ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode, 226ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy SkMatrix* matrix, bool blend): 227ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy SkiaSweepGradientShader(kCircularGradient, x, y, colors, positions, count, key, 22814830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy tileMode, matrix, blend) { 22914830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy SkMatrix unitMatrix; 23014830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy toCircularUnitMatrix(x, y, radius, &unitMatrix); 23114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy mUnitMatrix.load(unitMatrix); 23214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy 23314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy updateLocalMatrix(matrix); 234ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy} 235ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy 236ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guyvoid SkiaCircularGradientShader::describe(ProgramDescription& description, 237ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy const Extensions& extensions) { 238ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy description.hasGradient = true; 239ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy description.gradientType = ProgramDescription::kGradientCircular; 240ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy} 241ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy 242ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy/////////////////////////////////////////////////////////////////////////////// 243ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy// Sweep gradient shader 244ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy/////////////////////////////////////////////////////////////////////////////// 245ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy 24614830948d02f768c41b97b7a8d15e1b3cab78267Romain Guystatic void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) { 24714830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy matrix->setTranslate(-x, -y); 24814830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy} 24914830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy 250ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain GuySkiaSweepGradientShader::SkiaSweepGradientShader(float x, float y, uint32_t* colors, 251ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy float* positions, int count, SkShader* key, SkMatrix* matrix, bool blend): 252ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy SkiaShader(kSweepGradient, key, SkShader::kClamp_TileMode, 253ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy SkShader::kClamp_TileMode, matrix, blend), 25414830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy mColors(colors), mPositions(positions), mCount(count) { 25514830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy SkMatrix unitMatrix; 25614830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy toSweepUnitMatrix(x, y, &unitMatrix); 25714830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy mUnitMatrix.load(unitMatrix); 25814830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy 25914830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy updateLocalMatrix(matrix); 260ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy} 261ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy 262ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain GuySkiaSweepGradientShader::SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, 263ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy float* positions, int count, SkShader* key, SkShader::TileMode tileMode, 264ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy SkMatrix* matrix, bool blend): 265ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy SkiaShader(type, key, tileMode, tileMode, matrix, blend), 26614830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy mColors(colors), mPositions(positions), mCount(count) { 267ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy} 268ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy 269ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain GuySkiaSweepGradientShader::~SkiaSweepGradientShader() { 270ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy delete[] mColors; 271ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy delete[] mPositions; 272ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy} 273ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy 274ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyvoid SkiaSweepGradientShader::describe(ProgramDescription& description, 275ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy const Extensions& extensions) { 276ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy description.hasGradient = true; 277ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy description.gradientType = ProgramDescription::kGradientSweep; 278ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy} 279ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy 280ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyvoid SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelView, 281ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy const Snapshot& snapshot, GLuint* textureUnit) { 282ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy GLuint textureSlot = (*textureUnit)++; 283ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy glActiveTexture(gTextureUnitsMap[textureSlot]); 284ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy 285ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy Texture* texture = mGradientCache->get(mKey); 286ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy if (!texture) { 287ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount); 288ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy } 289ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy 29014830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy mat4 screenSpace; 29114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy computeScreenSpaceMatrix(screenSpace, modelView); 292ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy 293ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Uniforms 294ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy bindTexture(texture->id, gTileModes[mTileX], gTileModes[mTileY], textureSlot); 295ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy glUniform1i(program->getUniform("gradientSampler"), textureSlot); 296ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); 297ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy} 298ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy 299ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyvoid SkiaSweepGradientShader::updateTransforms(Program* program, const mat4& modelView, 300ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy const Snapshot& snapshot) { 30114830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy mat4 screenSpace; 30214830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy computeScreenSpaceMatrix(screenSpace, modelView); 303ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); 304ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy} 305ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy 306ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy/////////////////////////////////////////////////////////////////////////////// 30706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy// Compose shader 30806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy/////////////////////////////////////////////////////////////////////////////// 30906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 31006f96e2652e4855b6520ad9dd70583677605b79aRomain GuySkiaComposeShader::SkiaComposeShader(SkiaShader* first, SkiaShader* second, 31106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy SkXfermode::Mode mode, SkShader* key): 31206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy SkiaShader(kCompose, key, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, 31306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy NULL, first->blend() || second->blend()), mFirst(first), mSecond(second), mMode(mode) { 31406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 31506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 31606f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaComposeShader::set(TextureCache* textureCache, GradientCache* gradientCache) { 31706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy SkiaShader::set(textureCache, gradientCache); 31806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mFirst->set(textureCache, gradientCache); 31906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mSecond->set(textureCache, gradientCache); 32006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 32106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 32206f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaComposeShader::describe(ProgramDescription& description, const Extensions& extensions) { 32306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mFirst->describe(description, extensions); 32406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mSecond->describe(description, extensions); 32506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy if (mFirst->type() == kBitmap) { 32606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy description.isBitmapFirst = true; 32706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy } 32806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy description.shadersMode = mMode; 32906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 33006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 33106f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid SkiaComposeShader::setupProgram(Program* program, const mat4& modelView, 33206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy const Snapshot& snapshot, GLuint* textureUnit) { 33306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mFirst->setupProgram(program, modelView, snapshot, textureUnit); 33406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mSecond->setupProgram(program, modelView, snapshot, textureUnit); 33506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 33606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 33706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}; // namespace uirenderer 33806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}; // namespace android 339