Layer.cpp revision 0732ba5756296f1ae3da48a39e4d498aba366386
1/* 2 * Copyright (C) 2012 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 <utils/Log.h> 20 21#include "Caches.h" 22#include "DeferredDisplayList.h" 23#include "Layer.h" 24#include "LayerRenderer.h" 25#include "OpenGLRenderer.h" 26#include "RenderNode.h" 27 28namespace android { 29namespace uirenderer { 30 31Layer::Layer(const uint32_t layerWidth, const uint32_t layerHeight): 32 caches(Caches::getInstance()), texture(caches) { 33 mesh = NULL; 34 meshElementCount = 0; 35 cacheable = true; 36 dirty = false; 37 textureLayer = false; 38 renderTarget = GL_TEXTURE_2D; 39 texture.width = layerWidth; 40 texture.height = layerHeight; 41 colorFilter = NULL; 42 deferredUpdateScheduled = false; 43 renderer = NULL; 44 displayList = NULL; 45 fbo = 0; 46 stencil = NULL; 47 debugDrawUpdate = false; 48 hasDrawnSinceUpdate = false; 49 forceFilter = false; 50 deferredList = NULL; 51 convexMask = NULL; 52 caches.resourceCache.incrementRefcount(this); 53} 54 55Layer::~Layer() { 56 SkSafeUnref(colorFilter); 57 removeFbo(); 58 deleteTexture(); 59 60 delete[] mesh; 61 delete deferredList; 62 delete renderer; 63} 64 65uint32_t Layer::computeIdealWidth(uint32_t layerWidth) { 66 return uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE); 67} 68 69uint32_t Layer::computeIdealHeight(uint32_t layerHeight) { 70 return uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE); 71} 72 73void Layer::requireRenderer() { 74 if (!renderer) { 75 renderer = new LayerRenderer(this); 76 renderer->initProperties(); 77 } 78} 79 80bool Layer::resize(const uint32_t width, const uint32_t height) { 81 uint32_t desiredWidth = computeIdealWidth(width); 82 uint32_t desiredHeight = computeIdealWidth(height); 83 84 if (desiredWidth <= getWidth() && desiredHeight <= getHeight()) { 85 return true; 86 } 87 88 const uint32_t maxTextureSize = caches.maxTextureSize; 89 if (desiredWidth > maxTextureSize || desiredHeight > maxTextureSize) { 90 ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)", 91 desiredWidth, desiredHeight, maxTextureSize, maxTextureSize); 92 return false; 93 } 94 95 uint32_t oldWidth = getWidth(); 96 uint32_t oldHeight = getHeight(); 97 98 setSize(desiredWidth, desiredHeight); 99 100 if (fbo) { 101 caches.activeTexture(0); 102 bindTexture(); 103 allocateTexture(); 104 105 if (glGetError() != GL_NO_ERROR) { 106 setSize(oldWidth, oldHeight); 107 return false; 108 } 109 } 110 111 if (stencil) { 112 stencil->bind(); 113 stencil->resize(desiredWidth, desiredHeight); 114 115 if (glGetError() != GL_NO_ERROR) { 116 setSize(oldWidth, oldHeight); 117 return false; 118 } 119 } 120 121 return true; 122} 123 124void Layer::removeFbo(bool flush) { 125 if (stencil) { 126 GLuint previousFbo; 127 glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); 128 if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, fbo); 129 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); 130 if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); 131 132 caches.renderBufferCache.put(stencil); 133 stencil = NULL; 134 } 135 136 if (fbo) { 137 if (flush) LayerRenderer::flushLayer(this); 138 // If put fails the cache will delete the FBO 139 caches.fboCache.put(fbo); 140 fbo = 0; 141 } 142} 143 144void Layer::updateDeferred(RenderNode* displayList, 145 int left, int top, int right, int bottom) { 146 requireRenderer(); 147 this->displayList = displayList; 148 const Rect r(left, top, right, bottom); 149 dirtyRect.unionWith(r); 150 deferredUpdateScheduled = true; 151} 152 153void Layer::setPaint(const SkPaint* paint) { 154 OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode); 155 setColorFilter((paint) ? paint->getColorFilter() : NULL); 156} 157 158void Layer::setColorFilter(SkColorFilter* filter) { 159 SkRefCnt_SafeAssign(colorFilter, filter); 160} 161 162void Layer::bindTexture() const { 163 if (texture.id) { 164 caches.bindTexture(renderTarget, texture.id); 165 } 166} 167 168void Layer::bindStencilRenderBuffer() const { 169 if (stencil) { 170 stencil->bind(); 171 } 172} 173 174void Layer::generateTexture() { 175 if (!texture.id) { 176 glGenTextures(1, &texture.id); 177 } 178} 179 180void Layer::deleteTexture() { 181 if (texture.id) { 182 texture.deleteTexture(); 183 texture.id = 0; 184 } 185} 186 187void Layer::clearTexture() { 188 caches.unbindTexture(texture.id); 189 texture.id = 0; 190} 191 192void Layer::allocateTexture() { 193#if DEBUG_LAYERS 194 ALOGD(" Allocate layer: %dx%d", getWidth(), getHeight()); 195#endif 196 if (texture.id) { 197 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 198 glTexImage2D(renderTarget, 0, GL_RGBA, getWidth(), getHeight(), 0, 199 GL_RGBA, GL_UNSIGNED_BYTE, NULL); 200 } 201} 202 203void Layer::defer() { 204 const float width = layer.getWidth(); 205 const float height = layer.getHeight(); 206 207 if (dirtyRect.isEmpty() || (dirtyRect.left <= 0 && dirtyRect.top <= 0 && 208 dirtyRect.right >= width && dirtyRect.bottom >= height)) { 209 dirtyRect.set(0, 0, width, height); 210 } 211 212 delete deferredList; 213 deferredList = new DeferredDisplayList(dirtyRect); 214 215 DeferStateStruct deferredState(*deferredList, *renderer, 216 RenderNode::kReplayFlag_ClipChildren); 217 218 renderer->setViewport(width, height); 219 renderer->setupFrameState(dirtyRect.left, dirtyRect.top, 220 dirtyRect.right, dirtyRect.bottom, !isBlend()); 221 222 displayList->computeOrdering(); 223 displayList->deferNodeTree(deferredState); 224 225 deferredUpdateScheduled = false; 226} 227 228void Layer::cancelDefer() { 229 displayList = NULL; 230 deferredUpdateScheduled = false; 231 if (deferredList) { 232 delete deferredList; 233 deferredList = NULL; 234 } 235} 236 237void Layer::flush() { 238 // renderer is checked as layer may be destroyed/put in layer cache with flush scheduled 239 if (deferredList && renderer) { 240 renderer->setViewport(layer.getWidth(), layer.getHeight()); 241 renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom, 242 !isBlend()); 243 244 deferredList->flush(*renderer, dirtyRect); 245 246 renderer->finish(); 247 248 dirtyRect.setEmpty(); 249 displayList = NULL; 250 } 251} 252 253void Layer::render() { 254 renderer->setViewport(layer.getWidth(), layer.getHeight()); 255 renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom, 256 !isBlend()); 257 258 renderer->drawDisplayList(displayList.get(), dirtyRect, RenderNode::kReplayFlag_ClipChildren); 259 260 renderer->finish(); 261 262 dirtyRect.setEmpty(); 263 264 deferredUpdateScheduled = false; 265 displayList = NULL; 266} 267 268}; // namespace uirenderer 269}; // namespace android 270