Layer.cpp revision 0908764b2b3cf5075df4178a5f0a8547dcb7b317
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2012 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 171d3165f10b12165f02b7015ac1a817c5f60e6399Neal Nguyen#define LOG_TAG "OpenGLRenderer" 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 191d3165f10b12165f02b7015ac1a817c5f60e6399Neal Nguyen#include <utils/Log.h> 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "DisplayList.h" 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "DeferredDisplayList.h" 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "Layer.h" 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "LayerRenderer.h" 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "OpenGLRenderer.h" 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "Caches.h" 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace uirenderer { 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectLayer::Layer(const uint32_t layerWidth, const uint32_t layerHeight) { 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mesh = NULL; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project meshIndices = NULL; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project meshElementCount = 0; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cacheable = true; 36 dirty = false; 37 textureLayer = false; 38 renderTarget = GL_TEXTURE_2D; 39 texture.width = layerWidth; 40 texture.height = layerHeight; 41 colorFilter = NULL; 42 deferredUpdateScheduled = false; 43 renderer = NULL; 44 displayList = NULL; 45 fbo = 0; 46 stencil = NULL; 47 debugDrawUpdate = false; 48 deferredList = NULL; 49 Caches::getInstance().resourceCache.incrementRefcount(this); 50} 51 52Layer::~Layer() { 53 if (colorFilter) Caches::getInstance().resourceCache.decrementRefcount(colorFilter); 54 removeFbo(); 55 deleteTexture(); 56 57 delete[] mesh; 58 delete[] meshIndices; 59 delete deferredList; 60} 61 62uint32_t Layer::computeIdealWidth(uint32_t layerWidth) { 63 return uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE); 64} 65 66uint32_t Layer::computeIdealHeight(uint32_t layerHeight) { 67 return uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE); 68} 69 70bool Layer::resize(const uint32_t width, const uint32_t height) { 71 uint32_t desiredWidth = computeIdealWidth(width); 72 uint32_t desiredHeight = computeIdealWidth(height); 73 74 if (desiredWidth <= getWidth() && desiredHeight <= getHeight()) { 75 return true; 76 } 77 78 const uint32_t maxTextureSize = Caches::getInstance().maxTextureSize; 79 if (desiredWidth > maxTextureSize || desiredHeight > maxTextureSize) { 80 ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)", 81 desiredWidth, desiredHeight, maxTextureSize, maxTextureSize); 82 return false; 83 } 84 85 uint32_t oldWidth = getWidth(); 86 uint32_t oldHeight = getHeight(); 87 88 setSize(desiredWidth, desiredHeight); 89 90 if (fbo) { 91 Caches::getInstance().activeTexture(0); 92 bindTexture(); 93 allocateTexture(); 94 95 if (glGetError() != GL_NO_ERROR) { 96 setSize(oldWidth, oldHeight); 97 return false; 98 } 99 } 100 101 if (stencil) { 102 stencil->bind(); 103 stencil->resize(desiredWidth, desiredHeight); 104 105 if (glGetError() != GL_NO_ERROR) { 106 setSize(oldWidth, oldHeight); 107 return false; 108 } 109 } 110 111 return true; 112} 113 114void Layer::removeFbo(bool flush) { 115 if (stencil) { 116 GLuint previousFbo; 117 glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); 118 if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, fbo); 119 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); 120 if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); 121 122 Caches::getInstance().renderBufferCache.put(stencil); 123 stencil = NULL; 124 } 125 126 if (fbo) { 127 if (flush) LayerRenderer::flushLayer(this); 128 // If put fails the cache will delete the FBO 129 Caches::getInstance().fboCache.put(fbo); 130 fbo = 0; 131 } 132} 133 134void Layer::setPaint(SkPaint* paint) { 135 OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode); 136} 137 138void Layer::setColorFilter(SkiaColorFilter* filter) { 139 if (colorFilter) { 140 Caches::getInstance().resourceCache.decrementRefcount(colorFilter); 141 } 142 colorFilter = filter; 143 if (colorFilter) { 144 Caches::getInstance().resourceCache.incrementRefcount(colorFilter); 145 } 146} 147 148void Layer::defer() { 149 if (!deferredList) { 150 deferredList = new DeferredDisplayList; 151 } 152 DeferStateStruct deferredState(*deferredList, *renderer, 153 DisplayList::kReplayFlag_ClipChildren); 154 155 const float width = layer.getWidth(); 156 const float height = layer.getHeight(); 157 158 if (dirtyRect.isEmpty() || (dirtyRect.left <= 0 && dirtyRect.top <= 0 && 159 dirtyRect.right >= width && dirtyRect.bottom >= height)) { 160 dirtyRect.set(0, 0, width, height); 161 } 162 163 renderer->initViewport(width, height); 164 renderer->setupFrameState(dirtyRect.left, dirtyRect.top, 165 dirtyRect.right, dirtyRect.bottom, !isBlend()); 166 167 displayList->defer(deferredState, 0); 168 169 deferredUpdateScheduled = false; 170 displayList = NULL; 171} 172 173void Layer::flush() { 174 if (deferredList) { 175 renderer->setViewport(layer.getWidth(), layer.getHeight()); 176 renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom, 177 !isBlend()); 178 179 deferredList->flush(*renderer, dirtyRect); 180 181 renderer->finish(); 182 renderer = NULL; 183 184 dirtyRect.setEmpty(); 185 deferredList->clear(); 186 } 187} 188 189void Layer::render() { 190 renderer->setViewport(layer.getWidth(), layer.getHeight()); 191 renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom, 192 !isBlend()); 193 194 renderer->drawDisplayList(displayList, dirtyRect, DisplayList::kReplayFlag_ClipChildren); 195 196 renderer->finish(); 197 renderer = NULL; 198 199 dirtyRect.setEmpty(); 200 201 deferredUpdateScheduled = false; 202 displayList = NULL; 203} 204 205}; // namespace uirenderer 206}; // namespace android 207