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