blob: dff19a9e9c58acce673858448a75fd80d1e9d42c [file] [log] [blame]
Romain Guy06f96e22010-07-30 19:18:16 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "OpenGLRenderer"
18
19#include <utils/Log.h>
20
21#include <SkMatrix.h>
22
Romain Guya1d3c912011-12-13 14:55:06 -080023#include "Caches.h"
Tom Hudson2dc236b2014-10-15 15:46:42 -040024#include "Extensions.h"
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -040025#include "Layer.h"
26#include "Matrix.h"
Romain Guy06f96e22010-07-30 19:18:16 -070027#include "SkiaShader.h"
28#include "Texture.h"
Romain Guy06f96e22010-07-30 19:18:16 -070029
30namespace android {
31namespace uirenderer {
32
33///////////////////////////////////////////////////////////////////////////////
34// Support
35///////////////////////////////////////////////////////////////////////////////
36
Romain Guy06f96e22010-07-30 19:18:16 -070037static const GLint gTileModes[] = {
38 GL_CLAMP_TO_EDGE, // == SkShader::kClamp_TileMode
39 GL_REPEAT, // == SkShader::kRepeat_Mode
40 GL_MIRRORED_REPEAT // == SkShader::kMirror_TileMode
41};
42
Romain Guy42e1e0d2012-07-30 14:47:51 -070043/**
44 * This function does not work for n == 0.
45 */
46static inline bool isPowerOfTwo(unsigned int n) {
47 return !(n & (n - 1));
48}
49
50static inline void bindUniformColor(int slot, uint32_t color) {
Romain Guyd679b572012-08-29 21:49:00 -070051 const float a = ((color >> 24) & 0xff) / 255.0f;
Romain Guy42e1e0d2012-07-30 14:47:51 -070052 glUniform4f(slot,
Romain Guyd679b572012-08-29 21:49:00 -070053 a * ((color >> 16) & 0xff) / 255.0f,
54 a * ((color >> 8) & 0xff) / 255.0f,
55 a * ((color ) & 0xff) / 255.0f,
56 a);
Romain Guy42e1e0d2012-07-30 14:47:51 -070057}
58
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -040059static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) {
60 caches->bindTexture(texture->id);
Romain Guyd21b6e12011-11-30 20:21:23 -080061 texture->setWrapST(wrapS, wrapT);
Romain Guy06f96e22010-07-30 19:18:16 -070062}
63
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -040064/**
65 * Compute the matrix to transform to screen space.
66 * @param screenSpace Output param for the computed matrix.
67 * @param unitMatrix The unit matrix for gradient shaders, as returned by SkShader::asAGradient,
68 * or identity.
69 * @param localMatrix Local matrix, as returned by SkShader::getLocalMatrix().
70 * @param modelViewMatrix Model view matrix, as supplied by the OpenGLRenderer.
71 */
72static void computeScreenSpaceMatrix(mat4& screenSpace, const SkMatrix& unitMatrix,
73 const SkMatrix& localMatrix, const mat4& modelViewMatrix) {
74 mat4 shaderMatrix;
75 // uses implicit construction
76 shaderMatrix.loadInverse(localMatrix);
77 // again, uses implicit construction
78 screenSpace.loadMultiply(unitMatrix, shaderMatrix);
79 screenSpace.multiply(modelViewMatrix);
80}
81
82// Returns true if one is a bitmap and the other is a gradient
83static bool bitmapAndGradient(SkiaShaderType type1, SkiaShaderType type2) {
84 return (type1 == kBitmap_SkiaShaderType && type2 == kGradient_SkiaShaderType)
85 || (type2 == kBitmap_SkiaShaderType && type1 == kGradient_SkiaShaderType);
86}
87
88SkiaShaderType SkiaShader::getType(const SkShader& shader) {
89 // First check for a gradient shader.
90 switch (shader.asAGradient(NULL)) {
91 case SkShader::kNone_GradientType:
92 // Not a gradient shader. Fall through to check for other types.
93 break;
94 case SkShader::kLinear_GradientType:
95 case SkShader::kRadial_GradientType:
96 case SkShader::kSweep_GradientType:
97 return kGradient_SkiaShaderType;
98 default:
99 // This is a Skia gradient that has no SkiaShader equivalent. Return None to skip.
100 return kNone_SkiaShaderType;
101 }
102
103 // The shader is not a gradient. Check for a bitmap shader.
104 if (shader.asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType) {
105 return kBitmap_SkiaShaderType;
106 }
107
108 // Check for a ComposeShader.
109 SkShader::ComposeRec rec;
110 if (shader.asACompose(&rec)) {
111 const SkiaShaderType shaderAType = getType(*rec.fShaderA);
112 const SkiaShaderType shaderBType = getType(*rec.fShaderB);
113
114 // Compose is only supported if one is a bitmap and the other is a
115 // gradient. Otherwise, return None to skip.
116 if (!bitmapAndGradient(shaderAType, shaderBType)) {
117 return kNone_SkiaShaderType;
118 }
119 return kCompose_SkiaShaderType;
120 }
121
122 if (shader.asACustomShader(NULL)) {
123 return kLayer_SkiaShaderType;
124 }
125
126 return kNone_SkiaShaderType;
127}
128
129typedef void (*describeProc)(Caches* caches, ProgramDescription& description,
130 const Extensions& extensions, const SkShader& shader);
131
132describeProc gDescribeProc[] = {
133 InvalidSkiaShader::describe,
134 SkiaBitmapShader::describe,
135 SkiaGradientShader::describe,
136 SkiaComposeShader::describe,
137 SkiaLayerShader::describe,
138};
139
140typedef void (*setupProgramProc)(Caches* caches, const mat4& modelViewMatrix,
141 GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
142
143setupProgramProc gSetupProgramProc[] = {
144 InvalidSkiaShader::setupProgram,
145 SkiaBitmapShader::setupProgram,
146 SkiaGradientShader::setupProgram,
147 SkiaComposeShader::setupProgram,
148 SkiaLayerShader::setupProgram,
149};
150
151void SkiaShader::describe(Caches* caches, ProgramDescription& description,
152 const Extensions& extensions, const SkShader& shader) {
153 gDescribeProc[getType(shader)](caches, description, extensions, shader);
154}
155
156void SkiaShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
157 GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
158
159 gSetupProgramProc[getType(shader)](caches, modelViewMatrix, textureUnit, extensions, shader);
Romain Guy14830942010-10-07 15:07:45 -0700160}
161
Romain Guy06f96e22010-07-30 19:18:16 -0700162///////////////////////////////////////////////////////////////////////////////
Chris Craik3f0854292014-04-15 16:18:08 -0700163// Layer shader
164///////////////////////////////////////////////////////////////////////////////
165
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400166void SkiaLayerShader::describe(Caches*, ProgramDescription& description,
167 const Extensions&, const SkShader& shader) {
Chris Craik3f0854292014-04-15 16:18:08 -0700168 description.hasBitmap = true;
169}
170
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400171void 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 }
Chris Craik3f0854292014-04-15 16:18:08 -0700177
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400178 GLuint textureSlot = (*textureUnit)++;
179 caches->activeTexture(textureSlot);
180
181 const float width = layer->getWidth();
182 const float height = layer->getHeight();
Chris Craik3f0854292014-04-15 16:18:08 -0700183
184 mat4 textureTransform;
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400185 computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
186 modelViewMatrix);
187
Chris Craik3f0854292014-04-15 16:18:08 -0700188
189 // Uniforms
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400190 layer->bindTexture();
191 layer->setWrap(GL_CLAMP_TO_EDGE);
192 layer->setFilter(GL_LINEAR);
Chris Craik3f0854292014-04-15 16:18:08 -0700193
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400194 Program* program = caches->currentProgram;
Chris Craik3f0854292014-04-15 16:18:08 -0700195 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///////////////////////////////////////////////////////////////////////////////
Romain Guy06f96e22010-07-30 19:18:16 -0700202// Bitmap shader
203///////////////////////////////////////////////////////////////////////////////
204
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400205struct BitmapShaderInfo {
206 float width;
207 float height;
208 GLenum wrapS;
209 GLenum wrapT;
210 Texture* texture;
211};
Romain Guy06f96e22010-07-30 19:18:16 -0700212
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400213static 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;
Romain Guy06f96e22010-07-30 19:18:16 -0700219
220 const float width = texture->width;
221 const float height = texture->height;
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400222 GLenum wrapS, wrapT;
Romain Guy06f96e22010-07-30 19:18:16 -0700223
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400224 if (description) {
225 description->hasBitmap = true;
226 }
Romain Guy06f96e22010-07-30 19:18:16 -0700227 // The driver does not support non-power of two mirrored/repeated
228 // textures, so do it ourselves
Romain Guy61c8c9c2010-08-09 20:48:09 -0700229 if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400230 (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;
Romain Guy29d89972010-09-22 16:10:57 -0700239 } else {
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400240 wrapS = gTileModes[tileModes[0]];
241 wrapT = gTileModes[tileModes[1]];
Romain Guy06f96e22010-07-30 19:18:16 -0700242 }
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400243
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;
Romain Guy06f96e22010-07-30 19:18:16 -0700252}
253
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400254void 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
Romain Guy06f96e22010-07-30 19:18:16 -0700272 GLuint textureSlot = (*textureUnit)++;
Romain Guya1d3c912011-12-13 14:55:06 -0800273 Caches::getInstance().activeTexture(textureSlot);
Romain Guy9cccc2b2010-08-07 23:46:15 -0700274
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400275 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
Romain Guy9cccc2b2010-08-07 23:46:15 -0700283 const AutoTexture autoCleanup(texture);
Romain Guy06f96e22010-07-30 19:18:16 -0700284
Romain Guy06f96e22010-07-30 19:18:16 -0700285 mat4 textureTransform;
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400286 computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
287 modelViewMatrix);
Romain Guy06f96e22010-07-30 19:18:16 -0700288
289 // Uniforms
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400290 bindTexture(caches, texture, shaderInfo.wrapS, shaderInfo.wrapT);
Romain Guyd21b6e12011-11-30 20:21:23 -0800291 texture->setFilter(GL_LINEAR);
Romain Guye3c26852011-07-25 16:36:01 -0700292
Romain Guy06f96e22010-07-30 19:18:16 -0700293 glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
294 glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
295 GL_FALSE, &textureTransform.data[0]);
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400296 glUniform2f(program->getUniform("textureDimension"), 1.0f / shaderInfo.width,
297 1.0f / shaderInfo.height);
Romain Guy06f96e22010-07-30 19:18:16 -0700298}
299
300///////////////////////////////////////////////////////////////////////////////
301// Linear gradient shader
302///////////////////////////////////////////////////////////////////////////////
303
Romain Guye3095e02010-10-06 16:57:29 -0700304static 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
Romain Guy06f96e22010-07-30 19:18:16 -0700315///////////////////////////////////////////////////////////////////////////////
Romain Guyddb80be2010-09-20 19:04:33 -0700316// Circular gradient shader
317///////////////////////////////////////////////////////////////////////////////
318
Romain Guy14830942010-10-07 15:07:45 -0700319static 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
Romain Guyddb80be2010-09-20 19:04:33 -0700326///////////////////////////////////////////////////////////////////////////////
Romain Guyee916f12010-09-20 17:53:08 -0700327// Sweep gradient shader
328///////////////////////////////////////////////////////////////////////////////
329
Romain Guy14830942010-10-07 15:07:45 -0700330static void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) {
331 matrix->setTranslate(-x, -y);
332}
333
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400334///////////////////////////////////////////////////////////////////////////////
335// Common gradient code
336///////////////////////////////////////////////////////////////////////////////
Romain Guy14830942010-10-07 15:07:45 -0700337
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400338static bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) {
339 return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode;
Romain Guyee916f12010-09-20 17:53:08 -0700340}
341
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400342void 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;
Romain Guy42e1e0d2012-07-30 14:47:51 -0700348
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400349 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 }
Romain Guyee916f12010-09-20 17:53:08 -0700363 description.hasGradient = true;
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400364 description.isSimpleGradient = isSimpleGradient(gradInfo);
Romain Guyee916f12010-09-20 17:53:08 -0700365}
366
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400367void 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);
Romain Guyee916f12010-09-20 17:53:08 -0700376
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400377 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);
Romain Guy42e1e0d2012-07-30 14:47:51 -0700402
403 // Uniforms
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400404 bindTexture(caches, texture, gTileModes[gradInfo.fTileMode], gTileModes[gradInfo.fTileMode]);
Romain Guy42e1e0d2012-07-30 14:47:51 -0700405 glUniform1i(program->getUniform("gradientSampler"), textureSlot);
406 } else {
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400407 bindUniformColor(program->getUniform("startColor"), gradInfo.fColors[0]);
408 bindUniformColor(program->getUniform("endColor"), gradInfo.fColors[1]);
Romain Guy42e1e0d2012-07-30 14:47:51 -0700409 }
Romain Guyee916f12010-09-20 17:53:08 -0700410
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400411 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 }
Romain Guy211efea2012-07-31 21:16:07 -0700428
Romain Guy14830942010-10-07 15:07:45 -0700429 mat4 screenSpace;
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400430 computeScreenSpaceMatrix(screenSpace, unitMatrix, shader.getLocalMatrix(), modelViewMatrix);
Romain Guyee916f12010-09-20 17:53:08 -0700431 glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
432}
433
Romain Guyee916f12010-09-20 17:53:08 -0700434///////////////////////////////////////////////////////////////////////////////
Romain Guy06f96e22010-07-30 19:18:16 -0700435// Compose shader
436///////////////////////////////////////////////////////////////////////////////
437
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400438void 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!");
Romain Guy43ccf462011-01-14 18:51:01 -0800443 }
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400444 SkiaShader::describe(caches, description, extensions, *rec.fShaderA);
445 SkiaShader::describe(caches, description, extensions, *rec.fShaderB);
446 if (SkiaShader::getType(*rec.fShaderA) == kBitmap_SkiaShaderType) {
Romain Guy06f96e22010-07-30 19:18:16 -0700447 description.isBitmapFirst = true;
448 }
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400449 if (!SkXfermode::AsMode(rec.fMode, &description.shadersMode)) {
450 // TODO: Support other modes.
451 description.shadersMode = SkXfermode::kSrcOver_Mode;
452 }
Romain Guy06f96e22010-07-30 19:18:16 -0700453}
454
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400455void 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
Romain Guyd42899222013-03-18 19:30:48 -0700462 // 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;
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400466 computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(),
467 modelViewMatrix);
Romain Guyd42899222013-03-18 19:30:48 -0700468
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400469 SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderA);
470 SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderB);
Romain Guy06f96e22010-07-30 19:18:16 -0700471}
472
473}; // namespace uirenderer
474}; // namespace android