ProgramCache.cpp revision ac670c0433d19397d4e36ced2110475b6f54fe26
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///////////////////////////////////////////////////////////////////////////////
27ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy// Vertex shaders snippets
28ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy///////////////////////////////////////////////////////////////////////////////
29ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
30ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy// TODO: Implement BitmapShader, implement repeat/mirror for npot
31ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
32ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Header_Attributes =
33ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "attribute vec4 position;\n";
34ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Header_Attributes_TexCoords =
35ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "attribute vec2 texCoords;\n";
36ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Header_Uniforms =
37ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "uniform mat4 transform;\n";
38ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Header_Uniforms_HasGradient =
39ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "uniform float gradientLength;\n"
40ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "uniform vec2 gradient;\n"
41ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "uniform vec2 gradientStart;\n"
42ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "uniform mat4 screenSpace;\n";
43ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Header_Varyings_HasTexture =
44ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "varying vec2 outTexCoords;\n";
45ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Header_Varyings_HasBitmap =
46ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "varying vec2 outBitmapTexCoords;\n";
47ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Header_Varyings_HasGradient =
48ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "varying float index;\n";
49ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Main =
50ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "\nvoid main(void) {\n";
51ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Main_OutTexCoords =
52ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    outTexCoords = texCoords;\n";
53ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Main_OutGradientIndex =
54ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    vec4 location = screenSpace * position;\n"
55ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    index = dot(location.xy - gradientStart, gradient) * gradientLength;\n";
56ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Main_Position =
57ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    gl_Position = transform * position;\n";
58ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gVS_Footer =
59ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "}\n\n";
60ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
61ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy///////////////////////////////////////////////////////////////////////////////
62ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy// Fragment shaders snippets
63ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy///////////////////////////////////////////////////////////////////////////////
64ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
65ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Header =
66ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "precision mediump float;\n\n";
67ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Uniforms_Color =
68ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "uniform vec4 color;\n";
69ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Uniforms_TextureSampler =
70ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "uniform sampler2D sampler;\n";
71ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Uniforms_GradientSampler =
72ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "uniform sampler2D gradientSampler;\n";
73ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Uniforms_BitmapSampler =
74ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "uniform sampler2D bitmapSampler;\n";
75ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Uniforms_ColorOp[4] = {
76ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // None
77ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "",
78ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // Matrix
79ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "uniform mat4 colorMatrix;\n"
80ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "uniform vec4 colorMatrixVector;\n",
81ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // Lighting
82ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "uniform float lightingMul;\n"
83ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "uniform float lightingAdd;\n",
84ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // PorterDuff
85ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "uniform vec4 colorBLend;\n"
86ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy};
87ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main =
88ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "\nvoid main(void) {\n"
89ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    vec4 fragColor;\n";
90ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_FetchColor =
91ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    fragColor = color;\n";
92ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_FetchTexture =
93ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    fragColor = color * texture2D(sampler, outTexCoords);\n";
94ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_FetchA8Texture =
95ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    fragColor = color * texture2D(sampler, outTexCoords).a;\n";
96ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_FetchGradient =
97ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n";
98ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_FetchBitmap =
99ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n";
100ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_BlendShadersBG =
101ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    fragColor = blendShaders(bitmapColor, gradientColor)";
102ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_BlendShadersGB =
103ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    fragColor = blendShaders(gradientColor, bitmapColor)";
104ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_BlendShaders_Modulate =
105ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        " * fragColor.a;\n";
106ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_FragColor =
107ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    gl_FragColor = fragColor;\n";
108ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Main_ApplyColorOp[4] = {
109ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // None
110ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "",
111ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // Matrix
112ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    fragColor *= colorMatrix;\n"
113ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    fragColor += colorMatrixVector;\n",
114ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // Lighting
115ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    fragColor *= lightingMul;\n"
116ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    fragColor += lightingAdd;\n",
117ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // PorterDuff
118ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "    fragColor = blendColors(colorBlend, fragColor);\n"
119ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy};
120ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gFS_Footer =
121ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "}\n\n";
122ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
123ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy///////////////////////////////////////////////////////////////////////////////
124ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy// PorterDuff snippets
125ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy///////////////////////////////////////////////////////////////////////////////
126ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
127ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyconst char* gPorterDuff[12] = {
128ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // Clear
129ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "return vec4(0.0, 0.0, 0.0, 0.0);\n",
130ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // Src
131ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "return src;\n",
132ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // Dst
133ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "return dst;\n",
134ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // SrcOver
135ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "return vec4(src.rgb + (1.0 - src.a) * dst.rgb, src.a + dst.a - src.a * dst.a);\n",
136ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // DstOver
137ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "return vec4(dst.rgb + (1.0 - dst.a) * src.rgb, src.a + dst.a - src.a * dst.a);\n",
138ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // SrcIn
139ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "return vec4(src.rgb * dst.a, src.a * dst.a);\n",
140ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // DstIn
141ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "return vec4(dst.rgb * src.a, src.a * dst.a);\n",
142ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // SrcOut
143ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "return vec4(src.rgb * (1.0 - dst.a), src.a * (1.0 - dst.a));\n",
144ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // DstOut
145ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "return vec4(dst.rgb * (1.0 - src.a), dst.a * (1.0 - src.a));\n",
146ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // SrcAtop
147ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "return vec4(src.rgb * dst.a + (1.0 - src.a) * dst.rgb, dst.a);\n",
148ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // DstAtop
149ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "return vec4(dst.rgb * src.a + (1.0 - dst.a) * src.rgb, src.a);\n",
150ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // Xor
151ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb, "
152ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy                "src.a + dst.a - 2.0 * src.a * dst.a);\n",
153ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy};
154ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
155ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy///////////////////////////////////////////////////////////////////////////////
156ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy// Constructors/destructors
157ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy///////////////////////////////////////////////////////////////////////////////
158ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
159ac670c0433d19397d4e36ced2110475b6f54fe26Romain GuyProgramCache::ProgramCache() {
160ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}
161ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
162ac670c0433d19397d4e36ced2110475b6f54fe26Romain GuyProgramCache::~ProgramCache() {
163ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    clear();
164ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}
165ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
166ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy///////////////////////////////////////////////////////////////////////////////
167ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy// Cache management
168ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy///////////////////////////////////////////////////////////////////////////////
169ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
170ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyvoid ProgramCache::clear() {
171ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    size_t count = mCache.size();
172ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    for (size_t i = 0; i < count; i++) {
173ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        delete mCache.valueAt(i);
174ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
175ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    mCache.clear();
176ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}
177ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
178ac670c0433d19397d4e36ced2110475b6f54fe26Romain GuyProgram* ProgramCache::get(const ProgramDescription& description) {
179ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    programid key = description.key();
180ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    ssize_t index = mCache.indexOfKey(key);
181ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    Program* program = NULL;
182ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    if (index < 0) {
183ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        PROGRAM_LOGD("Could not find program with key 0x%x", key);
184ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        program = generateProgram(description, key);
185ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        mCache.add(key, program);
186ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    } else {
187ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        program = mCache.valueAt(index);
188ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
189ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    return program;
190ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}
191ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
192ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy///////////////////////////////////////////////////////////////////////////////
193ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy// Program generation
194ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy///////////////////////////////////////////////////////////////////////////////
195ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
196ac670c0433d19397d4e36ced2110475b6f54fe26Romain GuyProgram* ProgramCache::generateProgram(const ProgramDescription& description, programid key) {
197ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    String8 vertexShader = generateVertexShader(description);
198ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    String8 fragmentShader = generateFragmentShader(description);
199ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
200ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    Program* program = new Program(vertexShader.string(), fragmentShader.string());
201ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    return program;
202ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}
203ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
204ac670c0433d19397d4e36ced2110475b6f54fe26Romain GuyString8 ProgramCache::generateVertexShader(const ProgramDescription& description) {
205ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    // Add attributes
206ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    String8 shader(gVS_Header_Attributes);
207ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    if (description.hasTexture || description.hasBitmap) {
208ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        shader.append(gVS_Header_Attributes_TexCoords);
209ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
210ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    // Uniforms
211ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    shader.append(gVS_Header_Uniforms);
212ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    if (description.hasGradient) {
213ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        shader.append(gVS_Header_Uniforms_HasGradient);
214ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
215ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    // Varyings
216ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    if (description.hasTexture) {
217ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        shader.append(gVS_Header_Varyings_HasTexture);
218ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
219ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    if (description.hasGradient) {
220ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        shader.append(gVS_Header_Varyings_HasGradient);
221ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
222ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    if (description.hasBitmap) {
223ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        shader.append(gVS_Header_Varyings_HasBitmap);
224ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
225ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
226ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    // Begin the shader
227ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    shader.append(gVS_Main); {
228ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        if (description.hasTexture) {
229ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy            shader.append(gVS_Main_OutTexCoords);
230ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        }
231ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        if (description.hasGradient) {
232ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy            shader.append(gVS_Main_OutGradientIndex);
233ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        }
234ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // Output transformed position
235ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        shader.append(gVS_Main_Position);
236ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
237ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    // End the shader
238ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    shader.append(gVS_Footer);
239ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
240ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    PROGRAM_LOGD("*** Generated vertex shader:\n\n%s", shader.string());
241ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
242ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    return shader;
243ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}
244ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
245ac670c0433d19397d4e36ced2110475b6f54fe26Romain GuyString8 ProgramCache::generateFragmentShader(const ProgramDescription& description) {
246ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    // Set the default precision
247ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    String8 shader(gFS_Header);
248ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
249ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    // Varyings
250ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    if (description.hasTexture) {
251ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        shader.append(gVS_Header_Varyings_HasTexture);
252ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
253ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    if (description.hasGradient) {
254ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        shader.append(gVS_Header_Varyings_HasGradient);
255ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
256ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    if (description.hasBitmap) {
257ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        shader.append(gVS_Header_Varyings_HasBitmap);
258ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
259ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
260ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
261ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    // Uniforms
262ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    shader.append(gFS_Uniforms_Color);
263ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    if (description.hasTexture) {
264ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        shader.append(gFS_Uniforms_TextureSampler);
265ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
266ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    if (description.hasGradient) {
267ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        shader.append(gFS_Uniforms_GradientSampler);
268ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
269ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    if (description.hasBitmap) {
270ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        shader.append(gFS_Uniforms_BitmapSampler);
271ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
272ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    shader.append(gFS_Uniforms_ColorOp[description.colorOp]);
273ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
274ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    // Generate required functions
275ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    if (description.hasGradient && description.hasBitmap) {
276ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        generatePorterDuffBlend(shader, "blendShaders", description.shadersMode);
277ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
278ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    if (description.colorOp == ProgramDescription::kColorBlend) {
279ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        generatePorterDuffBlend(shader, "blendColors", description.colorMode);
280ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
281ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
282ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    // Begin the shader
283ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    shader.append(gFS_Main); {
284ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // Stores the result in fragColor directly
285ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        if (description.hasTexture) {
286ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy            if (description.hasAlpha8Texture) {
287ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy                shader.append(gFS_Main_FetchA8Texture);
288ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy            } else {
289ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy                shader.append(gFS_Main_FetchTexture);
290ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy            }
291ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        } else {
292ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy            shader.append(gFS_Main_FetchColor);
293ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        }
294ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        if (description.hasGradient) {
295ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy            shader.append(gFS_Main_FetchGradient);
296ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        }
297ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        if (description.hasBitmap) {
298ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy            shader.append(gFS_Main_FetchBitmap);
299ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        }
300ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // Case when we have two shaders set
301ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        if (description.hasGradient && description.hasBitmap) {
302ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy            if (description.isBitmapFirst) {
303ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy                shader.append(gFS_Main_BlendShadersBG);
304ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy            } else {
305ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy                shader.append(gFS_Main_BlendShadersGB);
306ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy            }
307ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy            shader.append(gFS_Main_BlendShaders_Modulate);
308ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        }
309ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // Apply the color op if needed
310ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        shader.append(gFS_Main_ApplyColorOp[description.colorOp]);
311ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        // Output the fragment
312ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        shader.append(gFS_Main_FragColor);
313ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    }
314ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    // End the shader
315ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    shader.append(gFS_Footer);
316ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
317ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    PROGRAM_LOGD("*** Generated fragment shader:\n\n%s", shader.string());
318ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    return shader;
319ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}
320ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
321ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyvoid ProgramCache::generatePorterDuffBlend(String8& shader, const char* name,
322ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        SkXfermode::Mode mode) {
323ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    shader.append("\nvec4 ");
324ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    shader.append(name);
325ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    shader.append("(vec4 src, vec4 dst) {\n");
326ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    shader.append("    ");
327ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    shader.append(gPorterDuff[mode]);
328ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    shader.append("}\n");
329ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}
330ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
331ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}; // namespace uirenderer
332ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy}; // namespace android
333