OpenGLRenderer.cpp revision 06f96e2652e4855b6520ad9dd70583677605b79a
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> 24694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy#include <SkTypeface.h> 255cbbce535744b89df5ecea95de21ee3733298260Romain Guy 26121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy#include <cutils/properties.h> 275cbbce535744b89df5ecea95de21ee3733298260Romain Guy#include <utils/Log.h> 2885bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy 2985bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include "OpenGLRenderer.h" 3051769a68a5cb34e9564740c6a854fcb93018789dRomain Guy#include "Properties.h" 31e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 32e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guynamespace android { 339d5316e3f56d138504565ff311145ac01621dff4Romain Guynamespace uirenderer { 349d5316e3f56d138504565ff311145ac01621dff4Romain Guy 359d5316e3f56d138504565ff311145ac01621dff4Romain Guy/////////////////////////////////////////////////////////////////////////////// 369d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Defines 379d5316e3f56d138504565ff311145ac01621dff4Romain Guy/////////////////////////////////////////////////////////////////////////////// 389d5316e3f56d138504565ff311145ac01621dff4Romain Guy 39c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy#define DEFAULT_TEXTURE_CACHE_SIZE 20.0f 40c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy#define DEFAULT_LAYER_CACHE_SIZE 10.0f 41f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy#define DEFAULT_PATCH_CACHE_SIZE 100 42c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy#define DEFAULT_GRADIENT_CACHE_SIZE 0.5f 43dda570201ac851dd85af3861f7e575721d3345daRomain Guy 4406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#define REQUIRED_TEXTURE_UNITS_COUNT 3 4506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 46121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy// Converts a number of mega-bytes into bytes 47121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy#define MB(s) s * 1024 * 1024 48121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 49dda570201ac851dd85af3861f7e575721d3345daRomain Guy// Generates simple and textured vertices 50bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy#define FV(x, y, u, v) { { x, y }, { u, v } } 519d5316e3f56d138504565ff311145ac01621dff4Romain Guy 529d5316e3f56d138504565ff311145ac01621dff4Romain Guy/////////////////////////////////////////////////////////////////////////////// 539d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Globals 549d5316e3f56d138504565ff311145ac01621dff4Romain Guy/////////////////////////////////////////////////////////////////////////////// 559d5316e3f56d138504565ff311145ac01621dff4Romain Guy 56026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy// This array is never used directly but used as a memcpy source in the 57026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy// OpenGLRenderer constructor 58ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guystatic const TextureVertex gMeshVertices[] = { 59c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy FV(0.0f, 0.0f, 0.0f, 0.0f), 60c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy FV(1.0f, 0.0f, 1.0f, 0.0f), 61c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy FV(0.0f, 1.0f, 0.0f, 1.0f), 62c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy FV(1.0f, 1.0f, 1.0f, 1.0f) 63bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy}; 64ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guystatic const GLsizei gMeshStride = sizeof(TextureVertex); 65ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guystatic const GLsizei gMeshCount = 4; 66026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 67889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy/** 68889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy * Structure mapping Skia xfermodes to OpenGL blending factors. 69889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy */ 70889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guystruct Blender { 71889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy SkXfermode::Mode mode; 72889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy GLenum src; 73889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy GLenum dst; 74889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy}; // struct Blender 75889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy 76026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy// In this array, the index of each Blender equals the value of the first 77026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode] 78026c5e16704e817cac7d9c382914c947e34f87e0Romain Guystatic const Blender gBlends[] = { 79026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy { SkXfermode::kClear_Mode, GL_ZERO, GL_ZERO }, 80026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy { SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO }, 81026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy { SkXfermode::kDst_Mode, GL_ZERO, GL_ONE }, 82026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy { SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, 83026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE }, 84026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy { SkXfermode::kSrcIn_Mode, GL_DST_ALPHA, GL_ZERO }, 85026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy { SkXfermode::kDstIn_Mode, GL_ZERO, GL_SRC_ALPHA }, 86026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy { SkXfermode::kSrcOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, 87026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy { SkXfermode::kDstOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, 88026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, 89026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA }, 90026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA } 91026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy}; 92e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 93889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guystatic const GLenum gTextureUnits[] = { 9406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy GL_TEXTURE0, 9506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy GL_TEXTURE1, 9606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy GL_TEXTURE2 97d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy}; 98d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy 99f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 100f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Constructors/destructor 101f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 102f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 103dda570201ac851dd85af3861f7e575721d3345daRomain GuyOpenGLRenderer::OpenGLRenderer(): 10482ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy mBlend(false), mLastSrcMode(GL_ZERO), mLastDstMode(GL_ZERO), 105dda570201ac851dd85af3861f7e575721d3345daRomain Guy mTextureCache(MB(DEFAULT_TEXTURE_CACHE_SIZE)), 106f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy mLayerCache(MB(DEFAULT_LAYER_CACHE_SIZE)), 107c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy mGradientCache(MB(DEFAULT_GRADIENT_CACHE_SIZE)), 108f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy mPatchCache(DEFAULT_PATCH_CACHE_SIZE) { 10985bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy LOGD("Create OpenGLRenderer"); 1109d5316e3f56d138504565ff311145ac01621dff4Romain Guy 111121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy char property[PROPERTY_VALUE_MAX]; 112121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, NULL) > 0) { 113dda570201ac851dd85af3861f7e575721d3345daRomain Guy LOGD(" Setting texture cache size to %sMB", property); 114c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy mTextureCache.setMaxSize(MB(atof(property))); 115dda570201ac851dd85af3861f7e575721d3345daRomain Guy } else { 116c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy LOGD(" Using default texture cache size of %.2fMB", DEFAULT_TEXTURE_CACHE_SIZE); 117dda570201ac851dd85af3861f7e575721d3345daRomain Guy } 118dda570201ac851dd85af3861f7e575721d3345daRomain Guy 119dda570201ac851dd85af3861f7e575721d3345daRomain Guy if (property_get(PROPERTY_LAYER_CACHE_SIZE, property, NULL) > 0) { 120dda570201ac851dd85af3861f7e575721d3345daRomain Guy LOGD(" Setting layer cache size to %sMB", property); 121c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy mLayerCache.setMaxSize(MB(atof(property))); 122dda570201ac851dd85af3861f7e575721d3345daRomain Guy } else { 123c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy LOGD(" Using default layer cache size of %.2fMB", DEFAULT_LAYER_CACHE_SIZE); 124c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy } 125c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 126c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy if (property_get(PROPERTY_GRADIENT_CACHE_SIZE, property, NULL) > 0) { 127c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy LOGD(" Setting gradient cache size to %sMB", property); 128c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy mLayerCache.setMaxSize(MB(atof(property))); 129c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy } else { 130c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy LOGD(" Using default gradient cache size of %.2fMB", DEFAULT_GRADIENT_CACHE_SIZE); 131121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy } 132121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 133889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy mCurrentProgram = NULL; 13406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mShader = NULL; 135026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 136ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices)); 137ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy 138ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy mFirstSnapshot = new Snapshot; 139ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy 140ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy GLint maxTextureUnits; 141ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits); 142ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy if (maxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) { 143889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy LOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT); 144889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } 145e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy} 146e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 14785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain GuyOpenGLRenderer::~OpenGLRenderer() { 14885bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy LOGD("Destroy OpenGLRenderer"); 149ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 150ce0537b80087a6225273040a987414b1dd081aa0Romain Guy mTextureCache.clear(); 151dda570201ac851dd85af3861f7e575721d3345daRomain Guy mLayerCache.clear(); 152c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy mGradientCache.clear(); 1536926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy mPatchCache.clear(); 154e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy} 155e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 156f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 157f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Setup 158f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 159f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 16085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guyvoid OpenGLRenderer::setViewport(int width, int height) { 16108ae317c21ec3086b5017672bba87420cc38a407Romain Guy glViewport(0, 0, width, height); 16208ae317c21ec3086b5017672bba87420cc38a407Romain Guy 163260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1); 164bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 165bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy mWidth = width; 166bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy mHeight = height; 167ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy mFirstSnapshot->height = height; 168e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy} 169e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 17085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guyvoid OpenGLRenderer::prepare() { 171b82da65cb1601be504241f36778395cd6cb9f87bRomain Guy mSnapshot = new Snapshot(mFirstSnapshot); 1727ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy mSaveCount = 0; 173f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 17408ae317c21ec3086b5017672bba87420cc38a407Romain Guy glDisable(GL_SCISSOR_TEST); 175bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 17608ae317c21ec3086b5017672bba87420cc38a407Romain Guy glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 17708ae317c21ec3086b5017672bba87420cc38a407Romain Guy glClear(GL_COLOR_BUFFER_BIT); 178bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 17908ae317c21ec3086b5017672bba87420cc38a407Romain Guy glEnable(GL_SCISSOR_TEST); 180c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy glScissor(0, 0, mWidth, mHeight); 181f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 182b82da65cb1601be504241f36778395cd6cb9f87bRomain Guy mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight); 183bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 184bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 185f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 186f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// State management 187f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 188f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 189bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyint OpenGLRenderer::getSaveCount() const { 1907ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy return mSaveCount; 191bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 192bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 193bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyint OpenGLRenderer::save(int flags) { 1947ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy return saveSnapshot(); 195bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 196bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 197bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid OpenGLRenderer::restore() { 1987ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy if (mSaveCount == 0) return; 199bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 2007ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy if (restoreSnapshot()) { 2017ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy setScissorFromClip(); 2027ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy } 203bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 204bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 205bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid OpenGLRenderer::restoreToCount(int saveCount) { 2067ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy if (saveCount <= 0 || saveCount > mSaveCount) return; 207bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 2087ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy bool restoreClip = false; 209bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 2107ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy while (mSaveCount != saveCount - 1) { 2117ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy restoreClip |= restoreSnapshot(); 2127ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy } 213bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 2147ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy if (restoreClip) { 2157ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy setScissorFromClip(); 2167ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy } 217bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 218bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 219bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyint OpenGLRenderer::saveSnapshot() { 2207ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy mSnapshot = new Snapshot(mSnapshot); 2217ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy return ++mSaveCount; 222bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 223bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 224bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guybool OpenGLRenderer::restoreSnapshot() { 2257ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet; 226bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy bool restoreLayer = mSnapshot->flags & Snapshot::kFlagIsLayer; 227f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy bool restoreOrtho = mSnapshot->flags & Snapshot::kFlagDirtyOrtho; 228bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 229bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy sp<Snapshot> current = mSnapshot; 2307ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy sp<Snapshot> previous = mSnapshot->previous; 231bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 232f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy if (restoreOrtho) { 233260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy mOrthoMatrix.load(current->orthoMatrix); 234f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy } 235f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy 236bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy if (restoreLayer) { 237d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy composeLayer(current, previous); 238d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy } 239bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 240d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy mSnapshot = previous; 241d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy mSaveCount--; 2425cbbce535744b89df5ecea95de21ee3733298260Romain Guy 243d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy return restoreClip; 244d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy} 2455cbbce535744b89df5ecea95de21ee3733298260Romain Guy 246d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guyvoid OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { 247dda570201ac851dd85af3861f7e575721d3345daRomain Guy if (!current->layer) { 248dda570201ac851dd85af3861f7e575721d3345daRomain Guy LOGE("Attempting to compose a layer that does not exist"); 249dda570201ac851dd85af3861f7e575721d3345daRomain Guy return; 250dda570201ac851dd85af3861f7e575721d3345daRomain Guy } 251dda570201ac851dd85af3861f7e575721d3345daRomain Guy 252d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy // Unbind current FBO and restore previous one 253d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy // Most of the time, previous->fbo will be 0 to bind the default buffer 254d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo); 2555cbbce535744b89df5ecea95de21ee3733298260Romain Guy 256d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy // Restore the clip from the previous snapshot 257079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy const Rect& clip = previous->clipRect; 258d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight()); 259bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 260dda570201ac851dd85af3861f7e575721d3345daRomain Guy Layer* layer = current->layer; 261dda570201ac851dd85af3861f7e575721d3345daRomain Guy const Rect& rect = layer->layer; 262dda570201ac851dd85af3861f7e575721d3345daRomain Guy 263dda570201ac851dd85af3861f7e575721d3345daRomain Guy drawTextureRect(rect.left, rect.top, rect.right, rect.bottom, 264a979474f15b454c8e2963f239a3770e200bb227cRomain Guy layer->texture, layer->alpha, layer->mode, layer->blend); 265bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 266dda570201ac851dd85af3861f7e575721d3345daRomain Guy LayerSize size(rect.getWidth(), rect.getHeight()); 267f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy // Failing to add the layer to the cache should happen only if the 268f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy // layer is too large 269dda570201ac851dd85af3861f7e575721d3345daRomain Guy if (!mLayerCache.put(size, layer)) { 270dda570201ac851dd85af3861f7e575721d3345daRomain Guy LAYER_LOGD("Deleting layer"); 271bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 272dda570201ac851dd85af3861f7e575721d3345daRomain Guy glDeleteFramebuffers(1, &layer->fbo); 273dda570201ac851dd85af3861f7e575721d3345daRomain Guy glDeleteTextures(1, &layer->texture); 274dda570201ac851dd85af3861f7e575721d3345daRomain Guy 275dda570201ac851dd85af3861f7e575721d3345daRomain Guy delete layer; 276dda570201ac851dd85af3861f7e575721d3345daRomain Guy } 277bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 278bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 279f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 280bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy// Layers 281bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy/////////////////////////////////////////////////////////////////////////////// 282bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 283bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyint OpenGLRenderer::saveLayer(float left, float top, float right, float bottom, 284bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy const SkPaint* p, int flags) { 285d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy int count = saveSnapshot(); 286d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy 287d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy int alpha = 255; 288d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy SkXfermode::Mode mode; 289d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy 290d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy if (p) { 291d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy alpha = p->getAlpha(); 292d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode); 293d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy if (!isMode) { 294d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy // Assume SRC_OVER 295d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy mode = SkXfermode::kSrcOver_Mode; 296d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy } 297d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy } else { 298d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy mode = SkXfermode::kSrcOver_Mode; 299d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy } 300d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy 301d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy createLayer(mSnapshot, left, top, right, bottom, alpha, mode, flags); 302d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy 303d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy return count; 304bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy} 305bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 306bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyint OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom, 307bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy int alpha, int flags) { 308bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy int count = saveSnapshot(); 309d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy createLayer(mSnapshot, left, top, right, bottom, alpha, SkXfermode::kSrcOver_Mode, flags); 310d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy return count; 311d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy} 312bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 313d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guybool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, 314d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy float right, float bottom, int alpha, SkXfermode::Mode mode,int flags) { 315d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy LAYER_LOGD("Requesting layer %fx%f", right - left, bottom - top); 316dda570201ac851dd85af3861f7e575721d3345daRomain Guy LAYER_LOGD("Layer cache size = %d", mLayerCache.getSize()); 317dda570201ac851dd85af3861f7e575721d3345daRomain Guy 318f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy GLuint previousFbo = snapshot->previous.get() ? snapshot->previous->fbo : 0; 319f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy LayerSize size(right - left, bottom - top); 320dda570201ac851dd85af3861f7e575721d3345daRomain Guy 321f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy Layer* layer = mLayerCache.get(size, previousFbo); 322f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy if (!layer) { 323f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy return false; 324bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy } 325bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 326f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); 327f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy 328f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy // Clear the FBO 329f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy glDisable(GL_SCISSOR_TEST); 330f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 331f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy glClear(GL_COLOR_BUFFER_BIT); 332f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy glEnable(GL_SCISSOR_TEST); 333f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy 334dda570201ac851dd85af3861f7e575721d3345daRomain Guy // Save the layer in the snapshot 335d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy snapshot->flags |= Snapshot::kFlagIsLayer; 336dda570201ac851dd85af3861f7e575721d3345daRomain Guy layer->mode = mode; 337dda570201ac851dd85af3861f7e575721d3345daRomain Guy layer->alpha = alpha / 255.0f; 338dda570201ac851dd85af3861f7e575721d3345daRomain Guy layer->layer.set(left, top, right, bottom); 339dda570201ac851dd85af3861f7e575721d3345daRomain Guy 340dda570201ac851dd85af3861f7e575721d3345daRomain Guy snapshot->layer = layer; 341dda570201ac851dd85af3861f7e575721d3345daRomain Guy snapshot->fbo = layer->fbo; 342d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy 343f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy // Creates a new snapshot to draw into the FBO 344f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy saveSnapshot(); 345f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy // TODO: This doesn't preserve other transformations (check Skia first) 346f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy mSnapshot->transform.loadTranslate(-left, -top, 0.0f); 347079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy mSnapshot->setClip(0.0f, 0.0f, right - left, bottom - top); 348f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy mSnapshot->height = bottom - top; 349f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy setScissorFromClip(); 350f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy 351079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy mSnapshot->flags = Snapshot::kFlagDirtyOrtho | Snapshot::kFlagClipSet; 352260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy mSnapshot->orthoMatrix.load(mOrthoMatrix); 353f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy 354f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy // Change the ortho projection 355260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy mOrthoMatrix.loadOrtho(0.0f, right - left, bottom - top, 0.0f, 0.0f, 1.0f); 356f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy 357d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy return true; 358bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy} 359bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 360bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy/////////////////////////////////////////////////////////////////////////////// 361f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Transforms 362f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 363f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 364f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::translate(float dx, float dy) { 3657ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy mSnapshot->transform.translate(dx, dy, 0.0f); 366f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy} 367f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 368f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::rotate(float degrees) { 3697ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy mSnapshot->transform.rotate(degrees, 0.0f, 0.0f, 1.0f); 370f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy} 371f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 372f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::scale(float sx, float sy) { 3737ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy mSnapshot->transform.scale(sx, sy, 1.0f); 374f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy} 375f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 376f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::setMatrix(SkMatrix* matrix) { 3777ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy mSnapshot->transform.load(*matrix); 378f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy} 379f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 380f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::getMatrix(SkMatrix* matrix) { 3817ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy mSnapshot->transform.copyTo(*matrix); 382f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy} 383f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 384f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::concatMatrix(SkMatrix* matrix) { 3857ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy mat4 m(*matrix); 3867ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy mSnapshot->transform.multiply(m); 387f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy} 388f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 389f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 390f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Clipping 391f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 392f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 393bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid OpenGLRenderer::setScissorFromClip() { 394079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy const Rect& clip = mSnapshot->clipRect; 395f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy glScissor(clip.left, mSnapshot->height - clip.bottom, clip.getWidth(), clip.getHeight()); 3969d5316e3f56d138504565ff311145ac01621dff4Romain Guy} 3979d5316e3f56d138504565ff311145ac01621dff4Romain Guy 3989d5316e3f56d138504565ff311145ac01621dff4Romain Guyconst Rect& OpenGLRenderer::getClipBounds() { 399079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy return mSnapshot->getLocalClip(); 400bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 401bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 402c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guybool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) { 403c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy Rect r(left, top, right, bottom); 404079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy mSnapshot->transform.mapRect(r); 405c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy return !mSnapshot->clipRect.intersects(r); 406c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy} 407c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy 408079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guybool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { 409079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy bool clipped = mSnapshot->clip(left, top, right, bottom, op); 4107ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy if (clipped) { 4117ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy setScissorFromClip(); 4127ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy } 413079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy return !mSnapshot->clipRect.isEmpty(); 414e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy} 415e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 416f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 417f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Drawing 418f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy/////////////////////////////////////////////////////////////////////////////// 419f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 420c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guyvoid OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) { 4216926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy const float right = left + bitmap->width(); 4226926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy const float bottom = top + bitmap->height(); 4236926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 4246926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy if (quickReject(left, top, right, bottom)) { 4256926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy return; 4266926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy } 4276926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 428f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy const Texture* texture = mTextureCache.get(bitmap); 4296926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy drawTextureRect(left, top, right, bottom, texture, paint); 4308ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy} 4318ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 432f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guyvoid OpenGLRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint) { 433f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy Rect r(0.0f, 0.0f, bitmap->width(), bitmap->height()); 434f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy const mat4 transform(*matrix); 435f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy transform.mapRect(r); 436f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy 4376926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy if (quickReject(r.left, r.top, r.right, r.bottom)) { 4386926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy return; 4396926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy } 4406926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 441f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy const Texture* texture = mTextureCache.get(bitmap); 44282ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy drawTextureRect(r.left, r.top, r.right, r.bottom, texture, paint); 443f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy} 444f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy 4458ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guyvoid OpenGLRenderer::drawBitmap(SkBitmap* bitmap, 4468ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy float srcLeft, float srcTop, float srcRight, float srcBottom, 4478ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy float dstLeft, float dstTop, float dstRight, float dstBottom, 448f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy const SkPaint* paint) { 4496926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy if (quickReject(dstLeft, dstTop, dstRight, dstBottom)) { 4506926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy return; 4516926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy } 4526926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 453f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy const Texture* texture = mTextureCache.get(bitmap); 4548ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 4558ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy const float width = texture->width; 4568ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy const float height = texture->height; 457c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy 4588ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy const float u1 = srcLeft / width; 4598ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy const float v1 = srcTop / height; 4608ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy const float u2 = srcRight / width; 4618ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy const float v2 = srcBottom / height; 462c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy 463889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy // TODO: Do this in the shader 4648ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy resetDrawTextureTexCoords(u1, v1, u2, v2); 4658ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 46682ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture, paint); 4678ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 4688ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); 469ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 470ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 471deba785f122a47915756ffd991f5540d952cf937Romain Guyvoid OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, 472deba785f122a47915756ffd991f5540d952cf937Romain Guy float left, float top, float right, float bottom, const SkPaint* paint) { 4736926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy if (quickReject(left, top, right, bottom)) { 4746926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy return; 4756926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy } 4766926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 477f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy const Texture* texture = mTextureCache.get(bitmap); 478f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 479f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy int alpha; 480f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy SkXfermode::Mode mode; 481f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy getAlphaAndMode(paint, &alpha, &mode); 482f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 483f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy Patch* mesh = mPatchCache.get(patch); 484fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy mesh->updateVertices(bitmap, left, top, right, bottom, 485fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6cRomain Guy &patch->xDivs[0], &patch->yDivs[0], patch->numXDivs, patch->numYDivs); 486f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 487f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy // Specify right and bottom as +1.0f from left/top to prevent scaling since the 488f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy // patch mesh already defines the final size 489a979474f15b454c8e2963f239a3770e200bb227cRomain Guy drawTextureMesh(left, top, left + 1.0f, top + 1.0f, texture->id, alpha / 255.0f, 490a979474f15b454c8e2963f239a3770e200bb227cRomain Guy mode, texture->blend, &mesh->vertices[0].position[0], 49116202fc9745e9b11db089ebc8f40119d13732016Romain Guy &mesh->vertices[0].texture[0], mesh->indices, mesh->indicesCount); 492f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy} 493f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 49485bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guyvoid OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { 495079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy const Rect& clip = mSnapshot->clipRect; 4963d58c03de0d8877b36cdb78b0ca8b5cac7f600e2Romain Guy drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true); 497c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy} 4989d5316e3f56d138504565ff311145ac01621dff4Romain Guy 499bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyvoid OpenGLRenderer::drawRect(float left, float top, float right, float bottom, const SkPaint* p) { 5006926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy if (quickReject(left, top, right, bottom)) { 5016926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy return; 5026926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy } 5036926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 504026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy SkXfermode::Mode mode; 505026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 506026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode); 507026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy if (!isMode) { 508026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy // Assume SRC_OVER 509026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy mode = SkXfermode::kSrcOver_Mode; 510026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy } 511026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 512026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy // Skia draws using the color's alpha channel if < 255 513026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy // Otherwise, it uses the paint's alpha 514026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy int color = p->getColor(); 515d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy if (((color >> 24) & 0xff) == 255) { 516026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy color |= p->getAlpha() << 24; 517026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy } 518026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 519026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy drawColorRect(left, top, right, bottom, color, mode); 520c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy} 5219d5316e3f56d138504565ff311145ac01621dff4Romain Guy 522e8e62a4a032a80409114a37908b5f18ab0080848Romain Guyvoid OpenGLRenderer::drawText(const char* text, int bytesCount, int count, 523e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy float x, float y, SkPaint* paint) { 524e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy if (text == NULL || count == 0 || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) { 525e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy return; 526e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy } 527e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy 528e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy float length; 529e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy switch (paint->getTextAlign()) { 530e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy case SkPaint::kCenter_Align: 531e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy length = paint->measureText(text, bytesCount); 532e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy x -= length / 2.0f; 533e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy break; 534e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy case SkPaint::kRight_Align: 535e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy length = paint->measureText(text, bytesCount); 536e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy x -= length; 537e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy break; 538e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy default: 539e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy break; 540e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy } 541e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy 542694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy int alpha; 543694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy SkXfermode::Mode mode; 544694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy getAlphaAndMode(paint, &alpha, &mode); 545694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 546694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy uint32_t color = paint->getColor(); 547694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy const GLfloat a = alpha / 255.0f; 548694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f; 549694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; 550694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy const GLfloat b = a * ((color ) & 0xFF) / 255.0f; 551694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 552694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy mModelView.loadIdentity(); 553694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 55406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy GLuint textureUnit = 0; 55506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 556889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy ProgramDescription description; 557889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy description.hasTexture = true; 558889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy description.hasAlpha8Texture = true; 55906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy if (mShader) { 56006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mShader->describe(description, mExtensions); 56106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy } 562889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy 563889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy useProgram(mProgramCache.get(description)); 564889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); 565694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 566694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy chooseBlending(true, mode); 56706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy bindTexture(mFontRenderer.getTexture(), GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit); 56806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy glUniform1i(mCurrentProgram->getUniform("sampler"), textureUnit); 569889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy 570889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy int texCoordsSlot = mCurrentProgram->getAttrib("texCoords"); 571889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy glEnableVertexAttribArray(texCoordsSlot); 572694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 573694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy // Always premultiplied 574889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy glUniform4f(mCurrentProgram->color, r, g, b, a); 575694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 57606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy textureUnit++; 57706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy // Setup attributes and uniforms required by the shaders 57806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy if (mShader) { 57906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit); 58006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy } 58106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 58209147fbdc8206a0cac78bfe9083e7e15b3c5689cRomain Guy // TODO: Implement scale properly 58309147fbdc8206a0cac78bfe9083e7e15b3c5689cRomain Guy const Rect& clip = mSnapshot->getLocalClip(); 58465ef909776c03417d8b597738da54ca211e37e4fAlex Sakhartchouk mFontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()), paint->getTextSize()); 585e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mFontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y); 586694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 587694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 588889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy glDisableVertexAttribArray(texCoordsSlot); 589694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 590694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 5916926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy/////////////////////////////////////////////////////////////////////////////// 592d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy// Shaders 593d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy/////////////////////////////////////////////////////////////////////////////// 594d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy 595d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guyvoid OpenGLRenderer::resetShader() { 59606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mShader = NULL; 59706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} 59806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 59906f96e2652e4855b6520ad9dd70583677605b79aRomain Guyvoid OpenGLRenderer::setupShader(SkiaShader* shader) { 60006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mShader = shader; 60106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy if (mShader) { 60206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mShader->set(&mTextureCache, &mGradientCache); 60306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy } 6047fac2e18339f765320d759e8d4c090f92431959eRomain Guy} 6057fac2e18339f765320d759e8d4c090f92431959eRomain Guy 606d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy/////////////////////////////////////////////////////////////////////////////// 6076926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy// Drawing implementation 6086926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy/////////////////////////////////////////////////////////////////////////////// 6096926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 610026c5e16704e817cac7d9c382914c947e34f87e0Romain Guyvoid OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, 6113d58c03de0d8877b36cdb78b0ca8b5cac7f600e2Romain Guy int color, SkXfermode::Mode mode, bool ignoreTransform) { 612d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy // If a shader is set, preserve only the alpha 61306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy if (mShader) { 614d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy color |= 0x00ffffff; 615d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy } 616d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy 617d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy // Render using pre-multiplied alpha 618026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy const int alpha = (color >> 24) & 0xFF; 619d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy const GLfloat a = alpha / 255.0f; 620c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f; 621c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; 622c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy const GLfloat b = a * ((color ) & 0xFF) / 255.0f; 623c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 62406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy GLuint textureUnit = 0; 6259d5316e3f56d138504565ff311145ac01621dff4Romain Guy 62606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy // Setup the blending mode 62706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy chooseBlending(alpha < 255 || (mShader && mShader->blend()), mode); 6289d5316e3f56d138504565ff311145ac01621dff4Romain Guy 62906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy // Describe the required shaders 630889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy ProgramDescription description; 63106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy if (mShader) { 63206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mShader->describe(description, mExtensions); 633c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy } 634c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 63506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy // Build and use the appropriate shader 636889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy useProgram(mProgramCache.get(description)); 637c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 63806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy // Setup attributes 639889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy glVertexAttribPointer(mCurrentProgram->position, 2, GL_FLOAT, GL_FALSE, 640ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy gMeshStride, &mMeshVertices[0].position[0]); 641c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy 64206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy // Setup uniforms 643889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy mModelView.loadTranslate(left, top, 0.0f); 644889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy mModelView.scale(right - left, bottom - top, 1.0f); 64506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy if (!ignoreTransform) { 64606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); 647889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } else { 64806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mat4 identity; 64906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mCurrentProgram->set(mOrthoMatrix, mModelView, identity); 650889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy } 65106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy glUniform4f(mCurrentProgram->color, r, g, b, a); 652d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy 65306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy // Setup attributes and uniforms required by the shaders 65406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy if (mShader) { 65506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit); 656d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy } 657d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy 65806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy // Draw the mesh 659889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); 660d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy} 661d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy 66282ba814ca0dea659be2cc6523bc0137679d961ceRomain Guyvoid OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, 663a979474f15b454c8e2963f239a3770e200bb227cRomain Guy const Texture* texture, const SkPaint* paint) { 66482ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy int alpha; 66582ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy SkXfermode::Mode mode; 66682ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy getAlphaAndMode(paint, &alpha, &mode); 66782ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy 668a979474f15b454c8e2963f239a3770e200bb227cRomain Guy drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode, texture->blend, 669ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], NULL); 67085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy} 67185bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy 672bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyvoid OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, 673a979474f15b454c8e2963f239a3770e200bb227cRomain Guy GLuint texture, float alpha, SkXfermode::Mode mode, bool blend) { 674a979474f15b454c8e2963f239a3770e200bb227cRomain Guy drawTextureMesh(left, top, right, bottom, texture, alpha, mode, blend, 675ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], NULL); 676f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy} 677f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 678f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guyvoid OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom, 679a979474f15b454c8e2963f239a3770e200bb227cRomain Guy GLuint texture, float alpha, SkXfermode::Mode mode, bool blend, 680f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount) { 681889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy ProgramDescription description; 682889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy description.hasTexture = true; 683889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy 684bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy mModelView.loadTranslate(left, top, 0.0f); 685bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy mModelView.scale(right - left, bottom - top, 1.0f); 686bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 687889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy useProgram(mProgramCache.get(description)); 688889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); 689bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 690a979474f15b454c8e2963f239a3770e200bb227cRomain Guy chooseBlending(blend || alpha < 1.0f, mode); 691889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy 692889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy // Texture 69306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy bindTexture(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0); 694889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy glUniform1i(mCurrentProgram->getUniform("sampler"), 0); 695c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy 696a979474f15b454c8e2963f239a3770e200bb227cRomain Guy // Always premultiplied 697889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy glUniform4f(mCurrentProgram->color, alpha, alpha, alpha, alpha); 698bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 699889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy // Mesh 700889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy int texCoordsSlot = mCurrentProgram->getAttrib("texCoords"); 701889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy glEnableVertexAttribArray(texCoordsSlot); 702889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy glVertexAttribPointer(mCurrentProgram->position, 2, GL_FLOAT, GL_FALSE, 703ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy gMeshStride, vertices); 704889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords); 705bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 706f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy if (!indices) { 707ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); 708f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy } else { 709f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy glDrawElements(GL_TRIANGLES, elementsCount, GL_UNSIGNED_SHORT, indices); 710f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy } 711889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy glDisableVertexAttribArray(texCoordsSlot); 71282ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy} 71382ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy 71482ba814ca0dea659be2cc6523bc0137679d961ceRomain Guyvoid OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, bool isPremultiplied) { 71582ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy // In theory we should not blend if the mode is Src, but it's rare enough 71682ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy // that it's not worth it 71782ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy blend = blend || mode != SkXfermode::kSrcOver_Mode; 71882ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy if (blend) { 71982ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy if (!mBlend) { 72082ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy glEnable(GL_BLEND); 72182ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy } 72282ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy 72382ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy GLenum sourceMode = gBlends[mode].src; 72482ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy GLenum destMode = gBlends[mode].dst; 72582ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy if (!isPremultiplied && sourceMode == GL_ONE) { 72682ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy sourceMode = GL_SRC_ALPHA; 72782ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy } 72882ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy 72982ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy if (sourceMode != mLastSrcMode || destMode != mLastDstMode) { 73082ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy glBlendFunc(sourceMode, destMode); 73182ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy mLastSrcMode = sourceMode; 73282ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy mLastDstMode = destMode; 73382ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy } 73482ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy } else if (mBlend) { 73582ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy glDisable(GL_BLEND); 73682ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy } 73782ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy mBlend = blend; 738bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy} 739bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 740889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guybool OpenGLRenderer::useProgram(Program* program) { 741d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy if (!program->isInUse()) { 742889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy if (mCurrentProgram != NULL) mCurrentProgram->remove(); 743d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy program->use(); 744d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy mCurrentProgram = program; 7456926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy return false; 746260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy } 7476926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy return true; 748260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy} 749260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy 750026c5e16704e817cac7d9c382914c947e34f87e0Romain Guyvoid OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) { 751ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy TextureVertex* v = &mMeshVertices[0]; 75282ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy TextureVertex::setUV(v++, u1, v1); 75382ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy TextureVertex::setUV(v++, u2, v1); 75482ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy TextureVertex::setUV(v++, u1, v2); 75582ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy TextureVertex::setUV(v++, u2, v2); 7568ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy} 7578ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 7588ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guyvoid OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode) { 7598ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy if (paint) { 7608ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy const bool isMode = SkXfermode::IsMode(paint->getXfermode(), mode); 7618ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy if (!isMode) { 7628ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy // Assume SRC_OVER 7638ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy *mode = SkXfermode::kSrcOver_Mode; 7648ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy } 7658ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 7668ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy // Skia draws using the color's alpha channel if < 255 7678ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy // Otherwise, it uses the paint's alpha 7688ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy int color = paint->getColor(); 7698ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy *alpha = (color >> 24) & 0xFF; 7708ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy if (*alpha == 255) { 7718ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy *alpha = paint->getAlpha(); 7728ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy } 7738ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy } else { 7748ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy *mode = SkXfermode::kSrcOver_Mode; 7758ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy *alpha = 255; 7768ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy } 777026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy} 778026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 779889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guyvoid OpenGLRenderer::bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint textureUnit) { 780889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy glActiveTexture(gTextureUnits[textureUnit]); 781ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy glBindTexture(GL_TEXTURE_2D, texture); 782a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); 783a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); 784a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy} 785a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy 7869d5316e3f56d138504565ff311145ac01621dff4Romain Guy}; // namespace uirenderer 787e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}; // namespace android 788