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>
2403d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy#include <SkPathMeasure.h>
25694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy#include <SkTypeface.h>
265cbbce535744b89df5ecea95de21ee3733298260Romain Guy
275cbbce535744b89df5ecea95de21ee3733298260Romain Guy#include <utils/Log.h>
28e2d345ea67e2960b37bfdc0fc8626d1bfa747404Romain Guy#include <utils/StopWatch.h>
2985bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy
3008aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy#include <private/hwui/DrawGlInfo.h>
3108aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy
325b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#include <ui/Rect.h>
335b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
3485bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include "OpenGLRenderer.h"
350fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy#include "DisplayListRenderer.h"
36710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik#include "PathRenderer.h"
3787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy#include "Properties.h"
38a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy#include "Vector.h"
39e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
40e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guynamespace android {
419d5316e3f56d138504565ff311145ac01621dff4Romain Guynamespace uirenderer {
429d5316e3f56d138504565ff311145ac01621dff4Romain Guy
439d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
449d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Defines
459d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
469d5316e3f56d138504565ff311145ac01621dff4Romain Guy
47759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy#define RAD_TO_DEG (180.0f / 3.14159265f)
48759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy#define MIN_ANGLE 0.001f
49759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy
50f877308f77f7c6f3edd91618a092207dd3be9077Romain Guy#define ALPHA_THRESHOLD 0
51dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy
52713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy#define FILTER(paint) (!paint || paint->isFilterBitmap() ? GL_LINEAR : GL_NEAREST)
53d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy
549d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
559d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Globals
569d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
579d5316e3f56d138504565ff311145ac01621dff4Romain Guy
58889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy/**
59889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy * Structure mapping Skia xfermodes to OpenGL blending factors.
60889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy */
61889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guystruct Blender {
62889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    SkXfermode::Mode mode;
63889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    GLenum src;
64889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    GLenum dst;
65889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy}; // struct Blender
66889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy
67026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy// In this array, the index of each Blender equals the value of the first
68026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
69026c5e16704e817cac7d9c382914c947e34f87e0Romain Guystatic const Blender gBlends[] = {
702ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kClear_Mode,    GL_ZERO,                GL_ONE_MINUS_SRC_ALPHA },
712ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrc_Mode,      GL_ONE,                 GL_ZERO },
722ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDst_Mode,      GL_ZERO,                GL_ONE },
732ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcOver_Mode,  GL_ONE,                 GL_ONE_MINUS_SRC_ALPHA },
742ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstOver_Mode,  GL_ONE_MINUS_DST_ALPHA, GL_ONE },
752ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcIn_Mode,    GL_DST_ALPHA,           GL_ZERO },
762ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstIn_Mode,    GL_ZERO,                GL_SRC_ALPHA },
772ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcOut_Mode,   GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
782ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstOut_Mode,   GL_ZERO,                GL_ONE_MINUS_SRC_ALPHA },
792ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcATop_Mode,  GL_DST_ALPHA,           GL_ONE_MINUS_SRC_ALPHA },
802ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstATop_Mode,  GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
812ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kXor_Mode,      GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
822ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kPlus_Mode,     GL_ONE,                 GL_ONE },
832ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kMultiply_Mode, GL_ZERO,                GL_SRC_COLOR },
842ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kScreen_Mode,   GL_ONE,                 GL_ONE_MINUS_SRC_COLOR }
85026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy};
86e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
8787a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy// This array contains the swapped version of each SkXfermode. For instance
8887a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy// this array's SrcOver blending mode is actually DstOver. You can refer to
8987a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy// createLayer() for more information on the purpose of this array.
90f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guystatic const Blender gBlendsSwap[] = {
912ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kClear_Mode,    GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
922ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrc_Mode,      GL_ZERO,                GL_ONE },
932ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDst_Mode,      GL_ONE,                 GL_ZERO },
942ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcOver_Mode,  GL_ONE_MINUS_DST_ALPHA, GL_ONE },
952ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstOver_Mode,  GL_ONE,                 GL_ONE_MINUS_SRC_ALPHA },
962ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcIn_Mode,    GL_ZERO,                GL_SRC_ALPHA },
972ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstIn_Mode,    GL_DST_ALPHA,           GL_ZERO },
982ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcOut_Mode,   GL_ZERO,                GL_ONE_MINUS_SRC_ALPHA },
992ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstOut_Mode,   GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
1002ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kSrcATop_Mode,  GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
1012ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kDstATop_Mode,  GL_DST_ALPHA,           GL_ONE_MINUS_SRC_ALPHA },
1022ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kXor_Mode,      GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
1032ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kPlus_Mode,     GL_ONE,                 GL_ONE },
1042ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kMultiply_Mode, GL_DST_COLOR,           GL_ZERO },
1052ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy    { SkXfermode::kScreen_Mode,   GL_ONE_MINUS_DST_COLOR, GL_ONE }
106f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy};
107f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy
108f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
109f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Constructors/destructor
110f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
111f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
112fb8b763f762ae21923c58d64caa729b012f40e05Romain GuyOpenGLRenderer::OpenGLRenderer(): mCaches(Caches::getInstance()) {
11306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    mShader = NULL;
114db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy    mColorFilter = NULL;
1151e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    mHasShadow = false;
1165ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy    mHasDrawFilter = false;
117026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
118ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
119ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
120ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy    mFirstSnapshot = new Snapshot;
12187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
12287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    mScissorOptimizationDisabled = false;
123e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
124e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
12585bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain GuyOpenGLRenderer::~OpenGLRenderer() {
12629d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy    // The context has already been destroyed at this point, do not call
12729d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy    // GL APIs. All GL state should be kept in Caches.h
128e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
129e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
13087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::initProperties() {
13187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    char property[PROPERTY_VALUE_MAX];
13287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    if (property_get(PROPERTY_DISABLE_SCISSOR_OPTIMIZATION, property, "false")) {
13387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mScissorOptimizationDisabled = !strcasecmp(property, "true");
13487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        INIT_LOGD("  Scissor optimization %s",
13587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy                mScissorOptimizationDisabled ? "disabled" : "enabled");
13687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    } else {
13787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        INIT_LOGD("  Scissor optimization enabled");
13887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    }
13913631f3da855f200a151e7837ed9f6b079622b58Romain Guy}
14013631f3da855f200a151e7837ed9f6b079622b58Romain Guy
14113631f3da855f200a151e7837ed9f6b079622b58Romain Guy///////////////////////////////////////////////////////////////////////////////
142f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Setup
143f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
144f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
14549c5fc0b9e850497233e189ff9dcc71a78ebe6e7Romain Guybool OpenGLRenderer::isDeferred() {
14649c5fc0b9e850497233e189ff9dcc71a78ebe6e7Romain Guy    return false;
14749c5fc0b9e850497233e189ff9dcc71a78ebe6e7Romain Guy}
14849c5fc0b9e850497233e189ff9dcc71a78ebe6e7Romain Guy
14985bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guyvoid OpenGLRenderer::setViewport(int width, int height) {
15035643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    initViewport(width, height);
15135643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy
15235643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    glDisable(GL_DITHER);
15335643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
15435643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy
15535643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    glEnableVertexAttribArray(Program::kBindingPosition);
15635643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy}
15735643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy
15835643ddc689913f5b5f80ceed864470d987bd6cdRomain Guyvoid OpenGLRenderer::initViewport(int width, int height) {
159260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy    mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
160bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
161bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    mWidth = width;
162bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    mHeight = height;
163eb99356a0548684a501766e6a524529ab93304c8Romain Guy
164eb99356a0548684a501766e6a524529ab93304c8Romain Guy    mFirstSnapshot->height = height;
165eb99356a0548684a501766e6a524529ab93304c8Romain Guy    mFirstSnapshot->viewport.set(0, 0, width, height);
166e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
167e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1687c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guystatus_t OpenGLRenderer::prepare(bool opaque) {
16944b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase    return prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque);
1707d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy}
1717d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy
1727c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guystatus_t OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom,
1737c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy        bool opaque) {
174fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy    mCaches.clearGarbage();
175fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy
1768aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy    mSnapshot = new Snapshot(mFirstSnapshot,
1778aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy            SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
17884962f2fe6ce779c583cc54b11a9de2b6a568117Romain Guy    mSnapshot->fbo = getTargetFbo();
1798fb954263dd2f918ad339045cc6d82e346515599Romain Guy    mSaveCount = 1;
180f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
1817d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy    mSnapshot->setClip(left, top, right, bottom);
18241308e2936c768103d0e9c82500e97938d6797f1Romain Guy    mDirtyClip = true;
183ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy
18411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    updateLayers();
18511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
18645e4c3df6c00ac98ff6144de9af574877d4fff19Romain Guy    // If we know that we are going to redraw the entire framebuffer,
18745e4c3df6c00ac98ff6144de9af574877d4fff19Romain Guy    // perform a discard to let the driver know we don't need to preserve
18845e4c3df6c00ac98ff6144de9af574877d4fff19Romain Guy    // the back buffer for this frame.
18945e4c3df6c00ac98ff6144de9af574877d4fff19Romain Guy    if (mCaches.extensions.hasDiscardFramebuffer() &&
19045e4c3df6c00ac98ff6144de9af574877d4fff19Romain Guy            left <= 0.0f && top <= 0.0f && right >= mWidth && bottom >= mHeight) {
19145e4c3df6c00ac98ff6144de9af574877d4fff19Romain Guy        const GLenum attachments[] = { getTargetFbo() == 0 ? GL_COLOR_EXT : GL_COLOR_ATTACHMENT0 };
19245e4c3df6c00ac98ff6144de9af574877d4fff19Romain Guy        glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments);
19345e4c3df6c00ac98ff6144de9af574877d4fff19Romain Guy    }
19445e4c3df6c00ac98ff6144de9af574877d4fff19Romain Guy
195ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy    syncState();
1967d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy
19754c1a64d5441a964890b44280e4457e11f4f924aRomain Guy    // Functors break the tiling extension in pretty spectacular ways
19854c1a64d5441a964890b44280e4457e11f4f924aRomain Guy    // This ensures we don't use tiling when a functor is going to be
19954c1a64d5441a964890b44280e4457e11f4f924aRomain Guy    // invoked during the frame
20054c1a64d5441a964890b44280e4457e11f4f924aRomain Guy    mSuppressTiling = mCaches.hasRegisteredFunctors();
20154c1a64d5441a964890b44280e4457e11f4f924aRomain Guy
2022b7028eabac80cec170572bc0e945a1d4224e595Romain Guy    mTilingSnapshot = mSnapshot;
20357b5268708c3b974296c7d4e58a02a957979224aRomain Guy    startTiling(mTilingSnapshot, true);
2042b7028eabac80cec170572bc0e945a1d4224e595Romain Guy
2057c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    debugOverdraw(true, true);
2067c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy
2077c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy    return clear(left, top, right, bottom, opaque);
2087c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy}
2097c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy
2107c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guystatus_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
2116b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy    if (!opaque) {
212586cae3ac69c0c667fbf8a954edbd399f620a717Romain Guy        mCaches.enableScissor();
213ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy        mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
2146b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy        glClear(GL_COLOR_BUFFER_BIT);
21544b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase        return DrawGlInfo::kStatusDrew;
216ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy    }
21744b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase
2187c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy    mCaches.resetScissor();
21944b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase    return DrawGlInfo::kStatusDone;
220ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy}
221ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy
222ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guyvoid OpenGLRenderer::syncState() {
223ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy    glViewport(0, 0, mWidth, mHeight);
224ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy
225ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy    if (mCaches.blend) {
226ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy        glEnable(GL_BLEND);
227ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy    } else {
228ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy        glDisable(GL_BLEND);
2296b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy    }
230bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
231bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
23257b5268708c3b974296c7d4e58a02a957979224aRomain Guyvoid OpenGLRenderer::startTiling(const sp<Snapshot>& s, bool opaque) {
23354c1a64d5441a964890b44280e4457e11f4f924aRomain Guy    if (!mSuppressTiling) {
23454c1a64d5441a964890b44280e4457e11f4f924aRomain Guy        Rect* clip = mTilingSnapshot->clipRect;
23554c1a64d5441a964890b44280e4457e11f4f924aRomain Guy        if (s->flags & Snapshot::kFlagIsFboLayer) {
23654c1a64d5441a964890b44280e4457e11f4f924aRomain Guy            clip = s->clipRect;
23754c1a64d5441a964890b44280e4457e11f4f924aRomain Guy        }
23854c1a64d5441a964890b44280e4457e11f4f924aRomain Guy
23954c1a64d5441a964890b44280e4457e11f4f924aRomain Guy        mCaches.startTiling(clip->left, s->height - clip->bottom,
24054c1a64d5441a964890b44280e4457e11f4f924aRomain Guy                clip->right - clip->left, clip->bottom - clip->top, opaque);
2412b7028eabac80cec170572bc0e945a1d4224e595Romain Guy    }
2422b7028eabac80cec170572bc0e945a1d4224e595Romain Guy}
2432b7028eabac80cec170572bc0e945a1d4224e595Romain Guy
2442b7028eabac80cec170572bc0e945a1d4224e595Romain Guyvoid OpenGLRenderer::endTiling() {
24554c1a64d5441a964890b44280e4457e11f4f924aRomain Guy    if (!mSuppressTiling) mCaches.endTiling();
2462b7028eabac80cec170572bc0e945a1d4224e595Romain Guy}
2472b7028eabac80cec170572bc0e945a1d4224e595Romain Guy
248b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guyvoid OpenGLRenderer::finish() {
2497c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    renderOverdraw();
2502b7028eabac80cec170572bc0e945a1d4224e595Romain Guy    endTiling();
2512b7028eabac80cec170572bc0e945a1d4224e595Romain Guy
25211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    if (!suppressErrorChecks()) {
253b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy#if DEBUG_OPENGL
25411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        GLenum status = GL_NO_ERROR;
25511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        while ((status = glGetError()) != GL_NO_ERROR) {
25611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            ALOGD("GL error from OpenGLRenderer: 0x%x", status);
25711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            switch (status) {
25811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy                case GL_INVALID_ENUM:
25911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy                    ALOGE("  GL_INVALID_ENUM");
26011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy                    break;
26111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy                case GL_INVALID_VALUE:
26211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy                    ALOGE("  GL_INVALID_VALUE");
26311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy                    break;
26411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy                case GL_INVALID_OPERATION:
26511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy                    ALOGE("  GL_INVALID_OPERATION");
26611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy                    break;
26711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy                case GL_OUT_OF_MEMORY:
26811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy                    ALOGE("  Out of memory!");
26911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy                    break;
27011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            }
271a07105b7d2a27e6d69407bf96ddb773bddb5e553Romain Guy        }
272b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy#endif
27311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
274c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#if DEBUG_MEMORY_USAGE
275e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy        mCaches.dumpMemoryUsage();
27611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy#else
27711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        if (mCaches.getDebugLevel() & kDebugMemory) {
27811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            mCaches.dumpMemoryUsage();
27911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        }
280c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#endif
28111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
282b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy}
283b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy
2846c319ca1275c8db892c39b48fc54864c949f9171Romain Guyvoid OpenGLRenderer::interrupt() {
285da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy    if (mCaches.currentProgram) {
286da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy        if (mCaches.currentProgram->isInUse()) {
287da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy            mCaches.currentProgram->remove();
288da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy            mCaches.currentProgram = NULL;
289da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy        }
290da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy    }
29150c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy    mCaches.unbindMeshBuffer();
29215bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy    mCaches.unbindIndicesBuffer();
293f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    mCaches.resetVertexPointers();
29415bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy    mCaches.disbaleTexCoordsVertexArray();
2957c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    debugOverdraw(false, false);
296da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy}
297da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy
2986c319ca1275c8db892c39b48fc54864c949f9171Romain Guyvoid OpenGLRenderer::resume() {
29908837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase    sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
30008837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase    glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
30135643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
3027c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    debugOverdraw(true, false);
30335643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy
3043e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3053e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy
3068025061c594e5171e1bf370d8fdd77e0e9a02b47Chet Haase    mCaches.scissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
307586cae3ac69c0c667fbf8a954edbd399f620a717Romain Guy    mCaches.enableScissor();
30882bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy    mCaches.resetScissor();
309746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy    dirtyClip();
310da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy
311a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy    mCaches.activeTexture(0);
31250c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy
31350c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy    mCaches.blend = true;
31450c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy    glEnable(GL_BLEND);
31550c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy    glBlendFunc(mCaches.lastSrcMode, mCaches.lastDstMode);
31650c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy    glBlendEquation(GL_FUNC_ADD);
317da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy}
318da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy
31935643ddc689913f5b5f80ceed864470d987bd6cdRomain Guyvoid OpenGLRenderer::resumeAfterLayer() {
32035643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
32135643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
32235643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
3237c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    debugOverdraw(true, false);
32435643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy
32535643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    mCaches.resetScissor();
32635643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy    dirtyClip();
32735643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy}
32835643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy
329ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guyvoid OpenGLRenderer::detachFunctor(Functor* functor) {
330932b7f6765968bd526c03512f3805fbc3924dc29Chris Craik    mFunctors.remove(functor);
331ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy}
3328f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
333ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guyvoid OpenGLRenderer::attachFunctor(Functor* functor) {
334ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy    mFunctors.add(functor);
335ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy}
3368f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
337ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guystatus_t OpenGLRenderer::invokeFunctors(Rect& dirty) {
338ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy    status_t result = DrawGlInfo::kStatusDone;
3393d745c03ace18ee59c539e1b7f1df13f22beb57dRomain Guy    size_t count = mFunctors.size();
3408f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
341ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy    if (count > 0) {
342ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        SortedVector<Functor*> functors(mFunctors);
343ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        mFunctors.clear();
344ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy
345ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        DrawGlInfo info;
346ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        info.clipLeft = 0;
347ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        info.clipTop = 0;
348ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        info.clipRight = 0;
349ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        info.clipBottom = 0;
350ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        info.isLayer = false;
351ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        info.width = 0;
352ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        info.height = 0;
353ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        memset(info.transform, 0, sizeof(float) * 16);
354ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy
355ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        for (size_t i = 0; i < count; i++) {
356ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy            Functor* f = functors.itemAt(i);
357ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy            result |= (*f)(DrawGlInfo::kModeProcess, &info);
358ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy
359c2c9543c135ffc4e18c7db0e817112ac03e3e97aChris Craik            if (result & DrawGlInfo::kStatusDraw) {
360ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy                Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
361ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy                dirty.unionWith(localDirty);
362c2c9543c135ffc4e18c7db0e817112ac03e3e97aChris Craik            }
363ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy
364c2c9543c135ffc4e18c7db0e817112ac03e3e97aChris Craik            if (result & DrawGlInfo::kStatusInvoke) {
365c2c9543c135ffc4e18c7db0e817112ac03e3e97aChris Craik                mFunctors.add(f);
3668f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy            }
3678f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy        }
368beb8bd0db28d8c5cad2a258f2ba2f3b8b76cf037Chet Haase        // protect against functors binding to other buffers
369beb8bd0db28d8c5cad2a258f2ba2f3b8b76cf037Chet Haase        mCaches.unbindMeshBuffer();
370beb8bd0db28d8c5cad2a258f2ba2f3b8b76cf037Chet Haase        mCaches.unbindIndicesBuffer();
371beb8bd0db28d8c5cad2a258f2ba2f3b8b76cf037Chet Haase        mCaches.activeTexture(0);
3728f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy    }
3738f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
3748f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy    return result;
3758f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy}
3768f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
3778f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guystatus_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
378daf98e941e140e8739458126640183b9f296a2abChet Haase    interrupt();
379932b7f6765968bd526c03512f3805fbc3924dc29Chris Craik    detachFunctor(functor);
380c8538ade8df2c2f013f8b93094912057ee1cc417Chris Craik
3818a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy    mCaches.enableScissor();
382f90f8171e6acb56f9f87093c01fd586f2140697aRomain Guy    if (mDirtyClip) {
383f90f8171e6acb56f9f87093c01fd586f2140697aRomain Guy        setScissorFromClip();
384f90f8171e6acb56f9f87093c01fd586f2140697aRomain Guy    }
385d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy
38680911b851764b073310fd0bffdf4a7db0d8fdd0bRomain Guy    Rect clip(*mSnapshot->clipRect);
38780911b851764b073310fd0bffdf4a7db0d8fdd0bRomain Guy    clip.snapToPixelBoundaries();
38880911b851764b073310fd0bffdf4a7db0d8fdd0bRomain Guy
389d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy    // Since we don't know what the functor will draw, let's dirty
390d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy    // tne entire clip region
391d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy    if (hasLayer()) {
392d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy        dirtyLayerUnchecked(clip, getRegion());
393d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy    }
394d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy
39508aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    DrawGlInfo info;
39608aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.clipLeft = clip.left;
39708aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.clipTop = clip.top;
39808aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.clipRight = clip.right;
39908aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.clipBottom = clip.bottom;
40008aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    info.isLayer = hasLayer();
4017b6a75872bd2df96a23453d31c2e2e7fcc373554Chet Haase    info.width = getSnapshot()->viewport.getWidth();
4027b6a75872bd2df96a23453d31c2e2e7fcc373554Chet Haase    info.height = getSnapshot()->height;
40308aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy    getSnapshot()->transform->copyTo(&info.transform[0]);
40480911b851764b073310fd0bffdf4a7db0d8fdd0bRomain Guy
405486590963e2207d68eebd6944fec70d50d41116aChet Haase    status_t result = (*functor)(DrawGlInfo::kModeDraw, &info) | DrawGlInfo::kStatusDrew;
406cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy
4078f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy    if (result != DrawGlInfo::kStatusDone) {
40808aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy        Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
409cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy        dirty.unionWith(localDirty);
4108f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
41165924a3e56c2e7ac863f8e25e9f9a58b9db7d513Chris Craik        if (result & DrawGlInfo::kStatusInvoke) {
412ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy            mFunctors.add(functor);
4138f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy        }
414cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy    }
415cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy
416daf98e941e140e8739458126640183b9f296a2abChet Haase    resume();
4176554943a1dd6854c0f4976900956e556767b49e1Romain Guy    return result;
418daf98e941e140e8739458126640183b9f296a2abChet Haase}
419daf98e941e140e8739458126640183b9f296a2abChet Haase
420f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
42187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy// Debug
42287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy///////////////////////////////////////////////////////////////////////////////
42387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
42487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::startMark(const char* name) const {
42587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    mCaches.startMark(0, name);
42687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy}
42787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
42887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::endMark() const {
42987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    mCaches.endMark();
43087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy}
43187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
43287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::debugOverdraw(bool enable, bool clear) {
43387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    if (mCaches.debugOverdraw && getTargetFbo() == 0) {
43487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        if (clear) {
43587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy            mCaches.disableScissor();
43687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy            mCaches.stencil.clear();
43787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        }
43887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        if (enable) {
43987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy            mCaches.stencil.enableDebugWrite();
44087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        } else {
44187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy            mCaches.stencil.disable();
44287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        }
44387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    }
44487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy}
44587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
44687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::renderOverdraw() {
44787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    if (mCaches.debugOverdraw && getTargetFbo() == 0) {
44887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        const Rect* clip = mTilingSnapshot->clipRect;
44987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
45087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mCaches.enableScissor();
45187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mCaches.setScissor(clip->left, mTilingSnapshot->height - clip->bottom,
45287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy                clip->right - clip->left, clip->bottom - clip->top);
45387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
45487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mCaches.stencil.enableDebugTest(2);
45587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        drawColor(0x2f0000ff, SkXfermode::kSrcOver_Mode);
45687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mCaches.stencil.enableDebugTest(3);
45787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        drawColor(0x2f00ff00, SkXfermode::kSrcOver_Mode);
45887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mCaches.stencil.enableDebugTest(4);
45987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        drawColor(0x3fff0000, SkXfermode::kSrcOver_Mode);
46087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mCaches.stencil.enableDebugTest(4, true);
46187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        drawColor(0x7fff0000, SkXfermode::kSrcOver_Mode);
46287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy        mCaches.stencil.disable();
46387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy    }
46487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy}
46587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy
46687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy///////////////////////////////////////////////////////////////////////////////
46711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy// Layers
46811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy///////////////////////////////////////////////////////////////////////////////
46911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
47011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guybool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
47111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) {
47211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        OpenGLRenderer* renderer = layer->renderer;
47311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        Rect& dirty = layer->dirtyRect;
47411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
4757c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy        if (inFrame) {
4767c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy            endTiling();
4777c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy            debugOverdraw(false, false);
4787c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy        }
47911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
48011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight());
48111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, !layer->isBlend());
48211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        renderer->drawDisplayList(layer->displayList, dirty, DisplayList::kReplayFlag_ClipChildren);
48311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        renderer->finish();
48411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
48511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        if (inFrame) {
48611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            resumeAfterLayer();
48711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            startTiling(mSnapshot);
48811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        }
48911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
49011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        dirty.setEmpty();
49111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        layer->deferredUpdateScheduled = false;
49211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        layer->renderer = NULL;
49311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        layer->displayList = NULL;
49411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
49511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        return true;
49611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
49711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
49811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    return false;
49911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy}
50011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
50111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guyvoid OpenGLRenderer::updateLayers() {
50211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    int count = mLayerUpdates.size();
50311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    if (count > 0) {
50411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        startMark("Layer Updates");
50511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
50611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        // Note: it is very important to update the layers in reverse order
50711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        for (int i = count - 1; i >= 0; i--) {
50811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            Layer* layer = mLayerUpdates.itemAt(i);
50911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            updateLayer(layer, false);
51011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            mCaches.resourceCache.decrementRefcount(layer);
51111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        }
51211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        mLayerUpdates.clear();
51311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
51411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
51511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        endMark();
51611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
51711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy}
51811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
51911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guyvoid OpenGLRenderer::pushLayerUpdate(Layer* layer) {
52011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    if (layer) {
52111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        mLayerUpdates.push_back(layer);
52211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        mCaches.resourceCache.incrementRefcount(layer);
52311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
52411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy}
52511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
52611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guyvoid OpenGLRenderer::clearLayerUpdates() {
52711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    size_t count = mLayerUpdates.size();
52811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    if (count > 0) {
52911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        mCaches.resourceCache.lock();
53011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        for (size_t i = 0; i < count; i++) {
53111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            mCaches.resourceCache.decrementRefcountLocked(mLayerUpdates.itemAt(i));
53211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        }
53311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        mCaches.resourceCache.unlock();
53411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        mLayerUpdates.clear();
53511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
53611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy}
53711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
53811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy///////////////////////////////////////////////////////////////////////////////
539f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// State management
540f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
541f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
542bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyint OpenGLRenderer::getSaveCount() const {
5437ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return mSaveCount;
544bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
545bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
546bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyint OpenGLRenderer::save(int flags) {
5478aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy    return saveSnapshot(flags);
548bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
549bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
550bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid OpenGLRenderer::restore() {
5512542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy    if (mSaveCount > 1) {
5522542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy        restoreSnapshot();
5537ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
554bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
555bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
556bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid OpenGLRenderer::restoreToCount(int saveCount) {
5578fb954263dd2f918ad339045cc6d82e346515599Romain Guy    if (saveCount < 1) saveCount = 1;
558bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
5598fb954263dd2f918ad339045cc6d82e346515599Romain Guy    while (mSaveCount > saveCount) {
5602542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy        restoreSnapshot();
5617ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
562bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
563bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
5648aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guyint OpenGLRenderer::saveSnapshot(int flags) {
5658aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy    mSnapshot = new Snapshot(mSnapshot, flags);
5668fb954263dd2f918ad339045cc6d82e346515599Romain Guy    return mSaveCount++;
567bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
568bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
569bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guybool OpenGLRenderer::restoreSnapshot() {
5707ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet;
571bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    bool restoreLayer = mSnapshot->flags & Snapshot::kFlagIsLayer;
572eb99356a0548684a501766e6a524529ab93304c8Romain Guy    bool restoreOrtho = mSnapshot->flags & Snapshot::kFlagDirtyOrtho;
573bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
574bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    sp<Snapshot> current = mSnapshot;
5757ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    sp<Snapshot> previous = mSnapshot->previous;
576bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
577eb99356a0548684a501766e6a524529ab93304c8Romain Guy    if (restoreOrtho) {
578eb99356a0548684a501766e6a524529ab93304c8Romain Guy        Rect& r = previous->viewport;
579eb99356a0548684a501766e6a524529ab93304c8Romain Guy        glViewport(r.left, r.top, r.right, r.bottom);
580eb99356a0548684a501766e6a524529ab93304c8Romain Guy        mOrthoMatrix.load(current->orthoMatrix);
581eb99356a0548684a501766e6a524529ab93304c8Romain Guy    }
582eb99356a0548684a501766e6a524529ab93304c8Romain Guy
5838b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy    mSaveCount--;
5848b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy    mSnapshot = previous;
5858b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy
5862542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy    if (restoreClip) {
587746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy        dirtyClip();
5888fb954263dd2f918ad339045cc6d82e346515599Romain Guy    }
5892542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy
5905ec9924d24495822b589f1a17996655d66273b30Romain Guy    if (restoreLayer) {
5915ec9924d24495822b589f1a17996655d66273b30Romain Guy        composeLayer(current, previous);
5925ec9924d24495822b589f1a17996655d66273b30Romain Guy    }
5935ec9924d24495822b589f1a17996655d66273b30Romain Guy
5942542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy    return restoreClip;
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,
6025c13d89c1332fcc499379b9064b891187b75ca32Chet Haase        SkPaint* p, int flags) {
603eb99356a0548684a501766e6a524529ab93304c8Romain Guy    const GLuint previousFbo = mSnapshot->fbo;
604eb99356a0548684a501766e6a524529ab93304c8Romain Guy    const int count = saveSnapshot(flags);
605d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
606af636ebf5feb2837683fbfe965040cb706b32ec1Romain Guy    if (!mSnapshot->isIgnored()) {
607e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy        int alpha = 255;
608e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy        SkXfermode::Mode mode;
609e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy
610e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy        if (p) {
611e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy            alpha = p->getAlpha();
612710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik            mode = getXfermode(p->getXfermode());
613a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy        } else {
614e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy            mode = SkXfermode::kSrcOver_Mode;
615d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy        }
616d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
617d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase        createLayer(left, top, right, bottom, alpha, mode, flags, previousFbo);
618dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy    }
619d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
620d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    return count;
621bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy}
622bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
623bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyint OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
624bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        int alpha, int flags) {
625f877308f77f7c6f3edd91618a092207dd3be9077Romain Guy    if (alpha >= 255) {
6268aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy        return saveLayer(left, top, right, bottom, NULL, flags);
6278b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy    } else {
6288aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy        SkPaint paint;
6298aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy        paint.setAlpha(alpha);
6308aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy        return saveLayer(left, top, right, bottom, &paint, flags);
6318b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy    }
632d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy}
633bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
6341c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy/**
6351c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Layers are viewed by Skia are slightly different than layers in image editing
6361c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * programs (for instance.) When a layer is created, previously created layers
6371c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * and the frame buffer still receive every drawing command. For instance, if a
6381c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * layer is created and a shape intersecting the bounds of the layers and the
6391c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * framebuffer is draw, the shape will be drawn on both (unless the layer was
6401c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * created with the SkCanvas::kClipToLayer_SaveFlag flag.)
6411c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
6421c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * A way to implement layers is to create an FBO for each layer, backed by an RGBA
6431c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * texture. Unfortunately, this is inefficient as it requires every primitive to
6441c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * be drawn n + 1 times, where n is the number of active layers. In practice this
6451c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * means, for every primitive:
6461c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *   - Switch active frame buffer
6471c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *   - Change viewport, clip and projection matrix
6481c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *   - Issue the drawing
6491c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
6501c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Switching rendering target n + 1 times per drawn primitive is extremely costly.
6516b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * To avoid this, layers are implemented in a different way here, at least in the
6526b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * general case. FBOs are used, as an optimization, when the "clip to layer" flag
6536b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * is set. When this flag is set we can redirect all drawing operations into a
6546b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * single FBO.
6551c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
6561c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * This implementation relies on the frame buffer being at least RGBA 8888. When
6571c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * a layer is created, only a texture is created, not an FBO. The content of the
6581c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * frame buffer contained within the layer's bounds is copied into this texture
65987a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * using glCopyTexImage2D(). The layer's region is then cleared(1) in the frame
6601c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * buffer and drawing continues as normal. This technique therefore treats the
6611c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * frame buffer as a scratch buffer for the layers.
6621c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
6631c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * To compose the layers back onto the frame buffer, each layer texture
6641c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * (containing the original frame buffer data) is drawn as a simple quad over
6651c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * the frame buffer. The trick is that the quad is set as the composition
6661c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * destination in the blending equation, and the frame buffer becomes the source
6671c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * of the composition.
6681c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
6691c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Drawing layers with an alpha value requires an extra step before composition.
6701c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * An empty quad is drawn over the layer's region in the frame buffer. This quad
6711c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * is drawn with the rgba color (0,0,0,alpha). The alpha value offered by the
6721c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * quad is used to multiply the colors in the frame buffer. This is achieved by
6731c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * changing the GL blend functions for the GL_FUNC_ADD blend equation to
6741c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * GL_ZERO, GL_SRC_ALPHA.
6751c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy *
6761c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Because glCopyTexImage2D() can be slow, an alternative implementation might
6771c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * be use to draw a single clipped layer. The implementation described above
6781c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * is correct in every case.
67987a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy *
68087a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * (1) The frame buffer is actually not cleared right away. To allow the GPU
68187a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy *     to potentially optimize series of calls to glCopyTexImage2D, the frame
68287a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy *     buffer is left untouched until the first drawing operation. Only when
68387a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy *     something actually gets drawn are the layers regions cleared.
6841c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy */
685d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haasebool OpenGLRenderer::createLayer(float left, float top, float right, float bottom,
686d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase        int alpha, SkXfermode::Mode mode, int flags, GLuint previousFbo) {
687eb99356a0548684a501766e6a524529ab93304c8Romain Guy    LAYER_LOGD("Requesting layer %.2fx%.2f", right - left, bottom - top);
688fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize());
689dda570201ac851dd85af3861f7e575721d3345daRomain Guy
690eb99356a0548684a501766e6a524529ab93304c8Romain Guy    const bool fboLayer = flags & SkCanvas::kClipToLayer_SaveFlag;
691eb99356a0548684a501766e6a524529ab93304c8Romain Guy
692f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy    // Window coordinates of the layer
693d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    Rect clip;
6948aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy    Rect bounds(left, top, right, bottom);
695d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    Rect untransformedBounds(bounds);
696d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    mSnapshot->transform->mapRect(bounds);
697d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase
698d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    // Layers only make sense if they are in the framebuffer's bounds
699d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    if (bounds.intersect(*mSnapshot->clipRect)) {
700d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase        // We cannot work with sub-pixels in this case
701d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase        bounds.snapToPixelBoundaries();
702d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase
703d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase        // When the layer is not an FBO, we may use glCopyTexImage so we
704d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase        // need to make sure the layer does not extend outside the bounds
705d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase        // of the framebuffer
706d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase        if (!bounds.intersect(mSnapshot->previous->viewport)) {
707ad37cd3b5d3de9dd0858af04fbccd102e8ff4b0eRomain Guy            bounds.setEmpty();
708d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase        } else if (fboLayer) {
709d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase            clip.set(bounds);
710d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase            mat4 inverse;
711d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase            inverse.loadInverse(*mSnapshot->transform);
712d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase            inverse.mapRect(clip);
713d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase            clip.snapToPixelBoundaries();
714d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase            if (clip.intersect(untransformedBounds)) {
715d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase                clip.translate(-left, -top);
716d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase                bounds.set(untransformedBounds);
717d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase            } else {
718d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase                clip.setEmpty();
719d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase            }
720ad37cd3b5d3de9dd0858af04fbccd102e8ff4b0eRomain Guy        }
721d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    } else {
722d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase        bounds.setEmpty();
723eb99356a0548684a501766e6a524529ab93304c8Romain Guy    }
724bf434114cbf55b216fdc76fc8d65a75e84c9dab5Romain Guy
725746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy    if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
726d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase            bounds.getHeight() > mCaches.maxTextureSize ||
727d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase            (fboLayer && clip.isEmpty())) {
728d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase        mSnapshot->empty = fboLayer;
729dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy    } else {
730d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase        mSnapshot->invisible = mSnapshot->invisible || (alpha <= ALPHA_THRESHOLD && fboLayer);
731dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy    }
732dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy
733dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy    // Bail out if we won't draw in this snapshot
734d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    if (mSnapshot->invisible || mSnapshot->empty) {
735b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy        return false;
736b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy    }
737dda570201ac851dd85af3861f7e575721d3345daRomain Guy
738a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy    mCaches.activeTexture(0);
7398550c4c7b5952b7a4e1e0ede95c9492d03099a13Romain Guy    Layer* layer = mCaches.layerCache.get(bounds.getWidth(), bounds.getHeight());
740f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy    if (!layer) {
741f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        return false;
742bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    }
743bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
7449ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy    layer->setAlpha(alpha, mode);
7458aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy    layer->layer.set(bounds);
7469ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy    layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
7479ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy            bounds.getWidth() / float(layer->getWidth()), 0.0f);
7489ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy    layer->setColorFilter(mColorFilter);
749a23eed808a1ae4ec0d818c0a9238385e797fd056Chet Haase    layer->setBlend(true);
7507c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy    layer->setDirty(false);
751dda570201ac851dd85af3861f7e575721d3345daRomain Guy
7528fb954263dd2f918ad339045cc6d82e346515599Romain Guy    // Save the layer in the snapshot
753d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    mSnapshot->flags |= Snapshot::kFlagIsLayer;
754d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    mSnapshot->layer = layer;
7551d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy
756eb99356a0548684a501766e6a524529ab93304c8Romain Guy    if (fboLayer) {
757d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase        return createFboLayer(layer, bounds, clip, previousFbo);
758eb99356a0548684a501766e6a524529ab93304c8Romain Guy    } else {
759eb99356a0548684a501766e6a524529ab93304c8Romain Guy        // Copy the framebuffer into the layer
7609ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy        layer->bindTexture();
761514fb18827186591d66973c2362c859b64b63556Romain Guy        if (!bounds.isEmpty()) {
7629ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy            if (layer->isEmpty()) {
7639ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy                glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
764d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase                        bounds.left, mSnapshot->height - bounds.bottom,
7659ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy                        layer->getWidth(), layer->getHeight(), 0);
7669ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy                layer->setEmpty(false);
767514fb18827186591d66973c2362c859b64b63556Romain Guy            } else {
768514fb18827186591d66973c2362c859b64b63556Romain Guy                glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left,
769d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase                        mSnapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight());
770514fb18827186591d66973c2362c859b64b63556Romain Guy            }
7717b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy
77254be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy            // Enqueue the buffer coordinates to clear the corresponding region later
77354be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy            mLayers.push(new Rect(bounds));
774ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy        }
775eb99356a0548684a501766e6a524529ab93304c8Romain Guy    }
776f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
777d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    return true;
778bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy}
779bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
780d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haasebool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip, GLuint previousFbo) {
7819ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy    layer->setFbo(mCaches.fboCache.get());
7825b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
783d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    mSnapshot->region = &mSnapshot->layer->region;
784d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    mSnapshot->flags |= Snapshot::kFlagFboTarget;
785d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase
786d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    mSnapshot->flags |= Snapshot::kFlagIsFboLayer;
787d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase    mSnapshot->fbo = layer->getFbo();
788