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