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
1785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#define LOG_TAG "OpenGLRenderer"
18e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
19e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <stdlib.h>
20e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <stdint.h>
21e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <sys/types.h>
22e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
23bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy#include <SkCanvas.h>
2498d608dba6a0b3c15fb08f1fa2c8b9d170124c7cChris Craik#include <SkColor.h>
25d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III#include <SkShader.h>
26694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy#include <SkTypeface.h>
275cbbce535744b89df5ecea95de21ee3733298260Romain Guy
285cbbce535744b89df5ecea95de21ee3733298260Romain Guy#include <utils/Log.h>
29e2d345ea67e2960b37bfdc0fc8626d1bfa747404Romain Guy#include <utils/StopWatch.h>
3085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy
3108aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy#include <private/hwui/DrawGlInfo.h>
3208aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy
335b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#include <ui/Rect.h>
345b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
3585bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include "OpenGLRenderer.h"
36c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#include "DeferredDisplayList.h"
370fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy#include "DisplayListRenderer.h"
38405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy#include "Fence.h"
393b20251a355c88193c439f928a84ae69483fb488John Reck#include "RenderState.h"
4065cd612face362d054a85d0f7e5881c59cd523beChris Craik#include "PathTessellator.h"
4187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy#include "Properties.h"
4255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include "ShadowTessellator.h"
43d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III#include "SkiaShader.h"
44e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik#include "utils/GLUtils.h"
4570850ea258cbf91477efa57a1f1a23cc0044cc93Chris Craik#include "utils/TraceUtils.h"
46a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy#include "Vector.h"
4755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#include "VertexBuffer.h"
48e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
4962d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik#if DEBUG_DETAILED_EVENTS
5062d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    #define EVENT_LOGD(...) eventMarkDEBUG(__VA_ARGS__)
5162d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik#else
5262d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    #define EVENT_LOGD(...)
5362d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik#endif
5462d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik
55e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guynamespace android {
569d5316e3f56d138504565ff311145ac01621dff4Romain Guynamespace uirenderer {
579d5316e3f56d138504565ff311145ac01621dff4Romain Guy
5867862524056ee2e73a94395139bb8bd0ec1ef38aChris Craikstatic GLenum getFilter(const SkPaint* paint) {
5967862524056ee2e73a94395139bb8bd0ec1ef38aChris Craik    if (!paint || paint->getFilterLevel() != SkPaint::kNone_FilterLevel) {
6067862524056ee2e73a94395139bb8bd0ec1ef38aChris Craik        return GL_LINEAR;
6167862524056ee2e73a94395139bb8bd0ec1ef38aChris Craik    }
6267862524056ee2e73a94395139bb8bd0ec1ef38aChris Craik    return GL_NEAREST;
6367862524056ee2e73a94395139bb8bd0ec1ef38aChris Craik}
64d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy
659d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
669d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Globals
679d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
689d5316e3f56d138504565ff311145ac01621dff4Romain Guy
69889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy/**
70889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy * Structure mapping Skia xfermodes to OpenGL blending factors.
71889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy */
72889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guystruct Blender {
73889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    SkXfermode::Mode mode;
74889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    GLenum src;
75889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    GLenum dst;
76889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy}; // struct Blender
77889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy
78026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy// In this array, the index of each Blender equals the value of the first
79026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
80026c5e16704e817cac7d9c382914c947e34f87e0Romain Guystatic const Blender gBlends[] = {
812ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kClear_Mode,    GL_ZERO,                GL_ONE_MINUS_SRC_ALPHA },
822ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrc_Mode,      GL_ONE,                 GL_ZERO },
832ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDst_Mode,      GL_ZERO,                GL_ONE },
842ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcOver_Mode,  GL_ONE,                 GL_ONE_MINUS_SRC_ALPHA },
852ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstOver_Mode,  GL_ONE_MINUS_DST_ALPHA, GL_ONE },
862ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcIn_Mode,    GL_DST_ALPHA,           GL_ZERO },
872ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstIn_Mode,    GL_ZERO,                GL_SRC_ALPHA },
882ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcOut_Mode,   GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
892ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstOut_Mode,   GL_ZERO,                GL_ONE_MINUS_SRC_ALPHA },
902ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcATop_Mode,  GL_DST_ALPHA,           GL_ONE_MINUS_SRC_ALPHA },
912ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstATop_Mode,  GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
922ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kXor_Mode,      GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
932ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kPlus_Mode,     GL_ONE,                 GL_ONE },
94d81ec456bb097a712bcbc093c5a1e0075434158eDerek Sollenberger    { SkXfermode::kModulate_Mode, GL_ZERO,                GL_SRC_COLOR },
952ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kScreen_Mode,   GL_ONE,                 GL_ONE_MINUS_SRC_COLOR }
96026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy};
97e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
9887a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy// This array contains the swapped version of each SkXfermode. For instance
9987a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy// this array's SrcOver blending mode is actually DstOver. You can refer to
10087a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy// createLayer() for more information on the purpose of this array.
101f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guystatic const Blender gBlendsSwap[] = {
1022ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kClear_Mode,    GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
1032ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrc_Mode,      GL_ZERO,                GL_ONE },
1042ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDst_Mode,      GL_ONE,                 GL_ZERO },
1052ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcOver_Mode,  GL_ONE_MINUS_DST_ALPHA, GL_ONE },
1062ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstOver_Mode,  GL_ONE,                 GL_ONE_MINUS_SRC_ALPHA },
1072ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcIn_Mode,    GL_ZERO,                GL_SRC_ALPHA },
1082ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstIn_Mode,    GL_DST_ALPHA,           GL_ZERO },
1092ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcOut_Mode,   GL_ZERO,                GL_ONE_MINUS_SRC_ALPHA },
1102ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstOut_Mode,   GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
1112ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcATop_Mode,  GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
1122ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstATop_Mode,  GL_DST_ALPHA,           GL_ONE_MINUS_SRC_ALPHA },
1132ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kXor_Mode,      GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
1142ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kPlus_Mode,     GL_ONE,                 GL_ONE },
115d81ec456bb097a712bcbc093c5a1e0075434158eDerek Sollenberger    { SkXfermode::kModulate_Mode, GL_DST_COLOR,           GL_ZERO },
1162ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kScreen_Mode,   GL_ONE_MINUS_DST_COLOR, GL_ONE }
117f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy};
118f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy
119f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
120448455fe783b0a711340322dca272b8cc0ebe473Romain Guy// Functions
121448455fe783b0a711340322dca272b8cc0ebe473Romain Guy///////////////////////////////////////////////////////////////////////////////
122448455fe783b0a711340322dca272b8cc0ebe473Romain Guy
123448455fe783b0a711340322dca272b8cc0ebe473Romain Guytemplate<typename T>
124448455fe783b0a711340322dca272b8cc0ebe473Romain Guystatic inline T min(T a, T b) {
125448455fe783b0a711340322dca272b8cc0ebe473Romain Guy    return a < b ? a : b;
126448455fe783b0a711340322dca272b8cc0ebe473Romain Guy}
127448455fe783b0a711340322dca272b8cc0ebe473Romain Guy
128448455fe783b0a711340322dca272b8cc0ebe473Romain Guy///////////////////////////////////////////////////////////////////////////////
129f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Constructors/destructor
130f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
131f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
1323b20251a355c88193c439f928a84ae69483fb488John ReckOpenGLRenderer::OpenGLRenderer(RenderState& renderState)
133058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        : mFrameStarted(false)
134058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mCaches(Caches::getInstance())
1353b20251a355c88193c439f928a84ae69483fb488John Reck        , mExtensions(Extensions::getInstance())
136058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mRenderState(renderState)
137058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mScissorOptimizationDisabled(false)
138284b24358410cb0200e525a5ba36994090c83f20Chris Craik        , mSuppressTiling(false)
139284b24358410cb0200e525a5ba36994090c83f20Chris Craik        , mFirstFrameAfterResize(true)
1401aa5d2d7068147ff781cfe911a93f01593a68c79John Reck        , mLightCenter((Vector3){FLT_MIN, FLT_MIN, FLT_MIN})
141058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mLightRadius(FLT_MIN)
142058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mAmbientShadowAlpha(0)
143058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mSpotShadowAlpha(0) {
144527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik    // *set* draw modifiers to be 0
145527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik    memset(&mDrawModifiers, 0, sizeof(mDrawModifiers));
14616ecda5317c40fc3da284952d9b3add34d6763aeChris Craik    mDrawModifiers.mOverrideLayerAlpha = 1.0f;
147026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
148ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
149e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
150e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
15185bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain GuyOpenGLRenderer::~OpenGLRenderer() {
15229d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy    // The context has already been destroyed at this point, do not call
15329d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy    // GL APIs. All GL state should be kept in Caches.h
154e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
155e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
15687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::initProperties() {
15787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    char property[PROPERTY_VALUE_MAX];
15887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    if (property_get(PROPERTY_DISABLE_SCISSOR_OPTIMIZATION, property, "false")) {
15987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mScissorOptimizationDisabled = !strcasecmp(property, "true");
16087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        INIT_LOGD("  Scissor optimization %s",
16187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy                mScissorOptimizationDisabled ? "disabled" : "enabled");
16287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    } else {
16387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        INIT_LOGD("  Scissor optimization enabled");
16487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    }
16513631f3da855f200a151e7837ed9f6b079622b58Romain Guy}
16613631f3da855f200a151e7837ed9f6b079622b58Romain Guy
167058fc640017c90120c599d378a4cbc55668b05b7Chris Craikvoid OpenGLRenderer::initLight(const Vector3& lightCenter, float lightRadius,
168058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
169058fc640017c90120c599d378a4cbc55668b05b7Chris Craik    mLightCenter = lightCenter;
170058fc640017c90120c599d378a4cbc55668b05b7Chris Craik    mLightRadius = lightRadius;
171058fc640017c90120c599d378a4cbc55668b05b7Chris Craik    mAmbientShadowAlpha = ambientShadowAlpha;
172058fc640017c90120c599d378a4cbc55668b05b7Chris Craik    mSpotShadowAlpha = spotShadowAlpha;
173058fc640017c90120c599d378a4cbc55668b05b7Chris Craik}
174058fc640017c90120c599d378a4cbc55668b05b7Chris Craik
17513631f3da855f200a151e7837ed9f6b079622b58Romain Guy///////////////////////////////////////////////////////////////////////////////
176f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Setup
177f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
178f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
179797b95b26bbb7557678af78b9a2a61830158920fChris Craikvoid OpenGLRenderer::onViewportInitialized() {
18035643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    glDisable(GL_DITHER);
18135643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
18235643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy
18335643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    glEnableVertexAttribArray(Program::kBindingPosition);
184284b24358410cb0200e525a5ba36994090c83f20Chris Craik    mFirstFrameAfterResize = true;
18535643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy}
18635643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy
18796885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guyvoid OpenGLRenderer::setupFrameState(float left, float top,
188c3fedafc5f50100219449125a000e3138f6fb987Romain Guy        float right, float bottom, bool opaque) {
189fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy    mCaches.clearGarbage();
19069e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    initializeSaveStack(left, top, right, bottom, mLightCenter);
19196885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    mOpaque = opaque;
1925f803623559aab395a29d575c37c4e39c23a4b4eChris Craik    mTilingClip.set(left, top, right, bottom);
19396885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy}
194ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy
19596885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guystatus_t OpenGLRenderer::startFrame() {
19696885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    if (mFrameStarted) return DrawGlInfo::kStatusDone;
19796885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    mFrameStarted = true;
19811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
19996885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    mDirtyClip = true;
20096885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
20196885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    discardFramebuffer(mTilingClip.left, mTilingClip.top, mTilingClip.right, mTilingClip.bottom);
20245e4c3df6c00ac98ff6144de9af574877d4fff19Romain Guy
2033b20251a355c88193c439f928a84ae69483fb488John Reck    mRenderState.setViewport(getWidth(), getHeight());
2047d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy
20554c1a64d5441a964890b44280e4457e11f4f924aRomain Guy    // Functors break the tiling extension in pretty spectacular ways
20654c1a64d5441a964890b44280e4457e11f4f924aRomain Guy    // This ensures we don't use tiling when a functor is going to be
20754c1a64d5441a964890b44280e4457e11f4f924aRomain Guy    // invoked during the frame
208284b24358410cb0200e525a5ba36994090c83f20Chris Craik    mSuppressTiling = mCaches.hasRegisteredFunctors()
209284b24358410cb0200e525a5ba36994090c83f20Chris Craik            || mFirstFrameAfterResize;
210284b24358410cb0200e525a5ba36994090c83f20Chris Craik    mFirstFrameAfterResize = false;
21154c1a64d5441a964890b44280e4457e11f4f924aRomain Guy
212d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    startTilingCurrentClip(true);
2132b7028eabac80cec170572bc0e945a1d4224e595Romain Guy
2147c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    debugOverdraw(true, true);
2157c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy
21696885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    return clear(mTilingClip.left, mTilingClip.top,
21796885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy            mTilingClip.right, mTilingClip.bottom, mOpaque);
21896885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy}
21996885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
22096885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guystatus_t OpenGLRenderer::prepareDirty(float left, float top,
22196885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        float right, float bottom, bool opaque) {
22278dd96d5af20f489f0e8b288617d57774ec284f7Romain Guy
22396885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    setupFrameState(left, top, right, bottom, opaque);
22496885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
22596885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    // Layer renderers will start the frame immediately
22696885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    // The framebuffer renderer will first defer the display list
22796885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    // for each layer and wait until the first drawing command
22896885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    // to start the frame
229d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    if (currentSnapshot()->fbo == 0) {
23096885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        syncState();
23196885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        updateLayers();
23296885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    } else {
23396885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        return startFrame();
23496885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    }
23596885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
23696885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    return DrawGlInfo::kStatusDone;
2377c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy}
2387c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy
239dcfc836b457a87881da409e1acf251515f121446Romain Guyvoid OpenGLRenderer::discardFramebuffer(float left, float top, float right, float bottom) {
240dcfc836b457a87881da409e1acf251515f121446Romain Guy    // If we know that we are going to redraw the entire framebuffer,
241dcfc836b457a87881da409e1acf251515f121446Romain Guy    // perform a discard to let the driver know we don't need to preserve
242dcfc836b457a87881da409e1acf251515f121446Romain Guy    // the back buffer for this frame.
2433bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    if (mExtensions.hasDiscardFramebuffer() &&
24414e513058ed4168c94e015638d16f5f87fd8063aChris Craik            left <= 0.0f && top <= 0.0f && right >= getWidth() && bottom >= getHeight()) {
245f158198ccc3a1f53bfebaa6b8f4426e80e1867eaRomain Guy        const bool isFbo = getTargetFbo() == 0;
246f158198ccc3a1f53bfebaa6b8f4426e80e1867eaRomain Guy        const GLenum attachments[] = {
247f158198ccc3a1f53bfebaa6b8f4426e80e1867eaRomain Guy                isFbo ? (const GLenum) GL_COLOR_EXT : (const GLenum) GL_COLOR_ATTACHMENT0,
248f158198ccc3a1f53bfebaa6b8f4426e80e1867eaRomain Guy                isFbo ? (const GLenum) GL_STENCIL_EXT : (const GLenum) GL_STENCIL_ATTACHMENT };
249dcfc836b457a87881da409e1acf251515f121446Romain Guy        glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments);
250dcfc836b457a87881da409e1acf251515f121446Romain Guy    }
251dcfc836b457a87881da409e1acf251515f121446Romain Guy}
252dcfc836b457a87881da409e1acf251515f121446Romain Guy
2537c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guystatus_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
25423d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    if (!opaque) {
255586cae3ac69c0c667fbf8a954edbd399f620a717Romain Guy        mCaches.enableScissor();
256a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik        mCaches.setScissor(left, getViewportHeight() - bottom, right - left, bottom - top);
2576b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy        glClear(GL_COLOR_BUFFER_BIT);
25844b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase        return DrawGlInfo::kStatusDrew;
259ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy    }
26044b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase
2617c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy    mCaches.resetScissor();
26244b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase    return DrawGlInfo::kStatusDone;
263ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy}
264ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy
265ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guyvoid OpenGLRenderer::syncState() {
266ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy    if (mCaches.blend) {
267ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy        glEnable(GL_BLEND);
268ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy    } else {
269ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy        glDisable(GL_BLEND);
2706b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy    }
271bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
272bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
27333f5a59ac3e304970920dda824958870f85f76efhenry.uh_chenvoid OpenGLRenderer::startTilingCurrentClip(bool opaque, bool expand) {
27454c1a64d5441a964890b44280e4457e11f4f924aRomain Guy    if (!mSuppressTiling) {
275d6b65f67717025b1162f86f04e2caa5723566cacChris Craik        const Snapshot* snapshot = currentSnapshot();
276d6b65f67717025b1162f86f04e2caa5723566cacChris Craik
27714e513058ed4168c94e015638d16f5f87fd8063aChris Craik        const Rect* clip = &mTilingClip;
278d6b65f67717025b1162f86f04e2caa5723566cacChris Craik        if (snapshot->flags & Snapshot::kFlagFboTarget) {
279d6b65f67717025b1162f86f04e2caa5723566cacChris Craik            clip = &(snapshot->layer->clipRect);
28054c1a64d5441a964890b44280e4457e11f4f924aRomain Guy        }
28154c1a64d5441a964890b44280e4457e11f4f924aRomain Guy
28233f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen        startTiling(*clip, getViewportHeight(), opaque, expand);
283c3fedafc5f50100219449125a000e3138f6fb987Romain Guy    }
284c3fedafc5f50100219449125a000e3138f6fb987Romain Guy}
285c3fedafc5f50100219449125a000e3138f6fb987Romain Guy
28633f5a59ac3e304970920dda824958870f85f76efhenry.uh_chenvoid OpenGLRenderer::startTiling(const Rect& clip, int windowHeight, bool opaque, bool expand) {
287c3fedafc5f50100219449125a000e3138f6fb987Romain Guy    if (!mSuppressTiling) {
28833f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen        if(expand) {
28933f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen            // Expand the startTiling region by 1
29033f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen            int leftNotZero = (clip.left > 0) ? 1 : 0;
29133f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen            int topNotZero = (windowHeight - clip.bottom > 0) ? 1 : 0;
29233f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen
29333f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen            mCaches.startTiling(
29433f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen                clip.left - leftNotZero,
29533f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen                windowHeight - clip.bottom - topNotZero,
29633f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen                clip.right - clip.left + leftNotZero + 1,
29733f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen                clip.bottom - clip.top + topNotZero + 1,
29833f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen                opaque);
29933f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen        } else {
30033f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen            mCaches.startTiling(clip.left, windowHeight - clip.bottom,
30152036b19a5f82bc4d75cfcbff99c65df8d25a99bRomain Guy                clip.right - clip.left, clip.bottom - clip.top, opaque);
30233f5a59ac3e304970920dda824958870f85f76efhenry.uh_chen        }
3032b7028eabac80cec170572bc0e945a1d4224e595Romain Guy    }
3042b7028eabac80cec170572bc0e945a1d4224e595Romain Guy}
3052b7028eabac80cec170572bc0e945a1d4224e595Romain Guy
3062b7028eabac80cec170572bc0e945a1d4224e595Romain Guyvoid OpenGLRenderer::endTiling() {
30754c1a64d5441a964890b44280e4457e11f4f924aRomain Guy    if (!mSuppressTiling) mCaches.endTiling();
3082b7028eabac80cec170572bc0e945a1d4224e595Romain Guy}
3092b7028eabac80cec170572bc0e945a1d4224e595Romain Guy
310b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guyvoid OpenGLRenderer::finish() {
3117c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    renderOverdraw();
3122b7028eabac80cec170572bc0e945a1d4224e595Romain Guy    endTiling();
3132b7028eabac80cec170572bc0e945a1d4224e595Romain Guy
3144ac36f80beb958c77a92a3e1a235f6ed9daaa510Chris Craik    for (size_t i = 0; i < mTempPaths.size(); i++) {
3154ac36f80beb958c77a92a3e1a235f6ed9daaa510Chris Craik        delete mTempPaths[i];
3164ac36f80beb958c77a92a3e1a235f6ed9daaa510Chris Craik    }
3174ac36f80beb958c77a92a3e1a235f6ed9daaa510Chris Craik    mTempPaths.clear();
3184ac36f80beb958c77a92a3e1a235f6ed9daaa510Chris Craik
319ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy    // When finish() is invoked on FBO 0 we've reached the end
320ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy    // of the current frame
321ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy    if (getTargetFbo() == 0) {
322ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy        mCaches.pathCache.trim();
32305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        mCaches.tessellationCache.trim();
324ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy    }
325ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy
32611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    if (!suppressErrorChecks()) {
327b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy#if DEBUG_OPENGL
328e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik        GLUtils::dumpGLErrors();
329b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy#endif
33011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
331c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#if DEBUG_MEMORY_USAGE
332e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy        mCaches.dumpMemoryUsage();
33311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy#else
33411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        if (mCaches.getDebugLevel() & kDebugMemory) {
33511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            mCaches.dumpMemoryUsage();
33611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        }
337c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#endif
33811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
33996885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
34096885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    mFrameStarted = false;
341b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy}
342b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy
34335643ddc689913f5b5f80ceed864470d987bd6cdRomain Guyvoid OpenGLRenderer::resumeAfterLayer() {
3443b20251a355c88193c439f928a84ae69483fb488John Reck    mRenderState.setViewport(getViewportWidth(), getViewportHeight());
3453b20251a355c88193c439f928a84ae69483fb488John Reck    mRenderState.bindFramebuffer(currentSnapshot()->fbo);
3467c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    debugOverdraw(true, false);
34735643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy
34835643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    mCaches.resetScissor();
34935643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    dirtyClip();
35035643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy}
35135643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy
3528f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guystatus_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
353d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
354408eb12631376cbdc96803e918decf6ea804d346Chris Craik
355d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    Rect clip(*currentClipRect());
35680911b851764b073310fd0bffdf4a7db0d8fdd0bRomain Guy    clip.snapToPixelBoundaries();
35780911b851764b073310fd0bffdf4a7db0d8fdd0bRomain Guy
358d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy    // Since we don't know what the functor will draw, let's dirty
359d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    // the entire clip region
360d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy    if (hasLayer()) {
361d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy        dirtyLayerUnchecked(clip, getRegion());
362d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy    }
363d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy
36408aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    DrawGlInfo info;
36508aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.clipLeft = clip.left;
36608aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.clipTop = clip.top;
36708aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.clipRight = clip.right;
36808aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.clipBottom = clip.bottom;
36908aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.isLayer = hasLayer();
370a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik    info.width = getViewportWidth();
371a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik    info.height = getViewportHeight();
372d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    currentTransform()->copyTo(&info.transform[0]);
37380911b851764b073310fd0bffdf4a7db0d8fdd0bRomain Guy
3743b20251a355c88193c439f928a84ae69483fb488John Reck    bool prevDirtyClip = mDirtyClip;
37554f574acf4dd5483170b8f79e2f7c70b58763ce7Chris Craik    // setup GL state for functor
37654f574acf4dd5483170b8f79e2f7c70b58763ce7Chris Craik    if (mDirtyClip) {
37754f574acf4dd5483170b8f79e2f7c70b58763ce7Chris Craik        setStencilFromClip(); // can issue draws, so must precede enableScissor()/interrupt()
37854f574acf4dd5483170b8f79e2f7c70b58763ce7Chris Craik    }
3793b20251a355c88193c439f928a84ae69483fb488John Reck    if (mCaches.enableScissor() || prevDirtyClip) {
38025d2f7bc1ff9b475eff75bfff647466e91dbacb2John Reck        setScissorFromClip();
38125d2f7bc1ff9b475eff75bfff647466e91dbacb2John Reck    }
38254f574acf4dd5483170b8f79e2f7c70b58763ce7Chris Craik
3833b20251a355c88193c439f928a84ae69483fb488John Reck    mRenderState.invokeFunctor(functor, DrawGlInfo::kModeDraw, &info);
3843b20251a355c88193c439f928a84ae69483fb488John Reck    // Scissor may have been modified, reset dirty clip
3853b20251a355c88193c439f928a84ae69483fb488John Reck    dirtyClip();
386cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy
387750ca6dbdb259aea0ca5b77380a9303e586ef3eaJohn Reck    return DrawGlInfo::kStatusDrew;
388daf98e941e140e8739458126640183b9f296a2abChet Haase}
389daf98e941e140e8739458126640183b9f296a2abChet Haase
390f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
39187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy// Debug
39287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy///////////////////////////////////////////////////////////////////////////////
39387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
39462d307c2402777d5e53b4590af5f32f8c55afd81Chris Craikvoid OpenGLRenderer::eventMarkDEBUG(const char* fmt, ...) const {
39562d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik#if DEBUG_DETAILED_EVENTS
39662d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    const int BUFFER_SIZE = 256;
39762d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    va_list ap;
39862d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    char buf[BUFFER_SIZE];
39962d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik
40062d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    va_start(ap, fmt);
40162d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    vsnprintf(buf, BUFFER_SIZE, fmt, ap);
40262d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    va_end(ap);
40362d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik
40462d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik    eventMark(buf);
40562d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik#endif
40662d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik}
40762d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik
40862d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik
4090f6675332c04c74909425d1d328f02b32c0ff40eRomain Guyvoid OpenGLRenderer::eventMark(const char* name) const {
4100f6675332c04c74909425d1d328f02b32c0ff40eRomain Guy    mCaches.eventMark(0, name);
4110f6675332c04c74909425d1d328f02b32c0ff40eRomain Guy}
4120f6675332c04c74909425d1d328f02b32c0ff40eRomain Guy
41387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::startMark(const char* name) const {
41487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    mCaches.startMark(0, name);
41587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy}
41687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
41787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::endMark() const {
41887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    mCaches.endMark();
41987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy}
42087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
42187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::debugOverdraw(bool enable, bool clear) {
4223b20251a355c88193c439f928a84ae69483fb488John Reck    mRenderState.debugOverdraw(enable, clear);
42387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy}
42487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
42587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::renderOverdraw() {
42687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    if (mCaches.debugOverdraw && getTargetFbo() == 0) {
4275f803623559aab395a29d575c37c4e39c23a4b4eChris Craik        const Rect* clip = &mTilingClip;
42887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
42987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mCaches.enableScissor();
430a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik        mCaches.setScissor(clip->left, firstSnapshot()->getViewportHeight() - clip->bottom,
43187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy                clip->right - clip->left, clip->bottom - clip->top);
43287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
433627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        // 1x overdraw
43487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mCaches.stencil.enableDebugTest(2);
435627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        drawColor(mCaches.getOverdrawColor(1), SkXfermode::kSrcOver_Mode);
436627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy
437627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        // 2x overdraw
43887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mCaches.stencil.enableDebugTest(3);
439627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        drawColor(mCaches.getOverdrawColor(2), SkXfermode::kSrcOver_Mode);
440627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy
441627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        // 3x overdraw
44287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mCaches.stencil.enableDebugTest(4);
443627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        drawColor(mCaches.getOverdrawColor(3), SkXfermode::kSrcOver_Mode);
444627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy
445627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        // 4x overdraw and higher
44687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mCaches.stencil.enableDebugTest(4, true);
447627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy        drawColor(mCaches.getOverdrawColor(4), SkXfermode::kSrcOver_Mode);
448627c6fd91377ead85f74a365438e25610ef1e2eeRomain Guy
44987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mCaches.stencil.disable();
45087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    }
45187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy}
45287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
45387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy///////////////////////////////////////////////////////////////////////////////
45411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy// Layers
45511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy///////////////////////////////////////////////////////////////////////////////
45611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
45711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guybool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
458a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik    if (layer->deferredUpdateScheduled && layer->renderer
459a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik            && layer->renderNode.get() && layer->renderNode->isRenderable()) {
46011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        Rect& dirty = layer->dirtyRect;
46111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
4627c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy        if (inFrame) {
4637c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy            endTiling();
4647c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy            debugOverdraw(false, false);
4657c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy        }
46611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
46796885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        if (CC_UNLIKELY(inFrame || mCaches.drawDeferDisabled)) {
46869e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik            layer->render(*this);
46996885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        } else {
47069e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik            layer->defer(*this);
47196885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        }
47211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
47311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        if (inFrame) {
47411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            resumeAfterLayer();
475d6b65f67717025b1162f86f04e2caa5723566cacChris Craik            startTilingCurrentClip();
47611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        }
47711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
4785bb3c730f5ebd2a0db1b02a8981c6fdbea6c1a2eRomain Guy        layer->debugDrawUpdate = mCaches.debugLayersUpdates;
47934416eaa1c07b3d7a139e780cea8f8d73219650eChris Craik        layer->hasDrawnSinceUpdate = false;
48011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
48111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        return true;
48211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
48311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
48411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    return false;
48511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy}
48611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
48711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guyvoid OpenGLRenderer::updateLayers() {
48896885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    // If draw deferring is enabled this method will simply defer
48996885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    // the display list of each individual layer. The layers remain
49096885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    // in the layer updates list which will be cleared by flushLayers().
49111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    int count = mLayerUpdates.size();
49211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    if (count > 0) {
49396885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
49496885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy            startMark("Layer Updates");
49596885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        } else {
49696885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy            startMark("Defer Layer Updates");
49796885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        }
49811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
4991206b9bba91f7ed899c5c87427cce725fe5aadfcChris Craik        // Note: it is very important to update the layers in order
5001206b9bba91f7ed899c5c87427cce725fe5aadfcChris Craik        for (int i = 0; i < count; i++) {
5010e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck            Layer* layer = mLayerUpdates.itemAt(i).get();
50211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            updateLayer(layer, false);
50311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        }
50411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
50596885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
50696885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy            mLayerUpdates.clear();
5073b20251a355c88193c439f928a84ae69483fb488John Reck            mRenderState.bindFramebuffer(getTargetFbo());
50896885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        }
50996885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        endMark();
51096885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    }
51196885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy}
51296885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
51396885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guyvoid OpenGLRenderer::flushLayers() {
51496885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    int count = mLayerUpdates.size();
51596885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy    if (count > 0) {
51696885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        startMark("Apply Layer Updates");
51796885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
5181206b9bba91f7ed899c5c87427cce725fe5aadfcChris Craik        // Note: it is very important to update the layers in order
5191206b9bba91f7ed899c5c87427cce725fe5aadfcChris Craik        for (int i = 0; i < count; i++) {
52070850ea258cbf91477efa57a1f1a23cc0044cc93Chris Craik            mLayerUpdates.itemAt(i)->flush();
52196885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        }
52296885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
52396885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy        mLayerUpdates.clear();
5243b20251a355c88193c439f928a84ae69483fb488John Reck        mRenderState.bindFramebuffer(getTargetFbo());
52596885eb480c5e0526fe2f77d30f6e551f3f3ceabRomain Guy
52611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        endMark();
52711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
52811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy}
52911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
53011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guyvoid OpenGLRenderer::pushLayerUpdate(Layer* layer) {
53111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    if (layer) {
53202b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy        // Make sure we don't introduce duplicates.
53302b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy        // SortedVector would do this automatically but we need to respect
53402b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy        // the insertion order. The linear search is not an issue since
53502b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy        // this list is usually very short (typically one item, at most a few)
53602b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy        for (int i = mLayerUpdates.size() - 1; i >= 0; i--) {
53702b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy            if (mLayerUpdates.itemAt(i) == layer) {
53802b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy                return;
53902b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy            }
54002b49b70ede0b9eb760ff334823aee1d9520ed85Romain Guy        }
54111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        mLayerUpdates.push_back(layer);
54211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
54311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy}
54411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
545e93482f5eac3df581d57e64c2a771a96aa868585Romain Guyvoid OpenGLRenderer::cancelLayerUpdate(Layer* layer) {
546e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy    if (layer) {
547e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy        for (int i = mLayerUpdates.size() - 1; i >= 0; i--) {
548e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy            if (mLayerUpdates.itemAt(i) == layer) {
549e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy                mLayerUpdates.removeAt(i);
550e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy                break;
551e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy            }
552e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy        }
553e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy    }
554e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy}
555e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy
556405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guyvoid OpenGLRenderer::flushLayerUpdates() {
55770850ea258cbf91477efa57a1f1a23cc0044cc93Chris Craik    ATRACE_NAME("Update HW Layers");
558405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    syncState();
559405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    updateLayers();
560405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    flushLayers();
561405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    // Wait for all the layer updates to be executed
562405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    AutoFence fence;
563405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy}
564405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
565443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reckvoid OpenGLRenderer::markLayersAsBuildLayers() {
566443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck    for (size_t i = 0; i < mLayerUpdates.size(); i++) {
567443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck        mLayerUpdates[i]->wasBuildLayered = true;
568443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck    }
569443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck}
570443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck
57111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy///////////////////////////////////////////////////////////////////////////////
572f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// State management
573f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
574f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
57514e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid OpenGLRenderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {
576a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik    bool restoreViewport = removed.flags & Snapshot::kFlagIsFboLayer;
57714e513058ed4168c94e015638d16f5f87fd8063aChris Craik    bool restoreClip = removed.flags & Snapshot::kFlagClipSet;
57814e513058ed4168c94e015638d16f5f87fd8063aChris Craik    bool restoreLayer = removed.flags & Snapshot::kFlagIsLayer;
579bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
580a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik    if (restoreViewport) {
5813b20251a355c88193c439f928a84ae69483fb488John Reck        mRenderState.setViewport(getViewportWidth(), getViewportHeight());
582eb99356a0548684a501766e6a524529ab93304c8Romain Guy    }
583eb99356a0548684a501766e6a524529ab93304c8Romain Guy
5842542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy    if (restoreClip) {
585746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy        dirtyClip();
5868fb954263dd2f918ad339045cc6d82e346515599Romain Guy    }
5872542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy
5885ec9924d24495822b589f1a17996655d66273b30Romain Guy    if (restoreLayer) {
5897273daace9303f4662444111c40bb83d3ead4a92Chris Craik        endMark(); // Savelayer
590a8bea8edde2f20cae48e5cc8de782679306b3cc3Chris Craik        ATRACE_END(); // SaveLayer
5917273daace9303f4662444111c40bb83d3ead4a92Chris Craik        startMark("ComposeLayer");
59214e513058ed4168c94e015638d16f5f87fd8063aChris Craik        composeLayer(removed, restored);
5937273daace9303f4662444111c40bb83d3ead4a92Chris Craik        endMark();
5945ec9924d24495822b589f1a17996655d66273b30Romain Guy    }
595d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy}
5965cbbce535744b89df5ecea95de21ee3733298260Romain Guy
597f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
598bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy// Layers
599bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy///////////////////////////////////////////////////////////////////////////////
600bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
601bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyint OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
6023f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik        const SkPaint* paint, int flags, const SkPath* convexMask) {
6034ace7305608442ab35ea9aa65a4220df152c187fChris Craik    // force matrix/clip isolation for layer
6044ace7305608442ab35ea9aa65a4220df152c187fChris Craik    flags |= SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag;
6054ace7305608442ab35ea9aa65a4220df152c187fChris Craik
606eb99356a0548684a501766e6a524529ab93304c8Romain Guy    const int count = saveSnapshot(flags);
607d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
608d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    if (!currentSnapshot()->isIgnored()) {
6093f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik        createLayer(left, top, right, bottom, paint, flags, convexMask);
610dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy    }
611d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
612d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    return count;
613bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy}
614bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
615d90144db52c7297879b950cbbc85137ed123ab5bChris Craikvoid OpenGLRenderer::calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool fboLayer) {
616d90144db52c7297879b950cbbc85137ed123ab5bChris Craik    const Rect untransformedBounds(bounds);
617d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
618d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    currentTransform()->mapRect(bounds);
619d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
620d90144db52c7297879b950cbbc85137ed123ab5bChris Craik    // Layers only make sense if they are in the framebuffer's bounds
621d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    if (bounds.intersect(*currentClipRect())) {
622d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        // We cannot work with sub-pixels in this case
623d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        bounds.snapToPixelBoundaries();
624d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
625d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        // When the layer is not an FBO, we may use glCopyTexImage so we
626d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        // need to make sure the layer does not extend outside the bounds
627d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        // of the framebuffer
628924197513aa2df4c1fb2977c1727f5d2c21f2689Chris Craik        const Snapshot& previous = *(currentSnapshot()->previous);
629924197513aa2df4c1fb2977c1727f5d2c21f2689Chris Craik        Rect previousViewport(0, 0, previous.getViewportWidth(), previous.getViewportHeight());
630924197513aa2df4c1fb2977c1727f5d2c21f2689Chris Craik        if (!bounds.intersect(previousViewport)) {
631d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            bounds.setEmpty();
632d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        } else if (fboLayer) {
633d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            clip.set(bounds);
634d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            mat4 inverse;
635d6b65f67717025b1162f86f04e2caa5723566cacChris Craik            inverse.loadInverse(*currentTransform());
636d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            inverse.mapRect(clip);
637d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            clip.snapToPixelBoundaries();
638d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            if (clip.intersect(untransformedBounds)) {
639d90144db52c7297879b950cbbc85137ed123ab5bChris Craik                clip.translate(-untransformedBounds.left, -untransformedBounds.top);
640d90144db52c7297879b950cbbc85137ed123ab5bChris Craik                bounds.set(untransformedBounds);
641d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            } else {
642d90144db52c7297879b950cbbc85137ed123ab5bChris Craik                clip.setEmpty();
643d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            }
644d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        }
645d90144db52c7297879b950cbbc85137ed123ab5bChris Craik    } else {
646d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        bounds.setEmpty();
647d90144db52c7297879b950cbbc85137ed123ab5bChris Craik    }
648d90144db52c7297879b950cbbc85137ed123ab5bChris Craik}
649d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
650408eb12631376cbdc96803e918decf6ea804d346Chris Craikvoid OpenGLRenderer::updateSnapshotIgnoreForLayer(const Rect& bounds, const Rect& clip,
651408eb12631376cbdc96803e918decf6ea804d346Chris Craik        bool fboLayer, int alpha) {
652408eb12631376cbdc96803e918decf6ea804d346Chris Craik    if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
653408eb12631376cbdc96803e918decf6ea804d346Chris Craik            bounds.getHeight() > mCaches.maxTextureSize ||
654408eb12631376cbdc96803e918decf6ea804d346Chris Craik            (fboLayer && clip.isEmpty())) {
655408eb12631376cbdc96803e918decf6ea804d346Chris Craik        mSnapshot->empty = fboLayer;
656408eb12631376cbdc96803e918decf6ea804d346Chris Craik    } else {
65774cf7e6a25c6d7b331c231b7bc2512044f9d2950Chris Craik        mSnapshot->invisible = mSnapshot->invisible || (alpha <= 0 && fboLayer);
658408eb12631376cbdc96803e918decf6ea804d346Chris Craik    }
659408eb12631376cbdc96803e918decf6ea804d346Chris Craik}
660408eb12631376cbdc96803e918decf6ea804d346Chris Craik
661d90144db52c7297879b950cbbc85137ed123ab5bChris Craikint OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float bottom,
662d44fbe55a9f434cb5bb0e34c143ba1445141990dDerek Sollenberger        const SkPaint* paint, int flags) {
663d90144db52c7297879b950cbbc85137ed123ab5bChris Craik    const int count = saveSnapshot(flags);
664d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
665d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    if (!currentSnapshot()->isIgnored() && (flags & SkCanvas::kClipToLayer_SaveFlag)) {
666d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        // initialize the snapshot as though it almost represents an FBO layer so deferred draw
667d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        // operations will be able to store and restore the current clip and transform info, and
668d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        // quick rejection will be correct (for display lists)
669d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
670d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        Rect bounds(left, top, right, bottom);
671d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        Rect clip;
672d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        calculateLayerBoundsAndClip(bounds, clip, true);
673d44fbe55a9f434cb5bb0e34c143ba1445141990dDerek Sollenberger        updateSnapshotIgnoreForLayer(bounds, clip, true, getAlphaDirect(paint));
674d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
675d6b65f67717025b1162f86f04e2caa5723566cacChris Craik        if (!currentSnapshot()->isIgnored()) {
676d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
677d90144db52c7297879b950cbbc85137ed123ab5bChris Craik            mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
678a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik            mSnapshot->initializeViewport(bounds.getWidth(), bounds.getHeight());
679deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik            mSnapshot->roundRectClipState = NULL;
680d90144db52c7297879b950cbbc85137ed123ab5bChris Craik        }
681d90144db52c7297879b950cbbc85137ed123ab5bChris Craik    }
682d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
683d90144db52c7297879b950cbbc85137ed123ab5bChris Craik    return count;
684d90144db52c7297879b950cbbc85137ed123ab5bChris Craik}
685d90144db52c7297879b950cbbc85137ed123ab5bChris Craik
6861c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy/**
6871c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Layers are viewed by Skia are slightly different than layers in image editing
6881c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * programs (for instance.) When a layer is created, previously created layers
6891c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * and the frame buffer still receive every drawing command. For instance, if a
6901c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * layer is created and a shape intersecting the bounds of the layers and the
6911c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * framebuffer is draw, the shape will be drawn on both (unless the layer was
6921c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * created with the SkCanvas::kClipToLayer_SaveFlag flag.)
6931c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
6941c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * A way to implement layers is to create an FBO for each layer, backed by an RGBA
6951c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * texture. Unfortunately, this is inefficient as it requires every primitive to
6961c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * be drawn n + 1 times, where n is the number of active layers. In practice this
6971c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * means, for every primitive:
6981c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *   - Switch active frame buffer
6991c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *   - Change viewport, clip and projection matrix
7001c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *   - Issue the drawing
7011c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
7021c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Switching rendering target n + 1 times per drawn primitive is extremely costly.
7036b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * To avoid this, layers are implemented in a different way here, at least in the
7046b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * general case. FBOs are used, as an optimization, when the "clip to layer" flag
7056b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * is set. When this flag is set we can redirect all drawing operations into a
7066b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * single FBO.
7071c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
7081c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * This implementation relies on the frame buffer being at least RGBA 8888. When
7091c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * a layer is created, only a texture is created, not an FBO. The content of the
7101c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * frame buffer contained within the layer's bounds is copied into this texture
71187a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * using glCopyTexImage2D(). The layer's region is then cleared(1) in the frame
7121c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * buffer and drawing continues as normal. This technique therefore treats the
7131c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * frame buffer as a scratch buffer for the layers.
7141c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
7151c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * To compose the layers back onto the frame buffer, each layer texture
7161c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * (containing the original frame buffer data) is drawn as a simple quad over
7171c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * the frame buffer. The trick is that the quad is set as the composition
7181c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * destination in the blending equation, and the frame buffer becomes the source
7191c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * of the composition.
7201c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
7211c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Drawing layers with an alpha value requires an extra step before composition.
7221c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * An empty quad is drawn over the layer's region in the frame buffer. This quad
7231c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * is drawn with the rgba color (0,0,0,alpha). The alpha value offered by the
7241c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * quad is used to multiply the colors in the frame buffer. This is achieved by
7251c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * changing the GL blend functions for the GL_FUNC_ADD blend equation to
7261c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * GL_ZERO, GL_SRC_ALPHA.
7271c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
7281c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Because glCopyTexImage2D() can be slow, an alternative implementation might
7291c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * be use to draw a single clipped layer. The implementation described above
7301c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * is correct in every case.
73187a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy *
73287a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * (1) The frame buffer is actually not cleared right away. To allow the GPU
73387a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy *     to potentially optimize series of calls to glCopyTexImage2D, the frame
73487a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy *     buffer is left untouched until the first drawing operation. Only when
73587a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy *     something actually gets drawn are the layers regions cleared.
7361c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy */
737d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haasebool OpenGLRenderer::createLayer(float left, float top, float right, float bottom,
7383f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik        const SkPaint* paint, int flags, const SkPath* convexMask) {
739eb99356a0548684a501766e6a524529ab93304c8Romain Guy    LAYER_LOGD("Requesting layer %.2fx%.2f", right - left, bottom - top);
740fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize());
741dda570201ac851dd85af3861f7e575721d3345daRomain Guy
742eb99356a0548684a501766e6a524529ab93304c8Romain Guy    const bool fboLayer = flags & SkCanvas::kClipToLayer_SaveFlag;
743eb99356a0548684a501766e6a524529ab93304c8Romain Guy
744f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy    // Window coordinates of the layer
745d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    Rect clip;
7468aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy    Rect bounds(left, top, right, bottom);
747d90144db52c7297879b950cbbc85137ed123ab5bChris Craik    calculateLayerBoundsAndClip(bounds, clip, fboLayer);
748674554fc36932ca50b15bba41ac6f650254d4e72Derek Sollenberger    updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, getAlphaDirect(paint));
749dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy
750dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy    // Bail out if we won't draw in this snapshot
751d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    if (currentSnapshot()->isIgnored()) {
752b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy        return false;
753b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy    }
754dda570201ac851dd85af3861f7e575721d3345daRomain Guy
755a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy    mCaches.activeTexture(0);
7563b20251a355c88193c439f928a84ae69483fb488John Reck    Layer* layer = mCaches.layerCache.get(mRenderState, bounds.getWidth(), bounds.getHeight());
757f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy    if (!layer) {
758f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        return false;
759bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    }
760bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
761674554fc36932ca50b15bba41ac6f650254d4e72Derek Sollenberger    layer->setPaint(paint);
7628aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy    layer->layer.set(bounds);
7639ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy    layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
7649ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy            bounds.getWidth() / float(layer->getWidth()), 0.0f);
765d44fbe55a9f434cb5bb0e34c143ba1445141990dDerek Sollenberger
766a23eed808a1ae4ec0d818c0a9238385e797fd056Chet Haase    layer->setBlend(true);
7677c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy    layer->setDirty(false);
7683f085429fd47ebd32ac2463b3eae2a5a6c17be25Chris Craik    layer->setConvexMask(convexMask); // note: the mask must be cleared before returning to the cache
769dda570201ac851dd85af3861f7e575721d3345daRomain Guy
770