1e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy/*
2e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Copyright (C) 2010 The Android Open Source Project
3e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
4e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * you may not use this file except in compliance with the License.
6e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * You may obtain a copy of the License at
7e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
8e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
10e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Unless required by applicable law or agreed to in writing, software
11e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * See the License for the specific language governing permissions and
14e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * limitations under the License.
15e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy */
16e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include <GpuMemoryTracker.h>
1885bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include "OpenGLRenderer.h"
1965fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik
20c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#include "DeferredDisplayList.h"
212dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include "GammaFontRenderer.h"
22031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik#include "Glop.h"
23031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik#include "GlopBuilder.h"
242dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include "Patch.h"
2565cd612face362d054a85d0f7e5881c59cd523beChris Craik#include "PathTessellator.h"
2687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy#include "Properties.h"
272dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include "RenderNode.h"
28031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik#include "renderstate/MeshState.h"
2965fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik#include "renderstate/RenderState.h"
3055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include "ShadowTessellator.h"
31d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III#include "SkiaShader.h"
32a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy#include "Vector.h"
3355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include "VertexBuffer.h"
34dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include "hwui/Canvas.h"
352dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include "utils/GLUtils.h"
368dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson#include "utils/PaintUtils.h"
3706e7fe5a70409d2050b2b3e1286500f5223099daChris Craik#include "utils/TraceUtils.h"
38e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
3965fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik#include <stdlib.h>
4065fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik#include <stdint.h>
4165fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik#include <sys/types.h>
4265fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik
4365fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik#include <SkColor.h>
44386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik#include <SkPaintDefaults.h>
45fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik#include <SkPathOps.h>
4665fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik#include <SkShader.h>
4765fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik#include <SkTypeface.h>
4865fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik
4965fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik#include <utils/Log.h>
5065fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik#include <utils/StopWatch.h>
5165fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik
5265fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik#include <private/hwui/DrawGlInfo.h>
5365fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik
5465fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik#include <ui/Rect.h>
5565fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik
5662d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik#if DEBUG_DETAILED_EVENTS
5762d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    #define EVENT_LOGD(...) eventMarkDEBUG(__VA_ARGS__)
5862d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik#else
5962d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    #define EVENT_LOGD(...)
6062d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik#endif
6162d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik
62e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guynamespace android {
639d5316e3f56d138504565ff311145ac01621dff4Romain Guynamespace uirenderer {
649d5316e3f56d138504565ff311145ac01621dff4Romain Guy
659d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
66f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Constructors/destructor
67f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
68f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
693b20251a355c88193c439f928a84ae69483fb488John ReckOpenGLRenderer::OpenGLRenderer(RenderState& renderState)
70984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson        : mState(*this)
71058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mCaches(Caches::getInstance())
72058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mRenderState(renderState)
7365fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik        , mFrameStarted(false)
74058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mScissorOptimizationDisabled(false)
75107843de4507b3511006cb9c77b8d0364374385aTom Hudson        , mDirty(false)
761aa5d2d7068147ff781cfe911a93f01593a68c79John Reck        , mLightCenter((Vector3){FLT_MIN, FLT_MIN, FLT_MIN})
77058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mLightRadius(FLT_MIN)
78058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mAmbientShadowAlpha(0)
79058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mSpotShadowAlpha(0) {
80e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
81e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
8285bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain GuyOpenGLRenderer::~OpenGLRenderer() {
8329d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy    // The context has already been destroyed at this point, do not call
8429d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy    // GL APIs. All GL state should be kept in Caches.h
85e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
86e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
8787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::initProperties() {
8887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    char property[PROPERTY_VALUE_MAX];
8987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    if (property_get(PROPERTY_DISABLE_SCISSOR_OPTIMIZATION, property, "false")) {
9087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mScissorOptimizationDisabled = !strcasecmp(property, "true");
9187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        INIT_LOGD("  Scissor optimization %s",
9287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy                mScissorOptimizationDisabled ? "disabled" : "enabled");
9387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    } else {
9487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        INIT_LOGD("  Scissor optimization enabled");
9587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    }
9613631f3da855f200a151e7837ed9f6b079622b58Romain Guy}
9713631f3da855f200a151e7837ed9f6b079622b58Romain Guy
9850210d912925aef14e4ce69be82e4949122a3cd9Alan Viverettevoid OpenGLRenderer::initLight(float lightRadius, uint8_t ambientShadowAlpha,
9950210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette        uint8_t spotShadowAlpha) {
100058fc640017c90120c599d378a4cbc55668b05b7Chris Craik    mLightRadius = lightRadius;
101058fc640017c90120c599d378a4cbc55668b05b7Chris Craik    mAmbientShadowAlpha = ambientShadowAlpha;
102058fc640017c90120c599d378a4cbc55668b05b7Chris Craik    mSpotShadowAlpha = spotShadowAlpha;
103058fc640017c90120c599d378a4cbc55668b05b7Chris Craik}
104058fc640017c90120c599d378a4cbc55668b05b7Chris Craik
10550210d912925aef14e4ce69be82e4949122a3cd9Alan Viverettevoid OpenGLRenderer::setLightCenter(const Vector3& lightCenter) {
10650210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette    mLightCenter = lightCenter;
10750210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette}
10850210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette
10913631f3da855f200a151e7837ed9f6b079622b58Romain Guy///////////////////////////////////////////////////////////////////////////////
110f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Setup
111f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
112f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
113797b95b26bbb7557678af78b9a2a61830158920fChris Craikvoid OpenGLRenderer::onViewportInitialized() {
11435643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    glDisable(GL_DITHER);
11535643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
11635643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy}
11735643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy
11864e445bf74bee2098781d608cedfd723d8cc88d3Chris Craikvoid OpenGLRenderer::setupFrameState(int viewportWidth, int viewportHeight,
11964e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik        float left, float top, float right, float bottom, bool opaque) {
120fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy    mCaches.clearGarbage();
12164e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik    mState.initializeSaveStack(viewportWidth, viewportHeight,
12264e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik            left, top, right, bottom, mLightCenter);
12396885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    mOpaque = opaque;
1245f803623559aab395a29d575c37c4e39c23a4b4eChris Craik    mTilingClip.set(left, top, right, bottom);
12596885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy}
126ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy
127107843de4507b3511006cb9c77b8d0364374385aTom Hudsonvoid OpenGLRenderer::startFrame() {
128107843de4507b3511006cb9c77b8d0364374385aTom Hudson    if (mFrameStarted) return;
12996885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    mFrameStarted = true;
13011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
131984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    mState.setDirtyClip(true);
13296885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
13396885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    discardFramebuffer(mTilingClip.left, mTilingClip.top, mTilingClip.right, mTilingClip.bottom);
13445e4c3df6c00ac98ff6144de9af574877d4fff19Romain Guy
135984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    mRenderState.setViewport(mState.getWidth(), mState.getHeight());
1367d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy
1377c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    debugOverdraw(true, true);
1387c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy
139107843de4507b3511006cb9c77b8d0364374385aTom Hudson    clear(mTilingClip.left, mTilingClip.top,
14096885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy            mTilingClip.right, mTilingClip.bottom, mOpaque);
14196885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy}
14296885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
14364e445bf74bee2098781d608cedfd723d8cc88d3Chris Craikvoid OpenGLRenderer::prepareDirty(int viewportWidth, int viewportHeight,
14464e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik        float left, float top, float right, float bottom, bool opaque) {
14578dd96d5af20f489f0e8b288617d57774ec284f7Romain Guy
14664e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik    setupFrameState(viewportWidth, viewportHeight, left, top, right, bottom, opaque);
14796885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
14896885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    // Layer renderers will start the frame immediately
14996885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    // The framebuffer renderer will first defer the display list
15096885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    // for each layer and wait until the first drawing command
15196885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    // to start the frame
152d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    if (currentSnapshot()->fbo == 0) {
15344eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik        mRenderState.blend().syncEnabled();
15496885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        updateLayers();
15596885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    } else {
156107843de4507b3511006cb9c77b8d0364374385aTom Hudson        startFrame();
15796885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    }
1587c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy}
1597c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy
160dcfc836b457a87881da409e1acf251515f121446Romain Guyvoid OpenGLRenderer::discardFramebuffer(float left, float top, float right, float bottom) {
161dcfc836b457a87881da409e1acf251515f121446Romain Guy    // If we know that we are going to redraw the entire framebuffer,
162dcfc836b457a87881da409e1acf251515f121446Romain Guy    // perform a discard to let the driver know we don't need to preserve
163dcfc836b457a87881da409e1acf251515f121446Romain Guy    // the back buffer for this frame.
164117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    if (mCaches.extensions().hasDiscardFramebuffer() &&
165984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            left <= 0.0f && top <= 0.0f && right >= mState.getWidth() && bottom >= mState.getHeight()) {
1666b109c74982033d4a220cd10a0eab8b024b351c9Chris Craik        const bool isFbo = getTargetFbo() == 0;
167f158198ccc3a1f53bfebaa6b8f4426e80e1867eaRomain Guy        const GLenum attachments[] = {
168f158198ccc3a1f53bfebaa6b8f4426e80e1867eaRomain Guy                isFbo ? (const GLenum) GL_COLOR_EXT : (const GLenum) GL_COLOR_ATTACHMENT0,
169f158198ccc3a1f53bfebaa6b8f4426e80e1867eaRomain Guy                isFbo ? (const GLenum) GL_STENCIL_EXT : (const GLenum) GL_STENCIL_ATTACHMENT };
170dcfc836b457a87881da409e1acf251515f121446Romain Guy        glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments);
171dcfc836b457a87881da409e1acf251515f121446Romain Guy    }
172dcfc836b457a87881da409e1acf251515f121446Romain Guy}
173dcfc836b457a87881da409e1acf251515f121446Romain Guy
174107843de4507b3511006cb9c77b8d0364374385aTom Hudsonvoid OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
17523d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    if (!opaque) {
17665fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik        mRenderState.scissor().setEnabled(true);
17765fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik        mRenderState.scissor().set(left, getViewportHeight() - bottom, right - left, bottom - top);
1786b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy        glClear(GL_COLOR_BUFFER_BIT);
179107843de4507b3511006cb9c77b8d0364374385aTom Hudson        mDirty = true;
180107843de4507b3511006cb9c77b8d0364374385aTom Hudson        return;
181ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy    }
18244b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase
18365fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik    mRenderState.scissor().reset();
184ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy}
185ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy
186107843de4507b3511006cb9c77b8d0364374385aTom Hudsonbool OpenGLRenderer::finish() {
1877c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    renderOverdraw();
1884ac36f80beb958c77a92a3e1a235f6ed9daaa510Chris Craik    mTempPaths.clear();
1894ac36f80beb958c77a92a3e1a235f6ed9daaa510Chris Craik
190ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy    // When finish() is invoked on FBO 0 we've reached the end
191ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy    // of the current frame
1926b109c74982033d4a220cd10a0eab8b024b351c9Chris Craik    if (getTargetFbo() == 0) {
193ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy        mCaches.pathCache.trim();
19405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        mCaches.tessellationCache.trim();
195ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy    }
196ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy
19711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    if (!suppressErrorChecks()) {
198975591a7af883d866d86ab819e164c6004694744John Reck        GL_CHECKPOINT(MODERATE);
19911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
200c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#if DEBUG_MEMORY_USAGE
201e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy        mCaches.dumpMemoryUsage();
20238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck        GPUMemoryTracker::dump();
20311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy#else
2042507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik        if (Properties::debugLevel & kDebugMemory) {
20511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            mCaches.dumpMemoryUsage();
20611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        }
207c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#endif
20811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
20996885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
21096885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    mFrameStarted = false;
211107843de4507b3511006cb9c77b8d0364374385aTom Hudson
212107843de4507b3511006cb9c77b8d0364374385aTom Hudson    return reportAndClearDirty();
213b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy}
214b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy
21535643ddc689913f5b5f80ceed864470d987bd6cdRomain Guyvoid OpenGLRenderer::resumeAfterLayer() {
2163b20251a355c88193c439f928a84ae69483fb488John Reck    mRenderState.setViewport(getViewportWidth(), getViewportHeight());
2173b20251a355c88193c439f928a84ae69483fb488John Reck    mRenderState.bindFramebuffer(currentSnapshot()->fbo);
2187c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    debugOverdraw(true, false);
21935643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy
22065fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik    mRenderState.scissor().reset();
22135643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    dirtyClip();
22235643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy}
22335643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy
22464bb413a664001c95c8439cf097dc3033f4ed733Andreas Gampevoid OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
225984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    if (mState.currentlyIgnored()) return;
226408eb12631376cbdc96803e918decf6ea804d346Chris Craik
2276fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Rect clip(mState.currentRenderTargetClip());
22880911b851764b073310fd0bffdf4a7db0d8fdd0bRomain Guy    clip.snapToPixelBoundaries();
22980911b851764b073310fd0bffdf4a7db0d8fdd0bRomain Guy
230d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy    // Since we don't know what the functor will draw, let's dirty
231d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    // the entire clip region
232d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy    if (hasLayer()) {
233d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy        dirtyLayerUnchecked(clip, getRegion());
234d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy    }
235d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy
23608aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    DrawGlInfo info;
23708aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.clipLeft = clip.left;
23808aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.clipTop = clip.top;
23908aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.clipRight = clip.right;
24008aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.clipBottom = clip.bottom;
24108aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.isLayer = hasLayer();
242a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik    info.width = getViewportWidth();
243a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik    info.height = getViewportHeight();
244d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    currentTransform()->copyTo(&info.transform[0]);
24580911b851764b073310fd0bffdf4a7db0d8fdd0bRomain Guy
246984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool prevDirtyClip = mState.getDirtyClip();
24754f574acf4dd5483170b8f79e2f7c70b58763ce7Chris Craik    // setup GL state for functor
248984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    if (mState.getDirtyClip()) {
24954f574acf4dd5483170b8f79e2f7c70b58763ce7Chris Craik        setStencilFromClip(); // can issue draws, so must precede enableScissor()/interrupt()
25054f574acf4dd5483170b8f79e2f7c70b58763ce7Chris Craik    }
25165fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik    if (mRenderState.scissor().setEnabled(true) || prevDirtyClip) {
25225d2f7bc1ff9b475eff75bfff647466e91dbacb2John Reck        setScissorFromClip();
25325d2f7bc1ff9b475eff75bfff647466e91dbacb2John Reck    }
25454f574acf4dd5483170b8f79e2f7c70b58763ce7Chris Craik
2553b20251a355c88193c439f928a84ae69483fb488John Reck    mRenderState.invokeFunctor(functor, DrawGlInfo::kModeDraw, &info);
2563b20251a355c88193c439f928a84ae69483fb488John Reck    // Scissor may have been modified, reset dirty clip
2573b20251a355c88193c439f928a84ae69483fb488John Reck    dirtyClip();
258cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy
259107843de4507b3511006cb9c77b8d0364374385aTom Hudson    mDirty = true;
260daf98e941e140e8739458126640183b9f296a2abChet Haase}
261daf98e941e140e8739458126640183b9f296a2abChet Haase
262f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
26387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy// Debug
26487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy///////////////////////////////////////////////////////////////////////////////
26587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
26662d307c2402777d5e53b4590af5f32f8c55afd81Chris Craikvoid OpenGLRenderer::eventMarkDEBUG(const char* fmt, ...) const {
26762d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik#if DEBUG_DETAILED_EVENTS
26862d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    const int BUFFER_SIZE = 256;
26962d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    va_list ap;
27062d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    char buf[BUFFER_SIZE];
27162d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik
27262d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    va_start(ap, fmt);
27362d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    vsnprintf(buf, BUFFER_SIZE, fmt, ap);
27462d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    va_end(ap);
27562d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik
27662d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    eventMark(buf);
27762d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik#endif
27862d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik}
27962d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik
28062d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik
2810f6675332c04c74909425d1d328f02b32c0ff40eRomain Guyvoid OpenGLRenderer::eventMark(const char* name) const {
2820f6675332c04c74909425d1d328f02b32c0ff40eRomain Guy    mCaches.eventMark(0, name);
2830f6675332c04c74909425d1d328f02b32c0ff40eRomain Guy}
2840f6675332c04c74909425d1d328f02b32c0ff40eRomain Guy
28587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::startMark(const char* name) const {
28687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    mCaches.startMark(0, name);
28787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy}
28887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
28987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::endMark() const {
29087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    mCaches.endMark();
29187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy}
29287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
29387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::debugOverdraw(bool enable, bool clear) {
2943b20251a355c88193c439f928a84ae69483fb488John Reck    mRenderState.debugOverdraw(enable, clear);
29587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy}
29687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
29787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::renderOverdraw() {
2982507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik    if (Properties::debugOverdraw && getTargetFbo() == 0) {
2995f803623559aab395a29d575c37c4e39c23a4b4eChris Craik        const Rect* clip = &mTilingClip;
30087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
30165fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik        mRenderState.scissor().setEnabled(true);
30265fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik        mRenderState.scissor().set(clip->left,
30365fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik                mState.firstSnapshot()->getViewportHeight() - clip->bottom,
30465fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik                clip->right - clip->left,
30565fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik                clip->bottom - clip->top);
30687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
307627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        // 1x overdraw
30896a5c4c7bab6718524de7253da8309143ab48befChris Craik        mRenderState.stencil().enableDebugTest(2);
309627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        drawColor(mCaches.getOverdrawColor(1), SkXfermode::kSrcOver_Mode);
310627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy
311627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        // 2x overdraw
31296a5c4c7bab6718524de7253da8309143ab48befChris Craik        mRenderState.stencil().enableDebugTest(3);
313627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        drawColor(mCaches.getOverdrawColor(2), SkXfermode::kSrcOver_Mode);
314627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy
315627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        // 3x overdraw
31696a5c4c7bab6718524de7253da8309143ab48befChris Craik        mRenderState.stencil().enableDebugTest(4);
317627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        drawColor(mCaches.getOverdrawColor(3), SkXfermode::kSrcOver_Mode);
318627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy
319627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        // 4x overdraw and higher
32096a5c4c7bab6718524de7253da8309143ab48befChris Craik        mRenderState.stencil().enableDebugTest(4, true);
321627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        drawColor(mCaches.getOverdrawColor(4), SkXfermode::kSrcOver_Mode);
322627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy
32396a5c4c7bab6718524de7253da8309143ab48befChris Craik        mRenderState.stencil().disable();
32487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    }
32587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy}
32687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
32787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy///////////////////////////////////////////////////////////////////////////////
32811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy// Layers
32911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy///////////////////////////////////////////////////////////////////////////////
33011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
33111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guybool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
332a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik    if (layer->deferredUpdateScheduled && layer->renderer
333a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik            && layer->renderNode.get() && layer->renderNode->isRenderable()) {
334405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
3357c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy        if (inFrame) {
3367c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy            debugOverdraw(false, false);
3377c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy        }
33811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
3392507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik        if (CC_UNLIKELY(inFrame || Properties::drawDeferDisabled)) {
34069e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik            layer->render(*this);
34196885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        } else {
34269e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik            layer->defer(*this);
34396885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        }
34411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
34511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        if (inFrame) {
34611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            resumeAfterLayer();
34711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        }
34811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
3492507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik        layer->debugDrawUpdate = Properties::debugLayersUpdates;
35034416eaa1c07b3d7a139e780cea8f8d73219650eChris Craik        layer->hasDrawnSinceUpdate = false;
35111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
35211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        return true;
35311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
35411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
35511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    return false;
35611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy}
35711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
35811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guyvoid OpenGLRenderer::updateLayers() {
35996885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    // If draw deferring is enabled this method will simply defer
36096885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    // the display list of each individual layer. The layers remain
36196885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    // in the layer updates list which will be cleared by flushLayers().
36211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    int count = mLayerUpdates.size();
36311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    if (count > 0) {
3642507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik        if (CC_UNLIKELY(Properties::drawDeferDisabled)) {
36596885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy            startMark("Layer Updates");
36696885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        } else {
36796885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy            startMark("Defer Layer Updates");
36896885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        }
36911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
3701206b9bba91f7ed899c5c87427cce725fe5aadfcChris Craik        // Note: it is very important to update the layers in order
3711206b9bba91f7ed899c5c87427cce725fe5aadfcChris Craik        for (int i = 0; i < count; i++) {
372272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck            Layer* layer = mLayerUpdates[i].get();
37311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            updateLayer(layer, false);
37411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        }
37511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
3762507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik        if (CC_UNLIKELY(Properties::drawDeferDisabled)) {
37796885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy            mLayerUpdates.clear();
3786b109c74982033d4a220cd10a0eab8b024b351c9Chris Craik            mRenderState.bindFramebuffer(getTargetFbo());
37996885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        }
38096885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        endMark();
38196885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    }
38296885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy}
38396885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
38496885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guyvoid OpenGLRenderer::flushLayers() {
38596885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    int count = mLayerUpdates.size();
38696885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    if (count > 0) {
38796885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        startMark("Apply Layer Updates");
38896885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
3891206b9bba91f7ed899c5c87427cce725fe5aadfcChris Craik        // Note: it is very important to update the layers in order
3901206b9bba91f7ed899c5c87427cce725fe5aadfcChris Craik        for (int i = 0; i < count; i++) {
391272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck            mLayerUpdates[i]->flush();
39296885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        }
39396885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
39496885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        mLayerUpdates.clear();
3956b109c74982033d4a220cd10a0eab8b024b351c9Chris Craik        mRenderState.bindFramebuffer(getTargetFbo());
39696885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
39711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        endMark();
39811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
39911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy}
40011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
40111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guyvoid OpenGLRenderer::pushLayerUpdate(Layer* layer) {
40211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    if (layer) {
40302b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy        // Make sure we don't introduce duplicates.
40402b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy        // SortedVector would do this automatically but we need to respect
40502b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy        // the insertion order. The linear search is not an issue since
40602b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy        // this list is usually very short (typically one item, at most a few)
40702b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy        for (int i = mLayerUpdates.size() - 1; i >= 0; i--) {
408272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck            if (mLayerUpdates[i] == layer) {
40902b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy                return;
41002b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy            }
41102b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy        }
41211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        mLayerUpdates.push_back(layer);
41311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
41411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy}
41511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
416e93482f5eac3df581d57e64c2a771a96aa868585Romain Guyvoid OpenGLRenderer::cancelLayerUpdate(Layer* layer) {
417e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy    if (layer) {
418e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy        for (int i = mLayerUpdates.size() - 1; i >= 0; i--) {
419272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck            if (mLayerUpdates[i] == layer) {
420272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck                mLayerUpdates.erase(mLayerUpdates.begin() + i);
421e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy                break;
422e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy            }
423e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy        }
424e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy    }
425e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy}
426e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy
427405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guyvoid OpenGLRenderer::flushLayerUpdates() {
42870850ea258cbf91477efa57a1f1a23cc0044cc93Chris Craik    ATRACE_NAME("Update HW Layers");
42944eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik    mRenderState.blend().syncEnabled();
430405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    updateLayers();
431405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    flushLayers();
432405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    // Wait for all the layer updates to be executed
4335515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck    glFinish();
434405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy}
435405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
436443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reckvoid OpenGLRenderer::markLayersAsBuildLayers() {
437443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck    for (size_t i = 0; i < mLayerUpdates.size(); i++) {
438443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck        mLayerUpdates[i]->wasBuildLayered = true;
439443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck    }
440443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck}
441443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck
44211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy///////////////////////////////////////////////////////////////////////////////
443f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// State management
444f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
445f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
44614e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid OpenGLRenderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {
447a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik    bool restoreViewport = removed.flags & Snapshot::kFlagIsFboLayer;
44814e513058ed4168c94e015638d16f5f87fd8063aChris Craik    bool restoreClip = removed.flags & Snapshot::kFlagClipSet;
44914e513058ed4168c94e015638d16f5f87fd8063aChris Craik    bool restoreLayer = removed.flags & Snapshot::kFlagIsLayer;
450bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
451a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik    if (restoreViewport) {
4523b20251a355c88193c439f928a84ae69483fb488John Reck        mRenderState.setViewport(getViewportWidth(), getViewportHeight());
453eb99356a0548684a501766e6a524529ab93304c8Romain Guy    }
454eb99356a0548684a501766e6a524529ab93304c8Romain Guy
4552542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy    if (restoreClip) {
456746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy        dirtyClip();
4578fb954263dd2f918ad339045cc6d82e346515599Romain Guy    }
4582542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy
4595ec9924d24495822b589f1a17996655d66273b30Romain Guy    if (restoreLayer) {
4607273daace9303f4662444111c40bb83d3ead4a92Chris Craik        endMark(); // Savelayer
461a8bea8edde2f20cae48e5cc8de782679306b3cc3Chris Craik        ATRACE_END(); // SaveLayer
4627273daace9303f4662444111c40bb83d3ead4a92Chris Craik        startMark("ComposeLayer");
46314e513058ed4168c94e015638d16f5f87fd8063aChris Craik        composeLayer(removed, restored);
4647273daace9303f4662444111c40bb83d3ead4a92Chris Craik        endMark();
4655ec9924d24495822b589f1a17996655d66273b30Romain Guy    }
466d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy}
4675cbbce535744b89df5ecea95de21ee3733298260Romain Guy
468f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
469bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy// Layers
470bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy///////////////////////////////////////////////////////////////////////////////
471bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
472bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyint OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
4733f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik        const SkPaint* paint, int flags, const SkPath* convexMask) {
4744ace7305608442ab35ea9aa65a4220df152c187fChris Craik    // force matrix/clip isolation for layer
475eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    flags |= SaveFlags::MatrixClip;
4764ace7305608442ab35ea9aa65a4220df152c187fChris Craik
477984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    const int count = mState.saveSnapshot(flags);
478d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
479984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    if (!mState.currentlyIgnored()) {
4803f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik        createLayer(left, top, right, bottom, paint, flags, convexMask);
481dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy    }
482d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
483d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    return count;
484bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy}
485bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
486d90144db52c7297879b950cbbc85137ed123ab5bChris Craikvoid OpenGLRenderer::calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool fboLayer) {
487d90144db52c7297879b950cbbc85137ed123ab5bChris Craik    const Rect untransformedBounds(bounds);
488d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
489d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    currentTransform()->mapRect(bounds);
490d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
491d90144db52c7297879b950cbbc85137ed123ab5bChris Craik    // Layers only make sense if they are in the framebuffer's bounds
4926fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    bounds.doIntersect(mState.currentRenderTargetClip());
493ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik    if (!bounds.isEmpty()) {
494d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        // We cannot work with sub-pixels in this case
495d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        bounds.snapToPixelBoundaries();
496d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
497d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        // When the layer is not an FBO, we may use glCopyTexImage so we
498d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        // need to make sure the layer does not extend outside the bounds
499d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        // of the framebuffer
500924197513aa2df4c1fb2977c1727f5d2c21f2689Chris Craik        const Snapshot& previous = *(currentSnapshot()->previous);
501924197513aa2df4c1fb2977c1727f5d2c21f2689Chris Craik        Rect previousViewport(0, 0, previous.getViewportWidth(), previous.getViewportHeight());
502ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik
503ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik        bounds.doIntersect(previousViewport);
504ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik        if (!bounds.isEmpty() && fboLayer) {
505d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            clip.set(bounds);
506d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            mat4 inverse;
507d6b65f67717025b1162f86f04e2caa5723566cacChris Craik            inverse.loadInverse(*currentTransform());
508d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            inverse.mapRect(clip);
509d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            clip.snapToPixelBoundaries();
510ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik            clip.doIntersect(untransformedBounds);
511ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik            if (!clip.isEmpty()) {
512d90144db52c7297879b950cbbc85137ed123ab5bChris Craik                clip.translate(-untransformedBounds.left, -untransformedBounds.top);
513d90144db52c7297879b950cbbc85137ed123ab5bChris Craik                bounds.set(untransformedBounds);
514d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            }
515d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        }
516d90144db52c7297879b950cbbc85137ed123ab5bChris Craik    }
517d90144db52c7297879b950cbbc85137ed123ab5bChris Craik}
518d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
519408eb12631376cbdc96803e918decf6ea804d346Chris Craikvoid OpenGLRenderer::updateSnapshotIgnoreForLayer(const Rect& bounds, const Rect& clip,
520408eb12631376cbdc96803e918decf6ea804d346Chris Craik        bool fboLayer, int alpha) {
521408eb12631376cbdc96803e918decf6ea804d346Chris Craik    if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
522408eb12631376cbdc96803e918decf6ea804d346Chris Craik            bounds.getHeight() > mCaches.maxTextureSize ||
523408eb12631376cbdc96803e918decf6ea804d346Chris Craik            (fboLayer && clip.isEmpty())) {
524984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson        writableSnapshot()->empty = fboLayer;
525408eb12631376cbdc96803e918decf6ea804d346Chris Craik    } else {
526984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson        writableSnapshot()->invisible = writableSnapshot()->invisible || (alpha <= 0 && fboLayer);
527408eb12631376cbdc96803e918decf6ea804d346Chris Craik    }
528408eb12631376cbdc96803e918decf6ea804d346Chris Craik}
529408eb12631376cbdc96803e918decf6ea804d346Chris Craik
530d90144db52c7297879b950cbbc85137ed123ab5bChris Craikint OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float bottom,
531d44fbe55a9f434cb5bb0e34c143ba1445141990dDerek Sollenberger        const SkPaint* paint, int flags) {
532984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    const int count = mState.saveSnapshot(flags);
533d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
534eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    if (!mState.currentlyIgnored() && (flags & SaveFlags::ClipToLayer)) {
535d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        // initialize the snapshot as though it almost represents an FBO layer so deferred draw
536d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        // operations will be able to store and restore the current clip and transform info, and
537d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        // quick rejection will be correct (for display lists)
538d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
539d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        Rect bounds(left, top, right, bottom);
540d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        Rect clip;
541d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        calculateLayerBoundsAndClip(bounds, clip, true);
542bf6f0f260886a04a1680c7f9917124a751322ca4Chris Craik        updateSnapshotIgnoreForLayer(bounds, clip, true, PaintUtils::getAlphaDirect(paint));
543d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
544984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson        if (!mState.currentlyIgnored()) {
545984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            writableSnapshot()->resetTransform(-bounds.left, -bounds.top, 0.0f);
546984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            writableSnapshot()->resetClip(clip.left, clip.top, clip.right, clip.bottom);
547984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            writableSnapshot()->initializeViewport(bounds.getWidth(), bounds.getHeight());
548e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            writableSnapshot()->roundRectClipState = nullptr;
549d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        }
550d90144db52c7297879b950cbbc85137ed123ab5bChris Craik    }
551d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
552d90144db52c7297879b950cbbc85137ed123ab5bChris Craik    return count;
553d90144db52c7297879b950cbbc85137ed123ab5bChris Craik}
554d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
5551c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy/**
5561c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Layers are viewed by Skia are slightly different than layers in image editing
5571c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * programs (for instance.) When a layer is created, previously created layers
5581c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * and the frame buffer still receive every drawing command. For instance, if a
5591c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * layer is created and a shape intersecting the bounds of the layers and the
5601c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * framebuffer is draw, the shape will be drawn on both (unless the layer was
561eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita * created with the SaveFlags::ClipToLayer flag.)
5621c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
5631c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * A way to implement layers is to create an FBO for each layer, backed by an RGBA
5641c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * texture. Unfortunately, this is inefficient as it requires every primitive to
5651c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * be drawn n + 1 times, where n is the number of active layers. In practice this
5661c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * means, for every primitive:
5671c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *   - Switch active frame buffer
5681c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *   - Change viewport, clip and projection matrix
5691c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *   - Issue the drawing
5701c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
5711c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Switching rendering target n + 1 times per drawn primitive is extremely costly.
5726b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * To avoid this, layers are implemented in a different way here, at least in the
5736b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * general case. FBOs are used, as an optimization, when the "clip to layer" flag
5746b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * is set. When this flag is set we can redirect all drawing operations into a
5756b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * single FBO.
5761c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
5771c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * This implementation relies on the frame buffer being at least RGBA 8888. When
5781c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * a layer is created, only a texture is created, not an FBO. The content of the
5791c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * frame buffer contained within the layer's bounds is copied into this texture
58087a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * using glCopyTexImage2D(). The layer's region is then cleared(1) in the frame
5811c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * buffer and drawing continues as normal. This technique therefore treats the
5821c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * frame buffer as a scratch buffer for the layers.
5831c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
5841c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * To compose the layers back onto the frame buffer, each layer texture
5851c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * (containing the original frame buffer data) is drawn as a simple quad over
5861c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * the frame buffer. The trick is that the quad is set as the composition
5871c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * destination in the blending equation, and the frame buffer becomes the source
5881c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * of the composition.
5891c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
5901c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Drawing layers with an alpha value requires an extra step before composition.
5911c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * An empty quad is drawn over the layer's region in the frame buffer. This quad
5921c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * is drawn with the rgba color (0,0,0,alpha). The alpha value offered by the
5931c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * quad is used to multiply the colors in the frame buffer. This is achieved by
5941c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * changing the GL blend functions for the GL_FUNC_ADD blend equation to
5951c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * GL_ZERO, GL_SRC_ALPHA.
5961c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
5971c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Because glCopyTexImage2D() can be slow, an alternative implementation might
5981c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * be use to draw a single clipped layer. The implementation described above
5991c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * is correct in every case.
60087a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy *
60187a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * (1) The frame buffer is actually not cleared right away. To allow the GPU
60287a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy *     to potentially optimize series of calls to glCopyTexImage2D, the frame
60387a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy *     buffer is left untouched until the first drawing operation. Only when
60487a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy *     something actually gets drawn are the layers regions cleared.
6051c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy */
606d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haasebool OpenGLRenderer::createLayer(float left, float top, float right, float bottom,
6073f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik        const SkPaint* paint, int flags, const SkPath* convexMask) {
60807adacf4996c8ca494332ec938786fa15832c722Chris Craik    LAYER_LOGD("Requesting layer %.2fx%.2f", right - left, bottom - top);
60907adacf4996c8ca494332ec938786fa15832c722Chris Craik    LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize());
610dda570201ac851dd85af3861f7e575721d3345daRomain Guy
611eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    const bool fboLayer = flags & SaveFlags::ClipToLayer;
612eb99356a0548684a501766e6a524529ab93304c8Romain Guy
613f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy    // Window coordinates of the layer
614d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    Rect clip;
6158aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy    Rect bounds(left, top, right, bottom);
616d90144db52c7297879b950cbbc85137ed123ab5bChris Craik    calculateLayerBoundsAndClip(bounds, clip, fboLayer);
617bf6f0f260886a04a1680c7f9917124a751322ca4Chris Craik    updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, PaintUtils::getAlphaDirect(paint));
618dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy
619dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy    // Bail out if we won't draw in this snapshot
620984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    if (mState.currentlyIgnored()) {
621b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy        return false;
622b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy    }
623dda570201ac851dd85af3861f7e575721d3345daRomain Guy
62444eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik    mCaches.textureState().activateTexture(0);
6253b20251a355c88193c439f928a84ae69483fb488John Reck    Layer* layer = mCaches.layerCache.get(mRenderState, bounds.getWidth(), bounds.getHeight());
626f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy    if (!layer) {
627f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        return false;
628bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    }
629bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
630674554fc36932ca50b15bba41ac6f650254d4e72Derek Sollenberger    layer->setPaint(paint);
6318aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy    layer->layer.set(bounds);
6329ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy    layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
6339ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy            bounds.getWidth() / float(layer->getWidth()), 0.0f);
634d44fbe55a9f434cb5bb0e34c143ba1445141990dDerek Sollenberger
635a23eed808a1ae4ec0d818c0a9238385e797fd056Chet Haase    layer->setBlend(true);
6367c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy    layer->setDirty(false);
6373f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    layer->setConvexMask(convexMask); // note: the mask must be cleared before returning to the cache
638dda570201ac851dd85af3861f7e575721d3345daRomain Guy
6398fb954263dd2f918ad339045cc6d82e346515599Romain Guy    // Save the layer in the snapshot
640984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    writableSnapshot()->flags |= Snapshot::kFlagIsLayer;
641984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    writableSnapshot()->layer = layer;
6421d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy
643a8bea8edde2f20cae48e5cc8de782679306b3cc3Chris Craik    ATRACE_FORMAT_BEGIN("%ssaveLayer %ux%u",
644a8bea8edde2f20cae48e5cc8de782679306b3cc3Chris Craik            fboLayer ? "" : "unclipped ",
645a8bea8edde2f20cae48e5cc8de782679306b3cc3Chris Craik            layer->getWidth(), layer->getHeight());
6467273daace9303f4662444111c40bb83d3ead4a92Chris Craik    startMark("SaveLayer");
647eb99356a0548684a501766e6a524529ab93304c8Romain Guy    if (fboLayer) {
648e63f7c622a2086aefa80983c6f41b74fb166bb42Chris Craik        return createFboLayer(layer, bounds, clip);
649eb99356a0548684a501766e6a524529ab93304c8Romain Guy    } else {
650eb99356a0548684a501766e6a524529ab93304c8Romain Guy        // Copy the framebuffer into the layer
6519ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy        layer->bindTexture();
652514fb18827186591d66973c2362c859b64b63556Romain Guy        if (!bounds.isEmpty()) {
6539ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy            if (layer->isEmpty()) {
654b254c242d98f4a9d98055726446351e52bece2c6Romain Guy                // Workaround for some GL drivers. When reading pixels lying outside
655b254c242d98f4a9d98055726446351e52bece2c6Romain Guy                // of the window we should get undefined values for those pixels.
656b254c242d98f4a9d98055726446351e52bece2c6Romain Guy                // Unfortunately some drivers will turn the entire target texture black
657b254c242d98f4a9d98055726446351e52bece2c6Romain Guy                // when reading outside of the window.
658b254c242d98f4a9d98055726446351e52bece2c6Romain Guy                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->getWidth(), layer->getHeight(),
659e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik                        0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6609ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy                layer->setEmpty(false);
661514fb18827186591d66973c2362c859b64b63556Romain Guy            }
6627b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy
663a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik            glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
664a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik                    bounds.left, getViewportHeight() - bounds.bottom,
665a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik                    bounds.getWidth(), bounds.getHeight());
666b254c242d98f4a9d98055726446351e52bece2c6Romain Guy
66754be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy            // Enqueue the buffer coordinates to clear the corresponding region later
66851d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik            mLayers.push_back(Rect(bounds));
669ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy        }
670eb99356a0548684a501766e6a524529ab93304c8Romain Guy    }
671f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
672d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    return true;
673bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy}
674bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
675e63f7c622a2086aefa80983c6f41b74fb166bb42Chris Craikbool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip) {
676c3fedafc5f50100219449125a000e3138f6fb987Romain Guy    layer->clipRect.set(clip);
6770b8d0677be2289bbc9e0b48c0878fb67d1cc0ebdJohn Reck    layer->setFbo(mRenderState.createFramebuffer());
6785b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
679984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    writableSnapshot()->region = &writableSnapshot()->layer->region;
680984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    writableSnapshot()->flags |= Snapshot::kFlagFboTarget | Snapshot::kFlagIsFboLayer;
681984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    writableSnapshot()->fbo = layer->getFbo();
682984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    writableSnapshot()->resetTransform(-bounds.left, -bounds.top, 0.0f);
683984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    writableSnapshot()->resetClip(clip.left, clip.top, clip.right, clip.bottom);
684984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    writableSnapshot()->initializeViewport(bounds.getWidth(), bounds.getHeight());
685e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik    writableSnapshot()->roundRectClipState = nullptr;
6865b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
6877c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    debugOverdraw(false, false);
6885b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    // Bind texture to FBO
6893b20251a355c88193c439f928a84ae69483fb488John Reck    mRenderState.bindFramebuffer(layer->getFbo());
6909ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy    layer->bindTexture();
6915b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
6925b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    // Initialize the texture if needed
6939ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy    if (layer->isEmpty()) {
6940908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy        layer->allocateTexture();
6959ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy        layer->setEmpty(false);
6965b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    }
6975b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
6985b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
699f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik            layer->getTextureId(), 0);
7005b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
7015b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    // Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
70265fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik    mRenderState.scissor().setEnabled(true);
70365fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik    mRenderState.scissor().set(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f,
7045b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy            clip.getWidth() + 2.0f, clip.getHeight() + 2.0f);
7055b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    glClear(GL_COLOR_BUFFER_BIT);
7065b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
7075b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    dirtyClip();
7085b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
7095b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    // Change the ortho projection
7103b20251a355c88193c439f928a84ae69483fb488John Reck    mRenderState.setViewport(bounds.getWidth(), bounds.getHeight());
7115b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    return true;
7125b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy}
7135b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
7141c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy/**
7151c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Read the documentation of createLayer() before doing anything in this method.
7161c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy */
71714e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& restored) {
71814e513058ed4168c94e015638d16f5f87fd8063aChris Craik    if (!removed.layer) {
7193762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Attempting to compose a layer that does not exist");
7201d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy        return;
7211d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy    }
7221d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy
72314e513058ed4168c94e015638d16f5f87fd8063aChris Craik    Layer* layer = removed.layer;
7248ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy    const Rect& rect = layer->layer;
72514e513058ed4168c94e015638d16f5f87fd8063aChris Craik    const bool fboLayer = removed.flags & Snapshot::kFlagIsFboLayer;
726eb99356a0548684a501766e6a524529ab93304c8Romain Guy
72739a908c1df89e1073627b0dcbce922d826b67055Chris Craik    bool clipRequired = false;
728984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    mState.calculateQuickRejectForScissor(rect.left, rect.top, rect.right, rect.bottom,
729e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            &clipRequired, nullptr, false); // safely ignore return, should never be rejected
73065fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik    mRenderState.scissor().setEnabled(mScissorOptimizationDisabled || clipRequired);
73139a908c1df89e1073627b0dcbce922d826b67055Chris Craik
732eb99356a0548684a501766e6a524529ab93304c8Romain Guy    if (fboLayer) {
733e0aa84b7dc087e999e20055dcc04cb6a48d5bd62Romain Guy        // Detach the texture from the FBO
734e0aa84b7dc087e999e20055dcc04cb6a48d5bd62Romain Guy        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
7358ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy
7368ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy        layer->removeFbo(false);
7378ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy
738eb99356a0548684a501766e6a524529ab93304c8Romain Guy        // Unbind current FBO and restore previous one
7393b20251a355c88193c439f928a84ae69483fb488John Reck        mRenderState.bindFramebuffer(restored.fbo);
7407c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy        debugOverdraw(true, false);
741eb99356a0548684a501766e6a524529ab93304c8Romain Guy    }
742eb99356a0548684a501766e6a524529ab93304c8Romain Guy
7439ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy    if (!fboLayer && layer->getAlpha() < 255) {
74476d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        SkPaint layerPaint;
74576d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        layerPaint.setAlpha(layer->getAlpha());
74676d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        layerPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
74776d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        layerPaint.setColorFilter(layer->getColorFilter());
74876d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger
74976d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        drawColorRect(rect.left, rect.top, rect.right, rect.bottom, &layerPaint, true);
7505b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        // Required below, composeLayerRect() will divide by 255
7519ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy        layer->setAlpha(255);
752f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy    }
753f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy
75496a5c4c7bab6718524de7253da8309143ab48befChris Craik    mRenderState.meshState().unbindMeshBuffer();
7558b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy
75644eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik    mCaches.textureState().activateTexture(0);
7575b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
7585b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    // When the layer is stored in an FBO, we can save a bit of fillrate by
7595b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    // drawing only the dirty region
760eb99356a0548684a501766e6a524529ab93304c8Romain Guy    if (fboLayer) {
76114e513058ed4168c94e015638d16f5f87fd8063aChris Craik        dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *restored.transform);
7625b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        composeLayerRegion(layer, rect);
7639ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy    } else if (!rect.isEmpty()) {
7649ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy        dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
765a5ff739d3c9e15d07f1d5c644b4f11205cdac0e8Digish Pandya
766a5ff739d3c9e15d07f1d5c644b4f11205cdac0e8Digish Pandya        save(0);
767a5ff739d3c9e15d07f1d5c644b4f11205cdac0e8Digish Pandya        // the layer contains screen buffer content that shouldn't be alpha modulated
768a5ff739d3c9e15d07f1d5c644b4f11205cdac0e8Digish Pandya        // (and any necessary alpha modulation was handled drawing into the layer)
769984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson        writableSnapshot()->alpha = 1.0f;
77053e51e4aa933f9603587e1780f446c18816bf9beChris Craik        composeLayerRectSwapped(layer, rect);
771a5ff739d3c9e15d07f1d5c644b4f11205cdac0e8Digish Pandya        restore();
772eb99356a0548684a501766e6a524529ab93304c8Romain Guy    }
7731d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy
774746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy    dirtyClip();
775746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy
776eb99356a0548684a501766e6a524529ab93304c8Romain Guy    // Failing to add the layer to the cache should happen only if the layer is too large
777e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik    layer->setConvexMask(nullptr);
7788550c4c7b5952b7a4e1e0ede95c9492d03099a13Romain Guy    if (!mCaches.layerCache.put(layer)) {
77907adacf4996c8ca494332ec938786fa15832c722Chris Craik        LAYER_LOGD("Deleting layer");
780e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik        layer->decStrong(nullptr);
7811d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy    }
7821d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy}
7831d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy
784aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyvoid OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
7851e4c8074fa9d1ab867d287b7788e5b83db295a5cChris Craik    const bool tryToSnap = !layer->getForceFilter()
78626bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik            && layer->getWidth() == (uint32_t) rect.getWidth()
787828407356dd5c34a3e441604aaf895cbec7c7e66Chris Craik            && layer->getHeight() == (uint32_t) rect.getHeight();
788828407356dd5c34a3e441604aaf895cbec7c7e66Chris Craik    Glop glop;
789828407356dd5c34a3e441604aaf895cbec7c7e66Chris Craik    GlopBuilder(mRenderState, mCaches, &glop)
790b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
791828407356dd5c34a3e441604aaf895cbec7c7e66Chris Craik            .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
792828407356dd5c34a3e441604aaf895cbec7c7e66Chris Craik            .setFillTextureLayer(*layer, getLayerAlpha(layer))
79353e51e4aa933f9603587e1780f446c18816bf9beChris Craik            .setTransform(*currentSnapshot(), TransformFlags::None)
7941e4c8074fa9d1ab867d287b7788e5b83db295a5cChris Craik            .setModelViewMapUnitToRectOptionalSnap(tryToSnap, rect)
795828407356dd5c34a3e441604aaf895cbec7c7e66Chris Craik            .build();
796828407356dd5c34a3e441604aaf895cbec7c7e66Chris Craik    renderGlop(glop);
797aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy}
798