SkiaShader.cpp revision 64bb413a664001c95c8439cf097dc3033f4ed733
1110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams/* 2110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams * Copyright (C) 2010 The Android Open Source Project 3110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams * 4110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams * Licensed under the Apache License, Version 2.0 (the "License"); 5110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams * you may not use this file except in compliance with the License. 6110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams * You may obtain a copy of the License at 7110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams * 8110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams * http://www.apache.org/licenses/LICENSE-2.0 9110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams * 10110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams * Unless required by applicable law or agreed to in writing, software 11110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams * distributed under the License is distributed on an "AS IS" BASIS, 12110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams * See the License for the specific language governing permissions and 14110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams * limitations under the License. 15110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams */ 16110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams 17a90842283e322b1210e2bea5850b05177e3d87afTim Murray#define LOG_TAG "OpenGLRenderer" 18a90842283e322b1210e2bea5850b05177e3d87afTim Murray 19c11e25c4e653124def1fb18e203b894f42106cbeTim Murray#include <utils/Log.h> 2011518acc8c416023d8c2192b441a1767205676d9Robert Ly 21c11e25c4e653124def1fb18e203b894f42106cbeTim Murray#include <SkMatrix.h> 2211518acc8c416023d8c2192b441a1767205676d9Robert Ly 2311518acc8c416023d8c2192b441a1767205676d9Robert Ly#include "Caches.h" 2411518acc8c416023d8c2192b441a1767205676d9Robert Ly#include "Extensions.h" 2511518acc8c416023d8c2192b441a1767205676d9Robert Ly#include "Layer.h" 2611518acc8c416023d8c2192b441a1767205676d9Robert Ly#include "Matrix.h" 2711518acc8c416023d8c2192b441a1767205676d9Robert Ly#include "SkiaShader.h" 2811518acc8c416023d8c2192b441a1767205676d9Robert Ly#include "Texture.h" 2911518acc8c416023d8c2192b441a1767205676d9Robert Ly 3011518acc8c416023d8c2192b441a1767205676d9Robert Lynamespace android { 31c11e25c4e653124def1fb18e203b894f42106cbeTim Murraynamespace uirenderer { 3211518acc8c416023d8c2192b441a1767205676d9Robert Ly 3311518acc8c416023d8c2192b441a1767205676d9Robert Ly/////////////////////////////////////////////////////////////////////////////// 3411518acc8c416023d8c2192b441a1767205676d9Robert Ly// Support 3511518acc8c416023d8c2192b441a1767205676d9Robert Ly/////////////////////////////////////////////////////////////////////////////// 3611518acc8c416023d8c2192b441a1767205676d9Robert Ly 3711518acc8c416023d8c2192b441a1767205676d9Robert Lystatic const GLint gTileModes[] = { 3811518acc8c416023d8c2192b441a1767205676d9Robert Ly GL_CLAMP_TO_EDGE, // == SkShader::kClamp_TileMode 39110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams GL_REPEAT, // == SkShader::kRepeat_Mode 40110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams GL_MIRRORED_REPEAT // == SkShader::kMirror_TileMode 41110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams}; 42c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk 43110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams/** 44110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams * This function does not work for n == 0. 45110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams */ 469c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hinesstatic inline bool isPowerOfTwo(unsigned int n) { 47a90842283e322b1210e2bea5850b05177e3d87afTim Murray return !(n & (n - 1)); 48d4ca9910982853e50429ea9233f2150ca619b3d8Jason Sams} 49df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk 50df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchoukstatic inline void bindUniformColor(int slot, uint32_t color) { 51df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk const float a = ((color >> 24) & 0xff) / 255.0f; 52110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams glUniform4f(slot, 53110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams a * ((color >> 16) & 0xff) / 255.0f, 540011bcf57ff711a221a3a4c73f2a79125111647dJason Sams a * ((color >> 8) & 0xff) / 255.0f, 550011bcf57ff711a221a3a4c73f2a79125111647dJason Sams a * ((color ) & 0xff) / 255.0f, 56460a04971c494fec39ffcb38e873bb8fdd82d113Tim Murray a); 570011bcf57ff711a221a3a4c73f2a79125111647dJason Sams} 58110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams 59110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Samsstatic inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) { 609c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines caches->bindTexture(texture->id); 61d4ca9910982853e50429ea9233f2150ca619b3d8Jason Sams texture->setWrapST(wrapS, wrapT); 62918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk} 63d5a62bb802887134ed652b01fa6a3159a5c6ad0eAlex Sakhartchouk 64d5a62bb802887134ed652b01fa6a3159a5c6ad0eAlex Sakhartchouk/** 65d5a62bb802887134ed652b01fa6a3159a5c6ad0eAlex Sakhartchouk * Compute the matrix to transform to screen space. 66d5a62bb802887134ed652b01fa6a3159a5c6ad0eAlex Sakhartchouk * @param screenSpace Output param for the computed matrix. 67d5a62bb802887134ed652b01fa6a3159a5c6ad0eAlex Sakhartchouk * @param unitMatrix The unit matrix for gradient shaders, as returned by SkShader::asAGradient, 689c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines * or identity. 69d4ca9910982853e50429ea9233f2150ca619b3d8Jason Sams * @param localMatrix Local matrix, as returned by SkShader::getLocalMatrix(). 70918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk * @param modelViewMatrix Model view matrix, as supplied by the OpenGLRenderer. 71918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk */ 72d5a62bb802887134ed652b01fa6a3159a5c6ad0eAlex Sakhartchoukstatic void computeScreenSpaceMatrix(mat4& screenSpace, const SkMatrix& unitMatrix, 73d5a62bb802887134ed652b01fa6a3159a5c6ad0eAlex Sakhartchouk const SkMatrix& localMatrix, const mat4& modelViewMatrix) { 74d5a62bb802887134ed652b01fa6a3159a5c6ad0eAlex Sakhartchouk mat4 shaderMatrix; 75d5a62bb802887134ed652b01fa6a3159a5c6ad0eAlex Sakhartchouk // uses implicit construction 76d5a62bb802887134ed652b01fa6a3159a5c6ad0eAlex Sakhartchouk shaderMatrix.loadInverse(localMatrix); 77d5a62bb802887134ed652b01fa6a3159a5c6ad0eAlex Sakhartchouk // again, uses implicit construction 78d5a62bb802887134ed652b01fa6a3159a5c6ad0eAlex Sakhartchouk screenSpace.loadMultiply(unitMatrix, shaderMatrix); 79d5a62bb802887134ed652b01fa6a3159a5c6ad0eAlex Sakhartchouk screenSpace.multiply(modelViewMatrix); 809c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines} 81a90842283e322b1210e2bea5850b05177e3d87afTim Murray 82a90842283e322b1210e2bea5850b05177e3d87afTim Murray// Returns true if one is a bitmap and the other is a gradient 83a90842283e322b1210e2bea5850b05177e3d87afTim Murraystatic bool bitmapAndGradient(SkiaShaderType type1, SkiaShaderType type2) { 84a90842283e322b1210e2bea5850b05177e3d87afTim Murray return (type1 == kBitmap_SkiaShaderType && type2 == kGradient_SkiaShaderType) 85a90842283e322b1210e2bea5850b05177e3d87afTim Murray || (type2 == kBitmap_SkiaShaderType && type1 == kGradient_SkiaShaderType); 86a90842283e322b1210e2bea5850b05177e3d87afTim Murray} 87a90842283e322b1210e2bea5850b05177e3d87afTim Murray 88a90842283e322b1210e2bea5850b05177e3d87afTim MurraySkiaShaderType SkiaShader::getType(const SkShader& shader) { 89a90842283e322b1210e2bea5850b05177e3d87afTim Murray // First check for a gradient shader. 90b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk switch (shader.asAGradient(NULL)) { 919c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines case SkShader::kNone_GradientType: 92d4ca9910982853e50429ea9233f2150ca619b3d8Jason Sams // Not a gradient shader. Fall through to check for other types. 93df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk break; 94df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk case SkShader::kLinear_GradientType: 95f5c876e82d7cc647ba94d29eb914e64b7977c303Alex Sakhartchouk case SkShader::kRadial_GradientType: 96df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk case SkShader::kSweep_GradientType: 97b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk return kGradient_SkiaShaderType; 980011bcf57ff711a221a3a4c73f2a79125111647dJason Sams default: 99110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams // This is a Skia gradient that has no SkiaShader equivalent. Return None to skip. 100110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams return kNone_SkiaShaderType; 1019c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines } 102d4ca9910982853e50429ea9233f2150ca619b3d8Jason Sams 103df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk // The shader is not a gradient. Check for a bitmap shader. 104df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk if (shader.asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType) { 105df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk return kBitmap_SkiaShaderType; 106df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk } 107df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk 108df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk // Check for a ComposeShader. 109b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk SkShader::ComposeRec rec; 110b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk if (shader.asACompose(&rec)) { 111b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk const SkiaShaderType shaderAType = getType(*rec.fShaderA); 112b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk const SkiaShaderType shaderBType = getType(*rec.fShaderB); 113b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk 114b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk // Compose is only supported if one is a bitmap and the other is a 115b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk // gradient. Otherwise, return None to skip. 116b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk if (!bitmapAndGradient(shaderAType, shaderBType)) { 117b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk return kNone_SkiaShaderType; 118b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk } 119b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk return kCompose_SkiaShaderType; 120b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk } 1219c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines 122d4ca9910982853e50429ea9233f2150ca619b3d8Jason Sams if (shader.asACustomShader(NULL)) { 123df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk return kLayer_SkiaShaderType; 124df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk } 125df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk 126df27202debdc2573b7882405010fba31ee4d46e6Alex Sakhartchouk return kNone_SkiaShaderType; 1270011bcf57ff711a221a3a4c73f2a79125111647dJason Sams} 1280011bcf57ff711a221a3a4c73f2a79125111647dJason Sams 12967f2e442a31b8395e3c1951f8e91139ec7f2be99Alex Sakhartchouktypedef void (*describeProc)(Caches* caches, ProgramDescription& description, 1302123b46ba85adb2cfb78068f8368e830640118d3Alex Sakhartchouk const Extensions& extensions, const SkShader& shader); 1310011bcf57ff711a221a3a4c73f2a79125111647dJason Sams 132110195fe9ff96255242bfa4df1d15c6a56b140d6Jason SamsdescribeProc gDescribeProc[] = { 1330011bcf57ff711a221a3a4c73f2a79125111647dJason Sams InvalidSkiaShader::describe, 13467f2e442a31b8395e3c1951f8e91139ec7f2be99Alex Sakhartchouk SkiaBitmapShader::describe, 135460a04971c494fec39ffcb38e873bb8fdd82d113Tim Murray SkiaGradientShader::describe, 136110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams SkiaComposeShader::describe, 1370011bcf57ff711a221a3a4c73f2a79125111647dJason Sams SkiaLayerShader::describe, 13867f2e442a31b8395e3c1951f8e91139ec7f2be99Alex Sakhartchouk}; 139460a04971c494fec39ffcb38e873bb8fdd82d113Tim Murray 140110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Samstypedef void (*setupProgramProc)(Caches* caches, const mat4& modelViewMatrix, 1410011bcf57ff711a221a3a4c73f2a79125111647dJason Sams GLuint* textureUnit, const Extensions& extensions, const SkShader& shader); 14267f2e442a31b8395e3c1951f8e91139ec7f2be99Alex Sakhartchouk 143460a04971c494fec39ffcb38e873bb8fdd82d113Tim MurraysetupProgramProc gSetupProgramProc[] = { 1440011bcf57ff711a221a3a4c73f2a79125111647dJason Sams InvalidSkiaShader::setupProgram, 14567f2e442a31b8395e3c1951f8e91139ec7f2be99Alex Sakhartchouk SkiaBitmapShader::setupProgram, 14667f2e442a31b8395e3c1951f8e91139ec7f2be99Alex Sakhartchouk SkiaGradientShader::setupProgram, 147460a04971c494fec39ffcb38e873bb8fdd82d113Tim Murray SkiaComposeShader::setupProgram, 1482123b46ba85adb2cfb78068f8368e830640118d3Alex Sakhartchouk SkiaLayerShader::setupProgram, 14967f2e442a31b8395e3c1951f8e91139ec7f2be99Alex Sakhartchouk}; 150110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams 151460a04971c494fec39ffcb38e873bb8fdd82d113Tim Murrayvoid SkiaShader::describe(Caches* caches, ProgramDescription& description, 1520011bcf57ff711a221a3a4c73f2a79125111647dJason Sams const Extensions& extensions, const SkShader& shader) { 1530011bcf57ff711a221a3a4c73f2a79125111647dJason Sams gDescribeProc[getType(shader)](caches, description, extensions, shader); 1540011bcf57ff711a221a3a4c73f2a79125111647dJason Sams} 155110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams 156110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Samsvoid SkiaShader::setupProgram(Caches* caches, const mat4& modelViewMatrix, 157110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) { 158110195fe9ff96255242bfa4df1d15c6a56b140d6Jason Sams 159 gSetupProgramProc[getType(shader)](caches, modelViewMatrix, textureUnit, extensions, shader); 160} 161 162/////////////////////////////////////////////////////////////////////////////// 163// Layer shader 164/////////////////////////////////////////////////////////////////////////////// 165 166void SkiaLayerShader::describe(Caches*, ProgramDescription& description, 167 const Extensions&, const SkShader& shader) { 168 description.hasBitmap = true; 169} 170 171void SkiaLayerShader::setupProgram(Caches* caches, const mat4& modelViewMatrix, 172 GLuint* textureUnit, const Extensions&, const SkShader& shader) { 173 Layer* layer; 174 if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) { 175 LOG_ALWAYS_FATAL("SkiaLayerShader::setupProgram called on the wrong type of shader!"); 176 } 177 178 GLuint textureSlot = (*textureUnit)++; 179 caches->activeTexture(textureSlot); 180 181 const float width = layer->getWidth(); 182 const float height = layer->getHeight(); 183 184 mat4 textureTransform; 185 computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(), 186 modelViewMatrix); 187 188 189 // Uniforms 190 layer->bindTexture(); 191 layer->setWrap(GL_CLAMP_TO_EDGE); 192 layer->setFilter(GL_LINEAR); 193 194 Program* program = caches->currentProgram; 195 glUniform1i(program->getUniform("bitmapSampler"), textureSlot); 196 glUniformMatrix4fv(program->getUniform("textureTransform"), 1, 197 GL_FALSE, &textureTransform.data[0]); 198 glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height); 199} 200 201/////////////////////////////////////////////////////////////////////////////// 202// Bitmap shader 203/////////////////////////////////////////////////////////////////////////////// 204 205struct BitmapShaderInfo { 206 float width; 207 float height; 208 GLenum wrapS; 209 GLenum wrapT; 210 Texture* texture; 211}; 212 213static bool bitmapShaderHelper(Caches* caches, ProgramDescription* description, 214 BitmapShaderInfo* shaderInfo, 215 const Extensions& extensions, 216 const SkBitmap& bitmap, SkShader::TileMode tileModes[2]) { 217 Texture* texture = caches->textureCache.get(&bitmap); 218 if (!texture) return false; 219 220 const float width = texture->width; 221 const float height = texture->height; 222 GLenum wrapS, wrapT; 223 224 if (description) { 225 description->hasBitmap = true; 226 } 227 // The driver does not support non-power of two mirrored/repeated 228 // textures, so do it ourselves 229 if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) && 230 (tileModes[0] != SkShader::kClamp_TileMode || 231 tileModes[1] != SkShader::kClamp_TileMode)) { 232 if (description) { 233 description->isBitmapNpot = true; 234 description->bitmapWrapS = gTileModes[tileModes[0]]; 235 description->bitmapWrapT = gTileModes[tileModes[1]]; 236 } 237 wrapS = GL_CLAMP_TO_EDGE; 238 wrapT = GL_CLAMP_TO_EDGE; 239 } else { 240 wrapS = gTileModes[tileModes[0]]; 241 wrapT = gTileModes[tileModes[1]]; 242 } 243 244 if (shaderInfo) { 245 shaderInfo->width = width; 246 shaderInfo->height = height; 247 shaderInfo->wrapS = wrapS; 248 shaderInfo->wrapT = wrapT; 249 shaderInfo->texture = texture; 250 } 251 return true; 252} 253 254void SkiaBitmapShader::describe(Caches* caches, ProgramDescription& description, 255 const Extensions& extensions, const SkShader& shader) { 256 SkBitmap bitmap; 257 SkShader::TileMode xy[2]; 258 if (shader.asABitmap(&bitmap, NULL, xy) != SkShader::kDefault_BitmapType) { 259 LOG_ALWAYS_FATAL("SkiaBitmapShader::describe called with a different kind of shader!"); 260 } 261 bitmapShaderHelper(caches, &description, NULL, extensions, bitmap, xy); 262} 263 264void SkiaBitmapShader::setupProgram(Caches* caches, const mat4& modelViewMatrix, 265 GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) { 266 SkBitmap bitmap; 267 SkShader::TileMode xy[2]; 268 if (shader.asABitmap(&bitmap, NULL, xy) != SkShader::kDefault_BitmapType) { 269 LOG_ALWAYS_FATAL("SkiaBitmapShader::setupProgram called with a different kind of shader!"); 270 } 271 272 GLuint textureSlot = (*textureUnit)++; 273 Caches::getInstance().activeTexture(textureSlot); 274 275 BitmapShaderInfo shaderInfo; 276 if (!bitmapShaderHelper(caches, NULL, &shaderInfo, extensions, bitmap, xy)) { 277 return; 278 } 279 280 Program* program = caches->currentProgram; 281 Texture* texture = shaderInfo.texture; 282 283 const AutoTexture autoCleanup(texture); 284 285 mat4 textureTransform; 286 computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(), 287 modelViewMatrix); 288 289 // Uniforms 290 bindTexture(caches, texture, shaderInfo.wrapS, shaderInfo.wrapT); 291 texture->setFilter(GL_LINEAR); 292 293 glUniform1i(program->getUniform("bitmapSampler"), textureSlot); 294 glUniformMatrix4fv(program->getUniform("textureTransform"), 1, 295 GL_FALSE, &textureTransform.data[0]); 296 glUniform2f(program->getUniform("textureDimension"), 1.0f / shaderInfo.width, 297 1.0f / shaderInfo.height); 298} 299 300/////////////////////////////////////////////////////////////////////////////// 301// Linear gradient shader 302/////////////////////////////////////////////////////////////////////////////// 303 304static void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) { 305 SkVector vec = pts[1] - pts[0]; 306 const float mag = vec.length(); 307 const float inv = mag ? 1.0f / mag : 0; 308 309 vec.scale(inv); 310 matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY); 311 matrix->postTranslate(-pts[0].fX, -pts[0].fY); 312 matrix->postScale(inv, inv); 313} 314 315/////////////////////////////////////////////////////////////////////////////// 316// Circular gradient shader 317/////////////////////////////////////////////////////////////////////////////// 318 319static void toCircularUnitMatrix(const float x, const float y, const float radius, 320 SkMatrix* matrix) { 321 const float inv = 1.0f / radius; 322 matrix->setTranslate(-x, -y); 323 matrix->postScale(inv, inv); 324} 325 326/////////////////////////////////////////////////////////////////////////////// 327// Sweep gradient shader 328/////////////////////////////////////////////////////////////////////////////// 329 330static void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) { 331 matrix->setTranslate(-x, -y); 332} 333 334/////////////////////////////////////////////////////////////////////////////// 335// Common gradient code 336/////////////////////////////////////////////////////////////////////////////// 337 338static bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) { 339 return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode; 340} 341 342void SkiaGradientShader::describe(Caches*, ProgramDescription& description, 343 const Extensions& extensions, const SkShader& shader) { 344 SkShader::GradientInfo gradInfo; 345 gradInfo.fColorCount = 0; 346 gradInfo.fColors = NULL; 347 gradInfo.fColorOffsets = NULL; 348 349 switch (shader.asAGradient(&gradInfo)) { 350 case SkShader::kLinear_GradientType: 351 description.gradientType = ProgramDescription::kGradientLinear; 352 break; 353 case SkShader::kRadial_GradientType: 354 description.gradientType = ProgramDescription::kGradientCircular; 355 break; 356 case SkShader::kSweep_GradientType: 357 description.gradientType = ProgramDescription::kGradientSweep; 358 break; 359 default: 360 // Do nothing. This shader is unsupported. 361 return; 362 } 363 description.hasGradient = true; 364 description.isSimpleGradient = isSimpleGradient(gradInfo); 365} 366 367void SkiaGradientShader::setupProgram(Caches* caches, const mat4& modelViewMatrix, 368 GLuint* textureUnit, const Extensions&, const SkShader& shader) { 369 // SkShader::GradientInfo.fColorCount is an in/out parameter. As input, it tells asAGradient 370 // how much space has been allocated for fColors and fColorOffsets. 10 was chosen 371 // arbitrarily, but should be >= 2. 372 // As output, it tells the number of actual colors/offsets in the gradient. 373 const int COLOR_COUNT = 10; 374 SkAutoSTMalloc<COLOR_COUNT, SkColor> colorStorage(COLOR_COUNT); 375 SkAutoSTMalloc<COLOR_COUNT, SkScalar> positionStorage(COLOR_COUNT); 376 377 SkShader::GradientInfo gradInfo; 378 gradInfo.fColorCount = COLOR_COUNT; 379 gradInfo.fColors = colorStorage.get(); 380 gradInfo.fColorOffsets = positionStorage.get(); 381 382 SkShader::GradientType gradType = shader.asAGradient(&gradInfo); 383 384 Program* program = caches->currentProgram; 385 if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) { 386 if (gradInfo.fColorCount > COLOR_COUNT) { 387 // There was not enough room in our arrays for all the colors and offsets. Try again, 388 // now that we know the true number of colors. 389 gradInfo.fColors = colorStorage.reset(gradInfo.fColorCount); 390 gradInfo.fColorOffsets = positionStorage.reset(gradInfo.fColorCount); 391 392 shader.asAGradient(&gradInfo); 393 } 394 GLuint textureSlot = (*textureUnit)++; 395 caches->activeTexture(textureSlot); 396 397#ifndef SK_SCALAR_IS_FLOAT 398 #error Need to convert gradInfo.fColorOffsets to float! 399#endif 400 Texture* texture = caches->gradientCache.get(gradInfo.fColors, gradInfo.fColorOffsets, 401 gradInfo.fColorCount); 402 403 // Uniforms 404 bindTexture(caches, texture, gTileModes[gradInfo.fTileMode], gTileModes[gradInfo.fTileMode]); 405 glUniform1i(program->getUniform("gradientSampler"), textureSlot); 406 } else { 407 bindUniformColor(program->getUniform("startColor"), gradInfo.fColors[0]); 408 bindUniformColor(program->getUniform("endColor"), gradInfo.fColors[1]); 409 } 410 411 caches->dither.setupProgram(program, textureUnit); 412 413 SkMatrix unitMatrix; 414 switch (gradType) { 415 case SkShader::kLinear_GradientType: 416 toUnitMatrix(gradInfo.fPoint, &unitMatrix); 417 break; 418 case SkShader::kRadial_GradientType: 419 toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, 420 gradInfo.fRadius[0], &unitMatrix); 421 break; 422 case SkShader::kSweep_GradientType: 423 toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix); 424 break; 425 default: 426 LOG_ALWAYS_FATAL("Invalid SkShader gradient type %d", gradType); 427 } 428 429 mat4 screenSpace; 430 computeScreenSpaceMatrix(screenSpace, unitMatrix, shader.getLocalMatrix(), modelViewMatrix); 431 glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); 432} 433 434/////////////////////////////////////////////////////////////////////////////// 435// Compose shader 436/////////////////////////////////////////////////////////////////////////////// 437 438void SkiaComposeShader::describe(Caches* caches, ProgramDescription& description, 439 const Extensions& extensions, const SkShader& shader) { 440 SkShader::ComposeRec rec; 441 if (!shader.asACompose(&rec)) { 442 LOG_ALWAYS_FATAL("SkiaComposeShader::describe called on the wrong shader type!"); 443 } 444 SkiaShader::describe(caches, description, extensions, *rec.fShaderA); 445 SkiaShader::describe(caches, description, extensions, *rec.fShaderB); 446 if (SkiaShader::getType(*rec.fShaderA) == kBitmap_SkiaShaderType) { 447 description.isBitmapFirst = true; 448 } 449 if (!SkXfermode::AsMode(rec.fMode, &description.shadersMode)) { 450 // TODO: Support other modes. 451 description.shadersMode = SkXfermode::kSrcOver_Mode; 452 } 453} 454 455void SkiaComposeShader::setupProgram(Caches* caches, const mat4& modelViewMatrix, 456 GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) { 457 SkShader::ComposeRec rec; 458 if (!shader.asACompose(&rec)) { 459 LOG_ALWAYS_FATAL("SkiaComposeShader::setupProgram called on the wrong shader type!"); 460 } 461 462 // Apply this compose shader's local transform and pass it down to 463 // the child shaders. They will in turn apply their local transform 464 // to this matrix. 465 mat4 transform; 466 computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(), 467 modelViewMatrix); 468 469 SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderA); 470 SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderB); 471} 472 473}; // namespace uirenderer 474}; // namespace android 475