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