ProgramCache.cpp revision 80bbfb19eefe3cb9be8833b136381cece069e24d
1b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/* 2b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Copyright (C) 2010 The Android Open Source Project 3b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 4b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 5b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * you may not use this file except in compliance with the License. 6b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * You may obtain a copy of the License at 7b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 8b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * http://www.apache.org/licenses/LICENSE-2.0 9b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 10b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Unless required by applicable law or agreed to in writing, software 11b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * distributed under the License is distributed on an "AS IS" BASIS, 12b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * See the License for the specific language governing permissions and 14b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * limitations under the License. 15b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */ 16b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 17b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#define LOG_TAG "OpenGLRenderer" 18b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 19b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <utils/String8.h> 20b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 21b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "ProgramCache.h" 229fded232a9548a304e0145011df8849fba0dcda7Chris Craik 23b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android { 24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer { 259fded232a9548a304e0145011df8849fba0dcda7Chris Craik 26b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/////////////////////////////////////////////////////////////////////////////// 27b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Defines 28b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/////////////////////////////////////////////////////////////////////////////// 29b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 305854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik#define MODULATE_OP_NO_MODULATE 0 315854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik#define MODULATE_OP_MODULATE 1 325854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik#define MODULATE_OP_MODULATE_A8 2 33818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 34d3daa3198e2212c985c634821682d5819346b653Chris Craik/////////////////////////////////////////////////////////////////////////////// 359fded232a9548a304e0145011df8849fba0dcda7Chris Craik// Vertex shaders snippets 369fded232a9548a304e0145011df8849fba0dcda7Chris Craik/////////////////////////////////////////////////////////////////////////////// 379fded232a9548a304e0145011df8849fba0dcda7Chris Craik 38d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gVS_Header_Attributes = 390b7e8245db728d127ada698be63d78b33fc6e4daChris Craik "attribute vec4 position;\n"; 400b7e8245db728d127ada698be63d78b33fc6e4daChris Craikconst char* gVS_Header_Attributes_TexCoords = 410b7e8245db728d127ada698be63d78b33fc6e4daChris Craik "attribute vec2 texCoords;\n"; 42d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gVS_Header_Uniforms = 43d3daa3198e2212c985c634821682d5819346b653Chris Craik "uniform mat4 transform;\n"; 44d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gVS_Header_Uniforms_IsPoint = 450b7e8245db728d127ada698be63d78b33fc6e4daChris Craik "uniform mediump float pointSize;\n"; 46818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craikconst char* gVS_Header_Uniforms_HasGradient[3] = { 475854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // Linear 485854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "uniform mat4 screenSpace;\n", 495854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // Circular 50818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik "uniform mat4 screenSpace;\n", 51818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik // Sweep 52818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik "uniform mat4 screenSpace;\n" 530b7e8245db728d127ada698be63d78b33fc6e4daChris Craik}; 54818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craikconst char* gVS_Header_Uniforms_HasBitmap = 55818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik "uniform mat4 textureTransform;\n" 56818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik "uniform mediump vec2 textureDimension;\n"; 57818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craikconst char* gVS_Header_Varyings_HasTexture = 58818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik "varying vec2 outTexCoords;\n"; 595854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikconst char* gVS_Header_Varyings_HasBitmap = 60818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik "varying vec2 outBitmapTexCoords;\n"; 61818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craikconst char* gVS_Header_Varyings_PointHasBitmap = 62818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik "varying vec2 outPointBitmapTexCoords;\n"; 630b7e8245db728d127ada698be63d78b33fc6e4daChris Craikconst char* gVS_Header_Varyings_HasGradient[3] = { 64818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik // Linear 65818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik "varying vec2 linear;\n", 665854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // Circular 678d2cf943d9c7292e54726399faefdec4a01c084bChris Craik "varying vec2 circular;\n", 685854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // Sweep 69818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik "varying vec2 sweep;\n" 70818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik}; 71818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craikconst char* gVS_Main = 72818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik "\nvoid main(void) {\n"; 735854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikconst char* gVS_Main_OutTexCoords = 745854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik " outTexCoords = texCoords;\n"; 75818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craikconst char* gVS_Main_OutGradient[3] = { 76818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik // Linear 775854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik " linear = vec2((screenSpace * position).x, 0.5);\n", 785854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // Circular 795854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik " circular = (screenSpace * position).xy;\n", 805854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // Sweep 81b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik " sweep = (screenSpace * position).xy;\n" 825854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik}; 83b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikconst char* gVS_Main_OutBitmapTexCoords = 845854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik " outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n"; 85b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikconst char* gVS_Main_OutPointBitmapTexCoords = 865854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik " outPointBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n"; 87b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikconst char* gVS_Main_Position = 88b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik " gl_Position = transform * position;\n"; 895854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikconst char* gVS_Main_PointSize = 905854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik " gl_PointSize = pointSize;\n"; 915854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikconst char* gVS_Footer = 925854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "}\n\n"; 93b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 94b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/////////////////////////////////////////////////////////////////////////////// 95b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Fragment shaders snippets 96b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/////////////////////////////////////////////////////////////////////////////// 97b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 98b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikconst char* gFS_Header_Extension_FramebufferFetch = 995854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "#extension GL_NV_shader_framebuffer_fetch : enable\n\n"; 100b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikconst char* gFS_Header = 101b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "precision mediump float;\n\n"; 1025854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikconst char* gFS_Uniforms_Color = 103b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "uniform vec4 color;\n"; 104b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikconst char* gFS_Header_Uniforms_PointHasBitmap = 105b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "uniform vec2 textureDimension;\n" 106b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "uniform float pointSize;\n"; 1075854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikconst char* gFS_Uniforms_TextureSampler = 1085854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "uniform sampler2D sampler;\n"; 1095854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikconst char* gFS_Uniforms_GradientSampler[3] = { 1105854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // Linear 1115854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "uniform sampler2D gradientSampler;\n", 1125854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // Circular 1135854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "uniform sampler2D gradientSampler;\n", 1145854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // Sweep 1155854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "uniform sampler2D gradientSampler;\n" 1165854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik}; 1175854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikconst char* gFS_Uniforms_BitmapSampler = 1185854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "uniform sampler2D bitmapSampler;\n"; 1195854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikconst char* gFS_Uniforms_ColorOp[4] = { 1205854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // None 1215854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "", 1225854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // Matrix 1235854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "uniform mat4 colorMatrix;\n" 1245854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "uniform vec4 colorMatrixVector;\n", 1255854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // Lighting 1265854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "uniform vec4 lightingMul;\n" 1275854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "uniform vec4 lightingAdd;\n", 1285854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // PorterDuff 1295854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "uniform vec4 colorBlend;\n" 1305854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik}; 1315854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikconst char* gFS_Main = 1328d2cf943d9c7292e54726399faefdec4a01c084bChris Craik "\nvoid main(void) {\n" 1338d2cf943d9c7292e54726399faefdec4a01c084bChris Craik " lowp vec4 fragColor;\n"; 1348d2cf943d9c7292e54726399faefdec4a01c084bChris Craik 1358d2cf943d9c7292e54726399faefdec4a01c084bChris Craikconst char* gFS_Main_PointBitmapTexCoords = 1368d2cf943d9c7292e54726399faefdec4a01c084bChris Craik " vec2 outBitmapTexCoords = outPointBitmapTexCoords + " 1378d2cf943d9c7292e54726399faefdec4a01c084bChris Craik "((gl_PointCoord - vec2(0.5, 0.5)) * textureDimension * vec2(pointSize, pointSize));\n"; 1385854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 1395854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik// Fast cases 1405854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikconst char* gFS_Fast_SingleColor = 1415854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "\nvoid main(void) {\n" 1425854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik " gl_FragColor = color;\n" 1435854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "}\n\n"; 1445854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikconst char* gFS_Fast_SingleTexture = 1455854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "\nvoid main(void) {\n" 1465854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik " gl_FragColor = texture2D(sampler, outTexCoords);\n" 147b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "}\n\n"; 148b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikconst char* gFS_Fast_SingleModulateTexture = 149b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "\nvoid main(void) {\n" 1508d2cf943d9c7292e54726399faefdec4a01c084bChris Craik " gl_FragColor = color.a * texture2D(sampler, outTexCoords);\n" 1518d2cf943d9c7292e54726399faefdec4a01c084bChris Craik "}\n\n"; 1528d2cf943d9c7292e54726399faefdec4a01c084bChris Craikconst char* gFS_Fast_SingleA8Texture = 1538d2cf943d9c7292e54726399faefdec4a01c084bChris Craik "\nvoid main(void) {\n" 1548d2cf943d9c7292e54726399faefdec4a01c084bChris Craik " gl_FragColor = texture2D(sampler, outTexCoords);\n" 1558d2cf943d9c7292e54726399faefdec4a01c084bChris Craik "}\n\n"; 1568d2cf943d9c7292e54726399faefdec4a01c084bChris Craikconst char* gFS_Fast_SingleModulateA8Texture = 1578d2cf943d9c7292e54726399faefdec4a01c084bChris Craik "\nvoid main(void) {\n" 1585854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik " gl_FragColor = color * texture2D(sampler, outTexCoords).a;\n" 1595854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "}\n\n"; 1605854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikconst char* gFS_Fast_SingleGradient = 161b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "\nvoid main(void) {\n" 162b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik " gl_FragColor = texture2D(gradientSampler, linear);\n" 163b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "}\n\n"; 164b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikconst char* gFS_Fast_SingleModulateGradient = 165b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "\nvoid main(void) {\n" 166b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik " gl_FragColor = color.a * texture2D(gradientSampler, linear);\n" 1675854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "}\n\n"; 168b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 169b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// General case 170b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikconst char* gFS_Main_FetchColor = 171b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik " fragColor = color;\n"; 172b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikconst char* gFS_Main_FetchTexture[2] = { 173b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Don't modulate 1745854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik " fragColor = texture2D(sampler, outTexCoords);\n", 175b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Modulate 176b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik " fragColor = color * texture2D(sampler, outTexCoords);\n" 1775854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik}; 178b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikconst char* gFS_Main_FetchA8Texture[2] = { 1795854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // Don't modulate 180b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik " fragColor = texture2D(sampler, outTexCoords);\n", 181b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Modulate 182b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik " fragColor = color * texture2D(sampler, outTexCoords).a;\n" 183b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; 184b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikconst char* gFS_Main_FetchGradient[3] = { 185b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Linear 1865854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik " vec4 gradientColor = texture2D(gradientSampler, linear);\n", 187b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Circular 188b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik " float index = length(circular);\n" 189d3daa3198e2212c985c634821682d5819346b653Chris Craik " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n", 190d3daa3198e2212c985c634821682d5819346b653Chris Craik // Sweep 191d3daa3198e2212c985c634821682d5819346b653Chris Craik " float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n" 192d3daa3198e2212c985c634821682d5819346b653Chris Craik " vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n" 193d3daa3198e2212c985c634821682d5819346b653Chris Craik}; 194d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gFS_Main_FetchBitmap = 195d3daa3198e2212c985c634821682d5819346b653Chris Craik " vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n"; 196d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gFS_Main_FetchBitmapNpot = 197d3daa3198e2212c985c634821682d5819346b653Chris Craik " vec4 bitmapColor = texture2D(bitmapSampler, wrap(outBitmapTexCoords));\n"; 198d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gFS_Main_BlendShadersBG = 199d3daa3198e2212c985c634821682d5819346b653Chris Craik " fragColor = blendShaders(gradientColor, bitmapColor)"; 200d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gFS_Main_BlendShadersGB = 201d3daa3198e2212c985c634821682d5819346b653Chris Craik " fragColor = blendShaders(bitmapColor, gradientColor)"; 202d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gFS_Main_BlendShaders_Modulate[3] = { 203d3daa3198e2212c985c634821682d5819346b653Chris Craik // Don't modulate 204d3daa3198e2212c985c634821682d5819346b653Chris Craik ";\n", 205d3daa3198e2212c985c634821682d5819346b653Chris Craik // Modulate 206d3daa3198e2212c985c634821682d5819346b653Chris Craik " * fragColor.a;\n", 207d3daa3198e2212c985c634821682d5819346b653Chris Craik // Modulate with alpha 8 texture 208d3daa3198e2212c985c634821682d5819346b653Chris Craik " * texture2D(sampler, outTexCoords).a;\n" 209d3daa3198e2212c985c634821682d5819346b653Chris Craik}; 210d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gFS_Main_GradientShader_Modulate[3] = { 211d3daa3198e2212c985c634821682d5819346b653Chris Craik // Don't modulate 212d3daa3198e2212c985c634821682d5819346b653Chris Craik " fragColor = gradientColor;\n", 213d3daa3198e2212c985c634821682d5819346b653Chris Craik // Modulate 214d3daa3198e2212c985c634821682d5819346b653Chris Craik " fragColor = gradientColor * fragColor.a;\n", 215d3daa3198e2212c985c634821682d5819346b653Chris Craik // Modulate with alpha 8 texture 216d3daa3198e2212c985c634821682d5819346b653Chris Craik " fragColor = gradientColor * texture2D(sampler, outTexCoords).a;\n" 217d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 218d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gFS_Main_BitmapShader_Modulate[3] = { 219d3daa3198e2212c985c634821682d5819346b653Chris Craik // Don't modulate 220d3daa3198e2212c985c634821682d5819346b653Chris Craik " fragColor = bitmapColor;\n", 221d3daa3198e2212c985c634821682d5819346b653Chris Craik // Modulate 222d3daa3198e2212c985c634821682d5819346b653Chris Craik " fragColor = bitmapColor * fragColor.a;\n", 223d3daa3198e2212c985c634821682d5819346b653Chris Craik // Modulate with alpha 8 texture 224d3daa3198e2212c985c634821682d5819346b653Chris Craik " fragColor = bitmapColor * texture2D(sampler, outTexCoords).a;\n" 225d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 226d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gFS_Main_FragColor = 227d3daa3198e2212c985c634821682d5819346b653Chris Craik " gl_FragColor = fragColor;\n"; 228d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gFS_Main_FragColor_Blend = 229d3daa3198e2212c985c634821682d5819346b653Chris Craik " gl_FragColor = blendFramebuffer(fragColor, gl_LastFragColor);\n"; 230d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gFS_Main_FragColor_Blend_Swap = 231d3daa3198e2212c985c634821682d5819346b653Chris Craik " gl_FragColor = blendFramebuffer(gl_LastFragColor, fragColor);\n"; 232d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gFS_Main_ApplyColorOp[4] = { 233d3daa3198e2212c985c634821682d5819346b653Chris Craik // None 234d3daa3198e2212c985c634821682d5819346b653Chris Craik "", 235d3daa3198e2212c985c634821682d5819346b653Chris Craik // Matrix 236d3daa3198e2212c985c634821682d5819346b653Chris Craik // TODO: Fix premultiplied alpha computations for color matrix 237d3daa3198e2212c985c634821682d5819346b653Chris Craik " fragColor *= colorMatrix;\n" 238d3daa3198e2212c985c634821682d5819346b653Chris Craik " fragColor += colorMatrixVector;\n" 239d3daa3198e2212c985c634821682d5819346b653Chris Craik " fragColor.rgb *= fragColor.a;\n", 240d3daa3198e2212c985c634821682d5819346b653Chris Craik // Lighting 241d3daa3198e2212c985c634821682d5819346b653Chris Craik " float lightingAlpha = fragColor.a;\n" 242d3daa3198e2212c985c634821682d5819346b653Chris Craik " fragColor = min(fragColor * lightingMul + (lightingAdd * lightingAlpha), lightingAlpha);\n" 243d3daa3198e2212c985c634821682d5819346b653Chris Craik " fragColor.a = lightingAlpha;\n", 244d3daa3198e2212c985c634821682d5819346b653Chris Craik // PorterDuff 245d3daa3198e2212c985c634821682d5819346b653Chris Craik " fragColor = blendColors(colorBlend, fragColor);\n" 246d3daa3198e2212c985c634821682d5819346b653Chris Craik}; 247d3daa3198e2212c985c634821682d5819346b653Chris Craikconst char* gFS_Footer = 248d3daa3198e2212c985c634821682d5819346b653Chris Craik "}\n\n"; 249d3daa3198e2212c985c634821682d5819346b653Chris Craik 250d3daa3198e2212c985c634821682d5819346b653Chris Craik/////////////////////////////////////////////////////////////////////////////// 251d3daa3198e2212c985c634821682d5819346b653Chris Craik// PorterDuff snippets 252d3daa3198e2212c985c634821682d5819346b653Chris Craik/////////////////////////////////////////////////////////////////////////////// 253d3daa3198e2212c985c634821682d5819346b653Chris Craik 2545854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikconst char* gBlendOps[18] = { 255b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Clear 2565854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "return vec4(0.0, 0.0, 0.0, 0.0);\n", 257b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Src 258b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "return src;\n", 259b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Dst 260b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "return dst;\n", 261b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // SrcOver 262b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "return src + dst * (1.0 - src.a);\n", 2635854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // DstOver 264b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "return dst + src * (1.0 - dst.a);\n", 265b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // SrcIn 2665854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "return src * dst.a;\n", 2675854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // DstIn 268818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik "return dst * src.a;\n", 2695854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // SrcOut 2705854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "return src * (1.0 - dst.a);\n", 2710b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // DstOut 272818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik "return dst * (1.0 - src.a);\n", 2735854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // SrcAtop 274818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik "return vec4(src.rgb * dst.a + (1.0 - src.a) * dst.rgb, dst.a);\n", 2758d2cf943d9c7292e54726399faefdec4a01c084bChris Craik // DstAtop 2760b7e8245db728d127ada698be63d78b33fc6e4daChris Craik "return vec4(dst.rgb * src.a + (1.0 - dst.a) * src.rgb, src.a);\n", 277818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik // Xor 2788d2cf943d9c7292e54726399faefdec4a01c084bChris Craik "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb, " 2798d2cf943d9c7292e54726399faefdec4a01c084bChris Craik "src.a + dst.a - 2.0 * src.a * dst.a);\n", 280818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik // Add 2815854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "return min(src + dst, 1.0);\n", 2825854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // Multiply 2830b7e8245db728d127ada698be63d78b33fc6e4daChris Craik "return src * dst;\n", 2849fded232a9548a304e0145011df8849fba0dcda7Chris Craik // Screen 2850b7e8245db728d127ada698be63d78b33fc6e4daChris Craik "return src + dst - src * dst;\n", 2866fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // Overlay 287b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "return clamp(vec4(mix(" 288b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "2.0 * src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), " 289b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "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), " 290 "step(dst.a, 2.0 * dst.rgb)), " 291 "src.a + dst.a - src.a * dst.a), 0.0, 1.0);\n", 292 // Darken 293 "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + " 294 "min(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n", 295 // Lighten 296 "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + " 297 "max(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n", 298}; 299 300/////////////////////////////////////////////////////////////////////////////// 301// Constructors/destructors 302/////////////////////////////////////////////////////////////////////////////// 303 304ProgramCache::ProgramCache() { 305} 306 307ProgramCache::~ProgramCache() { 308 clear(); 309} 310 311/////////////////////////////////////////////////////////////////////////////// 312// Cache management 313/////////////////////////////////////////////////////////////////////////////// 314 315void ProgramCache::clear() { 316 PROGRAM_LOGD("Clearing program cache"); 317 318 size_t count = mCache.size(); 319 for (size_t i = 0; i < count; i++) { 320 delete mCache.valueAt(i); 321 } 322 mCache.clear(); 323} 324 325Program* ProgramCache::get(const ProgramDescription& description) { 326 programid key = description.key(); 327 ssize_t index = mCache.indexOfKey(key); 328 Program* program = NULL; 329 if (index < 0) { 330 description.log("Could not find program"); 331 program = generateProgram(description, key); 332 mCache.add(key, program); 333 } else { 334 program = mCache.valueAt(index); 335 } 336 return program; 337} 338 339/////////////////////////////////////////////////////////////////////////////// 340// Program generation 341/////////////////////////////////////////////////////////////////////////////// 342 343Program* ProgramCache::generateProgram(const ProgramDescription& description, programid key) { 344 String8 vertexShader = generateVertexShader(description); 345 String8 fragmentShader = generateFragmentShader(description); 346 347 Program* program = new Program(vertexShader.string(), fragmentShader.string()); 348 return program; 349} 350 351String8 ProgramCache::generateVertexShader(const ProgramDescription& description) { 352 // Add attributes 353 String8 shader(gVS_Header_Attributes); 354 if (description.hasTexture) { 355 shader.append(gVS_Header_Attributes_TexCoords); 356 } 357 // Uniforms 358 shader.append(gVS_Header_Uniforms); 359 if (description.hasGradient) { 360 shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]); 361 } 362 if (description.hasBitmap) { 363 shader.append(gVS_Header_Uniforms_HasBitmap); 364 } 365 if (description.isPoint) { 366 shader.append(gVS_Header_Uniforms_IsPoint); 367 } 368 // Varyings 369 if (description.hasTexture) { 370 shader.append(gVS_Header_Varyings_HasTexture); 371 } 372 if (description.hasGradient) { 373 shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); 374 } 375 if (description.hasBitmap) { 376 shader.append(description.isPoint ? 377 gVS_Header_Varyings_PointHasBitmap : 378 gVS_Header_Varyings_HasBitmap); 379 } 380 381 // Begin the shader 382 shader.append(gVS_Main); { 383 if (description.hasTexture) { 384 shader.append(gVS_Main_OutTexCoords); 385 } 386 if (description.hasGradient) { 387 shader.append(gVS_Main_OutGradient[description.gradientType]); 388 } 389 if (description.hasBitmap) { 390 shader.append(description.isPoint ? 391 gVS_Main_OutPointBitmapTexCoords : 392 gVS_Main_OutBitmapTexCoords); 393 } 394 if (description.isPoint) { 395 shader.append(gVS_Main_PointSize); 396 } 397 // Output transformed position 398 shader.append(gVS_Main_Position); 399 } 400 // End the shader 401 shader.append(gVS_Footer); 402 403 PROGRAM_LOGD("*** Generated vertex shader:\n\n%s", shader.string()); 404 405 return shader; 406} 407 408String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) { 409 // Set the default precision 410 String8 shader; 411 412 const bool blendFramebuffer = description.framebufferMode >= SkXfermode::kPlus_Mode; 413 if (blendFramebuffer) { 414 shader.append(gFS_Header_Extension_FramebufferFetch); 415 } 416 417 shader.append(gFS_Header); 418 419 // Varyings 420 if (description.hasTexture) { 421 shader.append(gVS_Header_Varyings_HasTexture); 422 } 423 if (description.hasGradient) { 424 shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); 425 } 426 if (description.hasBitmap) { 427 shader.append(description.isPoint ? 428 gVS_Header_Varyings_PointHasBitmap : 429 gVS_Header_Varyings_HasBitmap); 430 } 431 432 // Uniforms 433 int modulateOp = MODULATE_OP_NO_MODULATE; 434 const bool singleColor = !description.hasTexture && 435 !description.hasGradient && !description.hasBitmap; 436 437 if (description.modulate || singleColor) { 438 shader.append(gFS_Uniforms_Color); 439 if (!singleColor) modulateOp = MODULATE_OP_MODULATE; 440 } 441 if (description.hasTexture) { 442 shader.append(gFS_Uniforms_TextureSampler); 443 } 444 if (description.hasGradient) { 445 shader.append(gFS_Uniforms_GradientSampler[description.gradientType]); 446 } 447 if (description.hasBitmap && description.isPoint) { 448 shader.append(gFS_Header_Uniforms_PointHasBitmap); 449 } 450 451 // Optimization for common cases 452 if (!blendFramebuffer && description.colorOp == ProgramDescription::kColorNone && 453 !description.isPoint) { 454 bool fast = false; 455 456 const bool noShader = !description.hasGradient && !description.hasBitmap; 457 const bool singleTexture = description.hasTexture && 458 !description.hasAlpha8Texture && noShader; 459 const bool singleA8Texture = description.hasTexture && 460 description.hasAlpha8Texture && noShader; 461 const bool singleGradient = !description.hasTexture && 462 description.hasGradient && !description.hasBitmap && 463 description.gradientType == ProgramDescription::kGradientLinear; 464 465 if (singleColor) { 466 shader.append(gFS_Fast_SingleColor); 467 fast = true; 468 } else if (singleTexture) { 469 if (!description.modulate) { 470 shader.append(gFS_Fast_SingleTexture); 471 } else { 472 shader.append(gFS_Fast_SingleModulateTexture); 473 } 474 fast = true; 475 } else if (singleA8Texture) { 476 if (!description.modulate) { 477 shader.append(gFS_Fast_SingleA8Texture); 478 } else { 479 shader.append(gFS_Fast_SingleModulateA8Texture); 480 } 481 fast = true; 482 } else if (singleGradient) { 483 if (!description.modulate) { 484 shader.append(gFS_Fast_SingleGradient); 485 } else { 486 shader.append(gFS_Fast_SingleModulateGradient); 487 } 488 fast = true; 489 } 490 491 if (fast) { 492#if DEBUG_PROGRAMS 493 PROGRAM_LOGD("*** Fast case:\n"); 494 PROGRAM_LOGD("*** Generated fragment shader:\n\n"); 495 printLongString(shader); 496#endif 497 498 return shader; 499 } 500 } 501 502 if (description.hasBitmap) { 503 shader.append(gFS_Uniforms_BitmapSampler); 504 } 505 shader.append(gFS_Uniforms_ColorOp[description.colorOp]); 506 507 // Generate required functions 508 if (description.hasGradient && description.hasBitmap) { 509 generateBlend(shader, "blendShaders", description.shadersMode); 510 } 511 if (description.colorOp == ProgramDescription::kColorBlend) { 512 generateBlend(shader, "blendColors", description.colorMode); 513 } 514 if (blendFramebuffer) { 515 generateBlend(shader, "blendFramebuffer", description.framebufferMode); 516 } 517 if (description.isBitmapNpot) { 518 generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT); 519 } 520 521 // Begin the shader 522 shader.append(gFS_Main); { 523 // Stores the result in fragColor directly 524 if (description.hasTexture) { 525 if (description.hasAlpha8Texture) { 526 if (!description.hasGradient && !description.hasBitmap) { 527 shader.append(gFS_Main_FetchA8Texture[modulateOp]); 528 } 529 } else { 530 shader.append(gFS_Main_FetchTexture[modulateOp]); 531 } 532 } else { 533 if ((!description.hasGradient && !description.hasBitmap) || description.modulate) { 534 shader.append(gFS_Main_FetchColor); 535 } 536 } 537 if (description.hasGradient) { 538 shader.append(gFS_Main_FetchGradient[description.gradientType]); 539 } 540 if (description.hasBitmap) { 541 if (description.isPoint) { 542 shader.append(gFS_Main_PointBitmapTexCoords); 543 } 544 if (!description.isBitmapNpot) { 545 shader.append(gFS_Main_FetchBitmap); 546 } else { 547 shader.append(gFS_Main_FetchBitmapNpot); 548 } 549 } 550 // Case when we have two shaders set 551 if (description.hasGradient && description.hasBitmap) { 552 int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; 553 if (description.isBitmapFirst) { 554 shader.append(gFS_Main_BlendShadersBG); 555 } else { 556 shader.append(gFS_Main_BlendShadersGB); 557 } 558 shader.append(gFS_Main_BlendShaders_Modulate[op]); 559 } else { 560 if (description.hasGradient) { 561 int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; 562 shader.append(gFS_Main_GradientShader_Modulate[op]); 563 } else if (description.hasBitmap) { 564 int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; 565 shader.append(gFS_Main_BitmapShader_Modulate[op]); 566 } 567 } 568 // Apply the color op if needed 569 shader.append(gFS_Main_ApplyColorOp[description.colorOp]); 570 // Output the fragment 571 if (!blendFramebuffer) { 572 shader.append(gFS_Main_FragColor); 573 } else { 574 shader.append(!description.swapSrcDst ? 575 gFS_Main_FragColor_Blend : gFS_Main_FragColor_Blend_Swap); 576 } 577 } 578 // End the shader 579 shader.append(gFS_Footer); 580 581#if DEBUG_PROGRAMS 582 PROGRAM_LOGD("*** Generated fragment shader:\n\n"); 583 printLongString(shader); 584#endif 585 586 return shader; 587} 588 589void ProgramCache::generateBlend(String8& shader, const char* name, SkXfermode::Mode mode) { 590 shader.append("\nvec4 "); 591 shader.append(name); 592 shader.append("(vec4 src, vec4 dst) {\n"); 593 shader.append(" "); 594 shader.append(gBlendOps[mode]); 595 shader.append("}\n"); 596} 597 598void ProgramCache::generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT) { 599 shader.append("\nvec2 wrap(vec2 texCoords) {\n"); 600 if (wrapS == GL_MIRRORED_REPEAT) { 601 shader.append(" float xMod2 = mod(texCoords.x, 2.0);\n"); 602 shader.append(" if (xMod2 > 1.0) xMod2 = 2.0 - xMod2;\n"); 603 } 604 if (wrapT == GL_MIRRORED_REPEAT) { 605 shader.append(" float yMod2 = mod(texCoords.y, 2.0);\n"); 606 shader.append(" if (yMod2 > 1.0) yMod2 = 2.0 - yMod2;\n"); 607 } 608 shader.append(" return vec2("); 609 switch (wrapS) { 610 case GL_CLAMP_TO_EDGE: 611 shader.append("texCoords.x"); 612 break; 613 case GL_REPEAT: 614 shader.append("mod(texCoords.x, 1.0)"); 615 break; 616 case GL_MIRRORED_REPEAT: 617 shader.append("xMod2"); 618 break; 619 } 620 shader.append(", "); 621 switch (wrapT) { 622 case GL_CLAMP_TO_EDGE: 623 shader.append("texCoords.y"); 624 break; 625 case GL_REPEAT: 626 shader.append("mod(texCoords.y, 1.0)"); 627 break; 628 case GL_MIRRORED_REPEAT: 629 shader.append("yMod2"); 630 break; 631 } 632 shader.append(");\n"); 633 shader.append("}\n"); 634} 635 636void ProgramCache::printLongString(const String8& shader) const { 637 ssize_t index = 0; 638 ssize_t lastIndex = 0; 639 const char* str = shader.string(); 640 while ((index = shader.find("\n", index)) > -1) { 641 String8 line(str, index - lastIndex); 642 if (line.length() == 0) line.append("\n"); 643 PROGRAM_LOGD("%s", line.string()); 644 index++; 645 str += (index - lastIndex); 646 lastIndex = index; 647 } 648} 649 650}; // namespace uirenderer 651}; // namespace android 652