blob: a16742982f6102e52969b7a89a96da8964467b09 [file] [log] [blame]
Romain Guy6c319ca2011-01-11 14:29:25 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "OpenGLRenderer"
18
19#include "LayerRenderer.h"
Romain Guy1fc883b2011-01-12 14:30:59 -080020#include "Properties.h"
Romain Guy6c319ca2011-01-11 14:29:25 -080021
22namespace android {
23namespace uirenderer {
24
25///////////////////////////////////////////////////////////////////////////////
26// Rendering
27///////////////////////////////////////////////////////////////////////////////
28
29void LayerRenderer::prepare(bool opaque) {
Romain Guyada830f2011-01-13 12:13:20 -080030 LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->fbo);
Romain Guy1fc883b2011-01-12 14:30:59 -080031
Romain Guyada830f2011-01-13 12:13:20 -080032 glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo);
Romain Guy1fc883b2011-01-12 14:30:59 -080033
Romain Guy6c319ca2011-01-11 14:29:25 -080034 OpenGLRenderer::prepare(opaque);
35}
36
37void LayerRenderer::finish() {
38 OpenGLRenderer::finish();
Romain Guy1fc883b2011-01-12 14:30:59 -080039
Romain Guyf219da52011-01-16 12:54:25 -080040 generateMesh();
41
Romain Guyada830f2011-01-13 12:13:20 -080042 LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mLayer->mFbo);
Romain Guy42f3a4b2011-01-19 13:42:26 -080043
44 // No need to unbind our FBO, this will be taken care of by the caller
45 // who will invoke OpenGLRenderer::resume()
46}
47
48GLint LayerRenderer::getTargetFbo() {
49 return mLayer->fbo;
Romain Guy6c319ca2011-01-11 14:29:25 -080050}
51
52///////////////////////////////////////////////////////////////////////////////
Romain Guyf219da52011-01-16 12:54:25 -080053// Dirty region tracking
54///////////////////////////////////////////////////////////////////////////////
55
56bool LayerRenderer::hasLayer() {
57 return true;
58}
59
60Region* LayerRenderer::getRegion() {
61#if RENDER_LAYERS_AS_REGIONS
62 if (getSnapshot()->flags & Snapshot::kFlagFboTarget) {
63 return OpenGLRenderer::getRegion();
64 }
65 return &mLayer->region;
66#else
67 return OpenGLRenderer::getRegion();
68#endif
69}
70
71void LayerRenderer::generateMesh() {
72#if RENDER_LAYERS_AS_REGIONS
73 if (mLayer->region.isRect() || mLayer->region.isEmpty()) {
74 if (mLayer->mesh) {
75 delete mLayer->mesh;
76 delete mLayer->meshIndices;
77
78 mLayer->mesh = NULL;
79 mLayer->meshIndices = NULL;
80 mLayer->meshElementCount = 0;
81 }
Romain Guyfb13abd2011-01-16 15:16:38 -080082 mLayer->region.clear();
Romain Guyf219da52011-01-16 12:54:25 -080083 return;
84 }
85
86 size_t count;
87 const android::Rect* rects = mLayer->region.getArray(&count);
88
89 GLsizei elementCount = count * 6;
90
91 if (mLayer->mesh && mLayer->meshElementCount < elementCount) {
92 delete mLayer->mesh;
93 delete mLayer->meshIndices;
94
95 mLayer->mesh = NULL;
96 mLayer->meshIndices = NULL;
97 }
98
99 if (!mLayer->mesh) {
100 mLayer->mesh = new TextureVertex[count * 4];
101 mLayer->meshIndices = new uint16_t[elementCount];
102 mLayer->meshElementCount = elementCount;
103 }
104
105 const float texX = 1.0f / float(mLayer->width);
106 const float texY = 1.0f / float(mLayer->height);
107 const float height = mLayer->layer.getHeight();
108
109 TextureVertex* mesh = mLayer->mesh;
110 uint16_t* indices = mLayer->meshIndices;
111
112 for (size_t i = 0; i < count; i++) {
113 const android::Rect* r = &rects[i];
114
115 const float u1 = r->left * texX;
116 const float v1 = (height - r->top) * texY;
117 const float u2 = r->right * texX;
118 const float v2 = (height - r->bottom) * texY;
119
120 TextureVertex::set(mesh++, r->left, r->top, u1, v1);
121 TextureVertex::set(mesh++, r->right, r->top, u2, v1);
122 TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
123 TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
124
125 uint16_t quad = i * 4;
126 int index = i * 6;
127 indices[index ] = quad; // top-left
128 indices[index + 1] = quad + 1; // top-right
129 indices[index + 2] = quad + 2; // bottom-left
130 indices[index + 3] = quad + 2; // bottom-left
131 indices[index + 4] = quad + 1; // top-right
132 indices[index + 5] = quad + 3; // bottom-right
133 }
Romain Guyfb13abd2011-01-16 15:16:38 -0800134
135 mLayer->region.clear();
Romain Guyf219da52011-01-16 12:54:25 -0800136#endif
137}
138
139///////////////////////////////////////////////////////////////////////////////
140// Layers management
Romain Guy6c319ca2011-01-11 14:29:25 -0800141///////////////////////////////////////////////////////////////////////////////
142
Romain Guyada830f2011-01-13 12:13:20 -0800143Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) {
Romain Guy1fc883b2011-01-12 14:30:59 -0800144 LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height);
145
Romain Guyada830f2011-01-13 12:13:20 -0800146 Layer* layer = new Layer(width, height);
147
Romain Guy6c319ca2011-01-11 14:29:25 -0800148 GLuint previousFbo;
149 glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
150
Romain Guyada830f2011-01-13 12:13:20 -0800151 glGenFramebuffers(1, &layer->fbo);
152 glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo);
Romain Guy6c319ca2011-01-11 14:29:25 -0800153
Romain Guy1fc883b2011-01-12 14:30:59 -0800154 if (glGetError() != GL_NO_ERROR) {
155 glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
Romain Guyada830f2011-01-13 12:13:20 -0800156 glDeleteBuffers(1, &layer->fbo);
Romain Guy1fc883b2011-01-12 14:30:59 -0800157 return 0;
158 }
159
Romain Guy6c319ca2011-01-11 14:29:25 -0800160 glActiveTexture(GL_TEXTURE0);
Romain Guyada830f2011-01-13 12:13:20 -0800161 glGenTextures(1, &layer->texture);
162 glBindTexture(GL_TEXTURE_2D, layer->texture);
Romain Guy6c319ca2011-01-11 14:29:25 -0800163
164 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
165
166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
168
169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
170 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
171
172 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
173 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
174
175 if (glGetError() != GL_NO_ERROR) {
Romain Guy1fc883b2011-01-12 14:30:59 -0800176 glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
Romain Guyada830f2011-01-13 12:13:20 -0800177 glDeleteBuffers(1, &layer->fbo);
178 glDeleteTextures(1, &layer->texture);
179 delete layer;
Romain Guy6c319ca2011-01-11 14:29:25 -0800180 return 0;
181 }
182
183 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
Romain Guyada830f2011-01-13 12:13:20 -0800184 layer->texture, 0);
Romain Guy6c319ca2011-01-11 14:29:25 -0800185
186 if (glGetError() != GL_NO_ERROR) {
Romain Guy1fc883b2011-01-12 14:30:59 -0800187 glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
Romain Guyada830f2011-01-13 12:13:20 -0800188 glDeleteBuffers(1, &layer->fbo);
189 glDeleteTextures(1, &layer->texture);
190 delete layer;
Romain Guy6c319ca2011-01-11 14:29:25 -0800191 return 0;
192 }
193
194 glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
195
Romain Guyada830f2011-01-13 12:13:20 -0800196 layer->layer.set(0.0f, 0.0f, width, height);
197 layer->texCoords.set(0.0f, 1.0f, 1.0f, 0.0f);
198 layer->alpha = 255;
199 layer->mode = SkXfermode::kSrcOver_Mode;
200 layer->blend = !isOpaque;
201 layer->empty = false;
202 layer->colorFilter = NULL;
Romain Guy6c319ca2011-01-11 14:29:25 -0800203
Romain Guyada830f2011-01-13 12:13:20 -0800204 return layer;
Romain Guy6c319ca2011-01-11 14:29:25 -0800205}
206
Romain Guyada830f2011-01-13 12:13:20 -0800207bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) {
208 if (layer) {
209 LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->fbo, width, height);
Romain Guy1fc883b2011-01-12 14:30:59 -0800210
Romain Guyada830f2011-01-13 12:13:20 -0800211 glActiveTexture(GL_TEXTURE0);
212 glBindTexture(GL_TEXTURE_2D, layer->texture);
Romain Guy6c319ca2011-01-11 14:29:25 -0800213
Romain Guyada830f2011-01-13 12:13:20 -0800214 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
215 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
Romain Guy6c319ca2011-01-11 14:29:25 -0800216
Romain Guyada830f2011-01-13 12:13:20 -0800217 if (glGetError() != GL_NO_ERROR) {
218 glDeleteBuffers(1, &layer->fbo);
219 glDeleteTextures(1, &layer->texture);
Romain Guy6c319ca2011-01-11 14:29:25 -0800220
Romain Guyada830f2011-01-13 12:13:20 -0800221 layer->width = 0;
222 layer->height = 0;
223 layer->fbo = 0;
224 layer->texture = 0;
Romain Guy6c319ca2011-01-11 14:29:25 -0800225
Romain Guyada830f2011-01-13 12:13:20 -0800226 return false;
227 }
228
229 layer->width = width;
230 layer->height = height;
Romain Guy6c319ca2011-01-11 14:29:25 -0800231 }
Romain Guyada830f2011-01-13 12:13:20 -0800232 return true;
Romain Guy6c319ca2011-01-11 14:29:25 -0800233}
234
Romain Guyada830f2011-01-13 12:13:20 -0800235void LayerRenderer::destroyLayer(Layer* layer) {
236 if (layer) {
237 LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->fbo);
Romain Guy1fc883b2011-01-12 14:30:59 -0800238
Romain Guyada830f2011-01-13 12:13:20 -0800239 if (layer->fbo) glDeleteFramebuffers(1, &layer->fbo);
240 if (layer->texture) glDeleteTextures(1, &layer->texture);
241
242 delete layer;
243 }
Romain Guy6c319ca2011-01-11 14:29:25 -0800244}
245
Romain Guyada830f2011-01-13 12:13:20 -0800246void LayerRenderer::destroyLayerDeferred(Layer* layer) {
247 if (layer) {
248 LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", layer->fbo);
Romain Guy1fc883b2011-01-12 14:30:59 -0800249
Romain Guyada830f2011-01-13 12:13:20 -0800250 Caches::getInstance().deleteLayerDeferred(layer);
251 }
Romain Guy57066eb2011-01-12 12:53:32 -0800252}
253
Romain Guy6c319ca2011-01-11 14:29:25 -0800254}; // namespace uirenderer
255}; // namespace android