blob: 439e6fbf4eb50c574b3e4a3bd141a4a003ca6a54 [file] [log] [blame]
Romain Guyac670c02010-07-27 17:39:27 -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/String8.h>
20
21#include "ProgramCache.h"
22
23namespace android {
24namespace uirenderer {
25
26///////////////////////////////////////////////////////////////////////////////
27// Vertex shaders snippets
28///////////////////////////////////////////////////////////////////////////////
29
Romain Guyac670c02010-07-27 17:39:27 -070030const char* gVS_Header_Attributes =
31 "attribute vec4 position;\n";
32const char* gVS_Header_Attributes_TexCoords =
33 "attribute vec2 texCoords;\n";
34const char* gVS_Header_Uniforms =
35 "uniform mat4 transform;\n";
Romain Guyee916f12010-09-20 17:53:08 -070036const char* gVS_Header_Uniforms_HasGradient[3] = {
37 // Linear
Romain Guyee916f12010-09-20 17:53:08 -070038 "uniform mat4 screenSpace;\n",
39 // Circular
Romain Guyddb80be2010-09-20 19:04:33 -070040 "uniform mat4 screenSpace;\n",
Romain Guyee916f12010-09-20 17:53:08 -070041 // Sweep
Romain Guyee916f12010-09-20 17:53:08 -070042 "uniform mat4 screenSpace;\n"
43};
Romain Guy889f8d12010-07-29 14:37:42 -070044const char* gVS_Header_Uniforms_HasBitmap =
45 "uniform mat4 textureTransform;\n"
46 "uniform vec2 textureDimension;\n";
Romain Guyac670c02010-07-27 17:39:27 -070047const char* gVS_Header_Varyings_HasTexture =
48 "varying vec2 outTexCoords;\n";
49const char* gVS_Header_Varyings_HasBitmap =
50 "varying vec2 outBitmapTexCoords;\n";
Romain Guyee916f12010-09-20 17:53:08 -070051const char* gVS_Header_Varyings_HasGradient[3] = {
52 // Linear
53 "varying float index;\n",
54 // Circular
Romain Guyddb80be2010-09-20 19:04:33 -070055 "varying vec2 circular;\n",
Romain Guyee916f12010-09-20 17:53:08 -070056 // Sweep
57 "varying vec2 sweep;\n"
58};
Romain Guyac670c02010-07-27 17:39:27 -070059const char* gVS_Main =
60 "\nvoid main(void) {\n";
61const char* gVS_Main_OutTexCoords =
62 " outTexCoords = texCoords;\n";
Romain Guyee916f12010-09-20 17:53:08 -070063const char* gVS_Main_OutGradient[3] = {
64 // Linear
Romain Guye3095e02010-10-06 16:57:29 -070065 " index = (screenSpace * position).x;\n",
Romain Guyee916f12010-09-20 17:53:08 -070066 // Circular
Romain Guy14830942010-10-07 15:07:45 -070067 " circular = (screenSpace * position).xy;\n",
Romain Guyee916f12010-09-20 17:53:08 -070068 // Sweep
Romain Guy14830942010-10-07 15:07:45 -070069 " sweep = (screenSpace * position).xy;\n"
Romain Guyee916f12010-09-20 17:53:08 -070070};
Romain Guy889f8d12010-07-29 14:37:42 -070071const char* gVS_Main_OutBitmapTexCoords =
72 " vec4 bitmapCoords = textureTransform * position;\n"
73 " outBitmapTexCoords = bitmapCoords.xy * textureDimension;\n";
Romain Guyac670c02010-07-27 17:39:27 -070074const char* gVS_Main_Position =
75 " gl_Position = transform * position;\n";
76const char* gVS_Footer =
77 "}\n\n";
78
79///////////////////////////////////////////////////////////////////////////////
80// Fragment shaders snippets
81///////////////////////////////////////////////////////////////////////////////
82
Romain Guya5aed0d2010-09-09 14:42:43 -070083const char* gFS_Header_Extension_FramebufferFetch =
84 "#extension GL_NV_shader_framebuffer_fetch : enable\n\n";
Romain Guyac670c02010-07-27 17:39:27 -070085const char* gFS_Header =
86 "precision mediump float;\n\n";
87const char* gFS_Uniforms_Color =
88 "uniform vec4 color;\n";
89const char* gFS_Uniforms_TextureSampler =
90 "uniform sampler2D sampler;\n";
Romain Guyee916f12010-09-20 17:53:08 -070091const char* gFS_Uniforms_GradientSampler[3] = {
92 // Linear
93 "uniform sampler2D gradientSampler;\n",
94 // Circular
95 "uniform sampler2D gradientSampler;\n",
96 // Sweep
97 "uniform sampler2D gradientSampler;\n"
98};
Romain Guyac670c02010-07-27 17:39:27 -070099const char* gFS_Uniforms_BitmapSampler =
100 "uniform sampler2D bitmapSampler;\n";
101const char* gFS_Uniforms_ColorOp[4] = {
102 // None
103 "",
104 // Matrix
105 "uniform mat4 colorMatrix;\n"
106 "uniform vec4 colorMatrixVector;\n",
107 // Lighting
Romain Guydb1938e2010-08-02 18:50:22 -0700108 "uniform vec4 lightingMul;\n"
109 "uniform vec4 lightingAdd;\n",
Romain Guyac670c02010-07-27 17:39:27 -0700110 // PorterDuff
Romain Guydb1938e2010-08-02 18:50:22 -0700111 "uniform vec4 colorBlend;\n"
Romain Guyac670c02010-07-27 17:39:27 -0700112};
113const char* gFS_Main =
114 "\nvoid main(void) {\n"
Romain Guy7fbcc042010-08-04 15:40:07 -0700115 " lowp vec4 fragColor;\n";
Romain Guyac670c02010-07-27 17:39:27 -0700116const char* gFS_Main_FetchColor =
117 " fragColor = color;\n";
118const char* gFS_Main_FetchTexture =
119 " fragColor = color * texture2D(sampler, outTexCoords);\n";
120const char* gFS_Main_FetchA8Texture =
121 " fragColor = color * texture2D(sampler, outTexCoords).a;\n";
Romain Guyee916f12010-09-20 17:53:08 -0700122const char* gFS_Main_FetchGradient[3] = {
123 // Linear
124 " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n",
125 // Circular
Romain Guy14830942010-10-07 15:07:45 -0700126 " float index = length(circular);\n"
Romain Guyddb80be2010-09-20 19:04:33 -0700127 " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n",
Romain Guyee916f12010-09-20 17:53:08 -0700128 // Sweep
129 " float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
130 " vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n"
131};
Romain Guyac670c02010-07-27 17:39:27 -0700132const char* gFS_Main_FetchBitmap =
133 " vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n";
Romain Guy889f8d12010-07-29 14:37:42 -0700134const char* gFS_Main_FetchBitmapNpot =
135 " vec4 bitmapColor = texture2D(bitmapSampler, wrap(outBitmapTexCoords));\n";
Romain Guyac670c02010-07-27 17:39:27 -0700136const char* gFS_Main_BlendShadersBG =
Romain Guyac670c02010-07-27 17:39:27 -0700137 " fragColor = blendShaders(gradientColor, bitmapColor)";
Romain Guy06f96e22010-07-30 19:18:16 -0700138const char* gFS_Main_BlendShadersGB =
139 " fragColor = blendShaders(bitmapColor, gradientColor)";
Romain Guyac670c02010-07-27 17:39:27 -0700140const char* gFS_Main_BlendShaders_Modulate =
141 " * fragColor.a;\n";
Romain Guy889f8d12010-07-29 14:37:42 -0700142const char* gFS_Main_GradientShader_Modulate =
143 " fragColor = gradientColor * fragColor.a;\n";
144const char* gFS_Main_BitmapShader_Modulate =
145 " fragColor = bitmapColor * fragColor.a;\n";
Romain Guyac670c02010-07-27 17:39:27 -0700146const char* gFS_Main_FragColor =
147 " gl_FragColor = fragColor;\n";
Romain Guya5aed0d2010-09-09 14:42:43 -0700148const char* gFS_Main_FragColor_Blend =
149 " gl_FragColor = blendFramebuffer(fragColor, gl_LastFragColor);\n";
Romain Guyf607bdc2010-09-10 19:20:06 -0700150const char* gFS_Main_FragColor_Blend_Swap =
151 " gl_FragColor = blendFramebuffer(gl_LastFragColor, fragColor);\n";
Romain Guyac670c02010-07-27 17:39:27 -0700152const char* gFS_Main_ApplyColorOp[4] = {
153 // None
154 "",
155 // Matrix
Romain Guydb1938e2010-08-02 18:50:22 -0700156 // TODO: Fix premultiplied alpha computations for color matrix
Romain Guyac670c02010-07-27 17:39:27 -0700157 " fragColor *= colorMatrix;\n"
Romain Guydb1938e2010-08-02 18:50:22 -0700158 " fragColor += colorMatrixVector;\n"
159 " fragColor.rgb *= fragColor.a;\n",
Romain Guyac670c02010-07-27 17:39:27 -0700160 // Lighting
Romain Guydb1938e2010-08-02 18:50:22 -0700161 " float lightingAlpha = fragColor.a;\n"
162 " fragColor = min(fragColor * lightingMul + (lightingAdd * lightingAlpha), lightingAlpha);\n"
163 " fragColor.a = lightingAlpha;\n",
Romain Guyac670c02010-07-27 17:39:27 -0700164 // PorterDuff
165 " fragColor = blendColors(colorBlend, fragColor);\n"
166};
167const char* gFS_Footer =
168 "}\n\n";
169
170///////////////////////////////////////////////////////////////////////////////
171// PorterDuff snippets
172///////////////////////////////////////////////////////////////////////////////
173
Romain Guy48daa542010-08-10 19:21:34 -0700174const char* gBlendOps[18] = {
Romain Guyac670c02010-07-27 17:39:27 -0700175 // Clear
176 "return vec4(0.0, 0.0, 0.0, 0.0);\n",
177 // Src
178 "return src;\n",
179 // Dst
180 "return dst;\n",
181 // SrcOver
Romain Guy06f96e22010-07-30 19:18:16 -0700182 "return src + dst * (1.0 - src.a);\n",
Romain Guyac670c02010-07-27 17:39:27 -0700183 // DstOver
Romain Guy06f96e22010-07-30 19:18:16 -0700184 "return dst + src * (1.0 - dst.a);\n",
Romain Guyac670c02010-07-27 17:39:27 -0700185 // SrcIn
Romain Guy06f96e22010-07-30 19:18:16 -0700186 "return src * dst.a;\n",
Romain Guyac670c02010-07-27 17:39:27 -0700187 // DstIn
Romain Guy06f96e22010-07-30 19:18:16 -0700188 "return dst * src.a;\n",
Romain Guyac670c02010-07-27 17:39:27 -0700189 // SrcOut
Romain Guy06f96e22010-07-30 19:18:16 -0700190 "return src * (1.0 - dst.a);\n",
Romain Guyac670c02010-07-27 17:39:27 -0700191 // DstOut
Romain Guy06f96e22010-07-30 19:18:16 -0700192 "return dst * (1.0 - src.a);\n",
Romain Guyac670c02010-07-27 17:39:27 -0700193 // SrcAtop
194 "return vec4(src.rgb * dst.a + (1.0 - src.a) * dst.rgb, dst.a);\n",
195 // DstAtop
196 "return vec4(dst.rgb * src.a + (1.0 - dst.a) * src.rgb, src.a);\n",
197 // Xor
Romain Guy48daa542010-08-10 19:21:34 -0700198 "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb, "
Romain Guyac670c02010-07-27 17:39:27 -0700199 "src.a + dst.a - 2.0 * src.a * dst.a);\n",
Romain Guy48daa542010-08-10 19:21:34 -0700200 // Add
201 "return min(src + dst, 1.0);\n",
202 // Multiply
203 "return src * dst;\n",
204 // Screen
205 "return src + dst - src * dst;\n",
206 // Overlay
207 "return clamp(vec4(mix("
208 "2.0 * src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), "
209 "src.a * dst.a - 2.0 * (dst.a - dst.rgb) * (src.a - src.rgb) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), "
210 "step(dst.a, 2.0 * dst.rgb)), "
211 "src.a + dst.a - src.a * dst.a), 0.0, 1.0);\n",
212 // Darken
213 "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + "
214 "min(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n",
215 // Lighten
216 "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + "
217 "max(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n",
Romain Guyac670c02010-07-27 17:39:27 -0700218};
219
220///////////////////////////////////////////////////////////////////////////////
221// Constructors/destructors
222///////////////////////////////////////////////////////////////////////////////
223
224ProgramCache::ProgramCache() {
225}
226
227ProgramCache::~ProgramCache() {
228 clear();
229}
230
231///////////////////////////////////////////////////////////////////////////////
232// Cache management
233///////////////////////////////////////////////////////////////////////////////
234
235void ProgramCache::clear() {
236 size_t count = mCache.size();
237 for (size_t i = 0; i < count; i++) {
238 delete mCache.valueAt(i);
239 }
240 mCache.clear();
241}
242
243Program* ProgramCache::get(const ProgramDescription& description) {
244 programid key = description.key();
245 ssize_t index = mCache.indexOfKey(key);
246 Program* program = NULL;
247 if (index < 0) {
Romain Guyee916f12010-09-20 17:53:08 -0700248 description.log("Could not find program");
Romain Guyac670c02010-07-27 17:39:27 -0700249 program = generateProgram(description, key);
250 mCache.add(key, program);
251 } else {
252 program = mCache.valueAt(index);
253 }
254 return program;
255}
256
257///////////////////////////////////////////////////////////////////////////////
258// Program generation
259///////////////////////////////////////////////////////////////////////////////
260
261Program* ProgramCache::generateProgram(const ProgramDescription& description, programid key) {
262 String8 vertexShader = generateVertexShader(description);
263 String8 fragmentShader = generateFragmentShader(description);
264
265 Program* program = new Program(vertexShader.string(), fragmentShader.string());
266 return program;
267}
268
269String8 ProgramCache::generateVertexShader(const ProgramDescription& description) {
270 // Add attributes
271 String8 shader(gVS_Header_Attributes);
Romain Guy889f8d12010-07-29 14:37:42 -0700272 if (description.hasTexture) {
Romain Guyac670c02010-07-27 17:39:27 -0700273 shader.append(gVS_Header_Attributes_TexCoords);
274 }
275 // Uniforms
276 shader.append(gVS_Header_Uniforms);
277 if (description.hasGradient) {
Romain Guyee916f12010-09-20 17:53:08 -0700278 shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]);
Romain Guyac670c02010-07-27 17:39:27 -0700279 }
Romain Guy889f8d12010-07-29 14:37:42 -0700280 if (description.hasBitmap) {
281 shader.append(gVS_Header_Uniforms_HasBitmap);
282 }
Romain Guyac670c02010-07-27 17:39:27 -0700283 // Varyings
284 if (description.hasTexture) {
285 shader.append(gVS_Header_Varyings_HasTexture);
286 }
287 if (description.hasGradient) {
Romain Guyee916f12010-09-20 17:53:08 -0700288 shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]);
Romain Guyac670c02010-07-27 17:39:27 -0700289 }
290 if (description.hasBitmap) {
291 shader.append(gVS_Header_Varyings_HasBitmap);
292 }
293
294 // Begin the shader
295 shader.append(gVS_Main); {
296 if (description.hasTexture) {
297 shader.append(gVS_Main_OutTexCoords);
298 }
299 if (description.hasGradient) {
Romain Guyee916f12010-09-20 17:53:08 -0700300 shader.append(gVS_Main_OutGradient[description.gradientType]);
Romain Guyac670c02010-07-27 17:39:27 -0700301 }
Romain Guy889f8d12010-07-29 14:37:42 -0700302 if (description.hasBitmap) {
303 shader.append(gVS_Main_OutBitmapTexCoords);
304 }
Romain Guyac670c02010-07-27 17:39:27 -0700305 // Output transformed position
306 shader.append(gVS_Main_Position);
307 }
308 // End the shader
309 shader.append(gVS_Footer);
310
311 PROGRAM_LOGD("*** Generated vertex shader:\n\n%s", shader.string());
312
313 return shader;
314}
315
316String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) {
317 // Set the default precision
Romain Guya5aed0d2010-09-09 14:42:43 -0700318 String8 shader;
319
320 bool blendFramebuffer = description.framebufferMode >= SkXfermode::kPlus_Mode;
321 if (blendFramebuffer) {
322 shader.append(gFS_Header_Extension_FramebufferFetch);
323 }
324
325 shader.append(gFS_Header);
Romain Guyac670c02010-07-27 17:39:27 -0700326
327 // Varyings
328 if (description.hasTexture) {
329 shader.append(gVS_Header_Varyings_HasTexture);
330 }
331 if (description.hasGradient) {
Romain Guyee916f12010-09-20 17:53:08 -0700332 shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]);
Romain Guyac670c02010-07-27 17:39:27 -0700333 }
334 if (description.hasBitmap) {
335 shader.append(gVS_Header_Varyings_HasBitmap);
336 }
337
338
339 // Uniforms
340 shader.append(gFS_Uniforms_Color);
341 if (description.hasTexture) {
342 shader.append(gFS_Uniforms_TextureSampler);
343 }
344 if (description.hasGradient) {
Romain Guyee916f12010-09-20 17:53:08 -0700345 shader.append(gFS_Uniforms_GradientSampler[description.gradientType]);
Romain Guyac670c02010-07-27 17:39:27 -0700346 }
347 if (description.hasBitmap) {
348 shader.append(gFS_Uniforms_BitmapSampler);
349 }
350 shader.append(gFS_Uniforms_ColorOp[description.colorOp]);
351
352 // Generate required functions
353 if (description.hasGradient && description.hasBitmap) {
Romain Guy48daa542010-08-10 19:21:34 -0700354 generateBlend(shader, "blendShaders", description.shadersMode);
Romain Guyac670c02010-07-27 17:39:27 -0700355 }
356 if (description.colorOp == ProgramDescription::kColorBlend) {
Romain Guy48daa542010-08-10 19:21:34 -0700357 generateBlend(shader, "blendColors", description.colorMode);
Romain Guyac670c02010-07-27 17:39:27 -0700358 }
Romain Guya5aed0d2010-09-09 14:42:43 -0700359 if (blendFramebuffer) {
360 generateBlend(shader, "blendFramebuffer", description.framebufferMode);
361 }
Romain Guy889f8d12010-07-29 14:37:42 -0700362 if (description.isBitmapNpot) {
363 generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT);
364 }
Romain Guyac670c02010-07-27 17:39:27 -0700365
366 // Begin the shader
367 shader.append(gFS_Main); {
368 // Stores the result in fragColor directly
369 if (description.hasTexture) {
370 if (description.hasAlpha8Texture) {
371 shader.append(gFS_Main_FetchA8Texture);
372 } else {
373 shader.append(gFS_Main_FetchTexture);
374 }
375 } else {
376 shader.append(gFS_Main_FetchColor);
377 }
378 if (description.hasGradient) {
Romain Guyee916f12010-09-20 17:53:08 -0700379 shader.append(gFS_Main_FetchGradient[description.gradientType]);
Romain Guyac670c02010-07-27 17:39:27 -0700380 }
381 if (description.hasBitmap) {
Romain Guy889f8d12010-07-29 14:37:42 -0700382 if (!description.isBitmapNpot) {
383 shader.append(gFS_Main_FetchBitmap);
384 } else {
385 shader.append(gFS_Main_FetchBitmapNpot);
386 }
Romain Guyac670c02010-07-27 17:39:27 -0700387 }
388 // Case when we have two shaders set
389 if (description.hasGradient && description.hasBitmap) {
390 if (description.isBitmapFirst) {
391 shader.append(gFS_Main_BlendShadersBG);
392 } else {
393 shader.append(gFS_Main_BlendShadersGB);
394 }
395 shader.append(gFS_Main_BlendShaders_Modulate);
Romain Guy889f8d12010-07-29 14:37:42 -0700396 } else {
397 if (description.hasGradient) {
398 shader.append(gFS_Main_GradientShader_Modulate);
399 } else if (description.hasBitmap) {
400 shader.append(gFS_Main_BitmapShader_Modulate);
401 }
Romain Guyac670c02010-07-27 17:39:27 -0700402 }
403 // Apply the color op if needed
404 shader.append(gFS_Main_ApplyColorOp[description.colorOp]);
405 // Output the fragment
Romain Guya5aed0d2010-09-09 14:42:43 -0700406 if (!blendFramebuffer) {
407 shader.append(gFS_Main_FragColor);
408 } else {
Romain Guyf607bdc2010-09-10 19:20:06 -0700409 shader.append(!description.swapSrcDst ?
410 gFS_Main_FragColor_Blend : gFS_Main_FragColor_Blend_Swap);
Romain Guya5aed0d2010-09-09 14:42:43 -0700411 }
Romain Guyac670c02010-07-27 17:39:27 -0700412 }
413 // End the shader
414 shader.append(gFS_Footer);
415
Romain Guydb1938e2010-08-02 18:50:22 -0700416 if (DEBUG_PROGRAM_CACHE) {
417 PROGRAM_LOGD("*** Generated fragment shader:\n\n");
418 printLongString(shader);
419 }
420
Romain Guyac670c02010-07-27 17:39:27 -0700421 return shader;
422}
423
Romain Guy48daa542010-08-10 19:21:34 -0700424void ProgramCache::generateBlend(String8& shader, const char* name, SkXfermode::Mode mode) {
Romain Guyac670c02010-07-27 17:39:27 -0700425 shader.append("\nvec4 ");
426 shader.append(name);
427 shader.append("(vec4 src, vec4 dst) {\n");
428 shader.append(" ");
Romain Guy48daa542010-08-10 19:21:34 -0700429 shader.append(gBlendOps[mode]);
Romain Guyac670c02010-07-27 17:39:27 -0700430 shader.append("}\n");
431}
432
Romain Guy889f8d12010-07-29 14:37:42 -0700433void ProgramCache::generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT) {
434 shader.append("\nvec2 wrap(vec2 texCoords) {\n");
435 if (wrapS == GL_MIRRORED_REPEAT) {
436 shader.append(" float xMod2 = mod(texCoords.x, 2.0);\n");
437 shader.append(" if (xMod2 > 1.0) xMod2 = 2.0 - xMod2;\n");
438 }
439 if (wrapT == GL_MIRRORED_REPEAT) {
440 shader.append(" float yMod2 = mod(texCoords.y, 2.0);\n");
441 shader.append(" if (yMod2 > 1.0) yMod2 = 2.0 - yMod2;\n");
442 }
443 shader.append(" return vec2(");
444 switch (wrapS) {
Romain Guy61c8c9c2010-08-09 20:48:09 -0700445 case GL_CLAMP_TO_EDGE:
446 shader.append("texCoords.x");
447 break;
Romain Guy889f8d12010-07-29 14:37:42 -0700448 case GL_REPEAT:
449 shader.append("mod(texCoords.x, 1.0)");
450 break;
451 case GL_MIRRORED_REPEAT:
452 shader.append("xMod2");
453 break;
454 }
455 shader.append(", ");
456 switch (wrapT) {
Romain Guy61c8c9c2010-08-09 20:48:09 -0700457 case GL_CLAMP_TO_EDGE:
458 shader.append("texCoords.y");
459 break;
Romain Guy889f8d12010-07-29 14:37:42 -0700460 case GL_REPEAT:
461 shader.append("mod(texCoords.y, 1.0)");
462 break;
463 case GL_MIRRORED_REPEAT:
464 shader.append("yMod2");
465 break;
466 }
467 shader.append(");\n");
468 shader.append("}\n");
469}
470
Romain Guydb1938e2010-08-02 18:50:22 -0700471void ProgramCache::printLongString(const String8& shader) const {
472 ssize_t index = 0;
473 ssize_t lastIndex = 0;
474 const char* str = shader.string();
475 while ((index = shader.find("\n", index)) > -1) {
476 String8 line(str, index - lastIndex);
477 if (line.length() == 0) line.append("\n");
478 PROGRAM_LOGD("%s", line.string());
479 index++;
480 str += (index - lastIndex);
481 lastIndex = index;
482 }
483}
484
Romain Guyac670c02010-07-27 17:39:27 -0700485}; // namespace uirenderer
486}; // namespace android