OpenGLRenderer.cpp revision 408eb12631376cbdc96803e918decf6ea804d346
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" 35c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#include "DeferredDisplayList.h" 360fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy#include "DisplayListRenderer.h" 3765cd612face362d054a85d0f7e5881c59cd523beChris Craik#include "PathTessellator.h" 3887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy#include "Properties.h" 39a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy#include "Vector.h" 40e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 41e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guynamespace android { 429d5316e3f56d138504565ff311145ac01621dff4Romain Guynamespace uirenderer { 439d5316e3f56d138504565ff311145ac01621dff4Romain Guy 449d5316e3f56d138504565ff311145ac01621dff4Romain Guy/////////////////////////////////////////////////////////////////////////////// 459d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Defines 469d5316e3f56d138504565ff311145ac01621dff4Romain Guy/////////////////////////////////////////////////////////////////////////////// 479d5316e3f56d138504565ff311145ac01621dff4Romain Guy 48759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy#define RAD_TO_DEG (180.0f / 3.14159265f) 49759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy#define MIN_ANGLE 0.001f 50759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy 51f877308f77f7c6f3edd91618a092207dd3be9077Romain Guy#define ALPHA_THRESHOLD 0 52dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy 53713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy#define FILTER(paint) (!paint || paint->isFilterBitmap() ? GL_LINEAR : GL_NEAREST) 54d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy 559d5316e3f56d138504565ff311145ac01621dff4Romain Guy/////////////////////////////////////////////////////////////////////////////// 569d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Globals 579d5316e3f56d138504565ff311145ac01621dff4Romain Guy/////////////////////////////////////////////////////////////////////////////// 589d5316e3f56d138504565ff311145ac01621dff4Romain Guy 59889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy/** 60889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy * Structure mapping Skia xfermodes to OpenGL blending factors. 61889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy */ 62889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guystruct Blender { 63889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy SkXfermode::Mode mode; 64889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy GLenum src; 65889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy GLenum dst; 66889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy}; // struct Blender 67889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy 68026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy// In this array, the index of each Blender equals the value of the first 69026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode] 70026c5e16704e817cac7d9c382914c947e34f87e0Romain Guystatic const Blender gBlends[] = { 712ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kClear_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, 722ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO }, 732ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kDst_Mode, GL_ZERO, GL_ONE }, 742ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, 752ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE }, 762ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kSrcIn_Mode, GL_DST_ALPHA, GL_ZERO }, 772ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kDstIn_Mode, GL_ZERO, GL_SRC_ALPHA }, 782ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kSrcOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, 792ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kDstOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, 802ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, 812ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA }, 822ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, 832ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kPlus_Mode, GL_ONE, GL_ONE }, 84d81ec456bb097a712bcbc093c5a1e0075434158eDerek Sollenberger { SkXfermode::kModulate_Mode, GL_ZERO, GL_SRC_COLOR }, 852ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kScreen_Mode, GL_ONE, GL_ONE_MINUS_SRC_COLOR } 86026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy}; 87e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 8887a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy// This array contains the swapped version of each SkXfermode. For instance 8987a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy// this array's SrcOver blending mode is actually DstOver. You can refer to 9087a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy// createLayer() for more information on the purpose of this array. 91f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guystatic const Blender gBlendsSwap[] = { 922ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kClear_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, 932ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kSrc_Mode, GL_ZERO, GL_ONE }, 942ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kDst_Mode, GL_ONE, GL_ZERO }, 952ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kSrcOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE }, 962ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kDstOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, 972ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kSrcIn_Mode, GL_ZERO, GL_SRC_ALPHA }, 982ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kDstIn_Mode, GL_DST_ALPHA, GL_ZERO }, 992ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kSrcOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, 1002ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kDstOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, 1012ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kSrcATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA }, 1022ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kDstATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, 1032ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, 1042ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kPlus_Mode, GL_ONE, GL_ONE }, 105d81ec456bb097a712bcbc093c5a1e0075434158eDerek Sollenberger { SkXfermode::kModulate_Mode, GL_DST_COLOR, GL_ZERO }, 1062ffefd48e20d311b38c0673edadb27c1f6ad328bRomain Guy { SkXfermode::kScreen_Mode, GL_ONE_MINUS_DST_COLOR, GL_ONE } 107f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy}; 108f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy 109f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 110f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Constructors/destructor 111f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 112f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 1133bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain GuyOpenGLRenderer::OpenGLRenderer(): 1143bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy mCaches(Caches::getInstance()), mExtensions(Extensions::getInstance()) { 115d90144db52c7297879b950cbbc85137ed123ab5bChris Craik mDrawModifiers.mShader = NULL; 116d90144db52c7297879b950cbbc85137ed123ab5bChris Craik mDrawModifiers.mColorFilter = NULL; 117d90144db52c7297879b950cbbc85137ed123ab5bChris Craik mDrawModifiers.mHasShadow = false; 118d90144db52c7297879b950cbbc85137ed123ab5bChris Craik mDrawModifiers.mHasDrawFilter = false; 119026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 120ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices)); 121ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 122ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy mFirstSnapshot = new Snapshot; 12387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy 12487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mScissorOptimizationDisabled = false; 125e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy} 126e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 12785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain GuyOpenGLRenderer::~OpenGLRenderer() { 12829d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy // The context has already been destroyed at this point, do not call 12929d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy // GL APIs. All GL state should be kept in Caches.h 130e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy} 131e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 13287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::initProperties() { 13387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy char property[PROPERTY_VALUE_MAX]; 13487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy if (property_get(PROPERTY_DISABLE_SCISSOR_OPTIMIZATION, property, "false")) { 13587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mScissorOptimizationDisabled = !strcasecmp(property, "true"); 13687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy INIT_LOGD(" Scissor optimization %s", 13787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mScissorOptimizationDisabled ? "disabled" : "enabled"); 13887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy } else { 13987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy INIT_LOGD(" Scissor optimization enabled"); 14087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy } 14113631f3da855f200a151e7837ed9f6b079622b58Romain Guy} 14213631f3da855f200a151e7837ed9f6b079622b58Romain Guy 14313631f3da855f200a151e7837ed9f6b079622b58Romain Guy/////////////////////////////////////////////////////////////////////////////// 144f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Setup 145f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 146f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 147ef35927abcd089652f87a985dd6dde7afde58b92Romain Guyvoid OpenGLRenderer::setName(const char* name) { 148ef35927abcd089652f87a985dd6dde7afde58b92Romain Guy if (name) { 149ef35927abcd089652f87a985dd6dde7afde58b92Romain Guy mName.setTo(name); 150ef35927abcd089652f87a985dd6dde7afde58b92Romain Guy } else { 151ef35927abcd089652f87a985dd6dde7afde58b92Romain Guy mName.clear(); 152ef35927abcd089652f87a985dd6dde7afde58b92Romain Guy } 153ef35927abcd089652f87a985dd6dde7afde58b92Romain Guy} 154ef35927abcd089652f87a985dd6dde7afde58b92Romain Guy 155ef35927abcd089652f87a985dd6dde7afde58b92Romain Guyconst char* OpenGLRenderer::getName() const { 156ef35927abcd089652f87a985dd6dde7afde58b92Romain Guy return mName.string(); 157ef35927abcd089652f87a985dd6dde7afde58b92Romain Guy} 158ef35927abcd089652f87a985dd6dde7afde58b92Romain Guy 15949c5fc0b9e850497233e189ff9dcc71a78ebe6e7Romain Guybool OpenGLRenderer::isDeferred() { 16049c5fc0b9e850497233e189ff9dcc71a78ebe6e7Romain Guy return false; 16149c5fc0b9e850497233e189ff9dcc71a78ebe6e7Romain Guy} 16249c5fc0b9e850497233e189ff9dcc71a78ebe6e7Romain Guy 16385bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guyvoid OpenGLRenderer::setViewport(int width, int height) { 16435643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy initViewport(width, height); 16535643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy 16635643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy glDisable(GL_DITHER); 16735643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 16835643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy 16935643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy glEnableVertexAttribArray(Program::kBindingPosition); 17035643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy} 17135643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy 17235643ddc689913f5b5f80ceed864470d987bd6cdRomain Guyvoid OpenGLRenderer::initViewport(int width, int height) { 173260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1); 174bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 175bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy mWidth = width; 176bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy mHeight = height; 177eb99356a0548684a501766e6a524529ab93304c8Romain Guy 178eb99356a0548684a501766e6a524529ab93304c8Romain Guy mFirstSnapshot->height = height; 179eb99356a0548684a501766e6a524529ab93304c8Romain Guy mFirstSnapshot->viewport.set(0, 0, width, height); 180e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy} 181e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 1827c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guystatus_t OpenGLRenderer::prepare(bool opaque) { 18344b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase return prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque); 1847d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy} 1857d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 186c3fedafc5f50100219449125a000e3138f6fb987Romain Guystatus_t OpenGLRenderer::prepareDirty(float left, float top, 187c3fedafc5f50100219449125a000e3138f6fb987Romain Guy float right, float bottom, bool opaque) { 188fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy mCaches.clearGarbage(); 189fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 1908aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy mSnapshot = new Snapshot(mFirstSnapshot, 1918aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 19284962f2fe6ce779c583cc54b11a9de2b6a568117Romain Guy mSnapshot->fbo = getTargetFbo(); 1938fb954263dd2f918ad339045cc6d82e346515599Romain Guy mSaveCount = 1; 194f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 1957d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy mSnapshot->setClip(left, top, right, bottom); 1965f803623559aab395a29d575c37c4e39c23a4b4eChris Craik mTilingClip.set(left, top, right, bottom); 19741308e2936c768103d0e9c82500e97938d6797f1Romain Guy mDirtyClip = true; 198ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy 19911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy updateLayers(); 20011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 201dcfc836b457a87881da409e1acf251515f121446Romain Guy discardFramebuffer(left, top, right, bottom); 20245e4c3df6c00ac98ff6144de9af574877d4fff19Romain Guy 203ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy syncState(); 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 20854c1a64d5441a964890b44280e4457e11f4f924aRomain Guy mSuppressTiling = mCaches.hasRegisteredFunctors(); 20954c1a64d5441a964890b44280e4457e11f4f924aRomain Guy 2105f803623559aab395a29d575c37c4e39c23a4b4eChris Craik startTiling(mSnapshot, true); 2112b7028eabac80cec170572bc0e945a1d4224e595Romain Guy 2127c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy debugOverdraw(true, true); 2137c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy 2147c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy return clear(left, top, right, bottom, opaque); 2157c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy} 2167c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy 217dcfc836b457a87881da409e1acf251515f121446Romain Guyvoid OpenGLRenderer::discardFramebuffer(float left, float top, float right, float bottom) { 218dcfc836b457a87881da409e1acf251515f121446Romain Guy // If we know that we are going to redraw the entire framebuffer, 219dcfc836b457a87881da409e1acf251515f121446Romain Guy // perform a discard to let the driver know we don't need to preserve 220dcfc836b457a87881da409e1acf251515f121446Romain Guy // the back buffer for this frame. 2213bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy if (mExtensions.hasDiscardFramebuffer() && 222dcfc836b457a87881da409e1acf251515f121446Romain Guy left <= 0.0f && top <= 0.0f && right >= mWidth && bottom >= mHeight) { 223f158198ccc3a1f53bfebaa6b8f4426e80e1867eaRomain Guy const bool isFbo = getTargetFbo() == 0; 224f158198ccc3a1f53bfebaa6b8f4426e80e1867eaRomain Guy const GLenum attachments[] = { 225f158198ccc3a1f53bfebaa6b8f4426e80e1867eaRomain Guy isFbo ? (const GLenum) GL_COLOR_EXT : (const GLenum) GL_COLOR_ATTACHMENT0, 226f158198ccc3a1f53bfebaa6b8f4426e80e1867eaRomain Guy isFbo ? (const GLenum) GL_STENCIL_EXT : (const GLenum) GL_STENCIL_ATTACHMENT }; 227dcfc836b457a87881da409e1acf251515f121446Romain Guy glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments); 228dcfc836b457a87881da409e1acf251515f121446Romain Guy } 229dcfc836b457a87881da409e1acf251515f121446Romain Guy} 230dcfc836b457a87881da409e1acf251515f121446Romain Guy 2317c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guystatus_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) { 2326b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy if (!opaque) { 233586cae3ac69c0c667fbf8a954edbd399f620a717Romain Guy mCaches.enableScissor(); 234ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top); 2356b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy glClear(GL_COLOR_BUFFER_BIT); 23644b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase return DrawGlInfo::kStatusDrew; 237ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy } 23844b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase 2397c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy mCaches.resetScissor(); 24044b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase return DrawGlInfo::kStatusDone; 241ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy} 242ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy 243ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guyvoid OpenGLRenderer::syncState() { 244ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy glViewport(0, 0, mWidth, mHeight); 245ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy 246ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy if (mCaches.blend) { 247ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy glEnable(GL_BLEND); 248ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy } else { 249ddf74373616c89e0880a28a2185fd7ce3db91de6Romain Guy glDisable(GL_BLEND); 2506b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy } 251bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 252bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 25357b5268708c3b974296c7d4e58a02a957979224aRomain Guyvoid OpenGLRenderer::startTiling(const sp<Snapshot>& s, bool opaque) { 25454c1a64d5441a964890b44280e4457e11f4f924aRomain Guy if (!mSuppressTiling) { 2555f803623559aab395a29d575c37c4e39c23a4b4eChris Craik Rect* clip = &mTilingClip; 256c3fedafc5f50100219449125a000e3138f6fb987Romain Guy if (s->flags & Snapshot::kFlagFboTarget) { 2575f803623559aab395a29d575c37c4e39c23a4b4eChris Craik clip = &(s->layer->clipRect); 25854c1a64d5441a964890b44280e4457e11f4f924aRomain Guy } 25954c1a64d5441a964890b44280e4457e11f4f924aRomain Guy 260c3fedafc5f50100219449125a000e3138f6fb987Romain Guy startTiling(*clip, s->height, opaque); 261c3fedafc5f50100219449125a000e3138f6fb987Romain Guy } 262c3fedafc5f50100219449125a000e3138f6fb987Romain Guy} 263c3fedafc5f50100219449125a000e3138f6fb987Romain Guy 264c3fedafc5f50100219449125a000e3138f6fb987Romain Guyvoid OpenGLRenderer::startTiling(const Rect& clip, int windowHeight, bool opaque) { 265c3fedafc5f50100219449125a000e3138f6fb987Romain Guy if (!mSuppressTiling) { 266c3fedafc5f50100219449125a000e3138f6fb987Romain Guy mCaches.startTiling(clip.left, windowHeight - clip.bottom, 26752036b19a5f82bc4d75cfcbff99c65df8d25a99bRomain Guy clip.right - clip.left, clip.bottom - clip.top, opaque); 2682b7028eabac80cec170572bc0e945a1d4224e595Romain Guy } 2692b7028eabac80cec170572bc0e945a1d4224e595Romain Guy} 2702b7028eabac80cec170572bc0e945a1d4224e595Romain Guy 2712b7028eabac80cec170572bc0e945a1d4224e595Romain Guyvoid OpenGLRenderer::endTiling() { 27254c1a64d5441a964890b44280e4457e11f4f924aRomain Guy if (!mSuppressTiling) mCaches.endTiling(); 2732b7028eabac80cec170572bc0e945a1d4224e595Romain Guy} 2742b7028eabac80cec170572bc0e945a1d4224e595Romain Guy 275b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guyvoid OpenGLRenderer::finish() { 2767c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy renderOverdraw(); 2772b7028eabac80cec170572bc0e945a1d4224e595Romain Guy endTiling(); 2782b7028eabac80cec170572bc0e945a1d4224e595Romain Guy 279ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // When finish() is invoked on FBO 0 we've reached the end 280ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy // of the current frame 281ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy if (getTargetFbo() == 0) { 282ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy mCaches.pathCache.trim(); 283ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy } 284ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 28511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy if (!suppressErrorChecks()) { 286b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy#if DEBUG_OPENGL 28711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy GLenum status = GL_NO_ERROR; 28811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy while ((status = glGetError()) != GL_NO_ERROR) { 28911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy ALOGD("GL error from OpenGLRenderer: 0x%x", status); 29011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy switch (status) { 29111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy case GL_INVALID_ENUM: 29211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy ALOGE(" GL_INVALID_ENUM"); 29311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy break; 29411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy case GL_INVALID_VALUE: 29511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy ALOGE(" GL_INVALID_VALUE"); 29611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy break; 29711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy case GL_INVALID_OPERATION: 29811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy ALOGE(" GL_INVALID_OPERATION"); 29911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy break; 30011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy case GL_OUT_OF_MEMORY: 30111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy ALOGE(" Out of memory!"); 30211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy break; 30311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy } 304a07105b7d2a27e6d69407bf96ddb773bddb5e553Romain Guy } 305b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy#endif 30611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 307c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#if DEBUG_MEMORY_USAGE 308e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy mCaches.dumpMemoryUsage(); 30911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy#else 31011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy if (mCaches.getDebugLevel() & kDebugMemory) { 31111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy mCaches.dumpMemoryUsage(); 31211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy } 313c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#endif 31411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy } 315b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy} 316b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy 3176c319ca1275c8db892c39b48fc54864c949f9171Romain Guyvoid OpenGLRenderer::interrupt() { 318da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy if (mCaches.currentProgram) { 319da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy if (mCaches.currentProgram->isInUse()) { 320da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy mCaches.currentProgram->remove(); 321da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy mCaches.currentProgram = NULL; 322da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy } 323da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy } 32450c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy mCaches.unbindMeshBuffer(); 32515bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy mCaches.unbindIndicesBuffer(); 326f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy mCaches.resetVertexPointers(); 327ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy mCaches.disableTexCoordsVertexArray(); 3287c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy debugOverdraw(false, false); 329da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy} 330da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy 3316c319ca1275c8db892c39b48fc54864c949f9171Romain Guyvoid OpenGLRenderer::resume() { 33208837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot; 33308837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight()); 33435643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo); 3357c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy debugOverdraw(true, false); 33635643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy 3373e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 3383e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy 3398025061c594e5171e1bf370d8fdd77e0e9a02b47Chet Haase mCaches.scissorEnabled = glIsEnabled(GL_SCISSOR_TEST); 340586cae3ac69c0c667fbf8a954edbd399f620a717Romain Guy mCaches.enableScissor(); 34182bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy mCaches.resetScissor(); 342746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy dirtyClip(); 343da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy 344a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy mCaches.activeTexture(0); 34550c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy 34650c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy mCaches.blend = true; 34750c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy glEnable(GL_BLEND); 34850c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy glBlendFunc(mCaches.lastSrcMode, mCaches.lastDstMode); 34950c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy glBlendEquation(GL_FUNC_ADD); 350da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy} 351da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy 35235643ddc689913f5b5f80ceed864470d987bd6cdRomain Guyvoid OpenGLRenderer::resumeAfterLayer() { 35335643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot; 35435643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight()); 35535643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo); 3567c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy debugOverdraw(true, false); 35735643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy 35835643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy mCaches.resetScissor(); 35935643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy dirtyClip(); 36035643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy} 36135643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy 362ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guyvoid OpenGLRenderer::detachFunctor(Functor* functor) { 363932b7f6765968bd526c03512f3805fbc3924dc29Chris Craik mFunctors.remove(functor); 364ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy} 3658f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy 366ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guyvoid OpenGLRenderer::attachFunctor(Functor* functor) { 367ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy mFunctors.add(functor); 368ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy} 3698f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy 370ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guystatus_t OpenGLRenderer::invokeFunctors(Rect& dirty) { 371ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy status_t result = DrawGlInfo::kStatusDone; 3723d745c03ace18ee59c539e1b7f1df13f22beb57dRomain Guy size_t count = mFunctors.size(); 3738f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy 374ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy if (count > 0) { 375d15321bbf57ff7a4615076fefcee5e196c4fc796Chris Craik interrupt(); 376ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy SortedVector<Functor*> functors(mFunctors); 377ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy mFunctors.clear(); 378ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy 379ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy DrawGlInfo info; 380ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy info.clipLeft = 0; 381ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy info.clipTop = 0; 382ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy info.clipRight = 0; 383ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy info.clipBottom = 0; 384ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy info.isLayer = false; 385ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy info.width = 0; 386ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy info.height = 0; 387ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy memset(info.transform, 0, sizeof(float) * 16); 388ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy 389ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy for (size_t i = 0; i < count; i++) { 390ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy Functor* f = functors.itemAt(i); 391ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy result |= (*f)(DrawGlInfo::kModeProcess, &info); 392ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy 393c2c9543c135ffc4e18c7db0e817112ac03e3e97aChris Craik if (result & DrawGlInfo::kStatusDraw) { 394ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom); 395ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy dirty.unionWith(localDirty); 396c2c9543c135ffc4e18c7db0e817112ac03e3e97aChris Craik } 397ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy 398c2c9543c135ffc4e18c7db0e817112ac03e3e97aChris Craik if (result & DrawGlInfo::kStatusInvoke) { 399c2c9543c135ffc4e18c7db0e817112ac03e3e97aChris Craik mFunctors.add(f); 4008f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy } 4018f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy } 402d15321bbf57ff7a4615076fefcee5e196c4fc796Chris Craik resume(); 4038f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy } 4048f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy 4058f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy return result; 4068f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy} 4078f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy 4088f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guystatus_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) { 409408eb12631376cbdc96803e918decf6ea804d346Chris Craik if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone; 410408eb12631376cbdc96803e918decf6ea804d346Chris Craik 411daf98e941e140e8739458126640183b9f296a2abChet Haase interrupt(); 412932b7f6765968bd526c03512f3805fbc3924dc29Chris Craik detachFunctor(functor); 413c8538ade8df2c2f013f8b93094912057ee1cc417Chris Craik 4148a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy mCaches.enableScissor(); 415f90f8171e6acb56f9f87093c01fd586f2140697aRomain Guy if (mDirtyClip) { 416f90f8171e6acb56f9f87093c01fd586f2140697aRomain Guy setScissorFromClip(); 417f90f8171e6acb56f9f87093c01fd586f2140697aRomain Guy } 418d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy 41980911b851764b073310fd0bffdf4a7db0d8fdd0bRomain Guy Rect clip(*mSnapshot->clipRect); 42080911b851764b073310fd0bffdf4a7db0d8fdd0bRomain Guy clip.snapToPixelBoundaries(); 42180911b851764b073310fd0bffdf4a7db0d8fdd0bRomain Guy 422d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy // Since we don't know what the functor will draw, let's dirty 423d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy // tne entire clip region 424d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy if (hasLayer()) { 425d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy dirtyLayerUnchecked(clip, getRegion()); 426d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy } 427d643bb56fdf21973ea75984f0816b7dc024698dfRomain Guy 42808aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy DrawGlInfo info; 42908aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy info.clipLeft = clip.left; 43008aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy info.clipTop = clip.top; 43108aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy info.clipRight = clip.right; 43208aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy info.clipBottom = clip.bottom; 43308aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy info.isLayer = hasLayer(); 4347b6a75872bd2df96a23453d31c2e2e7fcc373554Chet Haase info.width = getSnapshot()->viewport.getWidth(); 4357b6a75872bd2df96a23453d31c2e2e7fcc373554Chet Haase info.height = getSnapshot()->height; 43608aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy getSnapshot()->transform->copyTo(&info.transform[0]); 43780911b851764b073310fd0bffdf4a7db0d8fdd0bRomain Guy 438486590963e2207d68eebd6944fec70d50d41116aChet Haase status_t result = (*functor)(DrawGlInfo::kModeDraw, &info) | DrawGlInfo::kStatusDrew; 439cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy 4408f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy if (result != DrawGlInfo::kStatusDone) { 44108aa2cbd5e62e7ca140f78f8bea0477a19880fd9Romain Guy Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom); 442cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy dirty.unionWith(localDirty); 4438f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy 44465924a3e56c2e7ac863f8e25e9f9a58b9db7d513Chris Craik if (result & DrawGlInfo::kStatusInvoke) { 445ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy mFunctors.add(functor); 4468f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy } 447cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy } 448cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy 449daf98e941e140e8739458126640183b9f296a2abChet Haase resume(); 4506554943a1dd6854c0f4976900956e556767b49e1Romain Guy return result; 451daf98e941e140e8739458126640183b9f296a2abChet Haase} 452daf98e941e140e8739458126640183b9f296a2abChet Haase 453f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 45487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy// Debug 45587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy/////////////////////////////////////////////////////////////////////////////// 45687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy 4570f6675332c04c74909425d1d328f02b32c0ff40eRomain Guyvoid OpenGLRenderer::eventMark(const char* name) const { 4580f6675332c04c74909425d1d328f02b32c0ff40eRomain Guy mCaches.eventMark(0, name); 4590f6675332c04c74909425d1d328f02b32c0ff40eRomain Guy} 4600f6675332c04c74909425d1d328f02b32c0ff40eRomain Guy 46187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::startMark(const char* name) const { 46287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mCaches.startMark(0, name); 46387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy} 46487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy 46587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::endMark() const { 46687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mCaches.endMark(); 46787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy} 46887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy 46987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::debugOverdraw(bool enable, bool clear) { 47087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy if (mCaches.debugOverdraw && getTargetFbo() == 0) { 47187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy if (clear) { 47287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mCaches.disableScissor(); 47387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mCaches.stencil.clear(); 47487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy } 47587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy if (enable) { 47687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mCaches.stencil.enableDebugWrite(); 47787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy } else { 47887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mCaches.stencil.disable(); 47987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy } 48087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy } 48187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy} 48287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy 48387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guyvoid OpenGLRenderer::renderOverdraw() { 48487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy if (mCaches.debugOverdraw && getTargetFbo() == 0) { 4855f803623559aab395a29d575c37c4e39c23a4b4eChris Craik const Rect* clip = &mTilingClip; 48687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy 48787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mCaches.enableScissor(); 4885f803623559aab395a29d575c37c4e39c23a4b4eChris Craik mCaches.setScissor(clip->left, mFirstSnapshot->height - clip->bottom, 48987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy clip->right - clip->left, clip->bottom - clip->top); 49087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy 49187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mCaches.stencil.enableDebugTest(2); 49287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy drawColor(0x2f0000ff, SkXfermode::kSrcOver_Mode); 49387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mCaches.stencil.enableDebugTest(3); 49487e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy drawColor(0x2f00ff00, SkXfermode::kSrcOver_Mode); 49587e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mCaches.stencil.enableDebugTest(4); 49687e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy drawColor(0x3fff0000, SkXfermode::kSrcOver_Mode); 49787e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mCaches.stencil.enableDebugTest(4, true); 49887e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy drawColor(0x7fff0000, SkXfermode::kSrcOver_Mode); 49987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mCaches.stencil.disable(); 50087e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy } 50187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy} 50287e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy 50387e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy/////////////////////////////////////////////////////////////////////////////// 50411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy// Layers 50511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy/////////////////////////////////////////////////////////////////////////////// 50611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 50711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guybool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) { 50811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) { 50911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy OpenGLRenderer* renderer = layer->renderer; 51011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy Rect& dirty = layer->dirtyRect; 51111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 5127c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy if (inFrame) { 5137c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy endTiling(); 5147c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy debugOverdraw(false, false); 5157c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy } 51611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 51711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight()); 51811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, !layer->isBlend()); 51911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy renderer->drawDisplayList(layer->displayList, dirty, DisplayList::kReplayFlag_ClipChildren); 52011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy renderer->finish(); 52111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 52211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy if (inFrame) { 52311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy resumeAfterLayer(); 52411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy startTiling(mSnapshot); 52511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy } 52611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 52711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy dirty.setEmpty(); 52811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy layer->deferredUpdateScheduled = false; 52911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy layer->renderer = NULL; 53011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy layer->displayList = NULL; 5315bb3c730f5ebd2a0db1b02a8981c6fdbea6c1a2eRomain Guy layer->debugDrawUpdate = mCaches.debugLayersUpdates; 53211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 53311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy return true; 53411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy } 53511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 53611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy return false; 53711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy} 53811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 53911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guyvoid OpenGLRenderer::updateLayers() { 54011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy int count = mLayerUpdates.size(); 54111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy if (count > 0) { 54211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy startMark("Layer Updates"); 54311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 54411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy // Note: it is very important to update the layers in reverse order 54511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy for (int i = count - 1; i >= 0; i--) { 54611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy Layer* layer = mLayerUpdates.itemAt(i); 54711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy updateLayer(layer, false); 54811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy mCaches.resourceCache.decrementRefcount(layer); 54911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy } 55011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy mLayerUpdates.clear(); 55111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 55211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo()); 55311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy endMark(); 55411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy } 55511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy} 55611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 55711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guyvoid OpenGLRenderer::pushLayerUpdate(Layer* layer) { 55811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy if (layer) { 55911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy mLayerUpdates.push_back(layer); 56011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy mCaches.resourceCache.incrementRefcount(layer); 56111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy } 56211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy} 56311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 56411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guyvoid OpenGLRenderer::clearLayerUpdates() { 56511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy size_t count = mLayerUpdates.size(); 56611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy if (count > 0) { 56711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy mCaches.resourceCache.lock(); 56811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy for (size_t i = 0; i < count; i++) { 56911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy mCaches.resourceCache.decrementRefcountLocked(mLayerUpdates.itemAt(i)); 57011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy } 57111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy mCaches.resourceCache.unlock(); 57211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy mLayerUpdates.clear(); 57311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy } 57411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy} 57511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy 57611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy/////////////////////////////////////////////////////////////////////////////// 577f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// State management 578f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 579f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 580bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyint OpenGLRenderer::getSaveCount() const { 5817ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy return mSaveCount; 582bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 583bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 584bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyint OpenGLRenderer::save(int flags) { 5858aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy return saveSnapshot(flags); 586bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 587bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 588bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid OpenGLRenderer::restore() { 5892542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy if (mSaveCount > 1) { 5902542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy restoreSnapshot(); 5917ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy } 592bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 593bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 594bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid OpenGLRenderer::restoreToCount(int saveCount) { 5958fb954263dd2f918ad339045cc6d82e346515599Romain Guy if (saveCount < 1) saveCount = 1; 596bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 5978fb954263dd2f918ad339045cc6d82e346515599Romain Guy while (mSaveCount > saveCount) { 5982542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy restoreSnapshot(); 5997ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy } 600bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 601bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 6028aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guyint OpenGLRenderer::saveSnapshot(int flags) { 6038aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy mSnapshot = new Snapshot(mSnapshot, flags); 6048fb954263dd2f918ad339045cc6d82e346515599Romain Guy return mSaveCount++; 605bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 606bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 607bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guybool OpenGLRenderer::restoreSnapshot() { 6087ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet; 609bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy bool restoreLayer = mSnapshot->flags & Snapshot::kFlagIsLayer; 610eb99356a0548684a501766e6a524529ab93304c8Romain Guy bool restoreOrtho = mSnapshot->flags & Snapshot::kFlagDirtyOrtho; 611bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 612bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy sp<Snapshot> current = mSnapshot; 6137ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy sp<Snapshot> previous = mSnapshot->previous; 614bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 615eb99356a0548684a501766e6a524529ab93304c8Romain Guy if (restoreOrtho) { 616eb99356a0548684a501766e6a524529ab93304c8Romain Guy Rect& r = previous->viewport; 617eb99356a0548684a501766e6a524529ab93304c8Romain Guy glViewport(r.left, r.top, r.right, r.bottom); 618eb99356a0548684a501766e6a524529ab93304c8Romain Guy mOrthoMatrix.load(current->orthoMatrix); 619eb99356a0548684a501766e6a524529ab93304c8Romain Guy } 620eb99356a0548684a501766e6a524529ab93304c8Romain Guy 6218b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy mSaveCount--; 6228b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy mSnapshot = previous; 6238b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy 6242542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy if (restoreClip) { 625746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy dirtyClip(); 6268fb954263dd2f918ad339045cc6d82e346515599Romain Guy } 6272542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy 6285ec9924d24495822b589f1a17996655d66273b30Romain Guy if (restoreLayer) { 6295ec9924d24495822b589f1a17996655d66273b30Romain Guy composeLayer(current, previous); 6305ec9924d24495822b589f1a17996655d66273b30Romain Guy } 6315ec9924d24495822b589f1a17996655d66273b30Romain Guy 6322542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy return restoreClip; 633d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy} 6345cbbce535744b89df5ecea95de21ee3733298260Romain Guy 635f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 636bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy// Layers 637bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy/////////////////////////////////////////////////////////////////////////////// 638bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 639bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyint OpenGLRenderer::saveLayer(float left, float top, float right, float bottom, 640ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik int alpha, SkXfermode::Mode mode, int flags) { 641eb99356a0548684a501766e6a524529ab93304c8Romain Guy const GLuint previousFbo = mSnapshot->fbo; 642eb99356a0548684a501766e6a524529ab93304c8Romain Guy const int count = saveSnapshot(flags); 643d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy 644af636ebf5feb2837683fbfe965040cb706b32ec1Romain Guy if (!mSnapshot->isIgnored()) { 645d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase createLayer(left, top, right, bottom, alpha, mode, flags, previousFbo); 646dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy } 647d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy 648d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy return count; 649bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy} 650bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 651d90144db52c7297879b950cbbc85137ed123ab5bChris Craikvoid OpenGLRenderer::calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool fboLayer) { 652d90144db52c7297879b950cbbc85137ed123ab5bChris Craik const Rect untransformedBounds(bounds); 653d90144db52c7297879b950cbbc85137ed123ab5bChris Craik 654d90144db52c7297879b950cbbc85137ed123ab5bChris Craik currentTransform().mapRect(bounds); 655d90144db52c7297879b950cbbc85137ed123ab5bChris Craik 656d90144db52c7297879b950cbbc85137ed123ab5bChris Craik // Layers only make sense if they are in the framebuffer's bounds 657d90144db52c7297879b950cbbc85137ed123ab5bChris Craik if (bounds.intersect(*mSnapshot->clipRect)) { 658d90144db52c7297879b950cbbc85137ed123ab5bChris Craik // We cannot work with sub-pixels in this case 659d90144db52c7297879b950cbbc85137ed123ab5bChris Craik bounds.snapToPixelBoundaries(); 660d90144db52c7297879b950cbbc85137ed123ab5bChris Craik 661d90144db52c7297879b950cbbc85137ed123ab5bChris Craik // When the layer is not an FBO, we may use glCopyTexImage so we 662d90144db52c7297879b950cbbc85137ed123ab5bChris Craik // need to make sure the layer does not extend outside the bounds 663d90144db52c7297879b950cbbc85137ed123ab5bChris Craik // of the framebuffer 664d90144db52c7297879b950cbbc85137ed123ab5bChris Craik if (!bounds.intersect(mSnapshot->previous->viewport)) { 665d90144db52c7297879b950cbbc85137ed123ab5bChris Craik bounds.setEmpty(); 666d90144db52c7297879b950cbbc85137ed123ab5bChris Craik } else if (fboLayer) { 667d90144db52c7297879b950cbbc85137ed123ab5bChris Craik clip.set(bounds); 668d90144db52c7297879b950cbbc85137ed123ab5bChris Craik mat4 inverse; 669d90144db52c7297879b950cbbc85137ed123ab5bChris Craik inverse.loadInverse(currentTransform()); 670d90144db52c7297879b950cbbc85137ed123ab5bChris Craik inverse.mapRect(clip); 671d90144db52c7297879b950cbbc85137ed123ab5bChris Craik clip.snapToPixelBoundaries(); 672d90144db52c7297879b950cbbc85137ed123ab5bChris Craik if (clip.intersect(untransformedBounds)) { 673d90144db52c7297879b950cbbc85137ed123ab5bChris Craik clip.translate(-untransformedBounds.left, -untransformedBounds.top); 674d90144db52c7297879b950cbbc85137ed123ab5bChris Craik bounds.set(untransformedBounds); 675d90144db52c7297879b950cbbc85137ed123ab5bChris Craik } else { 676d90144db52c7297879b950cbbc85137ed123ab5bChris Craik clip.setEmpty(); 677d90144db52c7297879b950cbbc85137ed123ab5bChris Craik } 678d90144db52c7297879b950cbbc85137ed123ab5bChris Craik } 679d90144db52c7297879b950cbbc85137ed123ab5bChris Craik } else { 680d90144db52c7297879b950cbbc85137ed123ab5bChris Craik bounds.setEmpty(); 681d90144db52c7297879b950cbbc85137ed123ab5bChris Craik } 682d90144db52c7297879b950cbbc85137ed123ab5bChris Craik} 683d90144db52c7297879b950cbbc85137ed123ab5bChris Craik 684408eb12631376cbdc96803e918decf6ea804d346Chris Craikvoid OpenGLRenderer::updateSnapshotIgnoreForLayer(const Rect& bounds, const Rect& clip, 685408eb12631376cbdc96803e918decf6ea804d346Chris Craik bool fboLayer, int alpha) { 686408eb12631376cbdc96803e918decf6ea804d346Chris Craik if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize || 687408eb12631376cbdc96803e918decf6ea804d346Chris Craik bounds.getHeight() > mCaches.maxTextureSize || 688408eb12631376cbdc96803e918decf6ea804d346Chris Craik (fboLayer && clip.isEmpty())) { 689408eb12631376cbdc96803e918decf6ea804d346Chris Craik mSnapshot->empty = fboLayer; 690408eb12631376cbdc96803e918decf6ea804d346Chris Craik } else { 691408eb12631376cbdc96803e918decf6ea804d346Chris Craik mSnapshot->invisible = mSnapshot->invisible || (alpha <= ALPHA_THRESHOLD && fboLayer); 692408eb12631376cbdc96803e918decf6ea804d346Chris Craik } 693408eb12631376cbdc96803e918decf6ea804d346Chris Craik} 694408eb12631376cbdc96803e918decf6ea804d346Chris Craik 695d90144db52c7297879b950cbbc85137ed123ab5bChris Craikint OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float bottom, 696d90144db52c7297879b950cbbc85137ed123ab5bChris Craik int alpha, SkXfermode::Mode mode, int flags) { 697d90144db52c7297879b950cbbc85137ed123ab5bChris Craik const GLuint previousFbo = mSnapshot->fbo; 698d90144db52c7297879b950cbbc85137ed123ab5bChris Craik const int count = saveSnapshot(flags); 699d90144db52c7297879b950cbbc85137ed123ab5bChris Craik 700d90144db52c7297879b950cbbc85137ed123ab5bChris Craik if (!mSnapshot->isIgnored() && (flags & SkCanvas::kClipToLayer_SaveFlag)) { 701d90144db52c7297879b950cbbc85137ed123ab5bChris Craik // initialize the snapshot as though it almost represents an FBO layer so deferred draw 702d90144db52c7297879b950cbbc85137ed123ab5bChris Craik // operations will be able to store and restore the current clip and transform info, and 703d90144db52c7297879b950cbbc85137ed123ab5bChris Craik // quick rejection will be correct (for display lists) 704d90144db52c7297879b950cbbc85137ed123ab5bChris Craik 705d90144db52c7297879b950cbbc85137ed123ab5bChris Craik Rect bounds(left, top, right, bottom); 706d90144db52c7297879b950cbbc85137ed123ab5bChris Craik Rect clip; 707d90144db52c7297879b950cbbc85137ed123ab5bChris Craik calculateLayerBoundsAndClip(bounds, clip, true); 708408eb12631376cbdc96803e918decf6ea804d346Chris Craik updateSnapshotIgnoreForLayer(bounds, clip, true, alpha); 709d90144db52c7297879b950cbbc85137ed123ab5bChris Craik 710408eb12631376cbdc96803e918decf6ea804d346Chris Craik if (!mSnapshot->isIgnored()) { 711d90144db52c7297879b950cbbc85137ed123ab5bChris Craik mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f); 712d90144db52c7297879b950cbbc85137ed123ab5bChris Craik mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom); 713d90144db52c7297879b950cbbc85137ed123ab5bChris Craik } 714d90144db52c7297879b950cbbc85137ed123ab5bChris Craik } 715d90144db52c7297879b950cbbc85137ed123ab5bChris Craik 716d90144db52c7297879b950cbbc85137ed123ab5bChris Craik return count; 717d90144db52c7297879b950cbbc85137ed123ab5bChris Craik} 718d90144db52c7297879b950cbbc85137ed123ab5bChris Craik 719d90144db52c7297879b950cbbc85137ed123ab5bChris Craik 7201c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy/** 7211c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Layers are viewed by Skia are slightly different than layers in image editing 7221c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * programs (for instance.) When a layer is created, previously created layers 7231c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * and the frame buffer still receive every drawing command. For instance, if a 7241c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * layer is created and a shape intersecting the bounds of the layers and the 7251c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * framebuffer is draw, the shape will be drawn on both (unless the layer was 7261c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * created with the SkCanvas::kClipToLayer_SaveFlag flag.) 7271c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * 7281c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * A way to implement layers is to create an FBO for each layer, backed by an RGBA 7291c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * texture. Unfortunately, this is inefficient as it requires every primitive to 7301c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * be drawn n + 1 times, where n is the number of active layers. In practice this 7311c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * means, for every primitive: 7321c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * - Switch active frame buffer 7331c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * - Change viewport, clip and projection matrix 7341c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * - Issue the drawing 7351c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * 7361c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Switching rendering target n + 1 times per drawn primitive is extremely costly. 7376b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * To avoid this, layers are implemented in a different way here, at least in the 7386b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * general case. FBOs are used, as an optimization, when the "clip to layer" flag 7396b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * is set. When this flag is set we can redirect all drawing operations into a 7406b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * single FBO. 7411c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * 7421c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * This implementation relies on the frame buffer being at least RGBA 8888. When 7431c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * a layer is created, only a texture is created, not an FBO. The content of the 7441c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * frame buffer contained within the layer's bounds is copied into this texture 74587a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * using glCopyTexImage2D(). The layer's region is then cleared(1) in the frame 7461c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * buffer and drawing continues as normal. This technique therefore treats the 7471c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * frame buffer as a scratch buffer for the layers. 7481c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * 7491c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * To compose the layers back onto the frame buffer, each layer texture 7501c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * (containing the original frame buffer data) is drawn as a simple quad over 7511c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * the frame buffer. The trick is that the quad is set as the composition 7521c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * destination in the blending equation, and the frame buffer becomes the source 7531c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * of the composition. 7541c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * 7551c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Drawing layers with an alpha value requires an extra step before composition. 7561c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * An empty quad is drawn over the layer's region in the frame buffer. This quad 7571c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * is drawn with the rgba color (0,0,0,alpha). The alpha value offered by the 7581c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * quad is used to multiply the colors in the frame buffer. This is achieved by 7591c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * changing the GL blend functions for the GL_FUNC_ADD blend equation to 7601c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * GL_ZERO, GL_SRC_ALPHA. 7611c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * 7621c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Because glCopyTexImage2D() can be slow, an alternative implementation might 7631c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * be use to draw a single clipped layer. The implementation described above 7641c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * is correct in every case. 76587a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * 76687a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * (1) The frame buffer is actually not cleared right away. To allow the GPU 76787a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * to potentially optimize series of calls to glCopyTexImage2D, the frame 76887a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * buffer is left untouched until the first drawing operation. Only when 76987a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * something actually gets drawn are the layers regions cleared. 7701c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy */ 771d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haasebool OpenGLRenderer::createLayer(float left, float top, float right, float bottom, 772d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase int alpha, SkXfermode::Mode mode, int flags, GLuint previousFbo) { 773eb99356a0548684a501766e6a524529ab93304c8Romain Guy LAYER_LOGD("Requesting layer %.2fx%.2f", right - left, bottom - top); 774fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize()); 775dda570201ac851dd85af3861f7e575721d3345daRomain Guy 776eb99356a0548684a501766e6a524529ab93304c8Romain Guy const bool fboLayer = flags & SkCanvas::kClipToLayer_SaveFlag; 777eb99356a0548684a501766e6a524529ab93304c8Romain Guy 778f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy // Window coordinates of the layer 779d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase Rect clip; 7808aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy Rect bounds(left, top, right, bottom); 781d90144db52c7297879b950cbbc85137ed123ab5bChris Craik calculateLayerBoundsAndClip(bounds, clip, fboLayer); 782408eb12631376cbdc96803e918decf6ea804d346Chris Craik updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, alpha); 783dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy 784dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy // Bail out if we won't draw in this snapshot 785408eb12631376cbdc96803e918decf6ea804d346Chris Craik if (mSnapshot->isIgnored()) { 786b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy return false; 787b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy } 788dda570201ac851dd85af3861f7e575721d3345daRomain Guy 789a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy mCaches.activeTexture(0); 7908550c4c7b5952b7a4e1e0ede95c9492d03099a13Romain Guy Layer* layer = mCaches.layerCache.get(bounds.getWidth(), bounds.getHeight()); 791f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy if (!layer) { 792f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy return false; 793bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy } 794bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 7959ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy layer->setAlpha(alpha, mode); 7968aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy layer->layer.set(bounds); 7979ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()), 7989ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy bounds.getWidth() / float(layer->getWidth()), 0.0f); 799c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik layer->setColorFilter(mDrawModifiers.mColorFilter); 800a23eed808a1ae4ec0d818c0a9238385e797fd056Chet Haase layer->setBlend(true); 8017c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy layer->setDirty(false); 802dda570201ac851dd85af3861f7e575721d3345daRomain Guy 8038fb954263dd2f918ad339045cc6d82e346515599Romain Guy // Save the layer in the snapshot 804d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase mSnapshot->flags |= Snapshot::kFlagIsLayer; 805d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase mSnapshot->layer = layer; 8061d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy 807eb99356a0548684a501766e6a524529ab93304c8Romain Guy if (fboLayer) { 808d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase return createFboLayer(layer, bounds, clip, previousFbo); 809eb99356a0548684a501766e6a524529ab93304c8Romain Guy } else { 810eb99356a0548684a501766e6a524529ab93304c8Romain Guy // Copy the framebuffer into the layer 8119ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy layer->bindTexture(); 812514fb18827186591d66973c2362c859b64b63556Romain Guy if (!bounds.isEmpty()) { 8139ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy if (layer->isEmpty()) { 8149ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 815d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase bounds.left, mSnapshot->height - bounds.bottom, 8169ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy layer->getWidth(), layer->getHeight(), 0); 8179ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy layer->setEmpty(false); 818514fb18827186591d66973c2362c859b64b63556Romain Guy } else { 819514fb18827186591d66973c2362c859b64b63556Romain Guy glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left, 820d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase mSnapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight()); 821514fb18827186591d66973c2362c859b64b63556Romain Guy } 8227b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy 82354be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy // Enqueue the buffer coordinates to clear the corresponding region later 82454be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy mLayers.push(new Rect(bounds)); 825ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy } 826eb99356a0548684a501766e6a524529ab93304c8Romain Guy } 827f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy 828d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy return true; 829bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy} 830bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 831d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haasebool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip, GLuint previousFbo) { 832c3fedafc5f50100219449125a000e3138f6fb987Romain Guy layer->clipRect.set(clip); 8339ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy layer->setFbo(mCaches.fboCache.get()); 8345b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 835d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase mSnapshot->region = &mSnapshot->layer->region; 836c3fedafc5f50100219449125a000e3138f6fb987Romain Guy mSnapshot->flags |= Snapshot::kFlagFboTarget | Snapshot::kFlagIsFboLayer | 837c3fedafc5f50100219449125a000e3138f6fb987Romain Guy Snapshot::kFlagDirtyOrtho; 838d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase mSnapshot->fbo = layer->getFbo(); 839d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f); 840d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom); 841d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase mSnapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight()); 842d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase mSnapshot->height = bounds.getHeight(); 843d48885a6c8cd27a8a62552c33b5282e9882e19f6Chet Haase mSnapshot->orthoMatrix.load(mOrthoMatrix); 8445b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 8452b7028eabac80cec170572bc0e945a1d4224e595Romain Guy endTiling(); 8467c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy debugOverdraw(false, false); 8475b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // Bind texture to FBO 8489ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo()); 8499ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy layer->bindTexture(); 8505b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 8515b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // Initialize the texture if needed 8529ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy if (layer->isEmpty()) { 8539ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); 8549ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy layer->setEmpty(false); 8555b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 8565b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 8575b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 8589ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy layer->getTexture(), 0); 8595b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 860f735c8e5cb59d6e1d1aa152fed7a6480a08d1c2aRomain Guy startTiling(mSnapshot, true); 8615b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 8625b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // Clear the FBO, expand the clear region by 1 to get nice bilinear filtering 863586cae3ac69c0c667fbf8a954edbd399f620a717Romain Guy mCaches.enableScissor(); 8648f85e80b64b89fd38cc23b129f61ec36ddde7f15Romain Guy mCaches.setScissor(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f, 8655b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy clip.getWidth() + 2.0f, clip.getHeight() + 2.0f); 8665b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy glClear(GL_COLOR_BUFFER_BIT); 8675b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 8685b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy dirtyClip(); 8695b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 8705b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // Change the ortho projection 8715b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy glViewport(0, 0, bounds.getWidth(), bounds.getHeight()); 8725b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mOrthoMatrix.loadOrtho(0.0f, bounds.getWidth(), bounds.getHeight(), 0.0f, -1.0f, 1.0f); 8735b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 8745b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy return true; 8755b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy} 8765b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 8771c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy/** 8781c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy * Read the documentation of createLayer() before doing anything in this method. 8791c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy */ 8801d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guyvoid OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { 8811d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy if (!current->layer) { 8823762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Attempting to compose a layer that does not exist"); 8831d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy return; 8841d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy } 8851d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy 8868ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy Layer* layer = current->layer; 8878ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy const Rect& rect = layer->layer; 8885b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy const bool fboLayer = current->flags & Snapshot::kFlagIsFboLayer; 889eb99356a0548684a501766e6a524529ab93304c8Romain Guy 890eb99356a0548684a501766e6a524529ab93304c8Romain Guy if (fboLayer) { 8912b7028eabac80cec170572bc0e945a1d4224e595Romain Guy endTiling(); 8922b7028eabac80cec170572bc0e945a1d4224e595Romain Guy 893e0aa84b7dc087e999e20055dcc04cb6a48d5bd62Romain Guy // Detach the texture from the FBO 894e0aa84b7dc087e999e20055dcc04cb6a48d5bd62Romain Guy glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); 8958ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 8968ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy layer->removeFbo(false); 8978ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 898eb99356a0548684a501766e6a524529ab93304c8Romain Guy // Unbind current FBO and restore previous one 899eb99356a0548684a501766e6a524529ab93304c8Romain Guy glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo); 9007c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy debugOverdraw(true, false); 9012b7028eabac80cec170572bc0e945a1d4224e595Romain Guy 9022b7028eabac80cec170572bc0e945a1d4224e595Romain Guy startTiling(previous); 903eb99356a0548684a501766e6a524529ab93304c8Romain Guy } 904eb99356a0548684a501766e6a524529ab93304c8Romain Guy 9059ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy if (!fboLayer && layer->getAlpha() < 255) { 906f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy drawColorRect(rect.left, rect.top, rect.right, rect.bottom, 9079ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy layer->getAlpha() << 24, SkXfermode::kDstIn_Mode, true); 9085b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // Required below, composeLayerRect() will divide by 255 9099ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy layer->setAlpha(255); 910f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy } 911f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy 91203750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy mCaches.unbindMeshBuffer(); 9138b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy 914a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy mCaches.activeTexture(0); 9155b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 9165b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // When the layer is stored in an FBO, we can save a bit of fillrate by 9175b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // drawing only the dirty region 918eb99356a0548684a501766e6a524529ab93304c8Romain Guy if (fboLayer) { 9195b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *previous->transform); 9209ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy if (layer->getColorFilter()) { 9219ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy setupColorFilter(layer->getColorFilter()); 922171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy } 9235b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy composeLayerRegion(layer, rect); 9249ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy if (layer->getColorFilter()) { 925171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy resetColorFilter(); 926171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy } 9279ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } else if (!rect.isEmpty()) { 9289ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy dirtyLayer(rect.left, rect.top, rect.right, rect.bottom); 9299ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy composeLayerRect(layer, rect, true); 930eb99356a0548684a501766e6a524529ab93304c8Romain Guy } 9311d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy 932746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy dirtyClip(); 933746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy 934eb99356a0548684a501766e6a524529ab93304c8Romain Guy // Failing to add the layer to the cache should happen only if the layer is too large 9358550c4c7b5952b7a4e1e0ede95c9492d03099a13Romain Guy if (!mCaches.layerCache.put(layer)) { 9361d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy LAYER_LOGD("Deleting layer"); 937603f6de35f21d74ae242d52d501f4f5c25ff4f4cChet Haase Caches::getInstance().resourceCache.decrementRefcount(layer); 9381d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy } 9391d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy} 9401d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy 941aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyvoid OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { 942e83569ca76308bfe945efcfef5a12c64b8fb8849Chris Craik float alpha = layer->getAlpha() / 255.0f * mSnapshot->alpha; 943aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 944aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy setupDraw(); 9459ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy if (layer->getRenderTarget() == GL_TEXTURE_2D) { 9468f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy setupDrawWithTexture(); 9478f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy } else { 9488f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy setupDrawWithExternalTexture(); 9498f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy } 9508f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy setupDrawTextureTransform(); 951aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy setupDrawColor(alpha, alpha, alpha, alpha); 952aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy setupDrawColorFilter(); 9539ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy setupDrawBlending(layer->isBlend() || alpha < 1.0f, layer->getMode()); 954aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy setupDrawProgram(); 955aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy setupDrawPureColorUniforms(); 956aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy setupDrawColorFilterUniforms(); 9579ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy if (layer->getRenderTarget() == GL_TEXTURE_2D) { 9589ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy setupDrawTexture(layer->getTexture()); 9598f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy } else { 9609ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy setupDrawExternalTexture(layer->getTexture()); 9618f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy } 9623b753829ae858d424fe109f714745379a6daf455Romain Guy if (currentTransform().isPureTranslate() && 963ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy layer->getWidth() == (uint32_t) rect.getWidth() && 964ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy layer->getHeight() == (uint32_t) rect.getHeight()) { 9653b753829ae858d424fe109f714745379a6daf455Romain Guy const float x = (int) floorf(rect.left + currentTransform().getTranslateX() + 0.5f); 9663b753829ae858d424fe109f714745379a6daf455Romain Guy const float y = (int) floorf(rect.top + currentTransform().getTranslateY() + 0.5f); 9679ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy 968d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy layer->setFilter(GL_NEAREST); 9699ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy setupDrawModelView(x, y, x + rect.getWidth(), y + rect.getHeight(), true); 9709ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } else { 971d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy layer->setFilter(GL_LINEAR); 9729ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom); 9739ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } 9749ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy setupDrawTextureTransformUniforms(layer->getTexTransform()); 975aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy setupDrawMesh(&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]); 976aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 977aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); 978aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 979aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy finishDrawTexture(); 980aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy} 981aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 9825b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guyvoid OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) { 9839ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy if (!layer->isTextureLayer()) { 984aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy const Rect& texCoords = layer->texCoords; 985aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy resetDrawTextureTexCoords(texCoords.left, texCoords.top, 986aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy texCoords.right, texCoords.bottom); 9875b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 9889ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy float x = rect.left; 9899ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy float y = rect.top; 9903b753829ae858d424fe109f714745379a6daf455Romain Guy bool simpleTransform = currentTransform().isPureTranslate() && 991ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy layer->getWidth() == (uint32_t) rect.getWidth() && 992b2479153b743df9e54f7e17c7132a5ecd87fa453Romain Guy layer->getHeight() == (uint32_t) rect.getHeight(); 993b2479153b743df9e54f7e17c7132a5ecd87fa453Romain Guy 994b2479153b743df9e54f7e17c7132a5ecd87fa453Romain Guy if (simpleTransform) { 9959ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy // When we're swapping, the layer is already in screen coordinates 9969ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy if (!swap) { 9973b753829ae858d424fe109f714745379a6daf455Romain Guy x = (int) floorf(rect.left + currentTransform().getTranslateX() + 0.5f); 9983b753829ae858d424fe109f714745379a6daf455Romain Guy y = (int) floorf(rect.top + currentTransform().getTranslateY() + 0.5f); 9999ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } 10009ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy 1001d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy layer->setFilter(GL_NEAREST, true); 10029ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } else { 1003d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy layer->setFilter(GL_LINEAR, true); 10049ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } 10059ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy 1006e83569ca76308bfe945efcfef5a12c64b8fb8849Chris Craik float alpha = layer->getAlpha() / 255.0f * mSnapshot->alpha; 1007e83569ca76308bfe945efcfef5a12c64b8fb8849Chris Craik bool blend = layer->isBlend() || alpha < 1.0f; 10089ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(), 1009e83569ca76308bfe945efcfef5a12c64b8fb8849Chris Craik layer->getTexture(), alpha, layer->getMode(), blend, 10109ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], 10119ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy GL_TRIANGLE_STRIP, gMeshCount, swap, swap || simpleTransform); 10125b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 1013aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); 1014aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy } else { 1015aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f); 1016aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy drawTextureLayer(layer, rect); 1017aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); 1018aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy } 10195b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy} 10205b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 10215b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guyvoid OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { 10225b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (layer->region.isRect()) { 10239fc27819d75e24ad63d7b383d80f5cb66a577a0dRomain Guy layer->setRegionAsRect(); 10249fc27819d75e24ad63d7b383d80f5cb66a577a0dRomain Guy 102540667676e542a9daeafeac9904c30004e8706fd3Romain Guy composeLayerRect(layer, layer->regionRect); 10269fc27819d75e24ad63d7b383d80f5cb66a577a0dRomain Guy 10275b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy layer->region.clear(); 10285b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy return; 10295b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 10305b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 10318a3957d43bcae93fbb9f6b4b4c3de8abdb3c953cRomain Guy // TODO: See LayerRenderer.cpp::generateMesh() for important 10328a3957d43bcae93fbb9f6b4b4c3de8abdb3c953cRomain Guy // information about this implementation 1033211370fd943cf26905001b38b8b1791851b26adcRomain Guy if (CC_LIKELY(!layer->region.isEmpty())) { 10345b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy size_t count; 10356c5b9be7450903762f676522c32d65f7545730dfChris Craik const android::Rect* rects; 10366c5b9be7450903762f676522c32d65f7545730dfChris Craik Region safeRegion; 10376c5b9be7450903762f676522c32d65f7545730dfChris Craik if (CC_LIKELY(hasRectToRectTransform())) { 10386c5b9be7450903762f676522c32d65f7545730dfChris Craik rects = layer->region.getArray(&count); 10396c5b9be7450903762f676522c32d65f7545730dfChris Craik } else { 10406c5b9be7450903762f676522c32d65f7545730dfChris Craik safeRegion = Region::createTJunctionFreeRegion(layer->region); 10416c5b9be7450903762f676522c32d65f7545730dfChris Craik rects = safeRegion.getArray(&count); 10426c5b9be7450903762f676522c32d65f7545730dfChris Craik } 10435b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 1044e83569ca76308bfe945efcfef5a12c64b8fb8849Chris Craik const float alpha = layer->getAlpha() / 255.0f * mSnapshot->alpha; 10459ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy const float texX = 1.0f / float(layer->getWidth()); 10469ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy const float texY = 1.0f / float(layer->getHeight()); 1047f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy const float height = rect.getHeight(); 10485b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 10498ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy setupDraw(); 10508ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 10518ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // We must get (and therefore bind) the region mesh buffer 10528ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // after we setup drawing in case we need to mess with the 10538ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // stencil buffer in setupDraw() 10545b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy TextureVertex* mesh = mCaches.getRegionMesh(); 10555b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy GLsizei numQuads = 0; 10565b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 10577230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy setupDrawWithTexture(); 10587230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy setupDrawColor(alpha, alpha, alpha, alpha); 1059ada830f639591b99c3e40de22b07296c7932a33fRomain Guy setupDrawColorFilter(); 10609ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy setupDrawBlending(layer->isBlend() || alpha < 1.0f, layer->getMode(), false); 10617230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy setupDrawProgram(); 10627230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy setupDrawDirtyRegionsDisabled(); 10637230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy setupDrawPureColorUniforms(); 1064ada830f639591b99c3e40de22b07296c7932a33fRomain Guy setupDrawColorFilterUniforms(); 10659ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy setupDrawTexture(layer->getTexture()); 10663b753829ae858d424fe109f714745379a6daf455Romain Guy if (currentTransform().isPureTranslate()) { 10673b753829ae858d424fe109f714745379a6daf455Romain Guy const float x = (int) floorf(rect.left + currentTransform().getTranslateX() + 0.5f); 10683b753829ae858d424fe109f714745379a6daf455Romain Guy const float y = (int) floorf(rect.top + currentTransform().getTranslateY() + 0.5f); 10699ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy 1070d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy layer->setFilter(GL_NEAREST); 10719ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy setupDrawModelViewTranslate(x, y, x + rect.getWidth(), y + rect.getHeight(), true); 10729ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } else { 1073d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy layer->setFilter(GL_LINEAR); 10749ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom); 10759ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } 107615bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy setupDrawMeshIndices(&mesh[0].position[0], &mesh[0].texture[0]); 10775b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 10785b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy for (size_t i = 0; i < count; i++) { 10795b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy const android::Rect* r = &rects[i]; 10805b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 10815b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy const float u1 = r->left * texX; 1082f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy const float v1 = (height - r->top) * texY; 10835b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy const float u2 = r->right * texX; 1084f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy const float v2 = (height - r->bottom) * texY; 10855b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 10865b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // TODO: Reject quads outside of the clip 10875b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy TextureVertex::set(mesh++, r->left, r->top, u1, v1); 10885b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy TextureVertex::set(mesh++, r->right, r->top, u2, v1); 10895b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy TextureVertex::set(mesh++, r->left, r->bottom, u1, v2); 10905b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy TextureVertex::set(mesh++, r->right, r->bottom, u2, v2); 10915b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 10925b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy numQuads++; 10935b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 10945b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (numQuads >= REGION_MESH_QUAD_COUNT) { 10955b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy glDrawElements(GL_TRIANGLES, numQuads * 6, GL_UNSIGNED_SHORT, NULL); 10965b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy numQuads = 0; 10975b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mesh = mCaches.getRegionMesh(); 10985b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 10995b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 11005b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 11015b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (numQuads > 0) { 11025b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy glDrawElements(GL_TRIANGLES, numQuads * 6, GL_UNSIGNED_SHORT, NULL); 11035b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 11045b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 11057230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy finishDrawTexture(); 11065b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 11075b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#if DEBUG_LAYERS_AS_REGIONS 11083a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy drawRegionRects(layer->region); 11095b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#endif 11105b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 11115b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy layer->region.clear(); 11125b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 11135b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy} 11145b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 11153a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guyvoid OpenGLRenderer::drawRegionRects(const Region& region) { 11163a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy#if DEBUG_LAYERS_AS_REGIONS 11173a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy size_t count; 11183a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy const android::Rect* rects = region.getArray(&count); 11193a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy 11203a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy uint32_t colors[] = { 11213a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy 0x7fff0000, 0x7f00ff00, 11223a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy 0x7f0000ff, 0x7fff00ff, 11233a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy }; 11243a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy 11253a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy int offset = 0; 11263a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy int32_t top = rects[0].top; 11273a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy 11283a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy for (size_t i = 0; i < count; i++) { 11293a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy if (top != rects[i].top) { 11303a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy offset ^= 0x2; 11313a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy top = rects[i].top; 11323a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy } 11333a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy 11343a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy Rect r(rects[i].left, rects[i].top, rects[i].right, rects[i].bottom); 11353a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy drawColorRect(r.left, r.top, r.right, r.bottom, colors[offset + (i & 0x1)], 11363a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy SkXfermode::kSrcOver_Mode); 11373a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy } 11383a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy#endif 11393a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy} 11403a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy 11418ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guyvoid OpenGLRenderer::drawRegionRects(const SkRegion& region, int color, 11428ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy SkXfermode::Mode mode, bool dirty) { 11438ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy int count = 0; 11448ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy Vector<float> rects; 11458ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 11468ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy SkRegion::Iterator it(region); 11478ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy while (!it.done()) { 11488ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy const SkIRect& r = it.rect(); 11498ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy rects.push(r.fLeft); 11508ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy rects.push(r.fTop); 11518ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy rects.push(r.fRight); 11528ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy rects.push(r.fBottom); 11532af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik count += 4; 11548ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy it.next(); 11558ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy } 11568ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 11573bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy drawColorRects(rects.array(), count, color, mode, true, dirty, false); 11588ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy} 11598ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 11605b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guyvoid OpenGLRenderer::dirtyLayer(const float left, const float top, 11615b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy const float right, const float bottom, const mat4 transform) { 1162f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy if (hasLayer()) { 11635b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy Rect bounds(left, top, right, bottom); 11645b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy transform.mapRect(bounds); 1165f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy dirtyLayerUnchecked(bounds, getRegion()); 11665b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 11675b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy} 11685b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 11695b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guyvoid OpenGLRenderer::dirtyLayer(const float left, const float top, 11705b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy const float right, const float bottom) { 1171f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy if (hasLayer()) { 11725b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy Rect bounds(left, top, right, bottom); 1173f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy dirtyLayerUnchecked(bounds, getRegion()); 11741bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy } 11751bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy} 11761bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy 11771bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guyvoid OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) { 11781bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy if (bounds.intersect(*mSnapshot->clipRect)) { 11791bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy bounds.snapToPixelBoundaries(); 11801bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom); 11811bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy if (!dirty.isEmpty()) { 11821bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy region->orSelf(dirty); 11835b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 11845b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 11855b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy} 11865b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 118754be1cdf3d63095512120fa7ced5c16e462abffaRomain Guyvoid OpenGLRenderer::clearLayerRegions() { 118854be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy const size_t count = mLayers.size(); 118954be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy if (count == 0) return; 119054be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy 119154be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy if (!mSnapshot->isIgnored()) { 119254be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy // Doing several glScissor/glClear here can negatively impact 119354be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy // GPUs with a tiler architecture, instead we draw quads with 119454be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy // the Clear blending mode 119554be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy 119654be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy // The list contains bounds that have already been clipped 119754be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy // against their initial clip rect, and the current clip 119854be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy // is likely different so we need to disable clipping here 11998a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy bool scissorChanged = mCaches.disableScissor(); 120054be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy 120154be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy Vertex mesh[count * 6]; 120254be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy Vertex* vertex = mesh; 120354be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy 120454be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy for (uint32_t i = 0; i < count; i++) { 120554be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy Rect* bounds = mLayers.itemAt(i); 120654be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy 120754be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy Vertex::set(vertex++, bounds->left, bounds->bottom); 120854be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy Vertex::set(vertex++, bounds->left, bounds->top); 120954be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy Vertex::set(vertex++, bounds->right, bounds->top); 121054be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy Vertex::set(vertex++, bounds->left, bounds->bottom); 121154be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy Vertex::set(vertex++, bounds->right, bounds->top); 121254be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy Vertex::set(vertex++, bounds->right, bounds->bottom); 121354be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy 121454be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy delete bounds; 121554be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy } 1216e67307c816f3fdae2bfba8e9a4410dc015645e91Romain Guy // We must clear the list of dirty rects before we 1217e67307c816f3fdae2bfba8e9a4410dc015645e91Romain Guy // call setupDraw() to prevent stencil setup to do 1218e67307c816f3fdae2bfba8e9a4410dc015645e91Romain Guy // the same thing again 1219e67307c816f3fdae2bfba8e9a4410dc015645e91Romain Guy mLayers.clear(); 122054be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy 122154be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy setupDraw(false); 122254be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f); 122354be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy setupDrawBlending(true, SkXfermode::kClear_Mode); 122454be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy setupDrawProgram(); 122554be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy setupDrawPureColorUniforms(); 122654be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy setupDrawModelViewTranslate(0.0f, 0.0f, 0.0f, 0.0f, true); 122739d252a6632d057d5077f7eaf1b8ed7a142f3397Romain Guy setupDrawVertices(&mesh[0].position[0]); 122854be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy 122954be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy glDrawArrays(GL_TRIANGLES, 0, count * 6); 12308a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy 12318a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy if (scissorChanged) mCaches.enableScissor(); 123254be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy } else { 123354be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy for (uint32_t i = 0; i < count; i++) { 123454be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy delete mLayers.itemAt(i); 123554be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy } 1236e67307c816f3fdae2bfba8e9a4410dc015645e91Romain Guy mLayers.clear(); 123754be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy } 123854be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy} 123954be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy 1240bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy/////////////////////////////////////////////////////////////////////////////// 1241c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik// State Deferral 1242c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik/////////////////////////////////////////////////////////////////////////////// 1243c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik 1244ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craikbool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDeferFlags) { 1245c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik const Rect& currentClip = *(mSnapshot->clipRect); 1246c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik const mat4& currentMatrix = *(mSnapshot->transform); 1247c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik 1248ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik if (stateDeferFlags & kStateDeferFlag_Draw) { 1249ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik // state has bounds initialized in local coordinates 1250ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik if (!state.mBounds.isEmpty()) { 1251ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik currentMatrix.mapRect(state.mBounds); 1252ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik if (!state.mBounds.intersect(currentClip)) { 1253ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik // quick rejected 1254ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik return true; 1255ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik } 1256ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik } else { 1257ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik state.mBounds.set(currentClip); 1258c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik } 1259ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik state.mDrawModifiers = mDrawModifiers; 1260ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik state.mAlpha = mSnapshot->alpha; 1261ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik } 1262ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik 1263ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik if (stateDeferFlags & kStateDeferFlag_Clip) { 1264ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik state.mClip.set(currentClip); 12655d11676414b3606792e23c269cf75b44faa1a2afChris Craik } else { 1266ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik state.mClip.setEmpty(); 1267c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik } 1268c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik 1269ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik // transform always deferred 1270c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik state.mMatrix.load(currentMatrix); 1271c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik return false; 1272c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik} 1273c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik 1274ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craikvoid OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, int stateDeferFlags) { 12753b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().load(state.mMatrix); 1276c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik 1277ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik if (stateDeferFlags & kStateDeferFlag_Draw) { 1278ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik mDrawModifiers = state.mDrawModifiers; 1279ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik mSnapshot->alpha = state.mAlpha; 1280ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik } 1281ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik 1282d90144db52c7297879b950cbbc85137ed123ab5bChris Craik if (!state.mClip.isEmpty()) { 1283ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik mSnapshot->setClip(state.mClip.left, state.mClip.top, state.mClip.right, state.mClip.bottom); 1284ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik dirtyClip(); 1285ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik } 1286c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik} 1287c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik 1288c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik/////////////////////////////////////////////////////////////////////////////// 1289f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Transforms 1290f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 1291f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 1292f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::translate(float dx, float dy) { 12933b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().translate(dx, dy, 0.0f); 1294f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy} 1295f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 1296f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::rotate(float degrees) { 12973b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().rotate(degrees, 0.0f, 0.0f, 1.0f); 1298f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy} 1299f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 1300f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::scale(float sx, float sy) { 13013b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().scale(sx, sy, 1.0f); 1302f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy} 1303f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 1304807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guyvoid OpenGLRenderer::skew(float sx, float sy) { 13053b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().skew(sx, sy); 1306807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy} 1307807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy 1308f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::setMatrix(SkMatrix* matrix) { 1309e707859415f4c8e1c01228dfaa58fb0a690d442eRomain Guy if (matrix) { 13103b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().load(*matrix); 1311e707859415f4c8e1c01228dfaa58fb0a690d442eRomain Guy } else { 13123b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().loadIdentity(); 1313e707859415f4c8e1c01228dfaa58fb0a690d442eRomain Guy } 1314f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy} 1315f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 1316b98a016c6769b9e80d392df22fe77a2fca048d9fChris Craikbool OpenGLRenderer::hasRectToRectTransform() { 13173b753829ae858d424fe109f714745379a6daf455Romain Guy return CC_LIKELY(currentTransform().rectToRect()); 1318b98a016c6769b9e80d392df22fe77a2fca048d9fChris Craik} 1319b98a016c6769b9e80d392df22fe77a2fca048d9fChris Craik 1320f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::getMatrix(SkMatrix* matrix) { 13213b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().copyTo(*matrix); 1322f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy} 1323f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 1324f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::concatMatrix(SkMatrix* matrix) { 1325e5ebcb0107a939395e03592fd44c746cd09e311dRomain Guy SkMatrix transform; 13263b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().copyTo(transform); 1327e5ebcb0107a939395e03592fd44c746cd09e311dRomain Guy transform.preConcat(*matrix); 13283b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().load(transform); 1329f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy} 1330f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 1331f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 1332f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Clipping 1333f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 1334f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 1335bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid OpenGLRenderer::setScissorFromClip() { 1336e5ebcb0107a939395e03592fd44c746cd09e311dRomain Guy Rect clip(*mSnapshot->clipRect); 1337e5ebcb0107a939395e03592fd44c746cd09e311dRomain Guy clip.snapToPixelBoundaries(); 13388f85e80b64b89fd38cc23b129f61ec36ddde7f15Romain Guy 13398a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy if (mCaches.setScissor(clip.left, mSnapshot->height - clip.bottom, 13408a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy clip.getWidth(), clip.getHeight())) { 13418a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy mDirtyClip = false; 13428a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy } 13439d5316e3f56d138504565ff311145ac01621dff4Romain Guy} 13449d5316e3f56d138504565ff311145ac01621dff4Romain Guy 13458ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guyvoid OpenGLRenderer::ensureStencilBuffer() { 13468ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // Thanks to the mismatch between EGL and OpenGL ES FBO we 13478ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // cannot attach a stencil buffer to fbo0 dynamically. Let's 13488ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // just hope we have one when hasLayer() returns false. 13498ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy if (hasLayer()) { 13508ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy attachStencilBufferToLayer(mSnapshot->layer); 13518ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy } 13528ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy} 13538ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 13548ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guyvoid OpenGLRenderer::attachStencilBufferToLayer(Layer* layer) { 13558ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // The layer's FBO is already bound when we reach this stage 13568ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy if (!layer->getStencilRenderBuffer()) { 1357c3fedafc5f50100219449125a000e3138f6fb987Romain Guy // GL_QCOM_tiled_rendering doesn't like it if a renderbuffer 1358c3fedafc5f50100219449125a000e3138f6fb987Romain Guy // is attached after we initiated tiling. We must turn it off, 1359c3fedafc5f50100219449125a000e3138f6fb987Romain Guy // attach the new render buffer then turn tiling back on 1360c3fedafc5f50100219449125a000e3138f6fb987Romain Guy endTiling(); 1361c3fedafc5f50100219449125a000e3138f6fb987Romain Guy 13628d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy RenderBuffer* buffer = mCaches.renderBufferCache.get( 13633bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy Stencil::getSmallestStencilFormat(), layer->getWidth(), layer->getHeight()); 13648ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy layer->setStencilRenderBuffer(buffer); 1365c3fedafc5f50100219449125a000e3138f6fb987Romain Guy 1366f735c8e5cb59d6e1d1aa152fed7a6480a08d1c2aRomain Guy startTiling(layer->clipRect, layer->layer.getHeight()); 13678ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy } 13688ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy} 13698ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 13708ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guyvoid OpenGLRenderer::setStencilFromClip() { 13718ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy if (!mCaches.debugOverdraw) { 13728ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy if (!mSnapshot->clipRegion->isEmpty()) { 13738ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // NOTE: The order here is important, we must set dirtyClip to false 13748ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // before any draw call to avoid calling back into this method 13758ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy mDirtyClip = false; 13768ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 13778ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy ensureStencilBuffer(); 13788ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 13798ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy mCaches.stencil.enableWrite(); 13808ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 13818ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // Clear the stencil but first make sure we restrict drawing 13828ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // to the region's bounds 13838ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy bool resetScissor = mCaches.enableScissor(); 13848ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy if (resetScissor) { 13858ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // The scissor was not set so we now need to update it 13868ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy setScissorFromClip(); 13878ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy } 13888ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy mCaches.stencil.clear(); 13898ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy if (resetScissor) mCaches.disableScissor(); 13908ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 13918ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // NOTE: We could use the region contour path to generate a smaller mesh 13928ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // Since we are using the stencil we could use the red book path 13938ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // drawing technique. It might increase bandwidth usage though. 13948ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 13958ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // The last parameter is important: we are not drawing in the color buffer 13968ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // so we don't want to dirty the current layer, if any 13978ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy drawRegionRects(*mSnapshot->clipRegion, 0xff000000, SkXfermode::kSrc_Mode, false); 13988ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 13998ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy mCaches.stencil.enableTest(); 14003ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy 14013ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy // Draw the region used to generate the stencil if the appropriate debug 14023ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy // mode is enabled 14033ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy if (mCaches.debugStencilClip == Caches::kStencilShowRegion) { 14043ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy drawRegionRects(*mSnapshot->clipRegion, 0x7f0000ff, SkXfermode::kSrcOver_Mode); 14053ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy } 14068ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy } else { 14078ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy mCaches.stencil.disable(); 14088ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy } 14098ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy } 14108ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy} 14118ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 14129d5316e3f56d138504565ff311145ac01621dff4Romain Guyconst Rect& OpenGLRenderer::getClipBounds() { 1413079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy return mSnapshot->getLocalClip(); 1414bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 1415bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 14168a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guybool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, float bottom) { 14178a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy if (mSnapshot->isIgnored()) { 14188a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy return true; 14198a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy } 14208a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy 14218a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy Rect r(left, top, right, bottom); 14223b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().mapRect(r); 14238a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy r.snapToPixelBoundaries(); 14248a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy 14258a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy Rect clipRect(*mSnapshot->clipRect); 14268a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy clipRect.snapToPixelBoundaries(); 14278a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy 14288a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy return !clipRect.intersects(r); 14298a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy} 14308a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy 143135643ddc689913f5b5f80ceed864470d987bd6cdRomain Guybool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, float bottom, 143235643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy Rect& transformed, Rect& clip) { 143335643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy if (mSnapshot->isIgnored()) { 143435643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy return true; 143535643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy } 143635643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy 143735643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy transformed.set(left, top, right, bottom); 14383b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().mapRect(transformed); 143935643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy transformed.snapToPixelBoundaries(); 144035643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy 144135643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy clip.set(*mSnapshot->clipRect); 144235643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy clip.snapToPixelBoundaries(); 144335643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy 144435643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy return !clip.intersects(transformed); 144535643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy} 144635643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy 1447672433d90fab7383cd28beac9d4485b566a90940Romain Guybool OpenGLRenderer::quickRejectPreStroke(float left, float top, float right, float bottom, 1448672433d90fab7383cd28beac9d4485b566a90940Romain Guy SkPaint* paint) { 1449cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik if (paint->getStyle() != SkPaint::kFill_Style) { 1450cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik float outset = paint->getStrokeWidth() * 0.5f; 1451cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik return quickReject(left - outset, top - outset, right + outset, bottom + outset); 1452cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik } else { 1453cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik return quickReject(left, top, right, bottom); 1454cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik } 1455cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik} 1456cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik 1457c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guybool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) { 1458bf09ffb4e0dc820aeae56a3e576aed33cab218daChris Craik if (mSnapshot->isIgnored() || bottom <= top || right <= left) { 1459dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy return true; 1460dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy } 1461dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy 14621d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy Rect r(left, top, right, bottom); 14633b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().mapRect(r); 1464d2a1ff003b9b1212c9ab4b5f679b5b097720a359Romain Guy r.snapToPixelBoundaries(); 1465d2a1ff003b9b1212c9ab4b5f679b5b097720a359Romain Guy 1466d2a1ff003b9b1212c9ab4b5f679b5b097720a359Romain Guy Rect clipRect(*mSnapshot->clipRect); 1467d2a1ff003b9b1212c9ab4b5f679b5b097720a359Romain Guy clipRect.snapToPixelBoundaries(); 1468d2a1ff003b9b1212c9ab4b5f679b5b097720a359Romain Guy 1469586cae3ac69c0c667fbf8a954edbd399f620a717Romain Guy bool rejected = !clipRect.intersects(r); 1470586cae3ac69c0c667fbf8a954edbd399f620a717Romain Guy if (!isDeferred() && !rejected) { 147187e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mCaches.setScissorEnabled(mScissorOptimizationDisabled || !clipRect.contains(r)); 1472586cae3ac69c0c667fbf8a954edbd399f620a717Romain Guy } 1473586cae3ac69c0c667fbf8a954edbd399f620a717Romain Guy 1474586cae3ac69c0c667fbf8a954edbd399f620a717Romain Guy return rejected; 1475c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy} 1476c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy 14778ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guyvoid OpenGLRenderer::debugClip() { 1478735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy#if DEBUG_CLIP_REGIONS 14798ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy if (!isDeferred() && !mSnapshot->clipRegion->isEmpty()) { 14808ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy drawRegionRects(*mSnapshot->clipRegion, 0x7f00ff00, SkXfermode::kSrcOver_Mode); 14818ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy } 14828ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy#endif 14838ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy} 1484735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy 14858ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guybool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { 14863b753829ae858d424fe109f714745379a6daf455Romain Guy if (CC_LIKELY(currentTransform().rectToRect())) { 14878ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy bool clipped = mSnapshot->clip(left, top, right, bottom, op); 14888ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy if (clipped) { 14898ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy dirtyClip(); 1490735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy } 14918ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy return !mSnapshot->clipRect->isEmpty(); 14927ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy } 14938ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 14948ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy SkPath path; 14958ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy path.addRect(left, top, right, bottom); 14968ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 14978ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy return clipPath(&path, op); 1498e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy} 1499e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 1500735738c4ddf3229caa5f6e634bf591953ac29944Romain Guybool OpenGLRenderer::clipPath(SkPath* path, SkRegion::Op op) { 15018ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy SkMatrix transform; 15023b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().copyTo(transform); 15038ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 15048ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy SkPath transformed; 15058ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy path->transform(transform, &transformed); 15068ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 15078ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy SkRegion clip; 15088ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy if (!mSnapshot->clipRegion->isEmpty()) { 15098ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy clip.setRegion(*mSnapshot->clipRegion); 15108ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy } else { 15118ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy Rect* bounds = mSnapshot->clipRect; 15128ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy clip.setRect(bounds->left, bounds->top, bounds->right, bounds->bottom); 15138ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy } 15148ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 15158ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy SkRegion region; 15168ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy region.setPath(transformed, clip); 15178ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy 15188ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy bool clipped = mSnapshot->clipRegionTransformed(region, op); 15198ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy if (clipped) { 15208ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy dirtyClip(); 15218ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy } 15228ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy return !mSnapshot->clipRect->isEmpty(); 1523735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy} 1524735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy 1525735738c4ddf3229caa5f6e634bf591953ac29944Romain Guybool OpenGLRenderer::clipRegion(SkRegion* region, SkRegion::Op op) { 15268ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy bool clipped = mSnapshot->clipRegionTransformed(*region, op); 15278ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy if (clipped) { 15288ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy dirtyClip(); 15298ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy } 15308ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy return !mSnapshot->clipRect->isEmpty(); 1531735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy} 1532735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy 1533a23eed808a1ae4ec0d818c0a9238385e797fd056Chet HaaseRect* OpenGLRenderer::getClipRect() { 1534a23eed808a1ae4ec0d818c0a9238385e797fd056Chet Haase return mSnapshot->clipRect; 1535a23eed808a1ae4ec0d818c0a9238385e797fd056Chet Haase} 1536a23eed808a1ae4ec0d818c0a9238385e797fd056Chet Haase 1537f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 153870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy// Drawing commands 153970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy/////////////////////////////////////////////////////////////////////////////// 154070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 154154be1cdf3d63095512120fa7ced5c16e462abffaRomain Guyvoid OpenGLRenderer::setupDraw(bool clear) { 15428a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy // TODO: It would be best if we could do this before quickReject() 15438a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy // changes the scissor test state 154454be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy if (clear) clearLayerRegions(); 15458ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // Make sure setScissor & setStencil happen at the beginning of 15468ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy // this method 1547b98a016c6769b9e80d392df22fe77a2fca048d9fChris Craik if (mDirtyClip) { 1548b98a016c6769b9e80d392df22fe77a2fca048d9fChris Craik if (mCaches.scissorEnabled) { 1549b98a016c6769b9e80d392df22fe77a2fca048d9fChris Craik setScissorFromClip(); 1550b98a016c6769b9e80d392df22fe77a2fca048d9fChris Craik } 15518ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy setStencilFromClip(); 155270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 15533ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy 155470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mDescription.reset(); 15553ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy 155670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mSetShaderColor = false; 155770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mColorSet = false; 155870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mColorA = mColorR = mColorG = mColorB = 0.0f; 155970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mTextureUnit = 0; 156070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mTrackDirtyRegions = true; 15613ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy 15623ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy // Enable debug highlight when what we're about to draw is tested against 15633ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy // the stencil buffer and if stencil highlight debugging is on 15643ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy mDescription.hasDebugHighlight = !mCaches.debugOverdraw && 15653ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy mCaches.debugStencilClip == Caches::kStencilShowHighlight && 15663ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy mCaches.stencil.isTestEnabled(); 156770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 156870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 156970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) { 157070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mDescription.hasTexture = true; 157170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mDescription.hasAlpha8Texture = isAlpha8; 157270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 157370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 1574ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guyvoid OpenGLRenderer::setupDrawWithTextureAndColor(bool isAlpha8) { 1575ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy mDescription.hasTexture = true; 1576ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy mDescription.hasColors = true; 1577ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy mDescription.hasAlpha8Texture = isAlpha8; 1578ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy} 1579ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy 1580aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyvoid OpenGLRenderer::setupDrawWithExternalTexture() { 1581aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy mDescription.hasExternalTexture = true; 1582aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy} 1583aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 158415bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guyvoid OpenGLRenderer::setupDrawNoTexture() { 1585ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy mCaches.disableTexCoordsVertexArray(); 158615bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy} 158715bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy 1588710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craikvoid OpenGLRenderer::setupDrawAA() { 158999585adeb4167ca357a72eb866f34c1af944f4b9Chet Haase mDescription.isAA = true; 15905b0200bd47e8a9a4dc8d2e6c3a110d522b30bf82Chet Haase} 15915b0200bd47e8a9a4dc8d2e6c3a110d522b30bf82Chet Haase 1592ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guyvoid OpenGLRenderer::setupDrawPoint(float pointSize) { 1593ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy mDescription.isPoint = true; 1594ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy mDescription.pointSize = pointSize; 1595ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy} 1596ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy 15978d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guyvoid OpenGLRenderer::setupDrawColor(int color, int alpha) { 15988d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy mColorA = alpha / 255.0f; 1599886b275e529e44a59c54b933453d9bc902973178Romain Guy mColorR = mColorA * ((color >> 16) & 0xFF) / 255.0f; 1600886b275e529e44a59c54b933453d9bc902973178Romain Guy mColorG = mColorA * ((color >> 8) & 0xFF) / 255.0f; 1601886b275e529e44a59c54b933453d9bc902973178Romain Guy mColorB = mColorA * ((color ) & 0xFF) / 255.0f; 160270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mColorSet = true; 160370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mSetShaderColor = mDescription.setColor(mColorR, mColorG, mColorB, mColorA); 160470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 160570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 160686568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guyvoid OpenGLRenderer::setupDrawAlpha8Color(int color, int alpha) { 160786568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy mColorA = alpha / 255.0f; 1608886b275e529e44a59c54b933453d9bc902973178Romain Guy mColorR = mColorA * ((color >> 16) & 0xFF) / 255.0f; 1609886b275e529e44a59c54b933453d9bc902973178Romain Guy mColorG = mColorA * ((color >> 8) & 0xFF) / 255.0f; 1610886b275e529e44a59c54b933453d9bc902973178Romain Guy mColorB = mColorA * ((color ) & 0xFF) / 255.0f; 161186568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy mColorSet = true; 161286568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy mSetShaderColor = mDescription.setAlpha8Color(mColorR, mColorG, mColorB, mColorA); 161386568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy} 161486568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy 16154121063313ac0d6f69f6253cac821d0c1c122086Romain Guyvoid OpenGLRenderer::setupDrawTextGamma(const SkPaint* paint) { 16164121063313ac0d6f69f6253cac821d0c1c122086Romain Guy mCaches.fontRenderer->describe(mDescription, paint); 16174121063313ac0d6f69f6253cac821d0c1c122086Romain Guy} 16184121063313ac0d6f69f6253cac821d0c1c122086Romain Guy 161970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) { 162070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mColorA = a; 162170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mColorR = r; 162270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mColorG = g; 162370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mColorB = b; 162470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mColorSet = true; 162570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mSetShaderColor = mDescription.setColor(r, g, b, a); 162670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 162770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 162870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawShader() { 1629c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik if (mDrawModifiers.mShader) { 1630c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mShader->describe(mDescription, mExtensions); 163170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 163270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 163370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 163470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawColorFilter() { 1635c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik if (mDrawModifiers.mColorFilter) { 1636c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mColorFilter->describe(mDescription, mExtensions); 163770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 163870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 163970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 1640f09ef51889f75289b041f9e9f949b7b82ed5b686Romain Guyvoid OpenGLRenderer::accountForClear(SkXfermode::Mode mode) { 1641f09ef51889f75289b041f9e9f949b7b82ed5b686Romain Guy if (mColorSet && mode == SkXfermode::kClear_Mode) { 1642f09ef51889f75289b041f9e9f949b7b82ed5b686Romain Guy mColorA = 1.0f; 1643f09ef51889f75289b041f9e9f949b7b82ed5b686Romain Guy mColorR = mColorG = mColorB = 0.0f; 164454be1cdf3d63095512120fa7ced5c16e462abffaRomain Guy mSetShaderColor = mDescription.modulate = true; 1645f09ef51889f75289b041f9e9f949b7b82ed5b686Romain Guy } 1646f09ef51889f75289b041f9e9f949b7b82ed5b686Romain Guy} 1647f09ef51889f75289b041f9e9f949b7b82ed5b686Romain Guy 164870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawBlending(SkXfermode::Mode mode, bool swapSrcDst) { 1649f09ef51889f75289b041f9e9f949b7b82ed5b686Romain Guy // When the blending mode is kClear_Mode, we need to use a modulate color 1650f09ef51889f75289b041f9e9f949b7b82ed5b686Romain Guy // argb=1,0,0,0 1651f09ef51889f75289b041f9e9f949b7b82ed5b686Romain Guy accountForClear(mode); 1652c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik bool blend = (mColorSet && mColorA < 1.0f) || 1653c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik (mDrawModifiers.mShader && mDrawModifiers.mShader->blend()); 1654c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik chooseBlending(blend, mode, mDescription, swapSrcDst); 165570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 165670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 165770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawBlending(bool blend, SkXfermode::Mode mode, bool swapSrcDst) { 1658f09ef51889f75289b041f9e9f949b7b82ed5b686Romain Guy // When the blending mode is kClear_Mode, we need to use a modulate color 1659f09ef51889f75289b041f9e9f949b7b82ed5b686Romain Guy // argb=1,0,0,0 1660f09ef51889f75289b041f9e9f949b7b82ed5b686Romain Guy accountForClear(mode); 1661c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik blend |= (mColorSet && mColorA < 1.0f) || 1662c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik (mDrawModifiers.mShader && mDrawModifiers.mShader->blend()) || 1663c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik (mDrawModifiers.mColorFilter && mDrawModifiers.mColorFilter->blend()); 1664c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik chooseBlending(blend, mode, mDescription, swapSrcDst); 166570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 166670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 166770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawProgram() { 166870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy useProgram(mCaches.programCache.get(mDescription)); 166970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 167070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 167170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawDirtyRegionsDisabled() { 167270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mTrackDirtyRegions = false; 167370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 167470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 167570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawModelViewTranslate(float left, float top, float right, float bottom, 167670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy bool ignoreTransform) { 167770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mModelView.loadTranslate(left, top, 0.0f); 167870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (!ignoreTransform) { 16793b753829ae858d424fe109f714745379a6daf455Romain Guy mCaches.currentProgram->set(mOrthoMatrix, mModelView, currentTransform()); 16803b753829ae858d424fe109f714745379a6daf455Romain Guy if (mTrackDirtyRegions) dirtyLayer(left, top, right, bottom, currentTransform()); 168170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } else { 1682c74f45a334f0e3725c23cdd270cbcb0efac4ea75Romain Guy mCaches.currentProgram->set(mOrthoMatrix, mModelView, mat4::identity()); 168370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (mTrackDirtyRegions) dirtyLayer(left, top, right, bottom); 168470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 168570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 168670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 16878a5cc92a150bae38ec43732d941b38bb381fe153Chet Haasevoid OpenGLRenderer::setupDrawModelViewIdentity(bool offset) { 16883b753829ae858d424fe109f714745379a6daf455Romain Guy mCaches.currentProgram->set(mOrthoMatrix, mat4::identity(), currentTransform(), offset); 16898d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy} 16908d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy 169170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawModelView(float left, float top, float right, float bottom, 169270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy bool ignoreTransform, bool ignoreModelView) { 169370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (!ignoreModelView) { 169470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mModelView.loadTranslate(left, top, 0.0f); 169570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mModelView.scale(right - left, bottom - top, 1.0f); 169670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } else { 169770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mModelView.loadIdentity(); 169870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 169986568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy bool dirty = right - left > 0.0f && bottom - top > 0.0f; 170086568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy if (!ignoreTransform) { 17013b753829ae858d424fe109f714745379a6daf455Romain Guy mCaches.currentProgram->set(mOrthoMatrix, mModelView, currentTransform()); 170286568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy if (mTrackDirtyRegions && dirty) { 17033b753829ae858d424fe109f714745379a6daf455Romain Guy dirtyLayer(left, top, right, bottom, currentTransform()); 170486568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy } 170586568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy } else { 1706c74f45a334f0e3725c23cdd270cbcb0efac4ea75Romain Guy mCaches.currentProgram->set(mOrthoMatrix, mModelView, mat4::identity()); 170786568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy if (mTrackDirtyRegions && dirty) dirtyLayer(left, top, right, bottom); 170886568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy } 170970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 171070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 1711ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guyvoid OpenGLRenderer::setupDrawPointUniforms() { 1712ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy int slot = mCaches.currentProgram->getUniform("pointSize"); 1713ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy glUniform1f(slot, mDescription.pointSize); 1714ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy} 1715ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy 171670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawColorUniforms() { 1717c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik if ((mColorSet && !mDrawModifiers.mShader) || (mDrawModifiers.mShader && mSetShaderColor)) { 171870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mCaches.currentProgram->setColor(mColorR, mColorG, mColorB, mColorA); 171970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 172070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 172170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 172286568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guyvoid OpenGLRenderer::setupDrawPureColorUniforms() { 17235536841e5452172e7772d84ad5f4a2fc7059c9ddRomain Guy if (mSetShaderColor) { 172486568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy mCaches.currentProgram->setColor(mColorR, mColorG, mColorB, mColorA); 17255536841e5452172e7772d84ad5f4a2fc7059c9ddRomain Guy } 17265536841e5452172e7772d84ad5f4a2fc7059c9ddRomain Guy} 17275536841e5452172e7772d84ad5f4a2fc7059c9ddRomain Guy 172870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawShaderUniforms(bool ignoreTransform) { 1729c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik if (mDrawModifiers.mShader) { 173070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (ignoreTransform) { 17313b753829ae858d424fe109f714745379a6daf455Romain Guy mModelView.loadInverse(currentTransform()); 173270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 1733c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mShader->setupProgram(mCaches.currentProgram, 1734c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mModelView, *mSnapshot, &mTextureUnit); 173570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 173670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 173770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 17388d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guyvoid OpenGLRenderer::setupDrawShaderIdentityUniforms() { 1739c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik if (mDrawModifiers.mShader) { 1740c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mShader->setupProgram(mCaches.currentProgram, 1741c74f45a334f0e3725c23cdd270cbcb0efac4ea75Romain Guy mat4::identity(), *mSnapshot, &mTextureUnit); 17428d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy } 17438d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy} 17448d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy 174570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawColorFilterUniforms() { 1746c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik if (mDrawModifiers.mColorFilter) { 1747c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mColorFilter->setupProgram(mCaches.currentProgram); 174870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 174970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 175070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 17514121063313ac0d6f69f6253cac821d0c1c122086Romain Guyvoid OpenGLRenderer::setupDrawTextGammaUniforms() { 17524121063313ac0d6f69f6253cac821d0c1c122086Romain Guy mCaches.fontRenderer->setupProgram(mDescription, mCaches.currentProgram); 17534121063313ac0d6f69f6253cac821d0c1c122086Romain Guy} 17544121063313ac0d6f69f6253cac821d0c1c122086Romain Guy 175570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawSimpleMesh() { 1756f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy bool force = mCaches.bindMeshBuffer(); 1757cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik mCaches.bindPositionVertexPointer(force, 0); 175815bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy mCaches.unbindIndicesBuffer(); 175970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 176070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 176170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawTexture(GLuint texture) { 1762257ae3502cfad43df681b1783528d645bdabc63fRomain Guy if (texture) bindTexture(texture); 17632d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy mTextureUnit++; 176415bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy mCaches.enableTexCoordsVertexArray(); 176570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 176670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 1767aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyvoid OpenGLRenderer::setupDrawExternalTexture(GLuint texture) { 1768aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy bindExternalTexture(texture); 17692d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy mTextureUnit++; 177015bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy mCaches.enableTexCoordsVertexArray(); 1771aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy} 1772aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 17738f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyvoid OpenGLRenderer::setupDrawTextureTransform() { 17748f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy mDescription.hasTextureTransform = true; 17758f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy} 17768f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy 17778f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyvoid OpenGLRenderer::setupDrawTextureTransformUniforms(mat4& transform) { 1778aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy glUniformMatrix4fv(mCaches.currentProgram->getUniform("mainTextureTransform"), 1, 1779aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy GL_FALSE, &transform.data[0]); 1780aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy} 1781aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 178270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint vbo) { 1783f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy bool force = false; 178470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (!vertices) { 1785f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy force = mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo); 178670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } else { 1787f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy force = mCaches.unbindMeshBuffer(); 178870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 1789d71dd367af604571c7d00ca473184a1b9240eca2Romain Guy 1790cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik mCaches.bindPositionVertexPointer(force, vertices); 179115bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy if (mCaches.currentProgram->texCoords >= 0) { 1792cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik mCaches.bindTexCoordsVertexPointer(force, texCoords); 179315bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy } 179415bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy 179515bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy mCaches.unbindIndicesBuffer(); 179615bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy} 179715bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy 1798ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guyvoid OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLvoid* colors) { 1799ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy bool force = mCaches.unbindMeshBuffer(); 1800ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy GLsizei stride = sizeof(ColorTextureVertex); 1801ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy 1802ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy mCaches.bindPositionVertexPointer(force, vertices, stride); 1803ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy if (mCaches.currentProgram->texCoords >= 0) { 1804ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy mCaches.bindTexCoordsVertexPointer(force, texCoords, stride); 1805ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy } 1806ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy int slot = mCaches.currentProgram->getAttrib("colors"); 1807ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy if (slot >= 0) { 1808ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy glEnableVertexAttribArray(slot); 1809ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy glVertexAttribPointer(slot, 4, GL_FLOAT, GL_FALSE, stride, colors); 1810ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy } 1811ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy 1812ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy mCaches.unbindIndicesBuffer(); 1813ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy} 1814ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy 181515bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guyvoid OpenGLRenderer::setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords) { 181615bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy bool force = mCaches.unbindMeshBuffer(); 1817cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik mCaches.bindPositionVertexPointer(force, vertices); 181815bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy if (mCaches.currentProgram->texCoords >= 0) { 1819cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik mCaches.bindTexCoordsVertexPointer(force, texCoords); 18208d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy } 182170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 182270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 18235b0200bd47e8a9a4dc8d2e6c3a110d522b30bf82Chet Haasevoid OpenGLRenderer::setupDrawVertices(GLvoid* vertices) { 1824f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy bool force = mCaches.unbindMeshBuffer(); 1825cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik mCaches.bindPositionVertexPointer(force, vertices, gVertexStride); 182615bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy mCaches.unbindIndicesBuffer(); 18275b0200bd47e8a9a4dc8d2e6c3a110d522b30bf82Chet Haase} 18285b0200bd47e8a9a4dc8d2e6c3a110d522b30bf82Chet Haase 182970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guyvoid OpenGLRenderer::finishDrawTexture() { 183070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy} 183170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 183270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy/////////////////////////////////////////////////////////////////////////////// 1833f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Drawing 1834f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 1835f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 1836ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craikstatus_t OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, 1837ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik int32_t replayFlags) { 18380fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy // All the usual checks and setup operations (quickReject, setupDraw, etc.) 18390fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy // will be performed by the display list itself 184004c9d8c2ffd028c35c750bac0a4a7b79e48059b5Romain Guy if (displayList && displayList->isRenderable()) { 1841d90144db52c7297879b950cbbc85137ed123ab5bChris Craik if (CC_UNLIKELY(mCaches.drawDeferDisabled)) { 1842ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik ReplayStateStruct replayStruct(*this, dirty, replayFlags); 1843ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik displayList->replay(replayStruct, 0); 1844ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik return replayStruct.mDrawGlStatus; 1845c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik } 1846c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik 1847c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik DeferredDisplayList deferredList; 1848ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik DeferStateStruct deferStruct(deferredList, *this, replayFlags); 1849ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik displayList->defer(deferStruct, 0); 1850ff78583d8a73ca35ce65b5d2592570ff6fb9901bChris Craik return deferredList.flush(*this, dirty); 18510fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy } 18527b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy 18536554943a1dd6854c0f4976900956e556767b49e1Romain Guy return DrawGlInfo::kStatusDone; 18540fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy} 18550fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy 1856c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craikvoid OpenGLRenderer::outputDisplayList(DisplayList* displayList) { 1857ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase if (displayList) { 18587031ff68bb998dbbd7caf3b2fd75eef747a86725Romain Guy displayList->output(1); 1859ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase } 1860ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase} 1861ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase 1862a168d7372132d6c87835878794b6ed43d0d282fdRomain Guyvoid OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint) { 1863a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy int alpha; 1864a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy SkXfermode::Mode mode; 1865a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy getAlphaAndMode(paint, &alpha, &mode); 1866a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy 1867886b275e529e44a59c54b933453d9bc902973178Romain Guy int color = paint != NULL ? paint->getColor() : 0; 1868886b275e529e44a59c54b933453d9bc902973178Romain Guy 1869a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy float x = left; 1870a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy float y = top; 1871a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy 1872886b275e529e44a59c54b933453d9bc902973178Romain Guy texture->setWrap(GL_CLAMP_TO_EDGE, true); 1873886b275e529e44a59c54b933453d9bc902973178Romain Guy 1874a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy bool ignoreTransform = false; 18753b753829ae858d424fe109f714745379a6daf455Romain Guy if (currentTransform().isPureTranslate()) { 18763b753829ae858d424fe109f714745379a6daf455Romain Guy x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f); 18773b753829ae858d424fe109f714745379a6daf455Romain Guy y = (int) floorf(top + currentTransform().getTranslateY() + 0.5f); 1878a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy ignoreTransform = true; 1879a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy 1880886b275e529e44a59c54b933453d9bc902973178Romain Guy texture->setFilter(GL_NEAREST, true); 1881886b275e529e44a59c54b933453d9bc902973178Romain Guy } else { 1882886b275e529e44a59c54b933453d9bc902973178Romain Guy texture->setFilter(FILTER(paint), true); 18835b7a3150a6dbf193b371854b66fa654937633d3aRomain Guy } 1884e3c26851dc315b730ea0fe5ef35bb1db81f6d675Romain Guy 1885886b275e529e44a59c54b933453d9bc902973178Romain Guy drawAlpha8TextureMesh(x, y, x + texture->width, y + texture->height, texture->id, 1886886b275e529e44a59c54b933453d9bc902973178Romain Guy paint != NULL, color, alpha, mode, (GLvoid*) NULL, 1887886b275e529e44a59c54b933453d9bc902973178Romain Guy (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform); 1888a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy} 1889a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy 1890486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) { 18916926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy const float right = left + bitmap->width(); 18926926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy const float bottom = top + bitmap->height(); 18936926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 18946926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy if (quickReject(left, top, right, bottom)) { 1895486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDone; 18966926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy } 18976926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 1898a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy mCaches.activeTexture(0); 18998164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy Texture* texture = mCaches.textureCache.get(bitmap); 1900486590963e2207d68eebd6944fec70d50d41116aChet Haase if (!texture) return DrawGlInfo::kStatusDone; 190122158e139a3d6c6a9787ca0de224e9368f643284Romain Guy const AutoTexture autoCleanup(texture); 190222158e139a3d6c6a9787ca0de224e9368f643284Romain Guy 1903211370fd943cf26905001b38b8b1791851b26adcRomain Guy if (CC_UNLIKELY(bitmap->getConfig() == SkBitmap::kA8_Config)) { 1904a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy drawAlphaBitmap(texture, left, top, paint); 1905a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy } else { 1906a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy drawTextureRect(left, top, right, bottom, texture, paint); 1907a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy } 1908486590963e2207d68eebd6944fec70d50d41116aChet Haase 1909486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDrew; 19108ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy} 19118ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 1912486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) { 1913f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy Rect r(0.0f, 0.0f, bitmap->width(), bitmap->height()); 1914f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy const mat4 transform(*matrix); 1915f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy transform.mapRect(r); 1916f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy 19176926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy if (quickReject(r.left, r.top, r.right, r.bottom)) { 1918486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDone; 19196926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy } 19206926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 1921a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy mCaches.activeTexture(0); 19228164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy Texture* texture = mCaches.textureCache.get(bitmap); 1923486590963e2207d68eebd6944fec70d50d41116aChet Haase if (!texture) return DrawGlInfo::kStatusDone; 192422158e139a3d6c6a9787ca0de224e9368f643284Romain Guy const AutoTexture autoCleanup(texture); 192522158e139a3d6c6a9787ca0de224e9368f643284Romain Guy 19265b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // This could be done in a cheaper way, all we need is pass the matrix 19275b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // to the vertex shader. The save/restore is a bit overkill. 19285b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy save(SkCanvas::kMatrix_SaveFlag); 19295b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy concatMatrix(matrix); 1930886b275e529e44a59c54b933453d9bc902973178Romain Guy if (CC_UNLIKELY(bitmap->getConfig() == SkBitmap::kA8_Config)) { 1931886b275e529e44a59c54b933453d9bc902973178Romain Guy drawAlphaBitmap(texture, 0.0f, 0.0f, paint); 1932886b275e529e44a59c54b933453d9bc902973178Romain Guy } else { 1933886b275e529e44a59c54b933453d9bc902973178Romain Guy drawTextureRect(0.0f, 0.0f, bitmap->width(), bitmap->height(), texture, paint); 1934886b275e529e44a59c54b933453d9bc902973178Romain Guy } 19355b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy restore(); 1936486590963e2207d68eebd6944fec70d50d41116aChet Haase 1937486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDrew; 1938f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy} 1939f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy 1940486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top, SkPaint* paint) { 1941e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy const float right = left + bitmap->width(); 1942e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy const float bottom = top + bitmap->height(); 1943e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy 1944e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy if (quickReject(left, top, right, bottom)) { 1945486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDone; 1946e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy } 1947e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy 1948e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy mCaches.activeTexture(0); 1949e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy Texture* texture = mCaches.textureCache.getTransient(bitmap); 1950e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy const AutoTexture autoCleanup(texture); 1951e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy 1952886b275e529e44a59c54b933453d9bc902973178Romain Guy if (CC_UNLIKELY(bitmap->getConfig() == SkBitmap::kA8_Config)) { 1953886b275e529e44a59c54b933453d9bc902973178Romain Guy drawAlphaBitmap(texture, left, top, paint); 1954886b275e529e44a59c54b933453d9bc902973178Romain Guy } else { 1955886b275e529e44a59c54b933453d9bc902973178Romain Guy drawTextureRect(left, top, right, bottom, texture, paint); 1956886b275e529e44a59c54b933453d9bc902973178Romain Guy } 1957486590963e2207d68eebd6944fec70d50d41116aChet Haase 1958486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDrew; 1959e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy} 1960e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy 1961486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight, 19625a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy float* vertices, int* colors, SkPaint* paint) { 19635a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy if (!vertices || mSnapshot->isIgnored()) { 1964486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDone; 19655a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } 19665a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 1967b18d2d0079b4dbf5675ab79b7111b3dfb3cc1ad0Romain Guy float left = FLT_MAX; 1968b18d2d0079b4dbf5675ab79b7111b3dfb3cc1ad0Romain Guy float top = FLT_MAX; 1969b18d2d0079b4dbf5675ab79b7111b3dfb3cc1ad0Romain Guy float right = FLT_MIN; 1970b18d2d0079b4dbf5675ab79b7111b3dfb3cc1ad0Romain Guy float bottom = FLT_MIN; 1971b18d2d0079b4dbf5675ab79b7111b3dfb3cc1ad0Romain Guy 1972a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy const uint32_t count = meshWidth * meshHeight * 6; 1973b18d2d0079b4dbf5675ab79b7111b3dfb3cc1ad0Romain Guy 1974ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy ColorTextureVertex mesh[count]; 1975ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy ColorTextureVertex* vertex = mesh; 1976ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy 1977ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy bool cleanupColors = false; 1978ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy if (!colors) { 1979ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy uint32_t colorsCount = (meshWidth + 1) * (meshHeight + 1); 1980ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy colors = new int[colorsCount]; 1981ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy memset(colors, 0xff, colorsCount * sizeof(int)); 1982ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy cleanupColors = true; 1983ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy } 1984a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy 19855a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy for (int32_t y = 0; y < meshHeight; y++) { 19865a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy for (int32_t x = 0; x < meshWidth; x++) { 19875a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy uint32_t i = (y * (meshWidth + 1) + x) * 2; 19885a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 19895a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy float u1 = float(x) / meshWidth; 19905a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy float u2 = float(x + 1) / meshWidth; 19915a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy float v1 = float(y) / meshHeight; 19925a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy float v2 = float(y + 1) / meshHeight; 19935a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 19945a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy int ax = i + (meshWidth + 1) * 2; 19955a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy int ay = ax + 1; 19965a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy int bx = i; 19975a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy int by = bx + 1; 19985a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy int cx = i + 2; 19995a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy int cy = cx + 1; 20005a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy int dx = i + (meshWidth + 1) * 2 + 2; 20015a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy int dy = dx + 1; 20025a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 2003ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]); 2004ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy ColorTextureVertex::set(vertex++, vertices[ax], vertices[ay], u1, v2, colors[ax / 2]); 2005ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]); 20065a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 2007ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]); 2008ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]); 2009ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy ColorTextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1, colors[cx / 2]); 2010b18d2d0079b4dbf5675ab79b7111b3dfb3cc1ad0Romain Guy 2011a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy left = fminf(left, fminf(vertices[ax], fminf(vertices[bx], vertices[cx]))); 2012a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy top = fminf(top, fminf(vertices[ay], fminf(vertices[by], vertices[cy]))); 2013a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy right = fmaxf(right, fmaxf(vertices[ax], fmaxf(vertices[bx], vertices[cx]))); 2014a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy bottom = fmaxf(bottom, fmaxf(vertices[ay], fmaxf(vertices[by], vertices[cy]))); 20155a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } 20165a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } 20175a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 2018a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy if (quickReject(left, top, right, bottom)) { 2019ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy if (cleanupColors) delete[] colors; 2020a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy return DrawGlInfo::kStatusDone; 2021a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy } 2022a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy 2023a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy mCaches.activeTexture(0); 2024a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy Texture* texture = mCaches.textureCache.get(bitmap); 2025ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy if (!texture) { 2026ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy if (cleanupColors) delete[] colors; 2027ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy return DrawGlInfo::kStatusDone; 2028ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy } 2029a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy const AutoTexture autoCleanup(texture); 2030a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy 2031a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy texture->setWrap(GL_CLAMP_TO_EDGE, true); 2032a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy texture->setFilter(FILTER(paint), true); 2033a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy 2034a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy int alpha; 2035a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy SkXfermode::Mode mode; 2036a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy getAlphaAndMode(paint, &alpha, &mode); 2037a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy 2038ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy float a = alpha / 255.0f; 2039ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy 2040a92bb4dc9605c86b8773c929412af2dc242b1fa8Romain Guy if (hasLayer()) { 20413b753829ae858d424fe109f714745379a6daf455Romain Guy dirtyLayer(left, top, right, bottom, currentTransform()); 2042b18d2d0079b4dbf5675ab79b7111b3dfb3cc1ad0Romain Guy } 2043b18d2d0079b4dbf5675ab79b7111b3dfb3cc1ad0Romain Guy 2044ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy setupDraw(); 2045ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy setupDrawWithTextureAndColor(); 2046ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy setupDrawColor(a, a, a, a); 2047ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy setupDrawColorFilter(); 2048ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy setupDrawBlending(true, mode, false); 2049ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy setupDrawProgram(); 2050ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy setupDrawDirtyRegionsDisabled(); 2051ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy setupDrawModelView(0.0f, 0.0f, 1.0f, 1.0f, false); 2052ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy setupDrawTexture(texture->id); 2053ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy setupDrawPureColorUniforms(); 2054ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy setupDrawColorFilterUniforms(); 2055ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy setupDrawMesh(&mesh[0].position[0], &mesh[0].texture[0], &mesh[0].color[0]); 2056ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy 2057ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy glDrawArrays(GL_TRIANGLES, 0, count); 2058ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy 2059ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy finishDrawTexture(); 2060ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy 2061ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy int slot = mCaches.currentProgram->getAttrib("colors"); 2062ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy if (slot >= 0) { 2063ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy glDisableVertexAttribArray(slot); 2064ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy } 2065ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy 2066ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy if (cleanupColors) delete[] colors; 2067486590963e2207d68eebd6944fec70d50d41116aChet Haase 2068486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDrew; 20695a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy} 20705a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 2071486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, 20728ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy float srcLeft, float srcTop, float srcRight, float srcBottom, 20738ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy float dstLeft, float dstTop, float dstRight, float dstBottom, 20745c13d89c1332fcc499379b9064b891187b75ca32Chet Haase SkPaint* paint) { 20756926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy if (quickReject(dstLeft, dstTop, dstRight, dstBottom)) { 2076486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDone; 20776926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy } 20786926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 2079a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy mCaches.activeTexture(0); 20808164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy Texture* texture = mCaches.textureCache.get(bitmap); 2081486590963e2207d68eebd6944fec70d50d41116aChet Haase if (!texture) return DrawGlInfo::kStatusDone; 208222158e139a3d6c6a9787ca0de224e9368f643284Romain Guy const AutoTexture autoCleanup(texture); 20838ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 20848ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy const float width = texture->width; 20858ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy const float height = texture->height; 2086c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy 20876816972eb69ee8b294553dac92b3c1ad5b1ca1f7Romain Guy const float u1 = fmax(0.0f, srcLeft / width); 20886816972eb69ee8b294553dac92b3c1ad5b1ca1f7Romain Guy const float v1 = fmax(0.0f, srcTop / height); 20896816972eb69ee8b294553dac92b3c1ad5b1ca1f7Romain Guy const float u2 = fmin(1.0f, srcRight / width); 20906816972eb69ee8b294553dac92b3c1ad5b1ca1f7Romain Guy const float v2 = fmin(1.0f, srcBottom / height); 2091c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy 209203750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy mCaches.unbindMeshBuffer(); 20938ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy resetDrawTextureTexCoords(u1, v1, u2, v2); 20948ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 209503750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy int alpha; 209603750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy SkXfermode::Mode mode; 209703750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy getAlphaAndMode(paint, &alpha, &mode); 209803750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy 2099d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy texture->setWrap(GL_CLAMP_TO_EDGE, true); 2100d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy 2101886b275e529e44a59c54b933453d9bc902973178Romain Guy float scaleX = (dstRight - dstLeft) / (srcRight - srcLeft); 2102886b275e529e44a59c54b933453d9bc902973178Romain Guy float scaleY = (dstBottom - dstTop) / (srcBottom - srcTop); 21036620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy 2104886b275e529e44a59c54b933453d9bc902973178Romain Guy bool scaled = scaleX != 1.0f || scaleY != 1.0f; 2105886b275e529e44a59c54b933453d9bc902973178Romain Guy // Apply a scale transform on the canvas only when a shader is in use 2106886b275e529e44a59c54b933453d9bc902973178Romain Guy // Skia handles the ratio between the dst and src rects as a scale factor 2107886b275e529e44a59c54b933453d9bc902973178Romain Guy // when a shader is set 2108c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik bool useScaleTransform = mDrawModifiers.mShader && scaled; 2109886b275e529e44a59c54b933453d9bc902973178Romain Guy bool ignoreTransform = false; 2110b50149825fae95b2918bcf67b2ddb773b9797068Romain Guy 21113b753829ae858d424fe109f714745379a6daf455Romain Guy if (CC_LIKELY(currentTransform().isPureTranslate() && !useScaleTransform)) { 21123b753829ae858d424fe109f714745379a6daf455Romain Guy float x = (int) floorf(dstLeft + currentTransform().getTranslateX() + 0.5f); 21133b753829ae858d424fe109f714745379a6daf455Romain Guy float y = (int) floorf(dstTop + currentTransform().getTranslateY() + 0.5f); 2114886b275e529e44a59c54b933453d9bc902973178Romain Guy 2115886b275e529e44a59c54b933453d9bc902973178Romain Guy dstRight = x + (dstRight - dstLeft); 2116886b275e529e44a59c54b933453d9bc902973178Romain Guy dstBottom = y + (dstBottom - dstTop); 2117886b275e529e44a59c54b933453d9bc902973178Romain Guy 2118886b275e529e44a59c54b933453d9bc902973178Romain Guy dstLeft = x; 2119886b275e529e44a59c54b933453d9bc902973178Romain Guy dstTop = y; 2120886b275e529e44a59c54b933453d9bc902973178Romain Guy 2121886b275e529e44a59c54b933453d9bc902973178Romain Guy texture->setFilter(scaled ? FILTER(paint) : GL_NEAREST, true); 2122886b275e529e44a59c54b933453d9bc902973178Romain Guy ignoreTransform = true; 21236620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } else { 2124d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy texture->setFilter(FILTER(paint), true); 2125886b275e529e44a59c54b933453d9bc902973178Romain Guy } 2126886b275e529e44a59c54b933453d9bc902973178Romain Guy 2127886b275e529e44a59c54b933453d9bc902973178Romain Guy if (CC_UNLIKELY(useScaleTransform)) { 2128886b275e529e44a59c54b933453d9bc902973178Romain Guy save(SkCanvas::kMatrix_SaveFlag); 2129886b275e529e44a59c54b933453d9bc902973178Romain Guy translate(dstLeft, dstTop); 2130886b275e529e44a59c54b933453d9bc902973178Romain Guy scale(scaleX, scaleY); 2131886b275e529e44a59c54b933453d9bc902973178Romain Guy 2132886b275e529e44a59c54b933453d9bc902973178Romain Guy dstLeft = 0.0f; 2133886b275e529e44a59c54b933453d9bc902973178Romain Guy dstTop = 0.0f; 2134886b275e529e44a59c54b933453d9bc902973178Romain Guy 2135886b275e529e44a59c54b933453d9bc902973178Romain Guy dstRight = srcRight - srcLeft; 2136886b275e529e44a59c54b933453d9bc902973178Romain Guy dstBottom = srcBottom - srcTop; 2137886b275e529e44a59c54b933453d9bc902973178Romain Guy } 2138886b275e529e44a59c54b933453d9bc902973178Romain Guy 2139886b275e529e44a59c54b933453d9bc902973178Romain Guy if (CC_UNLIKELY(bitmap->getConfig() == SkBitmap::kA8_Config)) { 2140886b275e529e44a59c54b933453d9bc902973178Romain Guy int color = paint ? paint->getColor() : 0; 2141886b275e529e44a59c54b933453d9bc902973178Romain Guy drawAlpha8TextureMesh(dstLeft, dstTop, dstRight, dstBottom, 2142886b275e529e44a59c54b933453d9bc902973178Romain Guy texture->id, paint != NULL, color, alpha, mode, 2143886b275e529e44a59c54b933453d9bc902973178Romain Guy &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], 2144886b275e529e44a59c54b933453d9bc902973178Romain Guy GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform); 2145886b275e529e44a59c54b933453d9bc902973178Romain Guy } else { 2146886b275e529e44a59c54b933453d9bc902973178Romain Guy drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom, 2147886b275e529e44a59c54b933453d9bc902973178Romain Guy texture->id, alpha / 255.0f, mode, texture->blend, 2148886b275e529e44a59c54b933453d9bc902973178Romain Guy &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], 2149886b275e529e44a59c54b933453d9bc902973178Romain Guy GL_TRIANGLE_STRIP, gMeshCount, false, ignoreTransform); 2150886b275e529e44a59c54b933453d9bc902973178Romain Guy } 2151886b275e529e44a59c54b933453d9bc902973178Romain Guy 2152886b275e529e44a59c54b933453d9bc902973178Romain Guy if (CC_UNLIKELY(useScaleTransform)) { 2153886b275e529e44a59c54b933453d9bc902973178Romain Guy restore(); 21546620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } 21558ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 21568ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); 2157486590963e2207d68eebd6944fec70d50d41116aChet Haase 2158486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDrew; 2159ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 2160ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 2161486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs, 21624bb942083a0d4db746adf95349108dd8ef842e32Romain Guy const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors, 21635c13d89c1332fcc499379b9064b891187b75ca32Chet Haase float left, float top, float right, float bottom, SkPaint* paint) { 2164be6f9dc1e71b425b7ac1c40c0a2c72d03eb9fbeeRomain Guy int alpha; 2165be6f9dc1e71b425b7ac1c40c0a2c72d03eb9fbeeRomain Guy SkXfermode::Mode mode; 2166be6f9dc1e71b425b7ac1c40c0a2c72d03eb9fbeeRomain Guy getAlphaAndModeDirect(paint, &alpha, &mode); 2167be6f9dc1e71b425b7ac1c40c0a2c72d03eb9fbeeRomain Guy 2168be6f9dc1e71b425b7ac1c40c0a2c72d03eb9fbeeRomain Guy return drawPatch(bitmap, xDivs, yDivs, colors, width, height, numColors, 2169be6f9dc1e71b425b7ac1c40c0a2c72d03eb9fbeeRomain Guy left, top, right, bottom, alpha, mode); 2170be6f9dc1e71b425b7ac1c40c0a2c72d03eb9fbeeRomain Guy} 2171be6f9dc1e71b425b7ac1c40c0a2c72d03eb9fbeeRomain Guy 2172be6f9dc1e71b425b7ac1c40c0a2c72d03eb9fbeeRomain Guystatus_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs, 2173be6f9dc1e71b425b7ac1c40c0a2c72d03eb9fbeeRomain Guy const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors, 2174be6f9dc1e71b425b7ac1c40c0a2c72d03eb9fbeeRomain Guy float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode) { 21756926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy if (quickReject(left, top, right, bottom)) { 2176486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDone; 21776926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy } 21786926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 2179be6f9dc1e71b425b7ac1c40c0a2c72d03eb9fbeeRomain Guy alpha *= mSnapshot->alpha; 2180be6f9dc1e71b425b7ac1c40c0a2c72d03eb9fbeeRomain Guy 21812728f961614a385df1f056fc24803a9f65c90fabRomain Guy const Patch* mesh = mCaches.patchCache.get(bitmap->width(), bitmap->height(), 21824bb942083a0d4db746adf95349108dd8ef842e32Romain Guy right - left, bottom - top, xDivs, yDivs, colors, width, height, numColors); 2183f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 2184211370fd943cf26905001b38b8b1791851b26adcRomain Guy if (CC_LIKELY(mesh && mesh->verticesCount > 0)) { 2185a4adcf0239039eb8f005be252409901c41b28839Romain Guy mCaches.activeTexture(0); 2186a4adcf0239039eb8f005be252409901c41b28839Romain Guy Texture* texture = mCaches.textureCache.get(bitmap); 2187a4adcf0239039eb8f005be252409901c41b28839Romain Guy if (!texture) return DrawGlInfo::kStatusDone; 2188a4adcf0239039eb8f005be252409901c41b28839Romain Guy const AutoTexture autoCleanup(texture); 2189a4adcf0239039eb8f005be252409901c41b28839Romain Guy texture->setWrap(GL_CLAMP_TO_EDGE, true); 2190a4adcf0239039eb8f005be252409901c41b28839Romain Guy texture->setFilter(GL_LINEAR, true); 2191a4adcf0239039eb8f005be252409901c41b28839Romain Guy 21923b753829ae858d424fe109f714745379a6daf455Romain Guy const bool pureTranslate = currentTransform().isPureTranslate(); 21935b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // Mark the current layer dirty where we are going to draw the patch 21948168396d1acbcb5fdd29eeda4c30b2803d5283aeRomain Guy if (hasLayer() && mesh->hasEmptyQuads) { 21953b753829ae858d424fe109f714745379a6daf455Romain Guy const float offsetX = left + currentTransform().getTranslateX(); 21963b753829ae858d424fe109f714745379a6daf455Romain Guy const float offsetY = top + currentTransform().getTranslateY(); 21975b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy const size_t count = mesh->quads.size(); 21985b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy for (size_t i = 0; i < count; i++) { 21998ab4079ca27e36e5c584495bcd71b573598ac021Romain Guy const Rect& bounds = mesh->quads.itemAt(i); 2200211370fd943cf26905001b38b8b1791851b26adcRomain Guy if (CC_LIKELY(pureTranslate)) { 2201c78b5d50f961ac8f696f8282979ae283cacd3574Romain Guy const float x = (int) floorf(bounds.left + offsetX + 0.5f); 2202c78b5d50f961ac8f696f8282979ae283cacd3574Romain Guy const float y = (int) floorf(bounds.top + offsetY + 0.5f); 2203c78b5d50f961ac8f696f8282979ae283cacd3574Romain Guy dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getHeight()); 22046620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } else { 2205c78b5d50f961ac8f696f8282979ae283cacd3574Romain Guy dirtyLayer(left + bounds.left, top + bounds.top, 22063b753829ae858d424fe109f714745379a6daf455Romain Guy left + bounds.right, top + bounds.bottom, currentTransform()); 22076620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } 22085b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 22095b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 22105b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 2211211370fd943cf26905001b38b8b1791851b26adcRomain Guy if (CC_LIKELY(pureTranslate)) { 22123b753829ae858d424fe109f714745379a6daf455Romain Guy const float x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f); 22133b753829ae858d424fe109f714745379a6daf455Romain Guy const float y = (int) floorf(top + currentTransform().getTranslateY() + 0.5f); 22146620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy 22156620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy drawTextureMesh(x, y, x + right - left, y + bottom - top, texture->id, alpha / 255.0f, 22166620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy mode, texture->blend, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset, 22176620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy GL_TRIANGLES, mesh->verticesCount, false, true, mesh->meshBuffer, 22186620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy true, !mesh->hasEmptyQuads); 22196620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } else { 22206620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, 22216620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy mode, texture->blend, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset, 22226620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy GL_TRIANGLES, mesh->verticesCount, false, false, mesh->meshBuffer, 22236620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy true, !mesh->hasEmptyQuads); 22246620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } 2225054dc1840941665e32036f9523df51720ad069c8Romain Guy } 2226486590963e2207d68eebd6944fec70d50d41116aChet Haase 2227486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDrew; 2228f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy} 2229f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 223065cd612face362d054a85d0f7e5881c59cd523beChris Craikstatus_t OpenGLRenderer::drawVertexBuffer(const VertexBuffer& vertexBuffer, SkPaint* paint, 223165cd612face362d054a85d0f7e5881c59cd523beChris Craik bool useOffset) { 2232bf09ffb4e0dc820aeae56a3e576aed33cab218daChris Craik if (!vertexBuffer.getSize()) { 2233bf09ffb4e0dc820aeae56a3e576aed33cab218daChris Craik // no vertices to draw 223465cd612face362d054a85d0f7e5881c59cd523beChris Craik return DrawGlInfo::kStatusDone; 2235bf09ffb4e0dc820aeae56a3e576aed33cab218daChris Craik } 2236bf09ffb4e0dc820aeae56a3e576aed33cab218daChris Craik 223765cd612face362d054a85d0f7e5881c59cd523beChris Craik int color = paint->getColor(); 223865cd612face362d054a85d0f7e5881c59cd523beChris Craik SkXfermode::Mode mode = getXfermode(paint->getXfermode()); 223965cd612face362d054a85d0f7e5881c59cd523beChris Craik bool isAA = paint->isAntiAlias(); 224065cd612face362d054a85d0f7e5881c59cd523beChris Craik 2241710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik setupDraw(); 2242710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik setupDrawNoTexture(); 2243710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik if (isAA) setupDrawAA(); 2244710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha); 2245710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik setupDrawColorFilter(); 2246710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik setupDrawShader(); 2247710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik setupDrawBlending(isAA, mode); 2248710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik setupDrawProgram(); 224965cd612face362d054a85d0f7e5881c59cd523beChris Craik setupDrawModelViewIdentity(useOffset); 2250710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik setupDrawColorUniforms(); 2251710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik setupDrawColorFilterUniforms(); 2252710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik setupDrawShaderIdentityUniforms(); 2253858aa93ddb6e69e0503382af63bb681b6728aef1Chet Haase 2254710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik void* vertices = vertexBuffer.getBuffer(); 2255710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik bool force = mCaches.unbindMeshBuffer(); 2256cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik mCaches.bindPositionVertexPointer(true, vertices, isAA ? gAlphaVertexStride : gVertexStride); 2257710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik mCaches.resetTexCoordsVertexPointer(); 2258710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik mCaches.unbindIndicesBuffer(); 22596ebdc114e0d72137394f02bc8ffe9d7a782a65c4Chris Craik 2260710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik int alphaSlot = -1; 2261710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik if (isAA) { 2262710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik void* alphaCoords = ((GLbyte*) vertices) + gVertexAlphaOffset; 2263710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik alphaSlot = mCaches.currentProgram->getAttrib("vtxAlpha"); 22646ebdc114e0d72137394f02bc8ffe9d7a782a65c4Chris Craik 2265710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik // TODO: avoid enable/disable in back to back uses of the alpha attribute 22666ebdc114e0d72137394f02bc8ffe9d7a782a65c4Chris Craik glEnableVertexAttribArray(alphaSlot); 22676ebdc114e0d72137394f02bc8ffe9d7a782a65c4Chris Craik glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, alphaCoords); 2268710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik } 22696ebdc114e0d72137394f02bc8ffe9d7a782a65c4Chris Craik 2270710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getSize()); 22717b63142d2f4bc32beacedcc761453b8aea1f3a86Romain Guy 2272710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik if (isAA) { 22736ebdc114e0d72137394f02bc8ffe9d7a782a65c4Chris Craik glDisableVertexAttribArray(alphaSlot); 227404299385c681140239b0dc31d9780d087d2b4d7cRomain Guy } 227565cd612face362d054a85d0f7e5881c59cd523beChris Craik 227665cd612face362d054a85d0f7e5881c59cd523beChris Craik return DrawGlInfo::kStatusDrew; 2277858aa93ddb6e69e0503382af63bb681b6728aef1Chet Haase} 2278858aa93ddb6e69e0503382af63bb681b6728aef1Chet Haase 2279858aa93ddb6e69e0503382af63bb681b6728aef1Chet Haase/** 228065cd612face362d054a85d0f7e5881c59cd523beChris Craik * Renders a convex path via tessellation. For AA paths, this function uses a similar approach to 228165cd612face362d054a85d0f7e5881c59cd523beChris Craik * that of AA lines in the drawLines() function. We expand the convex path by a half pixel in 228265cd612face362d054a85d0f7e5881c59cd523beChris Craik * screen space in all directions. However, instead of using a fragment shader to compute the 228365cd612face362d054a85d0f7e5881c59cd523beChris Craik * translucency of the color from its position, we simply use a varying parameter to define how far 228465cd612face362d054a85d0f7e5881c59cd523beChris Craik * a given pixel is from the edge. For non-AA paths, the expansion and alpha varying are not used. 228565cd612face362d054a85d0f7e5881c59cd523beChris Craik * 228665cd612face362d054a85d0f7e5881c59cd523beChris Craik * Doesn't yet support joins, caps, or path effects. 228799ecdc480dd4f9b550b2a62ea39f77845a4fec49Chet Haase */ 228865cd612face362d054a85d0f7e5881c59cd523beChris Craikstatus_t OpenGLRenderer::drawConvexPath(const SkPath& path, SkPaint* paint) { 228965cd612face362d054a85d0f7e5881c59cd523beChris Craik VertexBuffer vertexBuffer; 229065cd612face362d054a85d0f7e5881c59cd523beChris Craik // TODO: try clipping large paths to viewport 229165cd612face362d054a85d0f7e5881c59cd523beChris Craik PathTessellator::tessellatePath(path, paint, mSnapshot->transform, vertexBuffer); 22927b63142d2f4bc32beacedcc761453b8aea1f3a86Romain Guy 2293c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy if (hasLayer()) { 2294c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy SkRect bounds = path.getBounds(); 2295c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy PathTessellator::expandBoundsForStroke(bounds, paint, false); 2296c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform()); 2297c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy } 22987b63142d2f4bc32beacedcc761453b8aea1f3a86Romain Guy 229965cd612face362d054a85d0f7e5881c59cd523beChris Craik return drawVertexBuffer(vertexBuffer, paint); 230065cd612face362d054a85d0f7e5881c59cd523beChris Craik} 23017b63142d2f4bc32beacedcc761453b8aea1f3a86Romain Guy 230265cd612face362d054a85d0f7e5881c59cd523beChris Craik/** 230365cd612face362d054a85d0f7e5881c59cd523beChris Craik * We create tristrips for the lines much like shape stroke tessellation, using a per-vertex alpha 230465cd612face362d054a85d0f7e5881c59cd523beChris Craik * and additional geometry for defining an alpha slope perimeter. 230565cd612face362d054a85d0f7e5881c59cd523beChris Craik * 230665cd612face362d054a85d0f7e5881c59cd523beChris Craik * Using GL_LINES can be difficult because the rasterization rules for those lines produces some 230765cd612face362d054a85d0f7e5881c59cd523beChris Craik * unexpected results, and may vary between hardware devices. Previously we used a varying-base 230865cd612face362d054a85d0f7e5881c59cd523beChris Craik * in-shader alpha region, but found it to be taxing on some GPUs. 230965cd612face362d054a85d0f7e5881c59cd523beChris Craik * 231065cd612face362d054a85d0f7e5881c59cd523beChris Craik * TODO: try using a fixed input buffer for non-capped lines as in text rendering. this may reduce 231165cd612face362d054a85d0f7e5881c59cd523beChris Craik * memory transfer by removing need for degenerate vertices. 231265cd612face362d054a85d0f7e5881c59cd523beChris Craik */ 231365cd612face362d054a85d0f7e5881c59cd523beChris Craikstatus_t OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { 231465cd612face362d054a85d0f7e5881c59cd523beChris Craik if (mSnapshot->isIgnored() || count < 4) return DrawGlInfo::kStatusDone; 23157b63142d2f4bc32beacedcc761453b8aea1f3a86Romain Guy 231665cd612face362d054a85d0f7e5881c59cd523beChris Craik count &= ~0x3; // round down to nearest four 23177b63142d2f4bc32beacedcc761453b8aea1f3a86Romain Guy 231865cd612face362d054a85d0f7e5881c59cd523beChris Craik VertexBuffer buffer; 231965cd612face362d054a85d0f7e5881c59cd523beChris Craik SkRect bounds; 232065cd612face362d054a85d0f7e5881c59cd523beChris Craik PathTessellator::tessellateLines(points, count, paint, mSnapshot->transform, bounds, buffer); 2321d71ff91dcd79f6beea4bbe768ab3bcbb1a6d7c39Romain Guy 2322d71ff91dcd79f6beea4bbe768ab3bcbb1a6d7c39Romain Guy if (quickReject(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom)) { 2323d71ff91dcd79f6beea4bbe768ab3bcbb1a6d7c39Romain Guy return DrawGlInfo::kStatusDone; 2324d71ff91dcd79f6beea4bbe768ab3bcbb1a6d7c39Romain Guy } 2325d71ff91dcd79f6beea4bbe768ab3bcbb1a6d7c39Romain Guy 23263b753829ae858d424fe109f714745379a6daf455Romain Guy dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform()); 2327486590963e2207d68eebd6944fec70d50d41116aChet Haase 232865cd612face362d054a85d0f7e5881c59cd523beChris Craik bool useOffset = !paint->isAntiAlias(); 232965cd612face362d054a85d0f7e5881c59cd523beChris Craik return drawVertexBuffer(buffer, paint, useOffset); 23305b0200bd47e8a9a4dc8d2e6c3a110d522b30bf82Chet Haase} 23315b0200bd47e8a9a4dc8d2e6c3a110d522b30bf82Chet Haase 2332486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) { 2333486590963e2207d68eebd6944fec70d50d41116aChet Haase if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone; 2334ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy 2335ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy // TODO: The paint's cap style defines whether the points are square or circular 2336ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy // TODO: Handle AA for round points 2337ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy 23385b0200bd47e8a9a4dc8d2e6c3a110d522b30bf82Chet Haase // A stroke width of 0 has a special meaning in Skia: 2339ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy // it draws an unscaled 1px point 23408a5cc92a150bae38ec43732d941b38bb381fe153Chet Haase float strokeWidth = paint->getStrokeWidth(); 2341ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy const bool isHairLine = paint->getStrokeWidth() == 0.0f; 23428a5cc92a150bae38ec43732d941b38bb381fe153Chet Haase if (isHairLine) { 23438a5cc92a150bae38ec43732d941b38bb381fe153Chet Haase // Now that we know it's hairline, we can set the effective width, to be used later 23448a5cc92a150bae38ec43732d941b38bb381fe153Chet Haase strokeWidth = 1.0f; 23458a5cc92a150bae38ec43732d941b38bb381fe153Chet Haase } 23468a5cc92a150bae38ec43732d941b38bb381fe153Chet Haase const float halfWidth = strokeWidth / 2; 2347d71ff91dcd79f6beea4bbe768ab3bcbb1a6d7c39Romain Guy 2348ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy int alpha; 2349ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy SkXfermode::Mode mode; 2350ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy getAlphaAndMode(paint, &alpha, &mode); 2351ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy 2352ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy int verticesCount = count >> 1; 2353ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy int generatedVerticesCount = 0; 2354ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy 2355ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy TextureVertex pointsData[verticesCount]; 2356ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy TextureVertex* vertex = &pointsData[0]; 2357ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy 235804299385c681140239b0dc31d9780d087d2b4d7cRomain Guy // TODO: We should optimize this method to not generate vertices for points 235904299385c681140239b0dc31d9780d087d2b4d7cRomain Guy // that lie outside of the clip. 236004299385c681140239b0dc31d9780d087d2b4d7cRomain Guy mCaches.enableScissor(); 236104299385c681140239b0dc31d9780d087d2b4d7cRomain Guy 2362ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy setupDraw(); 236315bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy setupDrawNoTexture(); 23648a5cc92a150bae38ec43732d941b38bb381fe153Chet Haase setupDrawPoint(strokeWidth); 2365ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy setupDrawColor(paint->getColor(), alpha); 2366ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy setupDrawColorFilter(); 2367ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy setupDrawShader(); 2368ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy setupDrawBlending(mode); 2369ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy setupDrawProgram(); 23708a5cc92a150bae38ec43732d941b38bb381fe153Chet Haase setupDrawModelViewIdentity(true); 2371ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy setupDrawColorUniforms(); 2372ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy setupDrawColorFilterUniforms(); 2373ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy setupDrawPointUniforms(); 2374ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy setupDrawShaderIdentityUniforms(); 2375ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy setupDrawMesh(vertex); 2376ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy 2377ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy for (int i = 0; i < count; i += 2) { 2378ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f); 2379ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy generatedVerticesCount++; 23807b63142d2f4bc32beacedcc761453b8aea1f3a86Romain Guy 23818a5cc92a150bae38ec43732d941b38bb381fe153Chet Haase float left = points[i] - halfWidth; 23828a5cc92a150bae38ec43732d941b38bb381fe153Chet Haase float right = points[i] + halfWidth; 23838a5cc92a150bae38ec43732d941b38bb381fe153Chet Haase float top = points[i + 1] - halfWidth; 23848a5cc92a150bae38ec43732d941b38bb381fe153Chet Haase float bottom = points [i + 1] + halfWidth; 23857b63142d2f4bc32beacedcc761453b8aea1f3a86Romain Guy 23863b753829ae858d424fe109f714745379a6daf455Romain Guy dirtyLayer(left, top, right, bottom, currentTransform()); 2387ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy } 2388ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy 2389ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy glDrawArrays(GL_POINTS, 0, generatedVerticesCount); 2390486590963e2207d68eebd6944fec70d50d41116aChet Haase 2391486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDrew; 2392ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy} 2393ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy 2394486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { 2395e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy // No need to check against the clip, we fill the clip region 2396486590963e2207d68eebd6944fec70d50d41116aChet Haase if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone; 2397e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy 2398ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy Rect& clip(*mSnapshot->clipRect); 2399ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy clip.snapToPixelBoundaries(); 240070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 24013d58c03de0d8877b36cdb78b0ca8b5cac7f600e2Romain Guy drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true); 2402486590963e2207d68eebd6944fec70d50d41116aChet Haase 2403486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDrew; 2404c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy} 24059d5316e3f56d138504565ff311145ac01621dff4Romain Guy 2406486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawShape(float left, float top, const PathTexture* texture, 2407486590963e2207d68eebd6944fec70d50d41116aChet Haase SkPaint* paint) { 2408486590963e2207d68eebd6944fec70d50d41116aChet Haase if (!texture) return DrawGlInfo::kStatusDone; 240901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy const AutoTexture autoCleanup(texture); 241001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 241101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy const float x = left + texture->left - texture->offset; 241201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy const float y = top + texture->top - texture->offset; 241301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 241401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy drawPathTexture(texture, x, y, paint); 2415486590963e2207d68eebd6944fec70d50d41116aChet Haase 2416486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDrew; 241701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy} 241801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 2419486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom, 2420710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik float rx, float ry, SkPaint* p) { 2421257ae3502cfad43df681b1783528d645bdabc63fRomain Guy if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) || 2422257ae3502cfad43df681b1783528d645bdabc63fRomain Guy (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { 2423710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik return DrawGlInfo::kStatusDone; 2424710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik } 242501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 2426cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik if (p->getPathEffect() != 0) { 2427710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik mCaches.activeTexture(0); 2428c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const PathTexture* texture = mCaches.pathCache.getRoundRect( 2429710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik right - left, bottom - top, rx, ry, p); 2430710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik return drawShape(left, top, texture, p); 2431710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik } 2432710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik 2433710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik SkPath path; 2434710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); 2435cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik if (p->getStyle() == SkPaint::kStrokeAndFill_Style) { 2436cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik float outset = p->getStrokeWidth() / 2; 2437cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik rect.outset(outset, outset); 2438cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik rx += outset; 2439cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik ry += outset; 2440cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik } 2441710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik path.addRoundRect(rect, rx, ry); 244265cd612face362d054a85d0f7e5881c59cd523beChris Craik return drawConvexPath(path, p); 2443c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy} 244401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 2445710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craikstatus_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p) { 2446cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik if (mSnapshot->isIgnored() || quickRejectPreStroke(x - radius, y - radius, 2447257ae3502cfad43df681b1783528d645bdabc63fRomain Guy x + radius, y + radius, p) || 2448257ae3502cfad43df681b1783528d645bdabc63fRomain Guy (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { 2449710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik return DrawGlInfo::kStatusDone; 2450710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik } 2451cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik if (p->getPathEffect() != 0) { 2452710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik mCaches.activeTexture(0); 2453c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const PathTexture* texture = mCaches.pathCache.getCircle(radius, p); 2454710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik return drawShape(x - radius, y - radius, texture, p); 2455710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik } 2456710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik 2457710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik SkPath path; 2458cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik if (p->getStyle() == SkPaint::kStrokeAndFill_Style) { 2459cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik path.addCircle(x, y, radius + p->getStrokeWidth() / 2); 2460cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik } else { 2461cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik path.addCircle(x, y, radius); 2462cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik } 246365cd612face362d054a85d0f7e5881c59cd523beChris Craik return drawConvexPath(path, p); 2464c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy} 246501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 2466486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom, 2467710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik SkPaint* p) { 2468257ae3502cfad43df681b1783528d645bdabc63fRomain Guy if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) || 2469257ae3502cfad43df681b1783528d645bdabc63fRomain Guy (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { 2470710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik return DrawGlInfo::kStatusDone; 2471710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik } 247201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 2473cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik if (p->getPathEffect() != 0) { 2474710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik mCaches.activeTexture(0); 2475c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const PathTexture* texture = mCaches.pathCache.getOval(right - left, bottom - top, p); 2476710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik return drawShape(left, top, texture, p); 2477710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik } 2478710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik 2479710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik SkPath path; 2480710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); 2481cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik if (p->getStyle() == SkPaint::kStrokeAndFill_Style) { 2482cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2); 2483cb4d6009576cf08195dc23f341a3f4939c0878bbChris Craik } 2484710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik path.addOval(rect); 248565cd612face362d054a85d0f7e5881c59cd523beChris Craik return drawConvexPath(path, p); 2486c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy} 2487c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy 2488486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom, 2489780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik float startAngle, float sweepAngle, bool useCenter, SkPaint* p) { 2490257ae3502cfad43df681b1783528d645bdabc63fRomain Guy if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) || 2491257ae3502cfad43df681b1783528d645bdabc63fRomain Guy (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { 2492780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik return DrawGlInfo::kStatusDone; 2493780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik } 24948b2f5267f16c295f12faab810527cd6311997e34Romain Guy 24958b2f5267f16c295f12faab810527cd6311997e34Romain Guy if (fabs(sweepAngle) >= 360.0f) { 2496780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik return drawOval(left, top, right, bottom, p); 24978b2f5267f16c295f12faab810527cd6311997e34Romain Guy } 24988b2f5267f16c295f12faab810527cd6311997e34Romain Guy 2499780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180) 250065cd612face362d054a85d0f7e5881c59cd523beChris Craik if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != 0 || useCenter) { 2501780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik mCaches.activeTexture(0); 2502c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy const PathTexture* texture = mCaches.pathCache.getArc(right - left, bottom - top, 2503780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik startAngle, sweepAngle, useCenter, p); 2504780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik return drawShape(left, top, texture, p); 2505780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik } 2506780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik 2507780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); 2508780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik if (p->getStyle() == SkPaint::kStrokeAndFill_Style) { 2509780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2); 2510780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik } 2511780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik 2512780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik SkPath path; 2513780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik if (useCenter) { 2514780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik path.moveTo(rect.centerX(), rect.centerY()); 2515780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik } 2516780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik path.arcTo(rect, startAngle, sweepAngle, !useCenter); 2517780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik if (useCenter) { 2518780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik path.close(); 2519780c12875ce0c0d3fd072484d4b8b3c327cc4f31Chris Craik } 252065cd612face362d054a85d0f7e5881c59cd523beChris Craik return drawConvexPath(path, p); 25218b2f5267f16c295f12faab810527cd6311997e34Romain Guy} 25228b2f5267f16c295f12faab810527cd6311997e34Romain Guy 2523cf8675ee176a375f873792684d38a47f78348dffRomain Guy// See SkPaintDefaults.h 2524cf8675ee176a375f873792684d38a47f78348dffRomain Guy#define SkPaintDefaults_MiterLimit SkIntToScalar(4) 2525cf8675ee176a375f873792684d38a47f78348dffRomain Guy 2526486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* p) { 2527257ae3502cfad43df681b1783528d645bdabc63fRomain Guy if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) || 2528257ae3502cfad43df681b1783528d645bdabc63fRomain Guy (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { 2529486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDone; 25306926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy } 25316926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 2532710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik if (p->getStyle() != SkPaint::kFill_Style) { 2533cf8675ee176a375f873792684d38a47f78348dffRomain Guy // only fill style is supported by drawConvexPath, since others have to handle joins 2534cf8675ee176a375f873792684d38a47f78348dffRomain Guy if (p->getPathEffect() != 0 || p->getStrokeJoin() != SkPaint::kMiter_Join || 2535cf8675ee176a375f873792684d38a47f78348dffRomain Guy p->getStrokeMiter() != SkPaintDefaults_MiterLimit) { 2536cf8675ee176a375f873792684d38a47f78348dffRomain Guy mCaches.activeTexture(0); 2537cf8675ee176a375f873792684d38a47f78348dffRomain Guy const PathTexture* texture = 2538c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guy mCaches.pathCache.getRect(right - left, bottom - top, p); 2539cf8675ee176a375f873792684d38a47f78348dffRomain Guy return drawShape(left, top, texture, p); 2540cf8675ee176a375f873792684d38a47f78348dffRomain Guy } 2541cf8675ee176a375f873792684d38a47f78348dffRomain Guy 2542cf8675ee176a375f873792684d38a47f78348dffRomain Guy SkPath path; 2543cf8675ee176a375f873792684d38a47f78348dffRomain Guy SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); 2544cf8675ee176a375f873792684d38a47f78348dffRomain Guy if (p->getStyle() == SkPaint::kStrokeAndFill_Style) { 2545cf8675ee176a375f873792684d38a47f78348dffRomain Guy rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2); 2546cf8675ee176a375f873792684d38a47f78348dffRomain Guy } 2547cf8675ee176a375f873792684d38a47f78348dffRomain Guy path.addRect(rect); 254865cd612face362d054a85d0f7e5881c59cd523beChris Craik return drawConvexPath(path, p); 2549026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy } 2550026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 25513b753829ae858d424fe109f714745379a6daf455Romain Guy if (p->isAntiAlias() && !currentTransform().isSimple()) { 2552710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik SkPath path; 2553710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik path.addRect(left, top, right, bottom); 255465cd612face362d054a85d0f7e5881c59cd523beChris Craik return drawConvexPath(path, p); 2555858aa93ddb6e69e0503382af63bb681b6728aef1Chet Haase } else { 2556710f46d9d6a5bf9ea1c1833384caf61e1934124fChris Craik drawColorRect(left, top, right, bottom, p->getColor(), getXfermode(p->getXfermode())); 255765cd612face362d054a85d0f7e5881c59cd523beChris Craik return DrawGlInfo::kStatusDrew; 2558858aa93ddb6e69e0503382af63bb681b6728aef1Chet Haase } 2559c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy} 25609d5316e3f56d138504565ff311145ac01621dff4Romain Guy 2561416a847633680d94efb926837efdc18726d54918Raph Levienvoid OpenGLRenderer::drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count, 2562416a847633680d94efb926837efdc18726d54918Raph Levien const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode, 2563416a847633680d94efb926837efdc18726d54918Raph Levien float x, float y) { 2564416a847633680d94efb926837efdc18726d54918Raph Levien mCaches.activeTexture(0); 2565416a847633680d94efb926837efdc18726d54918Raph Levien 2566416a847633680d94efb926837efdc18726d54918Raph Levien // NOTE: The drop shadow will not perform gamma correction 2567416a847633680d94efb926837efdc18726d54918Raph Levien // if shader-based correction is enabled 2568416a847633680d94efb926837efdc18726d54918Raph Levien mCaches.dropShadowCache.setFontRenderer(fontRenderer); 2569416a847633680d94efb926837efdc18726d54918Raph Levien const ShadowTexture* shadow = mCaches.dropShadowCache.get( 2570c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik paint, text, bytesCount, count, mDrawModifiers.mShadowRadius, positions); 2571416a847633680d94efb926837efdc18726d54918Raph Levien const AutoTexture autoCleanup(shadow); 2572416a847633680d94efb926837efdc18726d54918Raph Levien 2573c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik const float sx = x - shadow->left + mDrawModifiers.mShadowDx; 2574c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik const float sy = y - shadow->top + mDrawModifiers.mShadowDy; 2575416a847633680d94efb926837efdc18726d54918Raph Levien 2576c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik const int shadowAlpha = ((mDrawModifiers.mShadowColor >> 24) & 0xFF) * mSnapshot->alpha; 2577c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik int shadowColor = mDrawModifiers.mShadowColor; 2578c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik if (mDrawModifiers.mShader) { 2579416a847633680d94efb926837efdc18726d54918Raph Levien shadowColor = 0xffffffff; 2580416a847633680d94efb926837efdc18726d54918Raph Levien } 2581416a847633680d94efb926837efdc18726d54918Raph Levien 2582416a847633680d94efb926837efdc18726d54918Raph Levien setupDraw(); 2583416a847633680d94efb926837efdc18726d54918Raph Levien setupDrawWithTexture(true); 2584416a847633680d94efb926837efdc18726d54918Raph Levien setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha); 2585416a847633680d94efb926837efdc18726d54918Raph Levien setupDrawColorFilter(); 2586416a847633680d94efb926837efdc18726d54918Raph Levien setupDrawShader(); 2587416a847633680d94efb926837efdc18726d54918Raph Levien setupDrawBlending(true, mode); 2588416a847633680d94efb926837efdc18726d54918Raph Levien setupDrawProgram(); 2589416a847633680d94efb926837efdc18726d54918Raph Levien setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height); 2590416a847633680d94efb926837efdc18726d54918Raph Levien setupDrawTexture(shadow->id); 2591416a847633680d94efb926837efdc18726d54918Raph Levien setupDrawPureColorUniforms(); 2592416a847633680d94efb926837efdc18726d54918Raph Levien setupDrawColorFilterUniforms(); 2593416a847633680d94efb926837efdc18726d54918Raph Levien setupDrawShaderUniforms(); 2594416a847633680d94efb926837efdc18726d54918Raph Levien setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset); 2595416a847633680d94efb926837efdc18726d54918Raph Levien 2596416a847633680d94efb926837efdc18726d54918Raph Levien glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); 2597416a847633680d94efb926837efdc18726d54918Raph Levien} 2598416a847633680d94efb926837efdc18726d54918Raph Levien 2599768bffc9b814f6a1f7d9ff59d91285895c23bbe9Romain Guybool OpenGLRenderer::canSkipText(const SkPaint* paint) const { 2600768bffc9b814f6a1f7d9ff59d91285895c23bbe9Romain Guy float alpha = (mDrawModifiers.mHasShadow ? 1.0f : paint->getAlpha()) * mSnapshot->alpha; 2601768bffc9b814f6a1f7d9ff59d91285895c23bbe9Romain Guy return alpha == 0.0f && getXfermode(paint->getXfermode()) == SkXfermode::kSrcOver_Mode; 2602768bffc9b814f6a1f7d9ff59d91285895c23bbe9Romain Guy} 2603768bffc9b814f6a1f7d9ff59d91285895c23bbe9Romain Guy 2604257ae3502cfad43df681b1783528d645bdabc63fRomain Guyclass TextSetupFunctor: public Functor { 2605257ae3502cfad43df681b1783528d645bdabc63fRomain Guypublic: 2606257ae3502cfad43df681b1783528d645bdabc63fRomain Guy TextSetupFunctor(OpenGLRenderer& renderer, float x, float y, bool pureTranslate, 2607257ae3502cfad43df681b1783528d645bdabc63fRomain Guy int alpha, SkXfermode::Mode mode, SkPaint* paint): Functor(), 2608257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer(renderer), x(x), y(y), pureTranslate(pureTranslate), 2609257ae3502cfad43df681b1783528d645bdabc63fRomain Guy alpha(alpha), mode(mode), paint(paint) { 2610257ae3502cfad43df681b1783528d645bdabc63fRomain Guy } 2611257ae3502cfad43df681b1783528d645bdabc63fRomain Guy ~TextSetupFunctor() { } 2612257ae3502cfad43df681b1783528d645bdabc63fRomain Guy 2613257ae3502cfad43df681b1783528d645bdabc63fRomain Guy status_t operator ()(int what, void* data) { 2614257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDraw(); 2615257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDrawTextGamma(paint); 2616257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDrawDirtyRegionsDisabled(); 2617257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDrawWithTexture(true); 2618257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDrawAlpha8Color(paint->getColor(), alpha); 2619257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDrawColorFilter(); 2620257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDrawShader(); 2621257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDrawBlending(true, mode); 2622257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDrawProgram(); 2623257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDrawModelView(x, y, x, y, pureTranslate, true); 2624257ae3502cfad43df681b1783528d645bdabc63fRomain Guy // Calling setupDrawTexture with the name 0 will enable the 2625257ae3502cfad43df681b1783528d645bdabc63fRomain Guy // uv attributes and increase the texture unit count 2626257ae3502cfad43df681b1783528d645bdabc63fRomain Guy // texture binding will be performed by the font renderer as 2627257ae3502cfad43df681b1783528d645bdabc63fRomain Guy // needed 2628257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDrawTexture(0); 2629257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDrawPureColorUniforms(); 2630257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDrawColorFilterUniforms(); 2631257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDrawShaderUniforms(pureTranslate); 2632257ae3502cfad43df681b1783528d645bdabc63fRomain Guy renderer.setupDrawTextGammaUniforms(); 2633257ae3502cfad43df681b1783528d645bdabc63fRomain Guy 2634257ae3502cfad43df681b1783528d645bdabc63fRomain Guy return NO_ERROR; 2635257ae3502cfad43df681b1783528d645bdabc63fRomain Guy } 2636257ae3502cfad43df681b1783528d645bdabc63fRomain Guy 2637257ae3502cfad43df681b1783528d645bdabc63fRomain Guy OpenGLRenderer& renderer; 2638257ae3502cfad43df681b1783528d645bdabc63fRomain Guy float x; 2639257ae3502cfad43df681b1783528d645bdabc63fRomain Guy float y; 2640257ae3502cfad43df681b1783528d645bdabc63fRomain Guy bool pureTranslate; 2641257ae3502cfad43df681b1783528d645bdabc63fRomain Guy int alpha; 2642257ae3502cfad43df681b1783528d645bdabc63fRomain Guy SkXfermode::Mode mode; 2643257ae3502cfad43df681b1783528d645bdabc63fRomain Guy SkPaint* paint; 2644257ae3502cfad43df681b1783528d645bdabc63fRomain Guy}; 2645257ae3502cfad43df681b1783528d645bdabc63fRomain Guy 2646486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count, 2647eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy const float* positions, SkPaint* paint) { 2648768bffc9b814f6a1f7d9ff59d91285895c23bbe9Romain Guy if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint)) { 2649486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDone; 2650eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy } 2651eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy 2652671d6cf460531825a321edb200523d0faa7792c9Romain Guy // NOTE: Skia does not support perspective transform on drawPosText yet 26533b753829ae858d424fe109f714745379a6daf455Romain Guy if (!currentTransform().isSimple()) { 2654486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDone; 2655671d6cf460531825a321edb200523d0faa7792c9Romain Guy } 2656671d6cf460531825a321edb200523d0faa7792c9Romain Guy 2657671d6cf460531825a321edb200523d0faa7792c9Romain Guy float x = 0.0f; 2658671d6cf460531825a321edb200523d0faa7792c9Romain Guy float y = 0.0f; 26593b753829ae858d424fe109f714745379a6daf455Romain Guy const bool pureTranslate = currentTransform().isPureTranslate(); 2660671d6cf460531825a321edb200523d0faa7792c9Romain Guy if (pureTranslate) { 26613b753829ae858d424fe109f714745379a6daf455Romain Guy x = (int) floorf(x + currentTransform().getTranslateX() + 0.5f); 26623b753829ae858d424fe109f714745379a6daf455Romain Guy y = (int) floorf(y + currentTransform().getTranslateY() + 0.5f); 2663671d6cf460531825a321edb200523d0faa7792c9Romain Guy } 2664671d6cf460531825a321edb200523d0faa7792c9Romain Guy 2665b1d0a4ed21168fefcb82232c8f22cb95d60acb85Romain Guy FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint); 2666c74f45a334f0e3725c23cdd270cbcb0efac4ea75Romain Guy fontRenderer.setFont(paint, mat4::identity()); 2667671d6cf460531825a321edb200523d0faa7792c9Romain Guy 2668671d6cf460531825a321edb200523d0faa7792c9Romain Guy int alpha; 2669671d6cf460531825a321edb200523d0faa7792c9Romain Guy SkXfermode::Mode mode; 2670671d6cf460531825a321edb200523d0faa7792c9Romain Guy getAlphaAndMode(paint, &alpha, &mode); 2671671d6cf460531825a321edb200523d0faa7792c9Romain Guy 2672c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik if (CC_UNLIKELY(mDrawModifiers.mHasShadow)) { 2673e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, 2674e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy alpha, mode, 0.0f, 0.0f); 2675416a847633680d94efb926837efdc18726d54918Raph Levien } 2676416a847633680d94efb926837efdc18726d54918Raph Levien 2677671d6cf460531825a321edb200523d0faa7792c9Romain Guy // Pick the appropriate texture filtering 26783b753829ae858d424fe109f714745379a6daf455Romain Guy bool linearFilter = currentTransform().changesBounds(); 2679671d6cf460531825a321edb200523d0faa7792c9Romain Guy if (pureTranslate && !linearFilter) { 2680671d6cf460531825a321edb200523d0faa7792c9Romain Guy linearFilter = fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f; 2681671d6cf460531825a321edb200523d0faa7792c9Romain Guy } 2682257ae3502cfad43df681b1783528d645bdabc63fRomain Guy fontRenderer.setTextureFiltering(linearFilter); 2683671d6cf460531825a321edb200523d0faa7792c9Romain Guy 2684671d6cf460531825a321edb200523d0faa7792c9Romain Guy const Rect* clip = pureTranslate ? mSnapshot->clipRect : &mSnapshot->getLocalClip(); 2685671d6cf460531825a321edb200523d0faa7792c9Romain Guy Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); 2686671d6cf460531825a321edb200523d0faa7792c9Romain Guy 2687211370fd943cf26905001b38b8b1791851b26adcRomain Guy const bool hasActiveLayer = hasLayer(); 2688671d6cf460531825a321edb200523d0faa7792c9Romain Guy 2689257ae3502cfad43df681b1783528d645bdabc63fRomain Guy TextSetupFunctor functor(*this, x, y, pureTranslate, alpha, mode, paint); 2690671d6cf460531825a321edb200523d0faa7792c9Romain Guy if (fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y, 2691257ae3502cfad43df681b1783528d645bdabc63fRomain Guy positions, hasActiveLayer ? &bounds : NULL, &functor)) { 2692671d6cf460531825a321edb200523d0faa7792c9Romain Guy if (hasActiveLayer) { 2693671d6cf460531825a321edb200523d0faa7792c9Romain Guy if (!pureTranslate) { 26943b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().mapRect(bounds); 2695671d6cf460531825a321edb200523d0faa7792c9Romain Guy } 2696671d6cf460531825a321edb200523d0faa7792c9Romain Guy dirtyLayerUnchecked(bounds, getRegion()); 2697671d6cf460531825a321edb200523d0faa7792c9Romain Guy } 2698671d6cf460531825a321edb200523d0faa7792c9Romain Guy } 2699486590963e2207d68eebd6944fec70d50d41116aChet Haase 2700486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDrew; 2701eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy} 2702eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy 2703624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guymat4 OpenGLRenderer::findBestFontTransform(const mat4& transform) const { 2704624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy mat4 fontTransform; 2705624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy if (CC_LIKELY(transform.isPureTranslate())) { 2706624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy fontTransform = mat4::identity(); 2707624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy } else { 2708624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy if (CC_UNLIKELY(transform.isPerspective())) { 2709b09f1471262c3e629daacbc319bcefc2d621a484Romain Guy fontTransform = mat4::identity(); 2710624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy } else { 2711624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy float sx, sy; 2712624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy currentTransform().decomposeScale(sx, sy); 2713624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy fontTransform.loadScale(sx, sy, 1.0f); 2714624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy } 2715624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy } 2716624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy return fontTransform; 2717624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy} 2718624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy 2719c25259519f1b74bb62a2b051b74537f073436b5cRomain Guystatus_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, 2720996e57c84368058be793897ebc355b917a59abc2Raph Levien float x, float y, const float* positions, SkPaint* paint, float length) { 2721768bffc9b814f6a1f7d9ff59d91285895c23bbe9Romain Guy if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint)) { 2722486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDone; 2723e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy } 2724e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy 2725a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase if (length < 0.0f) length = paint->measureText(text, bytesCount); 2726e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy switch (paint->getTextAlign()) { 2727e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy case SkPaint::kCenter_Align: 2728e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy x -= length / 2.0f; 2729e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy break; 2730e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy case SkPaint::kRight_Align: 2731e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy x -= length; 2732e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy break; 2733e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy default: 2734e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy break; 2735e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy } 2736e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy 2737cac5fd3e09e9dc918753d4aff624bf29a367ade3Romain Guy SkPaint::FontMetrics metrics; 2738cac5fd3e09e9dc918753d4aff624bf29a367ade3Romain Guy paint->getFontMetrics(&metrics, 0.0f); 273933f6beb10f98e8ba96250e284876d607055d278dRomain Guy if (quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom)) { 2740486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDone; 2741cac5fd3e09e9dc918753d4aff624bf29a367ade3Romain Guy } 2742cac5fd3e09e9dc918753d4aff624bf29a367ade3Romain Guy 27433a3fa1be9ab8e11edc660ecb35ae21ae0b5c8cc2Romain Guy const float oldX = x; 27443a3fa1be9ab8e11edc660ecb35ae21ae0b5c8cc2Romain Guy const float oldY = y; 2745624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy 2746624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy const mat4& transform = currentTransform(); 2747624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy const bool pureTranslate = transform.isPureTranslate(); 2748c74f45a334f0e3725c23cdd270cbcb0efac4ea75Romain Guy 2749211370fd943cf26905001b38b8b1791851b26adcRomain Guy if (CC_LIKELY(pureTranslate)) { 2750624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy x = (int) floorf(x + transform.getTranslateX() + 0.5f); 2751624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy y = (int) floorf(y + transform.getTranslateY() + 0.5f); 27526620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } 27536620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy 275486568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy int alpha; 275586568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy SkXfermode::Mode mode; 275686568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy getAlphaAndMode(paint, &alpha, &mode); 27579d13fe25f4f10b25776b1dc5c858f9ebb0b28b30Romain Guy 2758c74f45a334f0e3725c23cdd270cbcb0efac4ea75Romain Guy FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint); 2759c74f45a334f0e3725c23cdd270cbcb0efac4ea75Romain Guy 2760c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik if (CC_UNLIKELY(mDrawModifiers.mHasShadow)) { 2761c74f45a334f0e3725c23cdd270cbcb0efac4ea75Romain Guy fontRenderer.setFont(paint, mat4::identity()); 2762c74f45a334f0e3725c23cdd270cbcb0efac4ea75Romain Guy drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, 2763c74f45a334f0e3725c23cdd270cbcb0efac4ea75Romain Guy alpha, mode, oldX, oldY); 27641e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy } 27651e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy 276619d4dd8599cb870923ab349d2ab96cacffd9c6f5Romain Guy const bool hasActiveLayer = hasLayer(); 276719d4dd8599cb870923ab349d2ab96cacffd9c6f5Romain Guy 2768624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy // We only pass a partial transform to the font renderer. That partial 2769624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy // matrix defines how glyphs are rasterized. Typically we want glyphs 2770624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy // to be rasterized at their final size on screen, which means the partial 2771624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy // matrix needs to take the scale factor into account. 2772624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy // When a partial matrix is used to transform glyphs during rasterization, 2773624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy // the mesh is generated with the inverse transform (in the case of scale, 2774624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy // the mesh is generated at 1.0 / scale for instance.) This allows us to 2775624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy // apply the full transform matrix at draw time in the vertex shader. 2776624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy // Applying the full matrix in the shader is the easiest way to handle 2777624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy // rotation and perspective and allows us to always generated quads in the 2778624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy // font renderer which greatly simplifies the code, clipping in particular. 2779624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy mat4 fontTransform = findBestFontTransform(transform); 27803b753829ae858d424fe109f714745379a6daf455Romain Guy fontRenderer.setFont(paint, fontTransform); 2781c74f45a334f0e3725c23cdd270cbcb0efac4ea75Romain Guy 27826620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy // Pick the appropriate texture filtering 2783a4adcf0239039eb8f005be252409901c41b28839Romain Guy bool linearFilter = !pureTranslate || fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f; 2784257ae3502cfad43df681b1783528d645bdabc63fRomain Guy fontRenderer.setTextureFiltering(linearFilter); 278506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 2786624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy // TODO: Implement better clipping for scaled/rotated text 2787624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy const Rect* clip = !pureTranslate ? NULL : mSnapshot->clipRect; 27885b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); 27895b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 2790996e57c84368058be793897ebc355b917a59abc2Raph Levien bool status; 2791257ae3502cfad43df681b1783528d645bdabc63fRomain Guy TextSetupFunctor functor(*this, x, y, pureTranslate, alpha, mode, paint); 2792a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guy if (CC_UNLIKELY(paint->getTextAlign() != SkPaint::kLeft_Align)) { 27938b4072d3fb9bb49d774d97689a065204beca1752Raph Levien SkPaint paintCopy(*paint); 27948b4072d3fb9bb49d774d97689a065204beca1752Raph Levien paintCopy.setTextAlign(SkPaint::kLeft_Align); 27958b4072d3fb9bb49d774d97689a065204beca1752Raph Levien status = fontRenderer.renderPosText(&paintCopy, clip, text, 0, bytesCount, count, x, y, 2796257ae3502cfad43df681b1783528d645bdabc63fRomain Guy positions, hasActiveLayer ? &bounds : NULL, &functor); 2797996e57c84368058be793897ebc355b917a59abc2Raph Levien } else { 27988b4072d3fb9bb49d774d97689a065204beca1752Raph Levien status = fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y, 2799257ae3502cfad43df681b1783528d645bdabc63fRomain Guy positions, hasActiveLayer ? &bounds : NULL, &functor); 2800996e57c84368058be793897ebc355b917a59abc2Raph Levien } 28014ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy 28024ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy if (status && hasActiveLayer) { 2803624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy if (!pureTranslate) { 2804624234f69b2a4781d24f3e4c6ae6450729e38397Romain Guy transform.mapRect(bounds); 2805a4adcf0239039eb8f005be252409901c41b28839Romain Guy } 28064ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy dirtyLayerUnchecked(bounds, getRegion()); 28075b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 2808694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 28093a3fa1be9ab8e11edc660ecb35ae21ae0b5c8cc2Romain Guy drawTextDecorations(text, bytesCount, length, oldX, oldY, paint); 2810486590963e2207d68eebd6944fec70d50d41116aChet Haase 2811486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDrew; 2812694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 2813694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 2814486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path, 2815325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy float hOffset, float vOffset, SkPaint* paint) { 2816768bffc9b814f6a1f7d9ff59d91285895c23bbe9Romain Guy if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint)) { 2817486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDone; 281803d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy } 281903d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy 2820b1d0a4ed21168fefcb82232c8f22cb95d60acb85Romain Guy FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint); 2821c74f45a334f0e3725c23cdd270cbcb0efac4ea75Romain Guy fontRenderer.setFont(paint, mat4::identity()); 2822257ae3502cfad43df681b1783528d645bdabc63fRomain Guy fontRenderer.setTextureFiltering(true); 282303d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy 282403d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy int alpha; 282503d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy SkXfermode::Mode mode; 282603d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy getAlphaAndMode(paint, &alpha, &mode); 282703d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy 282803d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy setupDraw(); 28294121063313ac0d6f69f6253cac821d0c1c122086Romain Guy setupDrawTextGamma(paint); 283003d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy setupDrawDirtyRegionsDisabled(); 283103d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy setupDrawWithTexture(true); 283203d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy setupDrawAlpha8Color(paint->getColor(), alpha); 283303d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy setupDrawColorFilter(); 283403d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy setupDrawShader(); 283503d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy setupDrawBlending(true, mode); 283603d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy setupDrawProgram(); 28379777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy setupDrawModelView(0.0f, 0.0f, 0.0f, 0.0f, false, true); 2838257ae3502cfad43df681b1783528d645bdabc63fRomain Guy // Calling setupDrawTexture with the name 0 will enable the 2839257ae3502cfad43df681b1783528d645bdabc63fRomain Guy // uv attributes and increase the texture unit count 2840257ae3502cfad43df681b1783528d645bdabc63fRomain Guy // texture binding will be performed by the font renderer as 2841257ae3502cfad43df681b1783528d645bdabc63fRomain Guy // needed 2842257ae3502cfad43df681b1783528d645bdabc63fRomain Guy setupDrawTexture(0); 284303d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy setupDrawPureColorUniforms(); 284403d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy setupDrawColorFilterUniforms(); 28459777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy setupDrawShaderUniforms(false); 28464121063313ac0d6f69f6253cac821d0c1c122086Romain Guy setupDrawTextGammaUniforms(); 28479777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 28489777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy const Rect* clip = &mSnapshot->getLocalClip(); 28499777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); 285003d58520c3eb6bb7efb7235bfd957550533d6725Romain Guy 28519777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy const bool hasActiveLayer = hasLayer(); 28529777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 28539777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy if (fontRenderer.renderTextOnPath(paint, clip, text, 0, bytesCount, count, path, 28549777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy hOffset, vOffset, hasActiveLayer ? &bounds : NULL)) { 28559777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy if (hasActiveLayer) { 28563b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().mapRect(bounds); 28579777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy dirtyLayerUnchecked(bounds, getRegion()); 28589777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy } 28599777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy } 2860486590963e2207d68eebd6944fec70d50d41116aChet Haase 2861486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDrew; 2862325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy} 2863325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy 2864486590963e2207d68eebd6944fec70d50d41116aChet Haasestatus_t OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) { 2865486590963e2207d68eebd6944fec70d50d41116aChet Haase if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone; 2866dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy 2867a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy mCaches.activeTexture(0); 28687fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 2869fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy const PathTexture* texture = mCaches.pathCache.get(path, paint); 2870486590963e2207d68eebd6944fec70d50d41116aChet Haase if (!texture) return DrawGlInfo::kStatusDone; 287122158e139a3d6c6a9787ca0de224e9368f643284Romain Guy const AutoTexture autoCleanup(texture); 28727fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 28738b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy const float x = texture->left - texture->offset; 28748b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy const float y = texture->top - texture->offset; 28758b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy 287601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy drawPathTexture(texture, x, y, paint); 2877486590963e2207d68eebd6944fec70d50d41116aChet Haase 2878486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDrew; 28797fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy} 28807fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy 2881a08f95cfeca7217f9c533b03663bf0dceedd259aChris Craikstatus_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) { 288235643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy if (!layer) { 2883486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDone; 28846c319ca1275c8db892c39b48fc54864c949f9171Romain Guy } 28856c319ca1275c8db892c39b48fc54864c949f9171Romain Guy 2886b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy mat4* transform = NULL; 2887b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy if (layer->isTextureLayer()) { 2888b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy transform = &layer->getTransform(); 2889b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy if (!transform->isIdentity()) { 2890b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy save(0); 28913b753829ae858d424fe109f714745379a6daf455Romain Guy currentTransform().multiply(*transform); 2892b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy } 2893b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy } 2894b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy 289535643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy Rect transformed; 289635643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy Rect clip; 289735643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy const bool rejected = quickRejectNoScissor(x, y, 289835643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy x + layer->layer.getWidth(), y + layer->layer.getHeight(), transformed, clip); 28994ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy 290035643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy if (rejected) { 2901b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy if (transform && !transform->isIdentity()) { 2902b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy restore(); 2903b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy } 290435643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy return DrawGlInfo::kStatusDone; 290535643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy } 290635643ddc689913f5b5f80ceed864470d987bd6cdRomain Guy 29075bb3c730f5ebd2a0db1b02a8981c6fdbea6c1a2eRomain Guy updateLayer(layer, true); 29082bf68f063b0077ddef6ebfe54f2ae5e063c2c229Romain Guy 290987e2f757be9b24d369bab354e37c276e851b1fc7Romain Guy mCaches.setScissorEnabled(mScissorOptimizationDisabled || !clip.contains(transformed)); 2910a1d3c91afbd52c7e8b01f4a9060c5459f02ae7a5Romain Guy mCaches.activeTexture(0); 29116c319ca1275c8db892c39b48fc54864c949f9171Romain Guy 2912211370fd943cf26905001b38b8b1791851b26adcRomain Guy if (CC_LIKELY(!layer->region.isEmpty())) { 2913c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik SkiaColorFilter* oldFilter = mDrawModifiers.mColorFilter; 2914c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mColorFilter = layer->getColorFilter(); 2915e529ece37f664f8947a1d4a1e27d679f6f286388Romain Guy 2916c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy if (layer->region.isRect()) { 291740667676e542a9daeafeac9904c30004e8706fd3Romain Guy composeLayerRect(layer, layer->regionRect); 2918c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy } else if (layer->mesh) { 2919a08f95cfeca7217f9c533b03663bf0dceedd259aChris Craik const float a = layer->getAlpha() / 255.0f * mSnapshot->alpha; 2920c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy setupDraw(); 2921c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy setupDrawWithTexture(); 29228168396d1acbcb5fdd29eeda4c30b2803d5283aeRomain Guy setupDrawColor(a, a, a, a); 2923c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy setupDrawColorFilter(); 29249ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy setupDrawBlending(layer->isBlend() || a < 1.0f, layer->getMode(), false); 2925c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy setupDrawProgram(); 2926c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy setupDrawPureColorUniforms(); 2927c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy setupDrawColorFilterUniforms(); 29289ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy setupDrawTexture(layer->getTexture()); 29293b753829ae858d424fe109f714745379a6daf455Romain Guy if (CC_LIKELY(currentTransform().isPureTranslate())) { 29303b753829ae858d424fe109f714745379a6daf455Romain Guy int tx = (int) floorf(x + currentTransform().getTranslateX() + 0.5f); 29313b753829ae858d424fe109f714745379a6daf455Romain Guy int ty = (int) floorf(y + currentTransform().getTranslateY() + 0.5f); 29329ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy 2933d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy layer->setFilter(GL_NEAREST); 29344ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy setupDrawModelViewTranslate(tx, ty, 29354ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy tx + layer->layer.getWidth(), ty + layer->layer.getHeight(), true); 29369ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } else { 2937d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy layer->setFilter(GL_LINEAR); 29389ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy setupDrawModelViewTranslate(x, y, 29399ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy x + layer->layer.getWidth(), y + layer->layer.getHeight()); 29409ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } 2941c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy setupDrawMesh(&layer->mesh[0].position[0], &layer->mesh[0].texture[0]); 2942c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy 2943c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy glDrawElements(GL_TRIANGLES, layer->meshElementCount, 2944c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy GL_UNSIGNED_SHORT, layer->meshIndices); 2945c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy 2946c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy finishDrawTexture(); 29473a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy 29483a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy#if DEBUG_LAYERS_AS_REGIONS 29493a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy drawRegionRects(layer->region); 29503a3133d876caf60ebff2176ad75c3dcf0259148dRomain Guy#endif 2951c88e357d1ed9dadfc0efb3dfbe92f24460674ef5Romain Guy } 29524ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy 2953c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mColorFilter = oldFilter; 2954e529ece37f664f8947a1d4a1e27d679f6f286388Romain Guy 29555bb3c730f5ebd2a0db1b02a8981c6fdbea6c1a2eRomain Guy if (layer->debugDrawUpdate) { 29565bb3c730f5ebd2a0db1b02a8981c6fdbea6c1a2eRomain Guy layer->debugDrawUpdate = false; 29574ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy drawColorRect(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight(), 29584ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy 0x7f00ff00, SkXfermode::kSrcOver_Mode); 29594ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy } 2960f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy } 2961486590963e2207d68eebd6944fec70d50d41116aChet Haase 2962b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy if (transform && !transform->isIdentity()) { 2963b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy restore(); 2964b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy } 2965b2e2f2470693e78baed20617f989d9a166864ed4Romain Guy 2966486590963e2207d68eebd6944fec70d50d41116aChet Haase return DrawGlInfo::kStatusDrew; 29676c319ca1275c8db892c39b48fc54864c949f9171Romain Guy} 29686c319ca1275c8db892c39b48fc54864c949f9171Romain Guy 29696926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy/////////////////////////////////////////////////////////////////////////////// 2970d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy// Shaders 2971d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy/////////////////////////////////////////////////////////////////////////////// 2972d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy 2973d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guyvoid OpenGLRenderer::resetShader() { 2974c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mShader = NULL; 297506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 297606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 297706f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid OpenGLRenderer::setupShader(SkiaShader* shader) { 2978c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mShader = shader; 2979c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik if (mDrawModifiers.mShader) { 2980c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mShader->set(&mCaches.textureCache, &mCaches.gradientCache); 298106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy } 29827fac2e18339f765320d759e8d4c090f92431959eRomain Guy} 29837fac2e18339f765320d759e8d4c090f92431959eRomain Guy 2984d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy/////////////////////////////////////////////////////////////////////////////// 2985db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy// Color filters 2986db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy/////////////////////////////////////////////////////////////////////////////// 2987db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy 2988db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guyvoid OpenGLRenderer::resetColorFilter() { 2989c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mColorFilter = NULL; 2990db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy} 2991db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy 2992db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guyvoid OpenGLRenderer::setupColorFilter(SkiaColorFilter* filter) { 2993c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mColorFilter = filter; 2994db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy} 2995db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy 2996db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy/////////////////////////////////////////////////////////////////////////////// 29971e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy// Drop shadow 29981e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy/////////////////////////////////////////////////////////////////////////////// 29991e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy 30001e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guyvoid OpenGLRenderer::resetShadow() { 3001c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mHasShadow = false; 30021e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy} 30031e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy 30041e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guyvoid OpenGLRenderer::setupShadow(float radius, float dx, float dy, int color) { 3005c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mHasShadow = true; 3006c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mShadowRadius = radius; 3007c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mShadowDx = dx; 3008c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mShadowDy = dy; 3009c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mShadowColor = color; 30101e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy} 30111e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy 30121e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy/////////////////////////////////////////////////////////////////////////////// 30135ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy// Draw filters 30145ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy/////////////////////////////////////////////////////////////////////////////// 30155ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy 30165ff9df658230d49e42c43586997a02d8e4dd417eRomain Guyvoid OpenGLRenderer::resetPaintFilter() { 3017c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mHasDrawFilter = false; 30185ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy} 30195ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy 30205ff9df658230d49e42c43586997a02d8e4dd417eRomain Guyvoid OpenGLRenderer::setupPaintFilter(int clearBits, int setBits) { 3021c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mHasDrawFilter = true; 3022c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mPaintFilterClearBits = clearBits & SkPaint::kAllFlags; 3023c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mPaintFilterSetBits = setBits & SkPaint::kAllFlags; 30245ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy} 30255ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy 3026a08f95cfeca7217f9c533b03663bf0dceedd259aChris CraikSkPaint* OpenGLRenderer::filterPaint(SkPaint* paint) { 3027758724fd09a1599f2c55130f81953cfa6c17c300Romain Guy if (CC_LIKELY(!mDrawModifiers.mHasDrawFilter || !paint)) { 3028758724fd09a1599f2c55130f81953cfa6c17c300Romain Guy return paint; 3029758724fd09a1599f2c55130f81953cfa6c17c300Romain Guy } 30305ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy 30315ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy uint32_t flags = paint->getFlags(); 30325ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy 30335ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy mFilteredPaint = *paint; 3034c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mFilteredPaint.setFlags((flags & ~mDrawModifiers.mPaintFilterClearBits) | 3035c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik mDrawModifiers.mPaintFilterSetBits); 30365ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy 30375ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy return &mFilteredPaint; 30385ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy} 30395ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy 30405ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy/////////////////////////////////////////////////////////////////////////////// 30416926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy// Drawing implementation 30426926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy/////////////////////////////////////////////////////////////////////////////// 30436926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 304401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyvoid OpenGLRenderer::drawPathTexture(const PathTexture* texture, 304501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy float x, float y, SkPaint* paint) { 304601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy if (quickReject(x, y, x + texture->width, y + texture->height)) { 304701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy return; 304801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy } 304901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 305001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy int alpha; 305101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy SkXfermode::Mode mode; 305201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy getAlphaAndMode(paint, &alpha, &mode); 305301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 305401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy setupDraw(); 305501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy setupDrawWithTexture(true); 305601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy setupDrawAlpha8Color(paint->getColor(), alpha); 305701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy setupDrawColorFilter(); 305801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy setupDrawShader(); 305901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy setupDrawBlending(true, mode); 306001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy setupDrawProgram(); 306101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy setupDrawModelView(x, y, x + texture->width, y + texture->height); 306201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy setupDrawTexture(texture->id); 306301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy setupDrawPureColorUniforms(); 306401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy setupDrawColorFilterUniforms(); 306501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy setupDrawShaderUniforms(); 306601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset); 306701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 306801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); 306901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 307001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy finishDrawTexture(); 307101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy} 307201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 3073f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy// Same values used by Skia 30740a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy#define kStdStrikeThru_Offset (-6.0f / 21.0f) 30750a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy#define kStdUnderline_Offset (1.0f / 9.0f) 30760a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy#define kStdUnderline_Thickness (1.0f / 18.0f) 30770a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy 30780a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guyvoid OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float length, 30790a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy float x, float y, SkPaint* paint) { 30800a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy // Handle underline and strike-through 30810a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy uint32_t flags = paint->getFlags(); 30820a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) { 3083726aeba80ffc6778a9bc3e0ee957b8d644183505Romain Guy SkPaint paintCopy(*paint); 30840a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy float underlineWidth = length; 30850a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy // If length is > 0.0f, we already measured the text for the text alignment 30860a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy if (length <= 0.0f) { 3087726aeba80ffc6778a9bc3e0ee957b8d644183505Romain Guy underlineWidth = paintCopy.measureText(text, bytesCount); 30880a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy } 30890a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy 3090211370fd943cf26905001b38b8b1791851b26adcRomain Guy if (CC_LIKELY(underlineWidth > 0.0f)) { 3091726aeba80ffc6778a9bc3e0ee957b8d644183505Romain Guy const float textSize = paintCopy.getTextSize(); 3092f6834478b379856d3e5de92ddce7de0e6ba9fa4aRomain Guy const float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f); 30930a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy 30948b4072d3fb9bb49d774d97689a065204beca1752Raph Levien const float left = x; 30950a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy float top = 0.0f; 3096e20ecbd12d26467754a7770d44bcce2ea92335efRomain Guy 3097f6834478b379856d3e5de92ddce7de0e6ba9fa4aRomain Guy int linesCount = 0; 3098f6834478b379856d3e5de92ddce7de0e6ba9fa4aRomain Guy if (flags & SkPaint::kUnderlineText_Flag) linesCount++; 3099f6834478b379856d3e5de92ddce7de0e6ba9fa4aRomain Guy if (flags & SkPaint::kStrikeThruText_Flag) linesCount++; 3100f6834478b379856d3e5de92ddce7de0e6ba9fa4aRomain Guy 3101f6834478b379856d3e5de92ddce7de0e6ba9fa4aRomain Guy const int pointsCount = 4 * linesCount; 3102e20ecbd12d26467754a7770d44bcce2ea92335efRomain Guy float points[pointsCount]; 3103e20ecbd12d26467754a7770d44bcce2ea92335efRomain Guy int currentPoint = 0; 31040a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy 31050a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy if (flags & SkPaint::kUnderlineText_Flag) { 31060a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy top = y + textSize * kStdUnderline_Offset; 3107e20ecbd12d26467754a7770d44bcce2ea92335efRomain Guy points[currentPoint++] = left; 3108e20ecbd12d26467754a7770d44bcce2ea92335efRomain Guy points[currentPoint++] = top; 3109e20ecbd12d26467754a7770d44bcce2ea92335efRomain Guy points[currentPoint++] = left + underlineWidth; 3110e20ecbd12d26467754a7770d44bcce2ea92335efRomain Guy points[currentPoint++] = top; 31110a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy } 31120a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy 31130a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy if (flags & SkPaint::kStrikeThruText_Flag) { 31140a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy top = y + textSize * kStdStrikeThru_Offset; 3115e20ecbd12d26467754a7770d44bcce2ea92335efRomain Guy points[currentPoint++] = left; 3116e20ecbd12d26467754a7770d44bcce2ea92335efRomain Guy points[currentPoint++] = top; 3117e20ecbd12d26467754a7770d44bcce2ea92335efRomain Guy points[currentPoint++] = left + underlineWidth; 3118e20ecbd12d26467754a7770d44bcce2ea92335efRomain Guy points[currentPoint++] = top; 31190a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy } 3120e20ecbd12d26467754a7770d44bcce2ea92335efRomain Guy 3121726aeba80ffc6778a9bc3e0ee957b8d644183505Romain Guy paintCopy.setStrokeWidth(strokeWidth); 3122e20ecbd12d26467754a7770d44bcce2ea92335efRomain Guy 3123726aeba80ffc6778a9bc3e0ee957b8d644183505Romain Guy drawLines(&points[0], pointsCount, &paintCopy); 31240a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy } 31250a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy } 31260a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy} 31270a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy 3128672433d90fab7383cd28beac9d4485b566a90940Romain Guystatus_t OpenGLRenderer::drawRects(const float* rects, int count, SkPaint* paint) { 3129672433d90fab7383cd28beac9d4485b566a90940Romain Guy if (mSnapshot->isIgnored()) { 3130672433d90fab7383cd28beac9d4485b566a90940Romain Guy return DrawGlInfo::kStatusDone; 3131672433d90fab7383cd28beac9d4485b566a90940Romain Guy } 3132672433d90fab7383cd28beac9d4485b566a90940Romain Guy 3133735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy int color = paint->getColor(); 3134735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy // If a shader is set, preserve only the alpha 3135c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik if (mDrawModifiers.mShader) { 3136735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy color |= 0x00ffffff; 3137735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy } 3138735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy SkXfermode::Mode mode = getXfermode(paint->getXfermode()); 3139735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy 3140735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy return drawColorRects(rects, count, color, mode); 3141735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy} 3142735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy 3143735738c4ddf3229caa5f6e634bf591953ac29944Romain Guystatus_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color, 31443bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy SkXfermode::Mode mode, bool ignoreTransform, bool dirty, bool clip) { 31453b753829ae858d424fe109f714745379a6daf455Romain Guy if (count == 0) { 31463b753829ae858d424fe109f714745379a6daf455Romain Guy return DrawGlInfo::kStatusDone; 31473b753829ae858d424fe109f714745379a6daf455Romain Guy } 3148735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy 3149672433d90fab7383cd28beac9d4485b566a90940Romain Guy float left = FLT_MAX; 3150672433d90fab7383cd28beac9d4485b566a90940Romain Guy float top = FLT_MAX; 3151672433d90fab7383cd28beac9d4485b566a90940Romain Guy float right = FLT_MIN; 3152672433d90fab7383cd28beac9d4485b566a90940Romain Guy float bottom = FLT_MIN; 3153672433d90fab7383cd28beac9d4485b566a90940Romain Guy 3154672433d90fab7383cd28beac9d4485b566a90940Romain Guy int vertexCount = 0; 3155672433d90fab7383cd28beac9d4485b566a90940Romain Guy Vertex mesh[count * 6]; 3156672433d90fab7383cd28beac9d4485b566a90940Romain Guy Vertex* vertex = mesh; 3157672433d90fab7383cd28beac9d4485b566a90940Romain Guy 31582af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik for (int index = 0; index < count; index += 4) { 3159672433d90fab7383cd28beac9d4485b566a90940Romain Guy float l = rects[index + 0]; 3160672433d90fab7383cd28beac9d4485b566a90940Romain Guy float t = rects[index + 1]; 3161672433d90fab7383cd28beac9d4485b566a90940Romain Guy float r = rects[index + 2]; 3162672433d90fab7383cd28beac9d4485b566a90940Romain Guy float b = rects[index + 3]; 3163672433d90fab7383cd28beac9d4485b566a90940Romain Guy 31643b753829ae858d424fe109f714745379a6daf455Romain Guy Vertex::set(vertex++, l, b); 31653b753829ae858d424fe109f714745379a6daf455Romain Guy Vertex::set(vertex++, l, t); 31663b753829ae858d424fe109f714745379a6daf455Romain Guy Vertex::set(vertex++, r, t); 31673b753829ae858d424fe109f714745379a6daf455Romain Guy Vertex::set(vertex++, l, b); 31683b753829ae858d424fe109f714745379a6daf455Romain Guy Vertex::set(vertex++, r, t); 31693b753829ae858d424fe109f714745379a6daf455Romain Guy Vertex::set(vertex++, r, b); 3170672433d90fab7383cd28beac9d4485b566a90940Romain Guy 31713b753829ae858d424fe109f714745379a6daf455Romain Guy vertexCount += 6; 3172672433d90fab7383cd28beac9d4485b566a90940Romain Guy 31733b753829ae858d424fe109f714745379a6daf455Romain Guy left = fminf(left, l); 31743b753829ae858d424fe109f714745379a6daf455Romain Guy top = fminf(top, t); 31753b753829ae858d424fe109f714745379a6daf455Romain Guy right = fmaxf(right, r); 31763b753829ae858d424fe109f714745379a6daf455Romain Guy bottom = fmaxf(bottom, b); 3177672433d90fab7383cd28beac9d4485b566a90940Romain Guy } 3178672433d90fab7383cd28beac9d4485b566a90940Romain Guy 31793b753829ae858d424fe109f714745379a6daf455Romain Guy if (clip && quickReject(left, top, right, bottom)) { 3180a362c69d6cdf448107e5a539f77df73937141870Romain Guy return DrawGlInfo::kStatusDone; 3181a362c69d6cdf448107e5a539f77df73937141870Romain Guy } 3182672433d90fab7383cd28beac9d4485b566a90940Romain Guy 3183672433d90fab7383cd28beac9d4485b566a90940Romain Guy setupDraw(); 3184672433d90fab7383cd28beac9d4485b566a90940Romain Guy setupDrawNoTexture(); 3185672433d90fab7383cd28beac9d4485b566a90940Romain Guy setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha); 3186672433d90fab7383cd28beac9d4485b566a90940Romain Guy setupDrawShader(); 3187672433d90fab7383cd28beac9d4485b566a90940Romain Guy setupDrawColorFilter(); 3188672433d90fab7383cd28beac9d4485b566a90940Romain Guy setupDrawBlending(mode); 3189672433d90fab7383cd28beac9d4485b566a90940Romain Guy setupDrawProgram(); 3190672433d90fab7383cd28beac9d4485b566a90940Romain Guy setupDrawDirtyRegionsDisabled(); 3191735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy setupDrawModelView(0.0f, 0.0f, 1.0f, 1.0f, ignoreTransform, true); 3192672433d90fab7383cd28beac9d4485b566a90940Romain Guy setupDrawColorUniforms(); 3193672433d90fab7383cd28beac9d4485b566a90940Romain Guy setupDrawShaderUniforms(); 3194672433d90fab7383cd28beac9d4485b566a90940Romain Guy setupDrawColorFilterUniforms(); 3195672433d90fab7383cd28beac9d4485b566a90940Romain Guy setupDrawVertices((GLvoid*) &mesh[0].position[0]); 3196672433d90fab7383cd28beac9d4485b566a90940Romain Guy 31978ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy if (dirty && hasLayer()) { 31983b753829ae858d424fe109f714745379a6daf455Romain Guy dirtyLayer(left, top, right, bottom, currentTransform()); 3199672433d90fab7383cd28beac9d4485b566a90940Romain Guy } 3200672433d90fab7383cd28beac9d4485b566a90940Romain Guy 3201672433d90fab7383cd28beac9d4485b566a90940Romain Guy glDrawArrays(GL_TRIANGLES, 0, vertexCount); 3202672433d90fab7383cd28beac9d4485b566a90940Romain Guy 3203672433d90fab7383cd28beac9d4485b566a90940Romain Guy return DrawGlInfo::kStatusDrew; 3204672433d90fab7383cd28beac9d4485b566a90940Romain Guy} 3205672433d90fab7383cd28beac9d4485b566a90940Romain Guy 3206026c5e16704e817cac7d9c382914c947e34f87e0Romain Guyvoid OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, 32071c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy int color, SkXfermode::Mode mode, bool ignoreTransform) { 3208d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy // If a shader is set, preserve only the alpha 3209c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik if (mDrawModifiers.mShader) { 3210d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy color |= 0x00ffffff; 3211d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy } 3212d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy 321370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDraw(); 321415bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy setupDrawNoTexture(); 32159c0b188e4231bcb967234f3646c178d22d8a9f50Romain Guy setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha); 321670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawShader(); 321770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawColorFilter(); 321870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawBlending(mode); 321970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawProgram(); 322070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawModelView(left, top, right, bottom, ignoreTransform); 322170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawColorUniforms(); 322270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawShaderUniforms(ignoreTransform); 322370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawColorFilterUniforms(); 322470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawSimpleMesh(); 3225c95c8d6bf8fda5c4e8ebd0033b789be7868e6e07Romain Guy 3226c95c8d6bf8fda5c4e8ebd0033b789be7868e6e07Romain Guy glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); 3227c95c8d6bf8fda5c4e8ebd0033b789be7868e6e07Romain Guy} 3228c95c8d6bf8fda5c4e8ebd0033b789be7868e6e07Romain Guy 322982ba814ca0dea659be2cc6523bc0137679d961ceRomain Guyvoid OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, 32308164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy Texture* texture, SkPaint* paint) { 323182ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy int alpha; 323282ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy SkXfermode::Mode mode; 323382ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy getAlphaAndMode(paint, &alpha, &mode); 323482ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy 3235d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy texture->setWrap(GL_CLAMP_TO_EDGE, true); 32368164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy 32373b753829ae858d424fe109f714745379a6daf455Romain Guy if (CC_LIKELY(currentTransform().isPureTranslate())) { 32383b753829ae858d424fe109f714745379a6daf455Romain Guy const float x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f); 32393b753829ae858d424fe109f714745379a6daf455Romain Guy const float y = (int) floorf(top + currentTransform().getTranslateY() + 0.5f); 32406620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy 3241d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy texture->setFilter(GL_NEAREST, true); 32426620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id, 32436620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy alpha / 255.0f, mode, texture->blend, (GLvoid*) NULL, 32446620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount, false, true); 32456620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } else { 3246d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy texture->setFilter(FILTER(paint), true); 32476620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode, 32486620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy texture->blend, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset, 32496620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy GL_TRIANGLE_STRIP, gMeshCount); 32506620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } 325185bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy} 325285bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy 3253bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyvoid OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, 3254a979474f15b454c8e2963f239a3770e200bb227cRomain Guy GLuint texture, float alpha, SkXfermode::Mode mode, bool blend) { 3255a979474f15b454c8e2963f239a3770e200bb227cRomain Guy drawTextureMesh(left, top, right, bottom, texture, alpha, mode, blend, 325603750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount); 3257f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy} 3258f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 3259f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guyvoid OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom, 3260a979474f15b454c8e2963f239a3770e200bb227cRomain Guy GLuint texture, float alpha, SkXfermode::Mode mode, bool blend, 32616820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount, 32625b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy bool swapSrcDst, bool ignoreTransform, GLuint vbo, bool ignoreScale, bool dirty) { 32638694230ff25fa0a60e480d424843e56b718f0516Romain Guy 326470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDraw(); 326570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawWithTexture(); 326670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawColor(alpha, alpha, alpha, alpha); 326770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawColorFilter(); 326870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawBlending(blend, mode, swapSrcDst); 326970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawProgram(); 3270886b275e529e44a59c54b933453d9bc902973178Romain Guy if (!dirty) setupDrawDirtyRegionsDisabled(); 32715b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (!ignoreScale) { 327270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawModelView(left, top, right, bottom, ignoreTransform); 327303750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy } else { 327470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawModelViewTranslate(left, top, right, bottom, ignoreTransform); 3275db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy } 3276886b275e529e44a59c54b933453d9bc902973178Romain Guy setupDrawTexture(texture); 327786568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy setupDrawPureColorUniforms(); 327870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawColorFilterUniforms(); 327970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setupDrawMesh(vertices, texCoords, vbo); 3280db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy 32816820ac8b14b4558f5d8b833dde80895306a3e137Romain Guy glDrawArrays(drawMode, 0, elementsCount); 328270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 328370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy finishDrawTexture(); 328482ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy} 328582ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy 3286886b275e529e44a59c54b933453d9bc902973178Romain Guyvoid OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, float bottom, 3287886b275e529e44a59c54b933453d9bc902973178Romain Guy GLuint texture, bool hasColor, int color, int alpha, SkXfermode::Mode mode, 3288886b275e529e44a59c54b933453d9bc902973178Romain Guy GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount, 3289886b275e529e44a59c54b933453d9bc902973178Romain Guy bool ignoreTransform, bool dirty) { 3290886b275e529e44a59c54b933453d9bc902973178Romain Guy 3291886b275e529e44a59c54b933453d9bc902973178Romain Guy setupDraw(); 3292886b275e529e44a59c54b933453d9bc902973178Romain Guy setupDrawWithTexture(true); 3293886b275e529e44a59c54b933453d9bc902973178Romain Guy if (hasColor) { 3294886b275e529e44a59c54b933453d9bc902973178Romain Guy setupDrawAlpha8Color(color, alpha); 3295886b275e529e44a59c54b933453d9bc902973178Romain Guy } 3296886b275e529e44a59c54b933453d9bc902973178Romain Guy setupDrawColorFilter(); 3297886b275e529e44a59c54b933453d9bc902973178Romain Guy setupDrawShader(); 3298886b275e529e44a59c54b933453d9bc902973178Romain Guy setupDrawBlending(true, mode); 3299886b275e529e44a59c54b933453d9bc902973178Romain Guy setupDrawProgram(); 3300886b275e529e44a59c54b933453d9bc902973178Romain Guy if (!dirty) setupDrawDirtyRegionsDisabled(); 3301886b275e529e44a59c54b933453d9bc902973178Romain Guy setupDrawModelView(left, top, right, bottom, ignoreTransform); 3302886b275e529e44a59c54b933453d9bc902973178Romain Guy setupDrawTexture(texture); 3303886b275e529e44a59c54b933453d9bc902973178Romain Guy setupDrawPureColorUniforms(); 3304886b275e529e44a59c54b933453d9bc902973178Romain Guy setupDrawColorFilterUniforms(); 3305886b275e529e44a59c54b933453d9bc902973178Romain Guy setupDrawShaderUniforms(); 3306886b275e529e44a59c54b933453d9bc902973178Romain Guy setupDrawMesh(vertices, texCoords); 3307886b275e529e44a59c54b933453d9bc902973178Romain Guy 3308886b275e529e44a59c54b933453d9bc902973178Romain Guy glDrawArrays(drawMode, 0, elementsCount); 3309886b275e529e44a59c54b933453d9bc902973178Romain Guy 3310886b275e529e44a59c54b933453d9bc902973178Romain Guy finishDrawTexture(); 3311886b275e529e44a59c54b933453d9bc902973178Romain Guy} 3312886b275e529e44a59c54b933453d9bc902973178Romain Guy 3313a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guyvoid OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, 3314f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy ProgramDescription& description, bool swapSrcDst) { 331582ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy blend = blend || mode != SkXfermode::kSrcOver_Mode; 3316c189ef53220059acf2adedc92ac4ac7e6a993e6bRomain Guy 331782ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy if (blend) { 331882bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy // These blend modes are not supported by OpenGL directly and have 331982bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy // to be implemented using shaders. Since the shader will perform 332082bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy // the blending, turn blending off here 332182bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy // If the blend mode cannot be implemented using shaders, fall 332282bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy // back to the default SrcOver blend mode instead 332333fa1f774c8e7289fd7c39fbc2c65b9361f2c2c4Romain Guy if (CC_UNLIKELY(mode > SkXfermode::kScreen_Mode)) { 33243bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy if (CC_UNLIKELY(mExtensions.hasFramebufferFetch())) { 3325a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy description.framebufferMode = mode; 3326f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy description.swapSrcDst = swapSrcDst; 3327a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy 332882bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy if (mCaches.blend) { 332982bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy glDisable(GL_BLEND); 333082bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy mCaches.blend = false; 333182bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy } 333282bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy 333382bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy return; 333482bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy } else { 333582bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy mode = SkXfermode::kSrcOver_Mode; 3336a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy } 333782bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy } 333882bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy 333982bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy if (!mCaches.blend) { 334082bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy glEnable(GL_BLEND); 334182bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy } 334282bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy 334382bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy GLenum sourceMode = swapSrcDst ? gBlendsSwap[mode].src : gBlends[mode].src; 334482bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy GLenum destMode = swapSrcDst ? gBlendsSwap[mode].dst : gBlends[mode].dst; 334582bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy 334682bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy if (sourceMode != mCaches.lastSrcMode || destMode != mCaches.lastDstMode) { 334782bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy glBlendFunc(sourceMode, destMode); 334882bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy mCaches.lastSrcMode = sourceMode; 334982bc7a772747fcf8a6fe7097f70bf2981429ffe9Romain Guy mCaches.lastDstMode = destMode; 335082ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy } 3351fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } else if (mCaches.blend) { 335282ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy glDisable(GL_BLEND); 335382ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy } 3354fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mCaches.blend = blend; 3355bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy} 3356bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 3357889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guybool OpenGLRenderer::useProgram(Program* program) { 3358d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy if (!program->isInUse()) { 3359fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (mCaches.currentProgram != NULL) mCaches.currentProgram->remove(); 3360d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy program->use(); 3361fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mCaches.currentProgram = program; 33626926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy return false; 3363260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy } 33646926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy return true; 3365260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy} 3366260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy 3367026c5e16704e817cac7d9c382914c947e34f87e0Romain Guyvoid OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) { 3368ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy TextureVertex* v = &mMeshVertices[0]; 336982ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy TextureVertex::setUV(v++, u1, v1); 337082ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy TextureVertex::setUV(v++, u2, v1); 337182ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy TextureVertex::setUV(v++, u1, v2); 337282ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy TextureVertex::setUV(v++, u2, v2); 33738ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy} 33748ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 33755c13d89c1332fcc499379b9064b891187b75ca32Chet Haasevoid OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) { 3376be6f9dc1e71b425b7ac1c40c0a2c72d03eb9fbeeRomain Guy getAlphaAndModeDirect(paint, alpha, mode); 3377db8c9a6a4d9bf8c39f834b25611926caf21380f6Chet Haase *alpha *= mSnapshot->alpha; 3378026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy} 3379026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 33809d5316e3f56d138504565ff311145ac01621dff4Romain Guy}; // namespace uirenderer 3381e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}; // namespace android 3382