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