blob: 0a1705279e7fbcf3b6e3d26c9fcb5822a64953c2 [file] [log] [blame]
Romain Guyac670c02010-07-27 17:39:27 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_UI_PROGRAM_CACHE_H
18#define ANDROID_UI_PROGRAM_CACHE_H
19
20#include <utils/KeyedVector.h>
21#include <utils/Log.h>
Romain Guy06f96e22010-07-30 19:18:16 -070022#include <utils/String8.h>
Romain Guyac670c02010-07-27 17:39:27 -070023
Romain Guy889f8d12010-07-29 14:37:42 -070024#include <GLES2/gl2.h>
25
Romain Guyac670c02010-07-27 17:39:27 -070026#include <SkXfermode.h>
27
28#include "Program.h"
29
30namespace android {
31namespace uirenderer {
32
33///////////////////////////////////////////////////////////////////////////////
34// Defines
35///////////////////////////////////////////////////////////////////////////////
36
37// Debug
Romain Guyf607bdc2010-09-10 19:20:06 -070038#define DEBUG_PROGRAM_CACHE 0
Romain Guyac670c02010-07-27 17:39:27 -070039
40// Debug
41#if DEBUG_PROGRAM_CACHE
42 #define PROGRAM_LOGD(...) LOGD(__VA_ARGS__)
43#else
44 #define PROGRAM_LOGD(...)
45#endif
46
Romain Guyf607bdc2010-09-10 19:20:06 -070047/*
48 * IMPORTANT: All 32 bits are used, switch to a long.
49 */
Romain Guyac670c02010-07-27 17:39:27 -070050#define PROGRAM_KEY_TEXTURE 0x1
51#define PROGRAM_KEY_A8_TEXTURE 0x2
52#define PROGRAM_KEY_BITMAP 0x4
53#define PROGRAM_KEY_GRADIENT 0x8
54#define PROGRAM_KEY_BITMAP_FIRST 0x10
55#define PROGRAM_KEY_COLOR_MATRIX 0x20
56#define PROGRAM_KEY_COLOR_LIGHTING 0x40
57#define PROGRAM_KEY_COLOR_BLEND 0x80
Romain Guy889f8d12010-07-29 14:37:42 -070058#define PROGRAM_KEY_BITMAP_NPOT 0x100
Romain Guyf607bdc2010-09-10 19:20:06 -070059#define PROGRAM_KEY_SWAP_SRC_DST 0x2000
Romain Guy889f8d12010-07-29 14:37:42 -070060
61#define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600
62#define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800
Romain Guyac670c02010-07-27 17:39:27 -070063
Romain Guy48daa542010-08-10 19:21:34 -070064// Encode the xfermodes on 6 bits
65#define PROGRAM_MAX_XFERMODE 0x1f
66#define PROGRAM_XFERMODE_SHADER_SHIFT 26
Romain Guyac670c02010-07-27 17:39:27 -070067#define PROGRAM_XFERMODE_COLOR_OP_SHIFT 20
Romain Guya5aed0d2010-09-09 14:42:43 -070068#define PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT 14
Romain Guyac670c02010-07-27 17:39:27 -070069
Romain Guy889f8d12010-07-29 14:37:42 -070070#define PROGRAM_BITMAP_WRAPS_SHIFT 9
71#define PROGRAM_BITMAP_WRAPT_SHIFT 11
72
Romain Guyac670c02010-07-27 17:39:27 -070073///////////////////////////////////////////////////////////////////////////////
74// Types
75///////////////////////////////////////////////////////////////////////////////
76
Romain Guyf607bdc2010-09-10 19:20:06 -070077/*
78 * IMPORTANT: All 32 bits are used, switch to a long.
79 */
Romain Guyac670c02010-07-27 17:39:27 -070080typedef uint32_t programid;
81
82///////////////////////////////////////////////////////////////////////////////
83// Cache
84///////////////////////////////////////////////////////////////////////////////
85
86/**
87 * Describe the features required for a given program. The features
88 * determine the generation of both the vertex and fragment shaders.
89 * A ProgramDescription must be used in conjunction with a ProgramCache.
90 */
91struct ProgramDescription {
92 enum ColorModifier {
93 kColorNone,
94 kColorMatrix,
95 kColorLighting,
96 kColorBlend
97 };
98
99 ProgramDescription():
100 hasTexture(false), hasAlpha8Texture(false),
Romain Guy889f8d12010-07-29 14:37:42 -0700101 hasBitmap(false), isBitmapNpot(false), hasGradient(false),
102 shadersMode(SkXfermode::kClear_Mode), isBitmapFirst(false),
103 bitmapWrapS(GL_CLAMP_TO_EDGE), bitmapWrapT(GL_CLAMP_TO_EDGE),
Romain Guya5aed0d2010-09-09 14:42:43 -0700104 colorOp(kColorNone), colorMode(SkXfermode::kClear_Mode),
Romain Guyf607bdc2010-09-10 19:20:06 -0700105 framebufferMode(SkXfermode::kClear_Mode), swapSrcDst(false) {
Romain Guyac670c02010-07-27 17:39:27 -0700106 }
107
108 // Texturing
109 bool hasTexture;
110 bool hasAlpha8Texture;
111
112 // Shaders
113 bool hasBitmap;
Romain Guy889f8d12010-07-29 14:37:42 -0700114 bool isBitmapNpot;
Romain Guyac670c02010-07-27 17:39:27 -0700115 bool hasGradient;
116 SkXfermode::Mode shadersMode;
117 bool isBitmapFirst;
Romain Guy889f8d12010-07-29 14:37:42 -0700118 GLenum bitmapWrapS;
119 GLenum bitmapWrapT;
Romain Guyac670c02010-07-27 17:39:27 -0700120
121 // Color operations
122 int colorOp;
123 SkXfermode::Mode colorMode;
124
Romain Guya5aed0d2010-09-09 14:42:43 -0700125 // Framebuffer blending (requires Extensions.hasFramebufferFetch())
126 // Ignored for all values < SkXfermode::kPlus_Mode
127 SkXfermode::Mode framebufferMode;
Romain Guyf607bdc2010-09-10 19:20:06 -0700128 bool swapSrcDst;
Romain Guya5aed0d2010-09-09 14:42:43 -0700129
Romain Guy889f8d12010-07-29 14:37:42 -0700130 inline uint32_t getEnumForWrap(GLenum wrap) const {
131 switch (wrap) {
132 case GL_CLAMP_TO_EDGE:
133 return 0;
134 case GL_REPEAT:
135 return 1;
136 case GL_MIRRORED_REPEAT:
137 return 2;
138 }
139 return 0;
140 }
141
Romain Guyac670c02010-07-27 17:39:27 -0700142 programid key() const {
143 programid key = 0;
144 if (hasTexture) key |= PROGRAM_KEY_TEXTURE;
145 if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE;
Romain Guy889f8d12010-07-29 14:37:42 -0700146 if (hasBitmap) {
147 key |= PROGRAM_KEY_BITMAP;
148 if (isBitmapNpot) {
149 key |= PROGRAM_KEY_BITMAP_NPOT;
150 key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
151 key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
152 }
153 }
Romain Guyac670c02010-07-27 17:39:27 -0700154 if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
155 if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
156 if (hasBitmap && hasGradient) {
157 key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
158 }
159 switch (colorOp) {
160 case kColorMatrix:
161 key |= PROGRAM_KEY_COLOR_MATRIX;
162 break;
163 case kColorLighting:
164 key |= PROGRAM_KEY_COLOR_LIGHTING;
165 break;
166 case kColorBlend:
167 key |= PROGRAM_KEY_COLOR_BLEND;
168 key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
169 break;
170 case kColorNone:
171 break;
172 }
Romain Guya5aed0d2010-09-09 14:42:43 -0700173 key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
Romain Guyf607bdc2010-09-10 19:20:06 -0700174 if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
Romain Guyac670c02010-07-27 17:39:27 -0700175 return key;
176 }
177}; // struct ProgramDescription
178
179/**
180 * Generates and caches program. Programs are generated based on
181 * ProgramDescriptions.
182 */
183class ProgramCache {
184public:
185 ProgramCache();
186 ~ProgramCache();
187
188 Program* get(const ProgramDescription& description);
189
190 void clear();
191
192private:
193 Program* generateProgram(const ProgramDescription& description, programid key);
194 String8 generateVertexShader(const ProgramDescription& description);
195 String8 generateFragmentShader(const ProgramDescription& description);
Romain Guy48daa542010-08-10 19:21:34 -0700196 void generateBlend(String8& shader, const char* name, SkXfermode::Mode mode);
Romain Guy889f8d12010-07-29 14:37:42 -0700197 void generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT);
Romain Guyac670c02010-07-27 17:39:27 -0700198
Romain Guydb1938e2010-08-02 18:50:22 -0700199 void printLongString(const String8& shader) const;
200
Romain Guyac670c02010-07-27 17:39:27 -0700201 KeyedVector<programid, Program*> mCache;
Romain Guyac670c02010-07-27 17:39:27 -0700202}; // class ProgramCache
203
204}; // namespace uirenderer
205}; // namespace android
206
207#endif // ANDROID_UI_PROGRAM_CACHE_H