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