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