LayerRenderer.cpp revision f219da5e32e85deb442468ee9a63bb28eb198557
1/* 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" 20#include "Properties.h" 21 22namespace android { 23namespace uirenderer { 24 25/////////////////////////////////////////////////////////////////////////////// 26// Rendering 27/////////////////////////////////////////////////////////////////////////////// 28 29void LayerRenderer::prepare(bool opaque) { 30 LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->fbo); 31 32#if RENDER_LAYERS_AS_REGIONS 33 mLayer->region.clear(); 34#endif 35 36 glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &mPreviousFbo); 37 glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo); 38 39 OpenGLRenderer::prepare(opaque); 40} 41 42void LayerRenderer::finish() { 43 OpenGLRenderer::finish(); 44 glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFbo); 45 46 generateMesh(); 47 48 LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mLayer->mFbo); 49} 50 51/////////////////////////////////////////////////////////////////////////////// 52// Dirty region tracking 53/////////////////////////////////////////////////////////////////////////////// 54 55bool LayerRenderer::hasLayer() { 56 return true; 57} 58 59Region* LayerRenderer::getRegion() { 60#if RENDER_LAYERS_AS_REGIONS 61 if (getSnapshot()->flags & Snapshot::kFlagFboTarget) { 62 return OpenGLRenderer::getRegion(); 63 } 64 return &mLayer->region; 65#else 66 return OpenGLRenderer::getRegion(); 67#endif 68} 69 70void LayerRenderer::generateMesh() { 71#if RENDER_LAYERS_AS_REGIONS 72 if (mLayer->region.isRect() || mLayer->region.isEmpty()) { 73 if (mLayer->mesh) { 74 delete mLayer->mesh; 75 delete mLayer->meshIndices; 76 77 mLayer->mesh = NULL; 78 mLayer->meshIndices = NULL; 79 mLayer->meshElementCount = 0; 80 } 81 return; 82 } 83 84 size_t count; 85 const android::Rect* rects = mLayer->region.getArray(&count); 86 87 GLsizei elementCount = count * 6; 88 89 if (mLayer->mesh && mLayer->meshElementCount < elementCount) { 90 delete mLayer->mesh; 91 delete mLayer->meshIndices; 92 93 mLayer->mesh = NULL; 94 mLayer->meshIndices = NULL; 95 } 96 97 if (!mLayer->mesh) { 98 mLayer->mesh = new TextureVertex[count * 4]; 99 mLayer->meshIndices = new uint16_t[elementCount]; 100 mLayer->meshElementCount = elementCount; 101 } 102 103 const float texX = 1.0f / float(mLayer->width); 104 const float texY = 1.0f / float(mLayer->height); 105 const float height = mLayer->layer.getHeight(); 106 107 TextureVertex* mesh = mLayer->mesh; 108 uint16_t* indices = mLayer->meshIndices; 109 110 for (size_t i = 0; i < count; i++) { 111 const android::Rect* r = &rects[i]; 112 113 const float u1 = r->left * texX; 114 const float v1 = (height - r->top) * texY; 115 const float u2 = r->right * texX; 116 const float v2 = (height - r->bottom) * texY; 117 118 TextureVertex::set(mesh++, r->left, r->top, u1, v1); 119 TextureVertex::set(mesh++, r->right, r->top, u2, v1); 120 TextureVertex::set(mesh++, r->left, r->bottom, u1, v2); 121 TextureVertex::set(mesh++, r->right, r->bottom, u2, v2); 122 123 uint16_t quad = i * 4; 124 int index = i * 6; 125 indices[index ] = quad; // top-left 126 indices[index + 1] = quad + 1; // top-right 127 indices[index + 2] = quad + 2; // bottom-left 128 indices[index + 3] = quad + 2; // bottom-left 129 indices[index + 4] = quad + 1; // top-right 130 indices[index + 5] = quad + 3; // bottom-right 131 } 132#endif 133} 134 135/////////////////////////////////////////////////////////////////////////////// 136// Layers management 137/////////////////////////////////////////////////////////////////////////////// 138 139Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) { 140 LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height); 141 142 Layer* layer = new Layer(width, height); 143 144 GLuint previousFbo; 145 glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); 146 147 glGenFramebuffers(1, &layer->fbo); 148 glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); 149 150 if (glGetError() != GL_NO_ERROR) { 151 glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); 152 glDeleteBuffers(1, &layer->fbo); 153 return 0; 154 } 155 156 glActiveTexture(GL_TEXTURE0); 157 glGenTextures(1, &layer->texture); 158 glBindTexture(GL_TEXTURE_2D, layer->texture); 159 160 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 161 162 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 163 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 164 165 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 167 168 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, 169 GL_RGBA, GL_UNSIGNED_BYTE, NULL); 170 171 if (glGetError() != GL_NO_ERROR) { 172 glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); 173 glDeleteBuffers(1, &layer->fbo); 174 glDeleteTextures(1, &layer->texture); 175 delete layer; 176 return 0; 177 } 178 179 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 180 layer->texture, 0); 181 182 if (glGetError() != GL_NO_ERROR) { 183 glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); 184 glDeleteBuffers(1, &layer->fbo); 185 glDeleteTextures(1, &layer->texture); 186 delete layer; 187 return 0; 188 } 189 190 glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); 191 192 layer->layer.set(0.0f, 0.0f, width, height); 193 layer->texCoords.set(0.0f, 1.0f, 1.0f, 0.0f); 194 layer->alpha = 255; 195 layer->mode = SkXfermode::kSrcOver_Mode; 196 layer->blend = !isOpaque; 197 layer->empty = false; 198 layer->colorFilter = NULL; 199 200 return layer; 201} 202 203bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) { 204 if (layer) { 205 LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->fbo, width, height); 206 207 glActiveTexture(GL_TEXTURE0); 208 glBindTexture(GL_TEXTURE_2D, layer->texture); 209 210 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, 211 GL_RGBA, GL_UNSIGNED_BYTE, NULL); 212 213 if (glGetError() != GL_NO_ERROR) { 214 glDeleteBuffers(1, &layer->fbo); 215 glDeleteTextures(1, &layer->texture); 216 217 layer->width = 0; 218 layer->height = 0; 219 layer->fbo = 0; 220 layer->texture = 0; 221 222 return false; 223 } 224 225 layer->width = width; 226 layer->height = height; 227 } 228 return true; 229} 230 231void LayerRenderer::destroyLayer(Layer* layer) { 232 if (layer) { 233 LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->fbo); 234 235 if (layer->fbo) glDeleteFramebuffers(1, &layer->fbo); 236 if (layer->texture) glDeleteTextures(1, &layer->texture); 237 238 delete layer; 239 } 240} 241 242void LayerRenderer::destroyLayerDeferred(Layer* layer) { 243 if (layer) { 244 LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", layer->fbo); 245 246 Caches::getInstance().deleteLayerDeferred(layer); 247 } 248} 249 250}; // namespace uirenderer 251}; // namespace android 252