blob: c672bc433ca0570f2ebe89982dd13e0f7d383da6 [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"
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -040024#include "Layer.h"
25#include "Matrix.h"
Romain Guy06f96e22010-07-30 19:18:16 -070026#include "SkiaShader.h"
27#include "Texture.h"
Romain Guy06f96e22010-07-30 19:18:16 -070028
29namespace android {
30namespace uirenderer {
31
32///////////////////////////////////////////////////////////////////////////////
33// Support
34///////////////////////////////////////////////////////////////////////////////
35
Romain Guy06f96e22010-07-30 19:18:16 -070036static const GLint gTileModes[] = {
37 GL_CLAMP_TO_EDGE, // == SkShader::kClamp_TileMode
38 GL_REPEAT, // == SkShader::kRepeat_Mode
39 GL_MIRRORED_REPEAT // == SkShader::kMirror_TileMode
40};
41
Romain Guy42e1e0d2012-07-30 14:47:51 -070042/**
43 * This function does not work for n == 0.
44 */
45static inline bool isPowerOfTwo(unsigned int n) {
46 return !(n & (n - 1));
47}
48
49static inline void bindUniformColor(int slot, uint32_t color) {
Romain Guyd679b572012-08-29 21:49:00 -070050 const float a = ((color >> 24) & 0xff) / 255.0f;
Romain Guy42e1e0d2012-07-30 14:47:51 -070051 glUniform4f(slot,
Romain Guyd679b572012-08-29 21:49:00 -070052 a * ((color >> 16) & 0xff) / 255.0f,
53 a * ((color >> 8) & 0xff) / 255.0f,
54 a * ((color ) & 0xff) / 255.0f,
55 a);
Romain Guy42e1e0d2012-07-30 14:47:51 -070056}
57
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -040058static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) {
59 caches->bindTexture(texture->id);
Romain Guyd21b6e12011-11-30 20:21:23 -080060 texture->setWrapST(wrapS, wrapT);
Romain Guy06f96e22010-07-30 19:18:16 -070061}
62
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -040063/**
64 * Compute the matrix to transform to screen space.
65 * @param screenSpace Output param for the computed matrix.
66 * @param unitMatrix The unit matrix for gradient shaders, as returned by SkShader::asAGradient,
67 * or identity.
68 * @param localMatrix Local matrix, as returned by SkShader::getLocalMatrix().
69 * @param modelViewMatrix Model view matrix, as supplied by the OpenGLRenderer.
70 */
71static void computeScreenSpaceMatrix(mat4& screenSpace, const SkMatrix& unitMatrix,
72 const SkMatrix& localMatrix, const mat4& modelViewMatrix) {
73 mat4 shaderMatrix;
74 // uses implicit construction
75 shaderMatrix.loadInverse(localMatrix);
76 // again, uses implicit construction
77 screenSpace.loadMultiply(unitMatrix, shaderMatrix);
78 screenSpace.multiply(modelViewMatrix);
79}
80
81// Returns true if one is a bitmap and the other is a gradient
82static bool bitmapAndGradient(SkiaShaderType type1, SkiaShaderType type2) {
83 return (type1 == kBitmap_SkiaShaderType && type2 == kGradient_SkiaShaderType)
84 || (type2 == kBitmap_SkiaShaderType && type1 == kGradient_SkiaShaderType);
85}
86
87SkiaShaderType SkiaShader::getType(const SkShader& shader) {
88 // First check for a gradient shader.
89 switch (shader.asAGradient(NULL)) {
90 case SkShader::kNone_GradientType:
91 // Not a gradient shader. Fall through to check for other types.
92 break;
93 case SkShader::kLinear_GradientType:
94 case SkShader::kRadial_GradientType:
95 case SkShader::kSweep_GradientType:
96 return kGradient_SkiaShaderType;
97 default:
98 // This is a Skia gradient that has no SkiaShader equivalent. Return None to skip.
99 return kNone_SkiaShaderType;
100 }
101
102 // The shader is not a gradient. Check for a bitmap shader.
103 if (shader.asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType) {
104 return kBitmap_SkiaShaderType;
105 }
106
107 // Check for a ComposeShader.
108 SkShader::ComposeRec rec;
109 if (shader.asACompose(&rec)) {
110 const SkiaShaderType shaderAType = getType(*rec.fShaderA);
111 const SkiaShaderType shaderBType = getType(*rec.fShaderB);
112
113 // Compose is only supported if one is a bitmap and the other is a
114 // gradient. Otherwise, return None to skip.
115 if (!bitmapAndGradient(shaderAType, shaderBType)) {
116 return kNone_SkiaShaderType;
117 }
118 return kCompose_SkiaShaderType;
119 }
120
121 if (shader.asACustomShader(NULL)) {
122 return kLayer_SkiaShaderType;
123 }
124
125 return kNone_SkiaShaderType;
126}
127
128typedef void (*describeProc)(Caches* caches, ProgramDescription& description,
129 const Extensions& extensions, const SkShader& shader);
130
131describeProc gDescribeProc[] = {
132 InvalidSkiaShader::describe,
133 SkiaBitmapShader::describe,
134 SkiaGradientShader::describe,
135 SkiaComposeShader::describe,
136 SkiaLayerShader::describe,
137};
138
139typedef void (*setupProgramProc)(Caches* caches, const mat4& modelViewMatrix,
140 GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
141
142setupProgramProc gSetupProgramProc[] = {
143 InvalidSkiaShader::setupProgram,
144 SkiaBitmapShader::setupProgram,
145 SkiaGradientShader::setupProgram,
146 SkiaComposeShader::setupProgram,
147 SkiaLayerShader::setupProgram,
148};
149
150void SkiaShader::describe(Caches* caches, ProgramDescription& description,
151 const Extensions& extensions, const SkShader& shader) {
152 gDescribeProc[getType(shader)](caches, description, extensions, shader);
153}
154
155void SkiaShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
156 GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
157
158 gSetupProgramProc[getType(shader)](caches, modelViewMatrix, textureUnit, extensions, shader);
Romain Guy14830942010-10-07 15:07:45 -0700159}
160
Romain Guy06f96e22010-07-30 19:18:16 -0700161///////////////////////////////////////////////////////////////////////////////
Chris Craik3f0854292014-04-15 16:18:08 -0700162// Layer shader
163///////////////////////////////////////////////////////////////////////////////
164
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400165void SkiaLayerShader::describe(Caches*, ProgramDescription& description,
John Reckf088c342014-12-12 09:49:29 -0800166 const Extensions&, const SkShader& shader) {
Chris Craik3f0854292014-04-15 16:18:08 -0700167 description.hasBitmap = true;
168}
169
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400170void SkiaLayerShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
171 GLuint* textureUnit, const Extensions&, const SkShader& shader) {
172 Layer* layer;
173 if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) {
174 LOG_ALWAYS_FATAL("SkiaLayerShader::setupProgram called on the wrong type of shader!");
175 }
Chris Craik3f0854292014-04-15 16:18:08 -0700176
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400177 GLuint textureSlot = (*textureUnit)++;
178 caches->activeTexture(textureSlot);
179
180 const float width = layer->getWidth();
181 const float height = layer->getHeight();
Chris Craik3f0854292014-04-15 16:18:08 -0700182
183 mat4 textureTransform;
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400184 computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
185 modelViewMatrix);
186
Chris Craik3f0854292014-04-15 16:18:08 -0700187
188 // Uniforms
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400189 layer->bindTexture();
190 layer->setWrap(GL_CLAMP_TO_EDGE);
191 layer->setFilter(GL_LINEAR);
Chris Craik3f0854292014-04-15 16:18:08 -0700192
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400193 Program* program = caches->currentProgram;
Chris Craik3f0854292014-04-15 16:18:08 -0700194 glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
195 glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
196 GL_FALSE, &textureTransform.data[0]);
197 glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height);
198}
199
200///////////////////////////////////////////////////////////////////////////////
Romain Guy06f96e22010-07-30 19:18:16 -0700201// Bitmap shader
202///////////////////////////////////////////////////////////////////////////////
203
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400204struct BitmapShaderInfo {
205 float width;
206 float height;
207 GLenum wrapS;
208 GLenum wrapT;
209 Texture* texture;
210};
Romain Guy06f96e22010-07-30 19:18:16 -0700211
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400212static bool bitmapShaderHelper(Caches* caches, ProgramDescription* description,
213 BitmapShaderInfo* shaderInfo,
214 const Extensions& extensions,
215 const SkBitmap& bitmap, SkShader::TileMode tileModes[2]) {
216 Texture* texture = caches->textureCache.get(&bitmap);
217 if (!texture) return false;
Romain Guy06f96e22010-07-30 19:18:16 -0700218
219 const float width = texture->width;
220 const float height = texture->height;
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400221 GLenum wrapS, wrapT;
Romain Guy06f96e22010-07-30 19:18:16 -0700222
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400223 if (description) {
224 description->hasBitmap = true;
225 }
Romain Guy06f96e22010-07-30 19:18:16 -0700226 // The driver does not support non-power of two mirrored/repeated
227 // textures, so do it ourselves
Romain Guy61c8c9c2010-08-09 20:48:09 -0700228 if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400229 (tileModes[0] != SkShader::kClamp_TileMode ||
230 tileModes[1] != SkShader::kClamp_TileMode)) {
231 if (description) {
232 description->isBitmapNpot = true;
233 description->bitmapWrapS = gTileModes[tileModes[0]];
234 description->bitmapWrapT = gTileModes[tileModes[1]];
235 }
236 wrapS = GL_CLAMP_TO_EDGE;
237 wrapT = GL_CLAMP_TO_EDGE;
Romain Guy29d89972010-09-22 16:10:57 -0700238 } else {
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400239 wrapS = gTileModes[tileModes[0]];
240 wrapT = gTileModes[tileModes[1]];
Romain Guy06f96e22010-07-30 19:18:16 -0700241 }
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400242
243 if (shaderInfo) {
244 shaderInfo->width = width;
245 shaderInfo->height = height;
246 shaderInfo->wrapS = wrapS;
247 shaderInfo->wrapT = wrapT;
248 shaderInfo->texture = texture;
249 }
250 return true;
Romain Guy06f96e22010-07-30 19:18:16 -0700251}
252
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400253void SkiaBitmapShader::describe(Caches* caches, ProgramDescription& description,
254 const Extensions& extensions, const SkShader& shader) {
255 SkBitmap bitmap;
256 SkShader::TileMode xy[2];
257 if (shader.asABitmap(&bitmap, NULL, xy) != SkShader::kDefault_BitmapType) {
258 LOG_ALWAYS_FATAL("SkiaBitmapShader::describe called with a different kind of shader!");
259 }
260 bitmapShaderHelper(caches, &description, NULL, extensions, bitmap, xy);
261}
262
263void SkiaBitmapShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
264 GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
265 SkBitmap bitmap;
266 SkShader::TileMode xy[2];
267 if (shader.asABitmap(&bitmap, NULL, xy) != SkShader::kDefault_BitmapType) {
268 LOG_ALWAYS_FATAL("SkiaBitmapShader::setupProgram called with a different kind of shader!");
269 }
270
Romain Guy06f96e22010-07-30 19:18:16 -0700271 GLuint textureSlot = (*textureUnit)++;
Romain Guya1d3c912011-12-13 14:55:06 -0800272 Caches::getInstance().activeTexture(textureSlot);
Romain Guy9cccc2b2010-08-07 23:46:15 -0700273
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400274 BitmapShaderInfo shaderInfo;
275 if (!bitmapShaderHelper(caches, NULL, &shaderInfo, extensions, bitmap, xy)) {
276 return;
277 }
278
279 Program* program = caches->currentProgram;
280 Texture* texture = shaderInfo.texture;
281
Romain Guy9cccc2b2010-08-07 23:46:15 -0700282 const AutoTexture autoCleanup(texture);
Romain Guy06f96e22010-07-30 19:18:16 -0700283
Romain Guy06f96e22010-07-30 19:18:16 -0700284 mat4 textureTransform;
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400285 computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
286 modelViewMatrix);
Romain Guy06f96e22010-07-30 19:18:16 -0700287
288 // Uniforms
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400289 bindTexture(caches, texture, shaderInfo.wrapS, shaderInfo.wrapT);
Romain Guyd21b6e12011-11-30 20:21:23 -0800290 texture->setFilter(GL_LINEAR);
Romain Guye3c26852011-07-25 16:36:01 -0700291
Romain Guy06f96e22010-07-30 19:18:16 -0700292 glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
293 glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
294 GL_FALSE, &textureTransform.data[0]);
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400295 glUniform2f(program->getUniform("textureDimension"), 1.0f / shaderInfo.width,
296 1.0f / shaderInfo.height);
Romain Guy06f96e22010-07-30 19:18:16 -0700297}
298
299///////////////////////////////////////////////////////////////////////////////
300// Linear gradient shader
301///////////////////////////////////////////////////////////////////////////////
302
Romain Guye3095e02010-10-06 16:57:29 -0700303static void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
304 SkVector vec = pts[1] - pts[0];
305 const float mag = vec.length();
306 const float inv = mag ? 1.0f / mag : 0;
307
308 vec.scale(inv);
309 matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY);
310 matrix->postTranslate(-pts[0].fX, -pts[0].fY);
311 matrix->postScale(inv, inv);
312}
313
Romain Guy06f96e22010-07-30 19:18:16 -0700314///////////////////////////////////////////////////////////////////////////////
Romain Guyddb80be2010-09-20 19:04:33 -0700315// Circular gradient shader
316///////////////////////////////////////////////////////////////////////////////
317
Romain Guy14830942010-10-07 15:07:45 -0700318static void toCircularUnitMatrix(const float x, const float y, const float radius,
319 SkMatrix* matrix) {
320 const float inv = 1.0f / radius;
321 matrix->setTranslate(-x, -y);
322 matrix->postScale(inv, inv);
323}
324
Romain Guyddb80be2010-09-20 19:04:33 -0700325///////////////////////////////////////////////////////////////////////////////
Romain Guyee916f12010-09-20 17:53:08 -0700326// Sweep gradient shader
327///////////////////////////////////////////////////////////////////////////////
328
Romain Guy14830942010-10-07 15:07:45 -0700329static void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) {
330 matrix->setTranslate(-x, -y);
331}
332
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400333///////////////////////////////////////////////////////////////////////////////
334// Common gradient code
335///////////////////////////////////////////////////////////////////////////////
Romain Guy14830942010-10-07 15:07:45 -0700336
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400337static bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) {
338 return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode;
Romain Guyee916f12010-09-20 17:53:08 -0700339}
340
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400341void SkiaGradientShader::describe(Caches*, ProgramDescription& description,
John Reckf088c342014-12-12 09:49:29 -0800342 const Extensions& extensions, const SkShader& shader) {
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400343 SkShader::GradientInfo gradInfo;
344 gradInfo.fColorCount = 0;
345 gradInfo.fColors = NULL;
346 gradInfo.fColorOffsets = NULL;
Romain Guy42e1e0d2012-07-30 14:47:51 -0700347
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400348 switch (shader.asAGradient(&gradInfo)) {
349 case SkShader::kLinear_GradientType:
350 description.gradientType = ProgramDescription::kGradientLinear;
351 break;
352 case SkShader::kRadial_GradientType:
353 description.gradientType = ProgramDescription::kGradientCircular;
354 break;
355 case SkShader::kSweep_GradientType:
356 description.gradientType = ProgramDescription::kGradientSweep;
357 break;
358 default:
359 // Do nothing. This shader is unsupported.
360 return;
361 }
Romain Guyee916f12010-09-20 17:53:08 -0700362 description.hasGradient = true;
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400363 description.isSimpleGradient = isSimpleGradient(gradInfo);
Romain Guyee916f12010-09-20 17:53:08 -0700364}
365
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400366void SkiaGradientShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
367 GLuint* textureUnit, const Extensions&, const SkShader& shader) {
368 // SkShader::GradientInfo.fColorCount is an in/out parameter. As input, it tells asAGradient
369 // how much space has been allocated for fColors and fColorOffsets. 10 was chosen
370 // arbitrarily, but should be >= 2.
371 // As output, it tells the number of actual colors/offsets in the gradient.
372 const int COLOR_COUNT = 10;
373 SkAutoSTMalloc<COLOR_COUNT, SkColor> colorStorage(COLOR_COUNT);
374 SkAutoSTMalloc<COLOR_COUNT, SkScalar> positionStorage(COLOR_COUNT);
Romain Guyee916f12010-09-20 17:53:08 -0700375
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400376 SkShader::GradientInfo gradInfo;
377 gradInfo.fColorCount = COLOR_COUNT;
378 gradInfo.fColors = colorStorage.get();
379 gradInfo.fColorOffsets = positionStorage.get();
380
381 SkShader::GradientType gradType = shader.asAGradient(&gradInfo);
382
383 Program* program = caches->currentProgram;
384 if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) {
385 if (gradInfo.fColorCount > COLOR_COUNT) {
386 // There was not enough room in our arrays for all the colors and offsets. Try again,
387 // now that we know the true number of colors.
388 gradInfo.fColors = colorStorage.reset(gradInfo.fColorCount);
389 gradInfo.fColorOffsets = positionStorage.reset(gradInfo.fColorCount);
390
391 shader.asAGradient(&gradInfo);
392 }
393 GLuint textureSlot = (*textureUnit)++;
394 caches->activeTexture(textureSlot);
395
396#ifndef SK_SCALAR_IS_FLOAT
397 #error Need to convert gradInfo.fColorOffsets to float!
398#endif
399 Texture* texture = caches->gradientCache.get(gradInfo.fColors, gradInfo.fColorOffsets,
400 gradInfo.fColorCount);
Romain Guy42e1e0d2012-07-30 14:47:51 -0700401
402 // Uniforms
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400403 bindTexture(caches, texture, gTileModes[gradInfo.fTileMode], gTileModes[gradInfo.fTileMode]);
Romain Guy42e1e0d2012-07-30 14:47:51 -0700404 glUniform1i(program->getUniform("gradientSampler"), textureSlot);
405 } else {
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400406 bindUniformColor(program->getUniform("startColor"), gradInfo.fColors[0]);
407 bindUniformColor(program->getUniform("endColor"), gradInfo.fColors[1]);
Romain Guy42e1e0d2012-07-30 14:47:51 -0700408 }
Romain Guyee916f12010-09-20 17:53:08 -0700409
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400410 caches->dither.setupProgram(program, textureUnit);
411
412 SkMatrix unitMatrix;
413 switch (gradType) {
414 case SkShader::kLinear_GradientType:
415 toUnitMatrix(gradInfo.fPoint, &unitMatrix);
416 break;
417 case SkShader::kRadial_GradientType:
418 toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY,
419 gradInfo.fRadius[0], &unitMatrix);
420 break;
421 case SkShader::kSweep_GradientType:
422 toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix);
423 break;
424 default:
425 LOG_ALWAYS_FATAL("Invalid SkShader gradient type %d", gradType);
426 }
Romain Guy211efea2012-07-31 21:16:07 -0700427
Romain Guy14830942010-10-07 15:07:45 -0700428 mat4 screenSpace;
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400429 computeScreenSpaceMatrix(screenSpace, unitMatrix, shader.getLocalMatrix(), modelViewMatrix);
Romain Guyee916f12010-09-20 17:53:08 -0700430 glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
431}
432
Romain Guyee916f12010-09-20 17:53:08 -0700433///////////////////////////////////////////////////////////////////////////////
Romain Guy06f96e22010-07-30 19:18:16 -0700434// Compose shader
435///////////////////////////////////////////////////////////////////////////////
436
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400437void SkiaComposeShader::describe(Caches* caches, ProgramDescription& description,
438 const Extensions& extensions, const SkShader& shader) {
439 SkShader::ComposeRec rec;
440 if (!shader.asACompose(&rec)) {
441 LOG_ALWAYS_FATAL("SkiaComposeShader::describe called on the wrong shader type!");
Romain Guy43ccf462011-01-14 18:51:01 -0800442 }
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400443 SkiaShader::describe(caches, description, extensions, *rec.fShaderA);
444 SkiaShader::describe(caches, description, extensions, *rec.fShaderB);
445 if (SkiaShader::getType(*rec.fShaderA) == kBitmap_SkiaShaderType) {
Romain Guy06f96e22010-07-30 19:18:16 -0700446 description.isBitmapFirst = true;
447 }
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400448 if (!SkXfermode::AsMode(rec.fMode, &description.shadersMode)) {
449 // TODO: Support other modes.
450 description.shadersMode = SkXfermode::kSrcOver_Mode;
451 }
Romain Guy06f96e22010-07-30 19:18:16 -0700452}
453
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400454void SkiaComposeShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
455 GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
456 SkShader::ComposeRec rec;
457 if (!shader.asACompose(&rec)) {
458 LOG_ALWAYS_FATAL("SkiaComposeShader::setupProgram called on the wrong shader type!");
459 }
460
Romain Guyd42899222013-03-18 19:30:48 -0700461 // Apply this compose shader's local transform and pass it down to
462 // the child shaders. They will in turn apply their local transform
463 // to this matrix.
464 mat4 transform;
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400465 computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(),
466 modelViewMatrix);
Romain Guyd42899222013-03-18 19:30:48 -0700467
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400468 SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderA);
469 SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderB);
Romain Guy06f96e22010-07-30 19:18:16 -0700470}
471
472}; // namespace uirenderer
473}; // namespace android