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