Layer.cpp revision 57998017ff137f7d4ec33df21b6596141f8c4547
1a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk/* 2a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * Copyright (C) 2012 The Android Open Source Project 3a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * 4a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * Licensed under the Apache License, Version 2.0 (the "License"); 5a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * you may not use this file except in compliance with the License. 6a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * You may obtain a copy of the License at 7a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * 8a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * http://www.apache.org/licenses/LICENSE-2.0 9a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * 10a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * Unless required by applicable law or agreed to in writing, software 11a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * distributed under the License is distributed on an "AS IS" BASIS, 12a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * See the License for the specific language governing permissions and 14a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk * limitations under the License. 15a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk */ 16a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk 17a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk#define LOG_TAG "OpenGLRenderer" 18a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk 19a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk#include <utils/Log.h> 20a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk 21a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk#include "Caches.h" 221cd84930b25bf12e094b416a0ea4ae5fe839f537Stephen Hines#include "DeferredDisplayList.h" 23a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk#include "Layer.h" 24a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk#include "LayerRenderer.h" 25a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk#include "OpenGLRenderer.h" 26a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk#include "RenderNode.h" 27a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk#include "RenderState.h" 28a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk#include "utils/TraceUtils.h" 29a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk 30a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk#define ATRACE_LAYER_WORK(label) \ 31a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk ATRACE_FORMAT("%s HW Layer DisplayList %s %ux%u", \ 32a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk label, \ 33a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk (renderNode.get() != NULL) ? renderNode->getName() : "", \ 34a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk getWidth(), getHeight()) 35a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk 36a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouknamespace android { 37a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouknamespace uirenderer { 38a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk 39a94952436aeb251f587c1bccdf94c7f75285dfe2Alex SakhartchoukLayer::Layer(Type layerType, RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight) 40a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk : state(kState_Uncached) 41a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk , caches(Caches::getInstance()) 42a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk , renderState(renderState) 43a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk , texture(caches) 44a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk , type(layerType) { 45a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk // TODO: This is a violation of Android's typical ref counting, but it 46a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk // preserves the old inc/dec ref locations. This should be changed... 47a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk incStrong(0); 48a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk mesh = NULL; 49a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk meshElementCount = 0; 50a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk cacheable = true; 51a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk dirty = false; 52a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk renderTarget = GL_TEXTURE_2D; 53a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk texture.width = layerWidth; 54a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk texture.height = layerHeight; 55a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk colorFilter = NULL; 56a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk deferredUpdateScheduled = false; 57a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk renderer = NULL; 58a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk renderNode = NULL; 59a94952436aeb251f587c1bccdf94c7f75285dfe2Alex Sakhartchouk fbo = 0; 60 stencil = NULL; 61 debugDrawUpdate = false; 62 hasDrawnSinceUpdate = false; 63 forceFilter = false; 64 deferredList = NULL; 65 convexMask = NULL; 66 rendererLightPosDirty = true; 67 wasBuildLayered = false; 68 renderState.registerLayer(this); 69} 70 71Layer::~Layer() { 72 renderState.unregisterLayer(this); 73 SkSafeUnref(colorFilter); 74 75 if (stencil || fbo || texture.id) { 76 renderState.requireGLContext(); 77 removeFbo(); 78 deleteTexture(); 79 } 80 81 delete[] mesh; 82 delete deferredList; 83 delete renderer; 84} 85 86void Layer::onGlContextLost() { 87 removeFbo(); 88 deleteTexture(); 89} 90 91uint32_t Layer::computeIdealWidth(uint32_t layerWidth) { 92 return uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE); 93} 94 95uint32_t Layer::computeIdealHeight(uint32_t layerHeight) { 96 return uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE); 97} 98 99void Layer::requireRenderer() { 100 if (!renderer) { 101 renderer = new LayerRenderer(renderState, this); 102 renderer->initProperties(); 103 } 104} 105 106void Layer::updateLightPosFromRenderer(const OpenGLRenderer& rootRenderer) { 107 if (renderer && rendererLightPosDirty) { 108 // re-init renderer's light position, based upon last cached location in window 109 Vector3 lightPos = rootRenderer.getLightCenter(); 110 cachedInvTransformInWindow.mapPoint3d(lightPos); 111 renderer->initLight(lightPos, rootRenderer.getLightRadius(), 112 rootRenderer.getAmbientShadowAlpha(), rootRenderer.getSpotShadowAlpha()); 113 rendererLightPosDirty = false; 114 } 115} 116 117bool Layer::resize(const uint32_t width, const uint32_t height) { 118 uint32_t desiredWidth = computeIdealWidth(width); 119 uint32_t desiredHeight = computeIdealWidth(height); 120 121 if (desiredWidth <= getWidth() && desiredHeight <= getHeight()) { 122 return true; 123 } 124 125 ATRACE_NAME("resizeLayer"); 126 127 const uint32_t maxTextureSize = caches.maxTextureSize; 128 if (desiredWidth > maxTextureSize || desiredHeight > maxTextureSize) { 129 ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)", 130 desiredWidth, desiredHeight, maxTextureSize, maxTextureSize); 131 return false; 132 } 133 134 uint32_t oldWidth = getWidth(); 135 uint32_t oldHeight = getHeight(); 136 137 setSize(desiredWidth, desiredHeight); 138 139 if (fbo) { 140 caches.activeTexture(0); 141 bindTexture(); 142 allocateTexture(); 143 144 if (glGetError() != GL_NO_ERROR) { 145 setSize(oldWidth, oldHeight); 146 return false; 147 } 148 } 149 150 if (stencil) { 151 stencil->bind(); 152 stencil->resize(desiredWidth, desiredHeight); 153 154 if (glGetError() != GL_NO_ERROR) { 155 setSize(oldWidth, oldHeight); 156 return false; 157 } 158 } 159 160 return true; 161} 162 163void Layer::removeFbo(bool flush) { 164 if (stencil) { 165 GLuint previousFbo = renderState.getFramebuffer(); 166 renderState.bindFramebuffer(fbo); 167 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); 168 renderState.bindFramebuffer(previousFbo); 169 170 caches.renderBufferCache.put(stencil); 171 stencil = NULL; 172 } 173 174 if (fbo) { 175 if (flush) LayerRenderer::flushLayer(renderState, this); 176 // If put fails the cache will delete the FBO 177 caches.fboCache.put(fbo); 178 fbo = 0; 179 } 180} 181 182void Layer::updateDeferred(RenderNode* renderNode, int left, int top, int right, int bottom) { 183 requireRenderer(); 184 this->renderNode = renderNode; 185 const Rect r(left, top, right, bottom); 186 dirtyRect.unionWith(r); 187 deferredUpdateScheduled = true; 188} 189 190void Layer::setPaint(const SkPaint* paint) { 191 OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode); 192 setColorFilter((paint) ? paint->getColorFilter() : NULL); 193} 194 195void Layer::setColorFilter(SkColorFilter* filter) { 196 SkRefCnt_SafeAssign(colorFilter, filter); 197} 198 199void Layer::bindTexture() const { 200 if (texture.id) { 201 caches.bindTexture(renderTarget, texture.id); 202 } 203} 204 205void Layer::bindStencilRenderBuffer() const { 206 if (stencil) { 207 stencil->bind(); 208 } 209} 210 211void Layer::generateTexture() { 212 if (!texture.id) { 213 glGenTextures(1, &texture.id); 214 } 215} 216 217void Layer::deleteTexture() { 218 if (texture.id) { 219 texture.deleteTexture(); 220 texture.id = 0; 221 } 222} 223 224void Layer::clearTexture() { 225 caches.unbindTexture(texture.id); 226 texture.id = 0; 227} 228 229void Layer::allocateTexture() { 230#if DEBUG_LAYERS 231 ALOGD(" Allocate layer: %dx%d", getWidth(), getHeight()); 232#endif 233 if (texture.id) { 234 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 235 glTexImage2D(renderTarget, 0, GL_RGBA, getWidth(), getHeight(), 0, 236 GL_RGBA, GL_UNSIGNED_BYTE, NULL); 237 } 238} 239 240void Layer::defer(const OpenGLRenderer& rootRenderer) { 241 ATRACE_LAYER_WORK("Optimize"); 242 243 updateLightPosFromRenderer(rootRenderer); 244 const float width = layer.getWidth(); 245 const float height = layer.getHeight(); 246 247 if (dirtyRect.isEmpty() || (dirtyRect.left <= 0 && dirtyRect.top <= 0 && 248 dirtyRect.right >= width && dirtyRect.bottom >= height)) { 249 dirtyRect.set(0, 0, width, height); 250 } 251 252 delete deferredList; 253 deferredList = new DeferredDisplayList(dirtyRect); 254 255 DeferStateStruct deferredState(*deferredList, *renderer, 256 RenderNode::kReplayFlag_ClipChildren); 257 258 renderer->setViewport(width, height); 259 renderer->setupFrameState(dirtyRect.left, dirtyRect.top, 260 dirtyRect.right, dirtyRect.bottom, !isBlend()); 261 262 renderNode->computeOrdering(); 263 renderNode->defer(deferredState, 0); 264 265 deferredUpdateScheduled = false; 266} 267 268void Layer::cancelDefer() { 269 renderNode = NULL; 270 deferredUpdateScheduled = false; 271 if (deferredList) { 272 delete deferredList; 273 deferredList = NULL; 274 } 275} 276 277void Layer::flush() { 278 // renderer is checked as layer may be destroyed/put in layer cache with flush scheduled 279 if (deferredList && renderer) { 280 ATRACE_LAYER_WORK("Issue"); 281 renderer->startMark((renderNode.get() != NULL) ? renderNode->getName() : "Layer"); 282 283 renderer->setViewport(layer.getWidth(), layer.getHeight()); 284 renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom, 285 !isBlend()); 286 287 deferredList->flush(*renderer, dirtyRect); 288 289 renderer->finish(); 290 291 dirtyRect.setEmpty(); 292 renderNode = NULL; 293 294 renderer->endMark(); 295 } 296} 297 298void Layer::render(const OpenGLRenderer& rootRenderer) { 299 ATRACE_LAYER_WORK("Direct-Issue"); 300 301 updateLightPosFromRenderer(rootRenderer); 302 renderer->setViewport(layer.getWidth(), layer.getHeight()); 303 renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom, 304 !isBlend()); 305 306 renderer->drawRenderNode(renderNode.get(), dirtyRect, RenderNode::kReplayFlag_ClipChildren); 307 308 renderer->finish(); 309 310 dirtyRect.setEmpty(); 311 312 deferredUpdateScheduled = false; 313 renderNode = NULL; 314} 315 316void Layer::postDecStrong() { 317 renderState.postDecStrong(this); 318} 319 320}; // namespace uirenderer 321}; // namespace android 322