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