Layer.cpp revision 96885eb480c5e0526fe2f77d30f6e551f3f3ceab
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 "DisplayList.h" 22#include "DeferredDisplayList.h" 23#include "Layer.h" 24#include "LayerRenderer.h" 25#include "OpenGLRenderer.h" 26#include "Caches.h" 27 28namespace android { 29namespace uirenderer { 30 31Layer::Layer(const uint32_t layerWidth, const uint32_t layerHeight) { 32 mesh = NULL; 33 meshIndices = NULL; 34 meshElementCount = 0; 35 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 uint32_t oldWidth = getWidth(); 79 uint32_t oldHeight = getHeight(); 80 81 setSize(desiredWidth, desiredHeight); 82 83 if (fbo) { 84 Caches::getInstance().activeTexture(0); 85 bindTexture(); 86 allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); 87 88 if (glGetError() != GL_NO_ERROR) { 89 setSize(oldWidth, oldHeight); 90 return false; 91 } 92 } 93 94 if (stencil) { 95 stencil->bind(); 96 stencil->resize(desiredWidth, desiredHeight); 97 98 if (glGetError() != GL_NO_ERROR) { 99 setSize(oldWidth, oldHeight); 100 return false; 101 } 102 } 103 104 return true; 105} 106 107void Layer::removeFbo(bool flush) { 108 if (stencil) { 109 GLuint previousFbo; 110 glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); 111 if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, fbo); 112 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); 113 if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); 114 115 Caches::getInstance().renderBufferCache.put(stencil); 116 stencil = NULL; 117 } 118 119 if (fbo) { 120 if (flush) LayerRenderer::flushLayer(this); 121 // If put fails the cache will delete the FBO 122 Caches::getInstance().fboCache.put(fbo); 123 fbo = 0; 124 } 125} 126 127void Layer::setPaint(SkPaint* paint) { 128 OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode); 129} 130 131void Layer::setColorFilter(SkiaColorFilter* filter) { 132 if (colorFilter) { 133 Caches::getInstance().resourceCache.decrementRefcount(colorFilter); 134 } 135 colorFilter = filter; 136 if (colorFilter) { 137 Caches::getInstance().resourceCache.incrementRefcount(colorFilter); 138 } 139} 140 141void Layer::defer() { 142 if (!deferredList) { 143 deferredList = new DeferredDisplayList; 144 } 145 DeferStateStruct deferredState(*deferredList, *renderer, 146 DisplayList::kReplayFlag_ClipChildren); 147 148 const float width = layer.getWidth(); 149 const float height = layer.getHeight(); 150 151 if (dirtyRect.isEmpty() || (dirtyRect.left <= 0 && dirtyRect.top <= 0 && 152 dirtyRect.right >= width && dirtyRect.bottom >= height)) { 153 dirtyRect.set(0, 0, width, height); 154 } 155 156 renderer->initViewport(width, height); 157 renderer->setupFrameState(dirtyRect.left, dirtyRect.top, 158 dirtyRect.right, dirtyRect.bottom, !isBlend()); 159 160 displayList->defer(deferredState, 0); 161} 162 163void Layer::flush() { 164 if (deferredList && !deferredList->isEmpty()) { 165 renderer->setViewport(layer.getWidth(), layer.getHeight()); 166 renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom, 167 !isBlend()); 168 169 deferredList->flush(*renderer, dirtyRect); 170 171 renderer->finish(); 172 renderer = NULL; 173 174 dirtyRect.setEmpty(); 175 deferredList->clear(); 176 } 177} 178 179}; // namespace uirenderer 180}; // namespace android 181