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