ProgramCache.cpp revision 707b2f78ccaa09965d7e030fda3a883ce9b75ea8
1ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy/* 2ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * Copyright (C) 2010 The Android Open Source Project 3ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * 4ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 5ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * you may not use this file except in compliance with the License. 6ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * You may obtain a copy of the License at 7ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * 8ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * http://www.apache.org/licenses/LICENSE-2.0 9ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * 10ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * Unless required by applicable law or agreed to in writing, software 11ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * distributed under the License is distributed on an "AS IS" BASIS, 12ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * See the License for the specific language governing permissions and 14ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * limitations under the License. 15ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy */ 16ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 17ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy#define LOG_TAG "OpenGLRenderer" 18ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 19ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy#include <utils/String8.h> 20ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 21ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy#include "ProgramCache.h" 22ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 23ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guynamespace android { 24ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guynamespace uirenderer { 25ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 26ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy/////////////////////////////////////////////////////////////////////////////// 27707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy// Defines 28707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy/////////////////////////////////////////////////////////////////////////////// 29707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy 30707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy#define MODULATE_OP_NO_MODULATE 0 31707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy#define MODULATE_OP_MODULATE 1 32707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy#define MODULATE_OP_MODULATE_A8 2 33707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy 34707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy/////////////////////////////////////////////////////////////////////////////// 35ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy// Vertex shaders snippets 36ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy/////////////////////////////////////////////////////////////////////////////// 37ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 38ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Header_Attributes = 39ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "attribute vec4 position;\n"; 40ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Header_Attributes_TexCoords = 41ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "attribute vec2 texCoords;\n"; 42ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Header_Uniforms = 43ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "uniform mat4 transform;\n"; 44ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyconst char* gVS_Header_Uniforms_HasGradient[3] = { 45ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Linear 46ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy "uniform mat4 screenSpace;\n", 47ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Circular 48ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy "uniform mat4 screenSpace;\n", 49ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Sweep 50ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy "uniform mat4 screenSpace;\n" 51ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}; 52889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guyconst char* gVS_Header_Uniforms_HasBitmap = 53889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy "uniform mat4 textureTransform;\n" 54889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy "uniform vec2 textureDimension;\n"; 55ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Header_Varyings_HasTexture = 56ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "varying vec2 outTexCoords;\n"; 57ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Header_Varyings_HasBitmap = 58ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "varying vec2 outBitmapTexCoords;\n"; 59ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyconst char* gVS_Header_Varyings_HasGradient[3] = { 60ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Linear 617537f856f9076a84db04d8de447f6527b67166fdRomain Guy "varying vec2 linear;\n", 62ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Circular 63ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy "varying vec2 circular;\n", 64ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Sweep 65ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy "varying vec2 sweep;\n" 66ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}; 67ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Main = 68ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "\nvoid main(void) {\n"; 69ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Main_OutTexCoords = 70ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy " outTexCoords = texCoords;\n"; 71ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyconst char* gVS_Main_OutGradient[3] = { 72ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Linear 737537f856f9076a84db04d8de447f6527b67166fdRomain Guy " linear = vec2((screenSpace * position).x, 0.5);\n", 74ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Circular 7514830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy " circular = (screenSpace * position).xy;\n", 76ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Sweep 7714830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy " sweep = (screenSpace * position).xy;\n" 78ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}; 79889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guyconst char* gVS_Main_OutBitmapTexCoords = 80707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n"; 81ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Main_Position = 82ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy " gl_Position = transform * position;\n"; 83ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Footer = 84ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "}\n\n"; 85ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 86ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy/////////////////////////////////////////////////////////////////////////////// 87ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy// Fragment shaders snippets 88ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy/////////////////////////////////////////////////////////////////////////////// 89ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 90a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guyconst char* gFS_Header_Extension_FramebufferFetch = 91a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy "#extension GL_NV_shader_framebuffer_fetch : enable\n\n"; 92ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Header = 93ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "precision mediump float;\n\n"; 94ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Uniforms_Color = 95ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "uniform vec4 color;\n"; 96ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Uniforms_TextureSampler = 97ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "uniform sampler2D sampler;\n"; 98ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyconst char* gFS_Uniforms_GradientSampler[3] = { 99ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Linear 100ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy "uniform sampler2D gradientSampler;\n", 101ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Circular 102ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy "uniform sampler2D gradientSampler;\n", 103ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Sweep 104ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy "uniform sampler2D gradientSampler;\n" 105ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}; 106ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Uniforms_BitmapSampler = 107ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "uniform sampler2D bitmapSampler;\n"; 108ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Uniforms_ColorOp[4] = { 109ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // None 110ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "", 111ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Matrix 112ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "uniform mat4 colorMatrix;\n" 113ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "uniform vec4 colorMatrixVector;\n", 114ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Lighting 115db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy "uniform vec4 lightingMul;\n" 116db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy "uniform vec4 lightingAdd;\n", 117ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // PorterDuff 118db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy "uniform vec4 colorBlend;\n" 119ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}; 120ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main = 121ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "\nvoid main(void) {\n" 1227fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy " lowp vec4 fragColor;\n"; 123707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy 124707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy// Fast cases 125707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guyconst char* gFS_Fast_SingleColor = 126707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy "\nvoid main(void) {\n" 127707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " gl_FragColor = color;\n" 128707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy "}\n\n"; 129707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guyconst char* gFS_Fast_SingleTexture = 130707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy "\nvoid main(void) {\n" 131707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " gl_FragColor = texture2D(sampler, outTexCoords);\n" 132707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy "}\n\n"; 133707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guyconst char* gFS_Fast_SingleModulateTexture = 134707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy "\nvoid main(void) {\n" 135707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " gl_FragColor = color.a * texture2D(sampler, outTexCoords);\n" 136707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy "}\n\n"; 137707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guyconst char* gFS_Fast_SingleA8Texture = 138707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy "\nvoid main(void) {\n" 139707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " gl_FragColor = vec4(0.0, 0.0, 0.0, texture2D(sampler, outTexCoords).a);\n" 140707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy "}\n\n"; 141707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guyconst char* gFS_Fast_SingleModulateA8Texture = 142707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy "\nvoid main(void) {\n" 143707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " gl_FragColor = color * texture2D(sampler, outTexCoords).a;\n" 144707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy "}\n\n"; 145707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guyconst char* gFS_Fast_SingleGradient = 146707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy "\nvoid main(void) {\n" 147707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " gl_FragColor = texture2D(gradientSampler, linear);\n" 148707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy "}\n\n"; 149707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guyconst char* gFS_Fast_SingleModulateGradient = 150707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy "\nvoid main(void) {\n" 151707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " gl_FragColor = color.a * texture2D(gradientSampler, linear);\n" 152707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy "}\n\n"; 153707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy 154707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy// General case 155ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_FetchColor = 156ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy " fragColor = color;\n"; 157707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guyconst char* gFS_Main_FetchTexture[2] = { 158707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy // Don't modulate 159707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " fragColor = texture2D(sampler, outTexCoords);\n", 160707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy // Modulate 161707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " fragColor = color * texture2D(sampler, outTexCoords);\n" 162707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy}; 163707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guyconst char* gFS_Main_FetchA8Texture[2] = { 164707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy // Don't modulate 165707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " fragColor = vec4(0.0, 0.0, 0.0, texture2D(sampler, outTexCoords).a);\n", 166707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy // Modulate 167707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " fragColor = color * texture2D(sampler, outTexCoords).a;\n" 168707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy}; 169ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guyconst char* gFS_Main_FetchGradient[3] = { 170ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Linear 1717537f856f9076a84db04d8de447f6527b67166fdRomain Guy " vec4 gradientColor = texture2D(gradientSampler, linear);\n", 172ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Circular 17314830948d02f768c41b97b7a8d15e1b3cab78267Romain Guy " float index = length(circular);\n" 174ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n", 175ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy // Sweep 176ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy " float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n" 177ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy " vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n" 178ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}; 179ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_FetchBitmap = 180ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy " vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n"; 181889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guyconst char* gFS_Main_FetchBitmapNpot = 182889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy " vec4 bitmapColor = texture2D(bitmapSampler, wrap(outBitmapTexCoords));\n"; 183ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_BlendShadersBG = 184ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy " fragColor = blendShaders(gradientColor, bitmapColor)"; 18506f96e2652e4855b6520ad9dd70583677605b79aRomain Guyconst char* gFS_Main_BlendShadersGB = 18606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy " fragColor = blendShaders(bitmapColor, gradientColor)"; 187707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guyconst char* gFS_Main_BlendShaders_Modulate[3] = { 188707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy // Don't modulate 189707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy ";\n", 190707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy // Modulate 191707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " * fragColor.a;\n", 192707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy // Modulate with alpha 8 texture 193707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " * texture2D(sampler, outTexCoords).a;\n" 194707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy}; 195707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guyconst char* gFS_Main_GradientShader_Modulate[3] = { 196707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy // Don't modulate 197707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " fragColor = gradientColor;\n", 198707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy // Modulate 199707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " fragColor = gradientColor * fragColor.a;\n", 200707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy // Modulate with alpha 8 texture 201707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " fragColor = gradientColor * texture2D(sampler, outTexCoords).a;\n" 202707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy }; 203707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guyconst char* gFS_Main_BitmapShader_Modulate[3] = { 204707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy // Don't modulate 205707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " fragColor = bitmapColor;\n", 206707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy // Modulate 207707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " fragColor = bitmapColor * fragColor.a;\n", 208707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy // Modulate with alpha 8 texture 209707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy " fragColor = bitmapColor * texture2D(sampler, outTexCoords).a;\n" 210707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy }; 211ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_FragColor = 212ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy " gl_FragColor = fragColor;\n"; 213a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guyconst char* gFS_Main_FragColor_Blend = 214a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy " gl_FragColor = blendFramebuffer(fragColor, gl_LastFragColor);\n"; 215f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guyconst char* gFS_Main_FragColor_Blend_Swap = 216f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy " gl_FragColor = blendFramebuffer(gl_LastFragColor, fragColor);\n"; 217ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_ApplyColorOp[4] = { 218ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // None 219ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "", 220ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Matrix 221db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy // TODO: Fix premultiplied alpha computations for color matrix 222ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy " fragColor *= colorMatrix;\n" 223db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy " fragColor += colorMatrixVector;\n" 224db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy " fragColor.rgb *= fragColor.a;\n", 225ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Lighting 226db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy " float lightingAlpha = fragColor.a;\n" 227db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy " fragColor = min(fragColor * lightingMul + (lightingAdd * lightingAlpha), lightingAlpha);\n" 228db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy " fragColor.a = lightingAlpha;\n", 229ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // PorterDuff 230ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy " fragColor = blendColors(colorBlend, fragColor);\n" 231ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}; 232ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Footer = 233ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "}\n\n"; 234ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 235ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy/////////////////////////////////////////////////////////////////////////////// 236ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy// PorterDuff snippets 237ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy/////////////////////////////////////////////////////////////////////////////// 238ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 23948daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guyconst char* gBlendOps[18] = { 240ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Clear 241ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "return vec4(0.0, 0.0, 0.0, 0.0);\n", 242ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Src 243ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "return src;\n", 244ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Dst 245ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "return dst;\n", 246ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // SrcOver 24706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy "return src + dst * (1.0 - src.a);\n", 248ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // DstOver 24906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy "return dst + src * (1.0 - dst.a);\n", 250ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // SrcIn 25106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy "return src * dst.a;\n", 252ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // DstIn 25306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy "return dst * src.a;\n", 254ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // SrcOut 25506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy "return src * (1.0 - dst.a);\n", 256ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // DstOut 25706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy "return dst * (1.0 - src.a);\n", 258ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // SrcAtop 259ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "return vec4(src.rgb * dst.a + (1.0 - src.a) * dst.rgb, dst.a);\n", 260ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // DstAtop 261ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "return vec4(dst.rgb * src.a + (1.0 - dst.a) * src.rgb, src.a);\n", 262ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Xor 26348daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb, " 264ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy "src.a + dst.a - 2.0 * src.a * dst.a);\n", 26548daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy // Add 26648daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy "return min(src + dst, 1.0);\n", 26748daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy // Multiply 26848daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy "return src * dst;\n", 26948daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy // Screen 27048daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy "return src + dst - src * dst;\n", 27148daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy // Overlay 27248daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy "return clamp(vec4(mix(" 27348daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy "2.0 * src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), " 27448daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy "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), " 27548daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy "step(dst.a, 2.0 * dst.rgb)), " 27648daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy "src.a + dst.a - src.a * dst.a), 0.0, 1.0);\n", 27748daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy // Darken 27848daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + " 27948daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy "min(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n", 28048daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy // Lighten 28148daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + " 28248daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy "max(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n", 283ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}; 284ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 285ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy/////////////////////////////////////////////////////////////////////////////// 286ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy// Constructors/destructors 287ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy/////////////////////////////////////////////////////////////////////////////// 288ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 289ac670c0433d19397d4e36ced2110475b6f54fe26Romain GuyProgramCache::ProgramCache() { 290ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy} 291ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 292ac670c0433d19397d4e36ced2110475b6f54fe26Romain GuyProgramCache::~ProgramCache() { 293ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy clear(); 294ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy} 295ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 296ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy/////////////////////////////////////////////////////////////////////////////// 297ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy// Cache management 298ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy/////////////////////////////////////////////////////////////////////////////// 299ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 300ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyvoid ProgramCache::clear() { 301ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy size_t count = mCache.size(); 302ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy for (size_t i = 0; i < count; i++) { 303ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy delete mCache.valueAt(i); 304ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 305ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy mCache.clear(); 306ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy} 307ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 308ac670c0433d19397d4e36ced2110475b6f54fe26Romain GuyProgram* ProgramCache::get(const ProgramDescription& description) { 309ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy programid key = description.key(); 310ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy ssize_t index = mCache.indexOfKey(key); 311ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy Program* program = NULL; 312ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (index < 0) { 313ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy description.log("Could not find program"); 314ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy program = generateProgram(description, key); 315ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy mCache.add(key, program); 316ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } else { 317ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy program = mCache.valueAt(index); 318ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 319ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy return program; 320ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy} 321ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 322ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy/////////////////////////////////////////////////////////////////////////////// 323ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy// Program generation 324ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy/////////////////////////////////////////////////////////////////////////////// 325ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 326ac670c0433d19397d4e36ced2110475b6f54fe26Romain GuyProgram* ProgramCache::generateProgram(const ProgramDescription& description, programid key) { 327ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy String8 vertexShader = generateVertexShader(description); 328ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy String8 fragmentShader = generateFragmentShader(description); 329ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 330ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy Program* program = new Program(vertexShader.string(), fragmentShader.string()); 331ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy return program; 332ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy} 333ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 334ac670c0433d19397d4e36ced2110475b6f54fe26Romain GuyString8 ProgramCache::generateVertexShader(const ProgramDescription& description) { 335ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Add attributes 336ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy String8 shader(gVS_Header_Attributes); 337889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy if (description.hasTexture) { 338ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gVS_Header_Attributes_TexCoords); 339ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 340ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Uniforms 341ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gVS_Header_Uniforms); 342ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasGradient) { 343ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]); 344ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 345889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy if (description.hasBitmap) { 346889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append(gVS_Header_Uniforms_HasBitmap); 347889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } 348ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Varyings 349ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasTexture) { 350ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gVS_Header_Varyings_HasTexture); 351ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 352ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasGradient) { 353ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); 354ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 355ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasBitmap) { 356ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gVS_Header_Varyings_HasBitmap); 357ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 358ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 359ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Begin the shader 360ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gVS_Main); { 361ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasTexture) { 362ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gVS_Main_OutTexCoords); 363ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 364ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasGradient) { 365ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy shader.append(gVS_Main_OutGradient[description.gradientType]); 366ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 367889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy if (description.hasBitmap) { 368889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append(gVS_Main_OutBitmapTexCoords); 369889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } 370ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Output transformed position 371ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gVS_Main_Position); 372ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 373ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // End the shader 374ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gVS_Footer); 375ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 376ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy PROGRAM_LOGD("*** Generated vertex shader:\n\n%s", shader.string()); 377ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 378ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy return shader; 379ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy} 380ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 381ac670c0433d19397d4e36ced2110475b6f54fe26Romain GuyString8 ProgramCache::generateFragmentShader(const ProgramDescription& description) { 382ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Set the default precision 383a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy String8 shader; 384a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy 385707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy const bool blendFramebuffer = description.framebufferMode >= SkXfermode::kPlus_Mode; 386a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy if (blendFramebuffer) { 387a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy shader.append(gFS_Header_Extension_FramebufferFetch); 388a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy } 389a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy 390a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy shader.append(gFS_Header); 391ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 392ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Varyings 393ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasTexture) { 394ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gVS_Header_Varyings_HasTexture); 395ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 396ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasGradient) { 397ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); 398ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 399ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasBitmap) { 400ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gVS_Header_Varyings_HasBitmap); 401ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 402ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 403ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Uniforms 404707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy int modulateOp = MODULATE_OP_NO_MODULATE; 405707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy const bool singleColor = !description.hasTexture && 406707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy !description.hasGradient && !description.hasBitmap; 407707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy 408707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy if (description.modulate || singleColor) { 409707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy shader.append(gFS_Uniforms_Color); 410707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy if (!singleColor) modulateOp = MODULATE_OP_MODULATE; 411707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } 412ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasTexture) { 413ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gFS_Uniforms_TextureSampler); 414ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 415ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasGradient) { 416ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy shader.append(gFS_Uniforms_GradientSampler[description.gradientType]); 417ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 418707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy 419707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy // Optimization for common cases 420707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy if (!blendFramebuffer) { 421707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy bool fast = false; 422707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy 423707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy const bool noShader = !description.hasGradient && !description.hasBitmap; 424707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy const bool singleTexture = description.hasTexture && 425707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy !description.hasAlpha8Texture && noShader; 426707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy const bool singleA8Texture = description.hasTexture && 427707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy description.hasAlpha8Texture && noShader; 428707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy const bool singleGradient = !description.hasTexture && 429707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy description.hasGradient && !description.hasBitmap && 430707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy description.gradientType == ProgramDescription::kGradientLinear; 431707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy 432707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy if (singleColor) { 433707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy shader.append(gFS_Fast_SingleColor); 434707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy fast = true; 435707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } else if (singleTexture) { 436707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy if (!description.modulate) { 437707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy shader.append(gFS_Fast_SingleTexture); 438707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } else { 439707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy shader.append(gFS_Fast_SingleModulateTexture); 440707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } 441707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy fast = true; 442707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } else if (singleA8Texture) { 443707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy if (!description.modulate) { 444707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy shader.append(gFS_Fast_SingleA8Texture); 445707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } else { 446707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy shader.append(gFS_Fast_SingleModulateA8Texture); 447707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } 448707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy fast = true; 449707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } else if (singleGradient) { 450707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy if (!description.modulate) { 451707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy shader.append(gFS_Fast_SingleGradient); 452707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } else { 453707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy shader.append(gFS_Fast_SingleModulateGradient); 454707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } 455707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy fast = true; 456707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } 457707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy 458707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy if (fast) { 459707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy if (DEBUG_PROGRAM_CACHE) { 460707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy PROGRAM_LOGD("*** Fast case:\n"); 461707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy PROGRAM_LOGD("*** Generated fragment shader:\n\n"); 462707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy printLongString(shader); 463707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } 464707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy 465707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy return shader; 466707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } 467707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } 468707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy 469ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasBitmap) { 470ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gFS_Uniforms_BitmapSampler); 471ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 472ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gFS_Uniforms_ColorOp[description.colorOp]); 473ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 474ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Generate required functions 475ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasGradient && description.hasBitmap) { 47648daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy generateBlend(shader, "blendShaders", description.shadersMode); 477ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 478ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.colorOp == ProgramDescription::kColorBlend) { 47948daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy generateBlend(shader, "blendColors", description.colorMode); 480ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 481a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy if (blendFramebuffer) { 482a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy generateBlend(shader, "blendFramebuffer", description.framebufferMode); 483a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy } 484889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy if (description.isBitmapNpot) { 485889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT); 486889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } 487ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 488ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Begin the shader 489ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gFS_Main); { 490ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Stores the result in fragColor directly 491ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasTexture) { 492ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasAlpha8Texture) { 493707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy if (!description.hasGradient && !description.hasBitmap) { 494707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy shader.append(gFS_Main_FetchA8Texture[modulateOp]); 495707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } 496ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } else { 497707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy shader.append(gFS_Main_FetchTexture[modulateOp]); 498ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 499ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } else { 500707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy if ((!description.hasGradient && !description.hasBitmap) || description.modulate) { 501707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy shader.append(gFS_Main_FetchColor); 502707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy } 503ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 504ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasGradient) { 505ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy shader.append(gFS_Main_FetchGradient[description.gradientType]); 506ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 507ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasBitmap) { 508889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy if (!description.isBitmapNpot) { 509889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append(gFS_Main_FetchBitmap); 510889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } else { 511889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append(gFS_Main_FetchBitmapNpot); 512889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } 513ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 514ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Case when we have two shaders set 515ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.hasGradient && description.hasBitmap) { 516707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; 517ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy if (description.isBitmapFirst) { 518ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gFS_Main_BlendShadersBG); 519ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } else { 520ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gFS_Main_BlendShadersGB); 521ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 522707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy shader.append(gFS_Main_BlendShaders_Modulate[op]); 523889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } else { 524889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy if (description.hasGradient) { 525707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; 526707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy shader.append(gFS_Main_GradientShader_Modulate[op]); 527889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } else if (description.hasBitmap) { 528707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; 529707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy shader.append(gFS_Main_BitmapShader_Modulate[op]); 530889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } 531ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 532ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Apply the color op if needed 533ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gFS_Main_ApplyColorOp[description.colorOp]); 534ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // Output the fragment 535a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy if (!blendFramebuffer) { 536a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy shader.append(gFS_Main_FragColor); 537a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy } else { 538f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy shader.append(!description.swapSrcDst ? 539f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy gFS_Main_FragColor_Blend : gFS_Main_FragColor_Blend_Swap); 540a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy } 541ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy } 542ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy // End the shader 543ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(gFS_Footer); 544ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 545db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy if (DEBUG_PROGRAM_CACHE) { 546db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy PROGRAM_LOGD("*** Generated fragment shader:\n\n"); 547db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy printLongString(shader); 548db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy } 549db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy 550ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy return shader; 551ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy} 552ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 55348daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guyvoid ProgramCache::generateBlend(String8& shader, const char* name, SkXfermode::Mode mode) { 554ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append("\nvec4 "); 555ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(name); 556ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append("(vec4 src, vec4 dst) {\n"); 557ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append(" "); 55848daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy shader.append(gBlendOps[mode]); 559ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy shader.append("}\n"); 560ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy} 561ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 562889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guyvoid ProgramCache::generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT) { 563889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append("\nvec2 wrap(vec2 texCoords) {\n"); 564889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy if (wrapS == GL_MIRRORED_REPEAT) { 565889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append(" float xMod2 = mod(texCoords.x, 2.0);\n"); 566889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append(" if (xMod2 > 1.0) xMod2 = 2.0 - xMod2;\n"); 567889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } 568889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy if (wrapT == GL_MIRRORED_REPEAT) { 569889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append(" float yMod2 = mod(texCoords.y, 2.0);\n"); 570889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append(" if (yMod2 > 1.0) yMod2 = 2.0 - yMod2;\n"); 571889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } 572889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append(" return vec2("); 573889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy switch (wrapS) { 57461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy case GL_CLAMP_TO_EDGE: 57561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy shader.append("texCoords.x"); 57661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy break; 577889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy case GL_REPEAT: 578889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append("mod(texCoords.x, 1.0)"); 579889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy break; 580889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy case GL_MIRRORED_REPEAT: 581889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append("xMod2"); 582889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy break; 583889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } 584889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append(", "); 585889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy switch (wrapT) { 58661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy case GL_CLAMP_TO_EDGE: 58761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy shader.append("texCoords.y"); 58861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy break; 589889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy case GL_REPEAT: 590889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append("mod(texCoords.y, 1.0)"); 591889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy break; 592889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy case GL_MIRRORED_REPEAT: 593889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append("yMod2"); 594889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy break; 595889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } 596889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append(");\n"); 597889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy shader.append("}\n"); 598889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy} 599889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy 600db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guyvoid ProgramCache::printLongString(const String8& shader) const { 601db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy ssize_t index = 0; 602db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy ssize_t lastIndex = 0; 603db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy const char* str = shader.string(); 604db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy while ((index = shader.find("\n", index)) > -1) { 605db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy String8 line(str, index - lastIndex); 606db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy if (line.length() == 0) line.append("\n"); 607db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy PROGRAM_LOGD("%s", line.string()); 608db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy index++; 609db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy str += (index - lastIndex); 610db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy lastIndex = index; 611db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy } 612db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy} 613db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy 614ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}; // namespace uirenderer 615ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}; // namespace android 616