OpenGLRenderer.cpp revision 03750a067e818ca7fbd0f590e2ff6a8fded21e6c
1bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber/* 2bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * Copyright (C) 2010 The Android Open Source Project 3bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * 4bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * you may not use this file except in compliance with the License. 6bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * You may obtain a copy of the License at 7bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * 8bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * 10bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * Unless required by applicable law or agreed to in writing, software 11bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * See the License for the specific language governing permissions and 14bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * limitations under the License. 15bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber */ 16bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 17bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber#define LOG_TAG "OpenGLRenderer" 18bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 19bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber#include <stdlib.h> 20bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber#include <stdint.h> 21988e3f0b2c74095deae580157c57935a98573052Andreas Huber#include <sys/types.h> 22988e3f0b2c74095deae580157c57935a98573052Andreas Huber 23cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <SkCanvas.h> 24bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber#include <SkTypeface.h> 25733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber 260a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber#include <utils/Log.h> 270a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber#include <utils/StopWatch.h> 28bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber 29bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber#include "OpenGLRenderer.h" 3039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 3139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubernamespace android { 3239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubernamespace uirenderer { 3339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 3439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber/////////////////////////////////////////////////////////////////////////////// 354844ac54e8b5997c3b03872dbafe8ebed4787517Andreas Huber// Defines 36e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber/////////////////////////////////////////////////////////////////////////////// 37e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 38e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber#define RAD_TO_DEG (180.0f / 3.14159265f) 39e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber#define MIN_ANGLE 0.001f 40bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 41bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber// TODO: This should be set in properties 42bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber#define ALPHA_THRESHOLD (0x7f / PANEL_BIT_DEPTH) 43bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 44717826ececd8d39596f62418677721d70776add1Andreas Huber/////////////////////////////////////////////////////////////////////////////// 45bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber// Globals 46bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber/////////////////////////////////////////////////////////////////////////////// 47bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 48bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber/** 49717826ececd8d39596f62418677721d70776add1Andreas Huber * Structure mapping Skia xfermodes to OpenGL blending factors. 505daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber */ 513cf613507f1e2f7bd932d921a6e222e426fd3be4Mathias Agopianstruct Blender { 52cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber SkXfermode::Mode mode; 5314acc736e336cbd6026df781d4f411e908831815Andreas Huber GLenum src; 54a44153c1a57202fb538659eb50706e60454d6273Andreas Huber GLenum dst; 55e71d10e7ad55ccbcb0756c007caef1c959090384Andreas Huber}; // struct Blender 56e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 57e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber// In this array, the index of each Blender equals the value of the first 58bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode] 59bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberstatic const Blender gBlends[] = { 608650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber { SkXfermode::kClear_Mode, GL_ZERO, GL_ZERO }, 618650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber { SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO }, 628650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber { SkXfermode::kDst_Mode, GL_ZERO, GL_ONE }, 63bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber { SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, 64c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE }, 65c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber { SkXfermode::kSrcIn_Mode, GL_DST_ALPHA, GL_ZERO }, 66c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber { SkXfermode::kDstIn_Mode, GL_ZERO, GL_SRC_ALPHA }, 67bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber { SkXfermode::kSrcOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, 68c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber { SkXfermode::kDstOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, 69bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, 70bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA }, 71bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA } 72bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber}; 73bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 74bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber// This array contains the swapped version of each SkXfermode. For instance 75c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber// this array's SrcOver blending mode is actually DstOver. You can refer to 76bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber// createLayer() for more information on the purpose of this array. 77bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberstatic const Blender gBlendsSwap[] = { 78bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber { SkXfermode::kClear_Mode, GL_ZERO, GL_ZERO }, 79bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber { SkXfermode::kSrc_Mode, GL_ZERO, GL_ONE }, 80c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber { SkXfermode::kDst_Mode, GL_ONE, GL_ZERO }, 81bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber { SkXfermode::kSrcOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE }, 82bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber { SkXfermode::kDstOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, 83bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber { SkXfermode::kSrcIn_Mode, GL_ZERO, GL_SRC_ALPHA }, 84bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber { SkXfermode::kDstIn_Mode, GL_DST_ALPHA, GL_ZERO }, 85bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber { SkXfermode::kSrcOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, 86733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber { SkXfermode::kDstOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, 87733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber { SkXfermode::kSrcATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA }, 88f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber { SkXfermode::kDstATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, 89f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA } 90733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber}; 91733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber 92733b7729ea462fae9c6899456444e28fef1c757cAndreas Huberstatic const GLenum gTextureUnits[] = { 93fa090f541bb84a546af2ec834e91a032ff10e66eAndreas Huber GL_TEXTURE0, 94fa090f541bb84a546af2ec834e91a032ff10e66eAndreas Huber GL_TEXTURE1, 95fa090f541bb84a546af2ec834e91a032ff10e66eAndreas Huber GL_TEXTURE2 96fa090f541bb84a546af2ec834e91a032ff10e66eAndreas Huber}; 97fa090f541bb84a546af2ec834e91a032ff10e66eAndreas Huber 98fa090f541bb84a546af2ec834e91a032ff10e66eAndreas Huber/////////////////////////////////////////////////////////////////////////////// 99733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber// Constructors/destructor 100733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber/////////////////////////////////////////////////////////////////////////////// 101733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber 102733b7729ea462fae9c6899456444e28fef1c757cAndreas HuberOpenGLRenderer::OpenGLRenderer(): mCaches(Caches::getInstance()) { 103733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber mShader = NULL; 104733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber mColorFilter = NULL; 105733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber mHasShadow = false; 106733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber 107733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices)); 1080a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber 109988e3f0b2c74095deae580157c57935a98573052Andreas Huber mFirstSnapshot = new Snapshot; 110733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber 111733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); 112733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber} 113733b7729ea462fae9c6899456444e28fef1c757cAndreas Huber 1146a9da9fc558263548ebfbae2cbf177eb7454a41bJamie GennisOpenGLRenderer::~OpenGLRenderer() { 115ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber // The context has already been destroyed at this point, do not call 116ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber // GL APIs. All GL state should be kept in Caches.h 117ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber} 1186a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis 119ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber/////////////////////////////////////////////////////////////////////////////// 1206a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis// Setup 1216a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis/////////////////////////////////////////////////////////////////////////////// 1226a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis 1236a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennisvoid OpenGLRenderer::setViewport(int width, int height) { 1246a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis glViewport(0, 0, width, height); 1256a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1); 1266a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis 1276a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis mWidth = width; 1286a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis mHeight = height; 1296a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis 1306a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis mFirstSnapshot->height = height; 1316a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis mFirstSnapshot->viewport.set(0, 0, width, height); 1326a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis} 1336a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis 1346a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennisvoid OpenGLRenderer::prepare(bool opaque) { 1356a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis mSnapshot = new Snapshot(mFirstSnapshot, 1366a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 1376a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis mSaveCount = 1; 1386a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis 1396a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis glViewport(0, 0, mWidth, mHeight); 1406a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis 141ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber glDisable(GL_DITHER); 142ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber glDisable(GL_SCISSOR_TEST); 143ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 144ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (!opaque) { 145ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 146ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber glClear(GL_COLOR_BUFFER_BIT); 147ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 148ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 149ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber glEnable(GL_SCISSOR_TEST); 150ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber glScissor(0, 0, mWidth, mHeight); 151ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 152ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight); 153ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber} 154ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 155ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Hubervoid OpenGLRenderer::finish() { 156ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if DEBUG_OPENGL 1576a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis GLenum status = GL_NO_ERROR; 1586a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis while ((status = glGetError()) != GL_NO_ERROR) { 1596a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis LOGD("GL error from OpenGLRenderer: 0x%x", status); 1606a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis } 1616a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis#endif 162e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber} 163e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 164e2b1028852120bcfded33b8f06f66b780437fe92Andreas Hubervoid OpenGLRenderer::acquireContext() { 165e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (mCaches.currentProgram) { 166e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (mCaches.currentProgram->isInUse()) { 167e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber mCaches.currentProgram->remove(); 168e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber mCaches.currentProgram = NULL; 169e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber } 170e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber } 171e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber} 172e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 173e2b1028852120bcfded33b8f06f66b780437fe92Andreas Hubervoid OpenGLRenderer::releaseContext() { 17414acc736e336cbd6026df781d4f411e908831815Andreas Huber glViewport(0, 0, mSnapshot->viewport.getWidth(), mSnapshot->viewport.getHeight()); 17514acc736e336cbd6026df781d4f411e908831815Andreas Huber 17614acc736e336cbd6026df781d4f411e908831815Andreas Huber glEnable(GL_SCISSOR_TEST); 177e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber setScissorFromClip(); 178e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 179e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber glDisable(GL_DITHER); 180e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 181e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber glBindFramebuffer(GL_FRAMEBUFFER, 0); 182e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 183e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber mCaches.bindMeshBuffer(); 184e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 185e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (mCaches.blend) { 186e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber glEnable(GL_BLEND); 187e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber glBlendFunc(mCaches.lastSrcMode, mCaches.lastDstMode); 188e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber glBlendEquation(GL_FUNC_ADD); 189e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber } else { 190e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber glDisable(GL_BLEND); 191e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber } 192e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber} 193e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 19414acc736e336cbd6026df781d4f411e908831815Andreas Huber/////////////////////////////////////////////////////////////////////////////// 19514acc736e336cbd6026df781d4f411e908831815Andreas Huber// State management 19614acc736e336cbd6026df781d4f411e908831815Andreas Huber/////////////////////////////////////////////////////////////////////////////// 19714acc736e336cbd6026df781d4f411e908831815Andreas Huber 19814acc736e336cbd6026df781d4f411e908831815Andreas Huberint OpenGLRenderer::getSaveCount() const { 199e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber return mSaveCount; 200e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber} 201e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 202e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huberint OpenGLRenderer::save(int flags) { 203e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber return saveSnapshot(flags); 204e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber} 205e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 206e2b1028852120bcfded33b8f06f66b780437fe92Andreas Hubervoid OpenGLRenderer::restore() { 207e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (mSaveCount > 1) { 20814acc736e336cbd6026df781d4f411e908831815Andreas Huber restoreSnapshot(); 20914acc736e336cbd6026df781d4f411e908831815Andreas Huber } 21014acc736e336cbd6026df781d4f411e908831815Andreas Huber} 21114acc736e336cbd6026df781d4f411e908831815Andreas Huber 21214acc736e336cbd6026df781d4f411e908831815Andreas Hubervoid OpenGLRenderer::restoreToCount(int saveCount) { 21314acc736e336cbd6026df781d4f411e908831815Andreas Huber if (saveCount < 1) saveCount = 1; 214e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 215e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber while (mSaveCount > saveCount) { 216e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber restoreSnapshot(); 217e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber } 218e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber} 219e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 220e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huberint OpenGLRenderer::saveSnapshot(int flags) { 221e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber mSnapshot = new Snapshot(mSnapshot, flags); 222e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber return mSaveCount++; 223e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber} 224e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 225e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huberbool OpenGLRenderer::restoreSnapshot() { 226e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet; 22714acc736e336cbd6026df781d4f411e908831815Andreas Huber bool restoreLayer = mSnapshot->flags & Snapshot::kFlagIsLayer; 228e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber bool restoreOrtho = mSnapshot->flags & Snapshot::kFlagDirtyOrtho; 229e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 230e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber sp<Snapshot> current = mSnapshot; 231e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber sp<Snapshot> previous = mSnapshot->previous; 232e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 233e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (restoreOrtho) { 234e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber Rect& r = previous->viewport; 235e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber glViewport(r.left, r.top, r.right, r.bottom); 236e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber mOrthoMatrix.load(current->orthoMatrix); 237e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber } 238e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 239e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber mSaveCount--; 240e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber mSnapshot = previous; 241e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 24214acc736e336cbd6026df781d4f411e908831815Andreas Huber if (restoreLayer) { 243e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber composeLayer(current, previous); 244e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber } 245e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 246e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (restoreClip) { 247e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber setScissorFromClip(); 248e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber } 249e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 250e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber return restoreClip; 251e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber} 252e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 253e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber/////////////////////////////////////////////////////////////////////////////// 254e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber// Layers 255e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber/////////////////////////////////////////////////////////////////////////////// 256e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 257e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huberint OpenGLRenderer::saveLayer(float left, float top, float right, float bottom, 258e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber const SkPaint* p, int flags) { 259e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber const GLuint previousFbo = mSnapshot->fbo; 260e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber const int count = saveSnapshot(flags); 261e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 262e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber int alpha = 255; 263e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber SkXfermode::Mode mode; 264e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 265e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (p) { 266e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber alpha = p->getAlpha(); 267e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (!mExtensions.hasFramebufferFetch()) { 268e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode); 269e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (!isMode) { 270e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber // Assume SRC_OVER 271e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber mode = SkXfermode::kSrcOver_Mode; 272e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber } 273e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber } else { 274e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber mode = getXfermode(p->getXfermode()); 27514acc736e336cbd6026df781d4f411e908831815Andreas Huber } 27614acc736e336cbd6026df781d4f411e908831815Andreas Huber } else { 27714acc736e336cbd6026df781d4f411e908831815Andreas Huber mode = SkXfermode::kSrcOver_Mode; 27814acc736e336cbd6026df781d4f411e908831815Andreas Huber } 279e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 280e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (!mSnapshot->previous->invisible) { 281e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber createLayer(mSnapshot, left, top, right, bottom, alpha, mode, flags, previousFbo); 28214acc736e336cbd6026df781d4f411e908831815Andreas Huber } 283e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 284e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber return count; 285e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber} 28614acc736e336cbd6026df781d4f411e908831815Andreas Huber 28714acc736e336cbd6026df781d4f411e908831815Andreas Huberint OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom, 28814acc736e336cbd6026df781d4f411e908831815Andreas Huber int alpha, int flags) { 28914acc736e336cbd6026df781d4f411e908831815Andreas Huber if (alpha == 0xff) { 29014acc736e336cbd6026df781d4f411e908831815Andreas Huber return saveLayer(left, top, right, bottom, NULL, flags); 29114acc736e336cbd6026df781d4f411e908831815Andreas Huber } else { 29214acc736e336cbd6026df781d4f411e908831815Andreas Huber SkPaint paint; 29314acc736e336cbd6026df781d4f411e908831815Andreas Huber paint.setAlpha(alpha); 29414acc736e336cbd6026df781d4f411e908831815Andreas Huber return saveLayer(left, top, right, bottom, &paint, flags); 29514acc736e336cbd6026df781d4f411e908831815Andreas Huber } 29614acc736e336cbd6026df781d4f411e908831815Andreas Huber} 29714acc736e336cbd6026df781d4f411e908831815Andreas Huber 29814acc736e336cbd6026df781d4f411e908831815Andreas Huber/** 29914acc736e336cbd6026df781d4f411e908831815Andreas Huber * Layers are viewed by Skia are slightly different than layers in image editing 30014acc736e336cbd6026df781d4f411e908831815Andreas Huber * programs (for instance.) When a layer is created, previously created layers 30114acc736e336cbd6026df781d4f411e908831815Andreas Huber * and the frame buffer still receive every drawing command. For instance, if a 30214acc736e336cbd6026df781d4f411e908831815Andreas Huber * layer is created and a shape intersecting the bounds of the layers and the 30314acc736e336cbd6026df781d4f411e908831815Andreas Huber * framebuffer is draw, the shape will be drawn on both (unless the layer was 30414acc736e336cbd6026df781d4f411e908831815Andreas Huber * created with the SkCanvas::kClipToLayer_SaveFlag flag.) 30514acc736e336cbd6026df781d4f411e908831815Andreas Huber * 30614acc736e336cbd6026df781d4f411e908831815Andreas Huber * A way to implement layers is to create an FBO for each layer, backed by an RGBA 30714acc736e336cbd6026df781d4f411e908831815Andreas Huber * texture. Unfortunately, this is inefficient as it requires every primitive to 30814acc736e336cbd6026df781d4f411e908831815Andreas Huber * be drawn n + 1 times, where n is the number of active layers. In practice this 30914acc736e336cbd6026df781d4f411e908831815Andreas Huber * means, for every primitive: 31014acc736e336cbd6026df781d4f411e908831815Andreas Huber * - Switch active frame buffer 31114acc736e336cbd6026df781d4f411e908831815Andreas Huber * - Change viewport, clip and projection matrix 31214acc736e336cbd6026df781d4f411e908831815Andreas Huber * - Issue the drawing 31314acc736e336cbd6026df781d4f411e908831815Andreas Huber * 31414acc736e336cbd6026df781d4f411e908831815Andreas Huber * Switching rendering target n + 1 times per drawn primitive is extremely costly. 315e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * To avoid this, layers are implemented in a different way here, at least in the 316e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * general case. FBOs are used, as an optimization, when the "clip to layer" flag 31714acc736e336cbd6026df781d4f411e908831815Andreas Huber * is set. When this flag is set we can redirect all drawing operations into a 31814acc736e336cbd6026df781d4f411e908831815Andreas Huber * single FBO. 31914acc736e336cbd6026df781d4f411e908831815Andreas Huber * 320e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * This implementation relies on the frame buffer being at least RGBA 8888. When 321e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * a layer is created, only a texture is created, not an FBO. The content of the 32214acc736e336cbd6026df781d4f411e908831815Andreas Huber * frame buffer contained within the layer's bounds is copied into this texture 32314acc736e336cbd6026df781d4f411e908831815Andreas Huber * using glCopyTexImage2D(). The layer's region is then cleared(1) in the frame 324e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * buffer and drawing continues as normal. This technique therefore treats the 325e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * frame buffer as a scratch buffer for the layers. 326e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * 32714acc736e336cbd6026df781d4f411e908831815Andreas Huber * To compose the layers back onto the frame buffer, each layer texture 32814acc736e336cbd6026df781d4f411e908831815Andreas Huber * (containing the original frame buffer data) is drawn as a simple quad over 329e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * the frame buffer. The trick is that the quad is set as the composition 330e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * destination in the blending equation, and the frame buffer becomes the source 33114acc736e336cbd6026df781d4f411e908831815Andreas Huber * of the composition. 33214acc736e336cbd6026df781d4f411e908831815Andreas Huber * 333e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * Drawing layers with an alpha value requires an extra step before composition. 334e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * An empty quad is drawn over the layer's region in the frame buffer. This quad 33514acc736e336cbd6026df781d4f411e908831815Andreas Huber * is drawn with the rgba color (0,0,0,alpha). The alpha value offered by the 33614acc736e336cbd6026df781d4f411e908831815Andreas Huber * quad is used to multiply the colors in the frame buffer. This is achieved by 33714acc736e336cbd6026df781d4f411e908831815Andreas Huber * changing the GL blend functions for the GL_FUNC_ADD blend equation to 338e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * GL_ZERO, GL_SRC_ALPHA. 339e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * 340e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * Because glCopyTexImage2D() can be slow, an alternative implementation might 341e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * be use to draw a single clipped layer. The implementation described above 342e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * is correct in every case. 343e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * 344e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * (1) The frame buffer is actually not cleared right away. To allow the GPU 345e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * to potentially optimize series of calls to glCopyTexImage2D, the frame 346e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * buffer is left untouched until the first drawing operation. Only when 347e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber * something actually gets drawn are the layers regions cleared. 348e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber */ 349e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huberbool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, 350e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber float right, float bottom, int alpha, SkXfermode::Mode mode, 351e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber int flags, GLuint previousFbo) { 35214acc736e336cbd6026df781d4f411e908831815Andreas Huber LAYER_LOGD("Requesting layer %.2fx%.2f", right - left, bottom - top); 35314acc736e336cbd6026df781d4f411e908831815Andreas Huber LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize()); 35414acc736e336cbd6026df781d4f411e908831815Andreas Huber 35514acc736e336cbd6026df781d4f411e908831815Andreas Huber const bool fboLayer = flags & SkCanvas::kClipToLayer_SaveFlag; 35614acc736e336cbd6026df781d4f411e908831815Andreas Huber 357e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber // Window coordinates of the layer 35814acc736e336cbd6026df781d4f411e908831815Andreas Huber Rect bounds(left, top, right, bottom); 359e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (!fboLayer) { 360e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber mSnapshot->transform->mapRect(bounds); 361e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber // Layers only make sense if they are in the framebuffer's bounds 36214acc736e336cbd6026df781d4f411e908831815Andreas Huber bounds.intersect(*mSnapshot->clipRect); 36314acc736e336cbd6026df781d4f411e908831815Andreas Huber bounds.snapToPixelBoundaries(); 36414acc736e336cbd6026df781d4f411e908831815Andreas Huber } 36514acc736e336cbd6026df781d4f411e908831815Andreas Huber 366e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (bounds.isEmpty() || bounds.getWidth() > mMaxTextureSize || 367e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber bounds.getHeight() > mMaxTextureSize) { 36814acc736e336cbd6026df781d4f411e908831815Andreas Huber snapshot->invisible = true; 36914acc736e336cbd6026df781d4f411e908831815Andreas Huber } else { 37014acc736e336cbd6026df781d4f411e908831815Andreas Huber // TODO: Should take the mode into account 37114acc736e336cbd6026df781d4f411e908831815Andreas Huber snapshot->invisible = snapshot->previous->invisible || 37214acc736e336cbd6026df781d4f411e908831815Andreas Huber (alpha <= ALPHA_THRESHOLD && fboLayer); 37314acc736e336cbd6026df781d4f411e908831815Andreas Huber } 37414acc736e336cbd6026df781d4f411e908831815Andreas Huber 37514acc736e336cbd6026df781d4f411e908831815Andreas Huber // Bail out if we won't draw in this snapshot 37614acc736e336cbd6026df781d4f411e908831815Andreas Huber if (snapshot->invisible) { 377e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber return false; 378e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber } 379e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 380e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber glActiveTexture(GL_TEXTURE0); 381e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 382e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber Layer* layer = mCaches.layerCache.get(bounds.getWidth(), bounds.getHeight()); 383e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (!layer) { 384e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber return false; 385e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber } 386e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 387e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber layer->mode = mode; 388e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber layer->alpha = alpha; 389e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber layer->layer.set(bounds); 390e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->height), 391e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber bounds.getWidth() / float(layer->width), 0.0f); 39214acc736e336cbd6026df781d4f411e908831815Andreas Huber 39314acc736e336cbd6026df781d4f411e908831815Andreas Huber // Save the layer in the snapshot 394e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber snapshot->flags |= Snapshot::kFlagIsLayer; 395e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber snapshot->layer = layer; 396e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 397e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (fboLayer) { 39814acc736e336cbd6026df781d4f411e908831815Andreas Huber layer->fbo = mCaches.fboCache.get(); 399e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 400e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber snapshot->flags |= Snapshot::kFlagIsFboLayer; 401e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber snapshot->fbo = layer->fbo; 402e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber snapshot->resetTransform(-bounds.left, -bounds.top, 0.0f); 403bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber snapshot->resetClip(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight()); 4042e8ffaf95bd35358ecd14ddf00cddaf3abefe0a9Andreas Huber snapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight()); 4052e8ffaf95bd35358ecd14ddf00cddaf3abefe0a9Andreas Huber snapshot->height = bounds.getHeight(); 406fa090f541bb84a546af2ec834e91a032ff10e66eAndreas Huber snapshot->flags |= Snapshot::kFlagDirtyOrtho; 407bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber snapshot->orthoMatrix.load(mOrthoMatrix); 408bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber 409acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huber // Bind texture to FBO 4107b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); 411dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang glBindTexture(GL_TEXTURE_2D, layer->texture); 412e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 413bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // Initialize the texture if needed 414bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (layer->empty) { 415bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber layer->empty = false; 416c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->width, layer->height, 0, 417bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber GL_RGBA, GL_UNSIGNED_BYTE, NULL); 418c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber } 419bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 420c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 42166b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber layer->texture, 0); 422c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber 423c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber#if DEBUG_LAYERS 424c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 425c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber if (status != GL_FRAMEBUFFER_COMPLETE) { 4261862a33b246249630b654182afb5914da3480d4cAndreas Huber LOGE("Framebuffer incomplete (GL error code 0x%x)", status); 427bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 428bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); 429bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber glDeleteTextures(1, &layer->texture); 430bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mCaches.fboCache.put(layer->fbo); 431bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 4322e8ffaf95bd35358ecd14ddf00cddaf3abefe0a9Andreas Huber delete layer; 4332e8ffaf95bd35358ecd14ddf00cddaf3abefe0a9Andreas Huber 4342e8ffaf95bd35358ecd14ddf00cddaf3abefe0a9Andreas Huber return false; 435bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 436bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber#endif 437bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 438bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // Clear the FBO 439bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber glScissor(0.0f, 0.0f, bounds.getWidth() + 1.0f, bounds.getHeight() + 1.0f); 440bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 44166b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber glClear(GL_COLOR_BUFFER_BIT); 442bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 443bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber setScissorFromClip(); 444bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 445bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // Change the ortho projection 4461862a33b246249630b654182afb5914da3480d4cAndreas Huber glViewport(0, 0, bounds.getWidth(), bounds.getHeight()); 4471862a33b246249630b654182afb5914da3480d4cAndreas Huber mOrthoMatrix.loadOrtho(0.0f, bounds.getWidth(), bounds.getHeight(), 0.0f, -1.0f, 1.0f); 44866b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber } else { 44966b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber // Copy the framebuffer into the layer 45066b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber glBindTexture(GL_TEXTURE_2D, layer->texture); 45166b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber 45266b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber if (layer->empty) { 453bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left, mHeight - bounds.bottom, 454bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber layer->width, layer->height, 0); 4550726045216f576e97672ebeefc265d39c4ebaaa5Andreas Huber layer->empty = false; 456bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } else { 457bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left, mHeight - bounds.bottom, 458bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber bounds.getWidth(), bounds.getHeight()); 459bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 4605561ccf4a8db88a2e44eac1b3ed13b4ff53a7f20Andreas Huber 4615561ccf4a8db88a2e44eac1b3ed13b4ff53a7f20Andreas Huber // Enqueue the buffer coordinates to clear the corresponding region later 462bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mLayers.push(new Rect(bounds)); 4637b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber } 4647b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 465bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return true; 4667b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber} 4677b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 468bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber/** 469bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber * Read the documentation of createLayer() before doing anything in this method. 470bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber */ 47166b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Hubervoid OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { 472e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (!current->layer) { 473e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber LOGE("Attempting to compose a layer that does not exist"); 474e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber return; 475e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 476decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber 477decd96988e495133e4a1728f612d4c9fdb4d218eAndreas Huber const bool fboLayer = current->flags & SkCanvas::kClipToLayer_SaveFlag; 478e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber 479e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber if (fboLayer) { 480e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber // Unbind current FBO and restore previous one 481e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo); 482e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber } 483bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber 484bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber // Restore the clip from the previous snapshot 48566b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber const Rect& clip = *previous->clipRect; 48666b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber glScissor(clip.left, previous->height - clip.bottom, clip.getWidth(), clip.getHeight()); 487bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber 488bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber Layer* layer = current->layer; 489bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber const Rect& rect = layer->layer; 49066b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber 491bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber if (!fboLayer && layer->alpha < 255) { 492bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber drawColorRect(rect.left, rect.top, rect.right, rect.bottom, 493bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber layer->alpha << 24, SkXfermode::kDstIn_Mode, true); 494bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 495bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 496bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const Rect& texCoords = layer->texCoords; 497bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mCaches.unbindMeshBuffer(); 498bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber resetDrawTextureTexCoords(texCoords.left, texCoords.top, texCoords.right, texCoords.bottom); 499bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 5007b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber if (fboLayer) { 501bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture, 5027b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0], 503bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount); 504bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } else { 505bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture, 506bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0], 507bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, true, true); 5087b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber } 5097b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 5107b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); 5117b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 5127b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber if (fboLayer) { 513e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber // Detach the texture from the FBO 514e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber glBindFramebuffer(GL_FRAMEBUFFER, current->fbo); 515e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); 516e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo); 517e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 518e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber // Put the FBO name back in the cache, if it doesn't fit, it will be destroyed 51914acc736e336cbd6026df781d4f411e908831815Andreas Huber mCaches.fboCache.put(current->fbo); 520e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber } 521e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 522e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber // Failing to add the layer to the cache should happen only if the layer is too large 523e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber if (!mCaches.layerCache.put(layer)) { 5247b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber LAYER_LOGD("Deleting layer"); 5257b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber glDeleteTextures(1, &layer->texture); 5267b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber delete layer; 527bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 528bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber} 529bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 530bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Hubervoid OpenGLRenderer::clearLayerRegions() { 531bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (mLayers.size() == 0 || mSnapshot->invisible) return; 532dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 53355426ce7eded04c9993149edd86f861cfccb4d19Gloria Wang for (uint32_t i = 0; i < mLayers.size(); i++) { 53455426ce7eded04c9993149edd86f861cfccb4d19Gloria Wang Rect* bounds = mLayers.itemAt(i); 53555426ce7eded04c9993149edd86f861cfccb4d19Gloria Wang 536dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang // Clear the framebuffer where the layer will draw 537dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang glScissor(bounds->left, mSnapshot->height - bounds->bottom, 538bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber bounds->getWidth(), bounds->getHeight()); 539bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 540bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber glClear(GL_COLOR_BUFFER_BIT); 541bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 5427fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber delete bounds; 5437fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber } 5447fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber mLayers.clear(); 5457fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber 5467fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber // Restore the clip 5477fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber setScissorFromClip(); 5487fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber} 5497fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber 5507fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber/////////////////////////////////////////////////////////////////////////////// 5517fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber// Transforms 5527fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber/////////////////////////////////////////////////////////////////////////////// 5537fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber 5547fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Hubervoid OpenGLRenderer::translate(float dx, float dy) { 5557fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber mSnapshot->transform->translate(dx, dy, 0.0f); 5567fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber} 5577fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber 5587fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Hubervoid OpenGLRenderer::rotate(float degrees) { 5597fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber mSnapshot->transform->rotate(degrees, 0.0f, 0.0f, 1.0f); 5607fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber} 5617fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber 5627fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Hubervoid OpenGLRenderer::scale(float sx, float sy) { 5637fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber mSnapshot->transform->scale(sx, sy, 1.0f); 564bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber} 565bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 566bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Hubervoid OpenGLRenderer::setMatrix(SkMatrix* matrix) { 567bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mSnapshot->transform->load(*matrix); 568bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber} 569bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 570bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberconst float* OpenGLRenderer::getMatrix() const { 571bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (mSnapshot->fbo != 0) { 572bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return &mSnapshot->transform->data[0]; 57388d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber } 57488d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber return &mIdentity.data[0]; 575bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber} 57688d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber 57788d8a83de12592635248aa1a3bd6b9ea46108501Andreas Hubervoid OpenGLRenderer::getMatrix(SkMatrix* matrix) { 5788ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber mSnapshot->transform->copyTo(*matrix); 5796954535ba64374e4e941cd83019a7af53edfb098Andreas Huber} 5806954535ba64374e4e941cd83019a7af53edfb098Andreas Huber 5816954535ba64374e4e941cd83019a7af53edfb098Andreas Hubervoid OpenGLRenderer::concatMatrix(SkMatrix* matrix) { 5826954535ba64374e4e941cd83019a7af53edfb098Andreas Huber SkMatrix transform; 5836954535ba64374e4e941cd83019a7af53edfb098Andreas Huber mSnapshot->transform->copyTo(transform); 5846954535ba64374e4e941cd83019a7af53edfb098Andreas Huber transform.preConcat(*matrix); 5856954535ba64374e4e941cd83019a7af53edfb098Andreas Huber mSnapshot->transform->load(transform); 5866954535ba64374e4e941cd83019a7af53edfb098Andreas Huber} 5876954535ba64374e4e941cd83019a7af53edfb098Andreas Huber 5886954535ba64374e4e941cd83019a7af53edfb098Andreas Huber/////////////////////////////////////////////////////////////////////////////// 5896954535ba64374e4e941cd83019a7af53edfb098Andreas Huber// Clipping 5908ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber/////////////////////////////////////////////////////////////////////////////// 591bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 592bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Hubervoid OpenGLRenderer::setScissorFromClip() { 593bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber Rect clip(*mSnapshot->clipRect); 594bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber clip.snapToPixelBoundaries(); 595bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber glScissor(clip.left, mSnapshot->height - clip.bottom, clip.getWidth(), clip.getHeight()); 596bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber} 597bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 598acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huberconst Rect& OpenGLRenderer::getClipBounds() { 599acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huber return mSnapshot->getLocalClip(); 600acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huber} 601acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huber 602acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huberbool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) { 603acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huber if (mSnapshot->invisible) { 604acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huber return true; 605bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 606bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 607bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber Rect r(left, top, right, bottom); 608bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mSnapshot->transform->mapRect(r); 609bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber r.snapToPixelBoundaries(); 610bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 611bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber Rect clipRect(*mSnapshot->clipRect); 612bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber clipRect.snapToPixelBoundaries(); 613dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 614dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return !clipRect.intersects(r); 615dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang} 616b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang 617dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wangbool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { 618dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang bool clipped = mSnapshot->clip(left, top, right, bottom, op); 619dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (clipped) { 620dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang setScissorFromClip(); 621e94bd14078d327ef2f800e69907efce641a13272Andreas Huber } 622e94bd14078d327ef2f800e69907efce641a13272Andreas Huber return !mSnapshot->clipRect->isEmpty(); 623e94bd14078d327ef2f800e69907efce641a13272Andreas Huber} 624e94bd14078d327ef2f800e69907efce641a13272Andreas Huber 625e94bd14078d327ef2f800e69907efce641a13272Andreas Huber/////////////////////////////////////////////////////////////////////////////// 626e94bd14078d327ef2f800e69907efce641a13272Andreas Huber// Drawing 6276a05c9e912aeb8bfe1ef99516def91a177a481b6Andreas Huber/////////////////////////////////////////////////////////////////////////////// 6286a05c9e912aeb8bfe1ef99516def91a177a481b6Andreas Huber 6296a05c9e912aeb8bfe1ef99516def91a177a481b6Andreas Hubervoid OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) { 6306a05c9e912aeb8bfe1ef99516def91a177a481b6Andreas Huber const float right = left + bitmap->width(); 6316a05c9e912aeb8bfe1ef99516def91a177a481b6Andreas Huber const float bottom = top + bitmap->height(); 6326a05c9e912aeb8bfe1ef99516def91a177a481b6Andreas Huber 633e94bd14078d327ef2f800e69907efce641a13272Andreas Huber if (quickReject(left, top, right, bottom)) { 634e94bd14078d327ef2f800e69907efce641a13272Andreas Huber return; 635bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber } 636bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber 637bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber glActiveTexture(GL_TEXTURE0); 638bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber const Texture* texture = mCaches.textureCache.get(bitmap); 639bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (!texture) return; 640bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const AutoTexture autoCleanup(texture); 6410a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber 64288d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber drawTextureRect(left, top, right, bottom, texture, paint); 64388d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber} 64488d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber 6457b3396acc702451be9bafb19d7fe26d55d43a316Andreas Hubervoid OpenGLRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint) { 6467b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Rect r(0.0f, 0.0f, bitmap->width(), bitmap->height()); 6477b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber const mat4 transform(*matrix); 6487b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber transform.mapRect(r); 6497b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 650e94bd14078d327ef2f800e69907efce641a13272Andreas Huber if (quickReject(r.left, r.top, r.right, r.bottom)) { 651e94bd14078d327ef2f800e69907efce641a13272Andreas Huber return; 652e94bd14078d327ef2f800e69907efce641a13272Andreas Huber } 653e94bd14078d327ef2f800e69907efce641a13272Andreas Huber 654e94bd14078d327ef2f800e69907efce641a13272Andreas Huber glActiveTexture(GL_TEXTURE0); 655e94bd14078d327ef2f800e69907efce641a13272Andreas Huber const Texture* texture = mCaches.textureCache.get(bitmap); 6567b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber if (!texture) return; 6577b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber const AutoTexture autoCleanup(texture); 6587b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 6597b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber drawTextureRect(r.left, r.top, r.right, r.bottom, texture, paint); 6607b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber} 6617b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 6627b3396acc702451be9bafb19d7fe26d55d43a316Andreas Hubervoid OpenGLRenderer::drawBitmap(SkBitmap* bitmap, 663b9280d5c2313c41eb490f58198c4e59118e0e3e6Andreas Huber float srcLeft, float srcTop, float srcRight, float srcBottom, 664b9280d5c2313c41eb490f58198c4e59118e0e3e6Andreas Huber float dstLeft, float dstTop, float dstRight, float dstBottom, 665bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const SkPaint* paint) { 666bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (quickReject(dstLeft, dstTop, dstRight, dstBottom)) { 667bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return; 668bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 669bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 670cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber glActiveTexture(GL_TEXTURE0); 671cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber const Texture* texture = mCaches.textureCache.get(bitmap); 672cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber if (!texture) return; 673cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber const AutoTexture autoCleanup(texture); 674cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 675a44153c1a57202fb538659eb50706e60454d6273Andreas Huber const float width = texture->width; 676a44153c1a57202fb538659eb50706e60454d6273Andreas Huber const float height = texture->height; 677a44153c1a57202fb538659eb50706e60454d6273Andreas Huber 678a44153c1a57202fb538659eb50706e60454d6273Andreas Huber const float u1 = srcLeft / width; 679a44153c1a57202fb538659eb50706e60454d6273Andreas Huber const float v1 = srcTop / height; 68039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber const float u2 = srcRight / width; 68139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber const float v2 = srcBottom / height; 68239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 683cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mCaches.unbindMeshBuffer(); 684bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber resetDrawTextureTexCoords(u1, v1, u2, v2); 685bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 68669f5f4c021ee55055df39718244c036faf2d3382Andreas Huber int alpha; 68769f5f4c021ee55055df39718244c036faf2d3382Andreas Huber SkXfermode::Mode mode; 68869f5f4c021ee55055df39718244c036faf2d3382Andreas Huber getAlphaAndMode(paint, &alpha, &mode); 68969f5f4c021ee55055df39718244c036faf2d3382Andreas Huber 69069f5f4c021ee55055df39718244c036faf2d3382Andreas Huber drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom, texture->id, alpha / 255.0f, 691bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], 69269f5f4c021ee55055df39718244c036faf2d3382Andreas Huber GL_TRIANGLE_STRIP, gMeshCount); 69369f5f4c021ee55055df39718244c036faf2d3382Andreas Huber 69469f5f4c021ee55055df39718244c036faf2d3382Andreas Huber resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); 69569f5f4c021ee55055df39718244c036faf2d3382Andreas Huber} 696bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 697bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Hubervoid OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs, 698bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors, 699bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber float left, float top, float right, float bottom, const SkPaint* paint) { 700acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huber if (quickReject(left, top, right, bottom)) { 701bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return; 702bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 703bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 704bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber glActiveTexture(GL_TEXTURE0); 7051321fdd94d354431b930735e9f38f32ecd189a2dAndreas Huber const Texture* texture = mCaches.textureCache.get(bitmap); 706bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (!texture) return; 70766b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber const AutoTexture autoCleanup(texture); 708bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber 709bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber int alpha; 7107b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber SkXfermode::Mode mode; 7117b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber getAlphaAndMode(paint, &alpha, &mode); 7127b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 7137fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber const Patch* mesh = mCaches.patchCache.get(bitmap->width(), bitmap->height(), 714bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber right - left, bottom - top, xDivs, yDivs, colors, width, height, numColors); 715bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 716c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber if (mesh) { 7170726045216f576e97672ebeefc265d39c4ebaaa5Andreas Huber // Specify right and bottom as +1.0f from left/top to prevent scaling since the 7180726045216f576e97672ebeefc265d39c4ebaaa5Andreas Huber // patch mesh already defines the final size 7190726045216f576e97672ebeefc265d39c4ebaaa5Andreas Huber drawTextureMesh(left, top, left + 1.0f, top + 1.0f, texture->id, alpha / 255.0f, 7200726045216f576e97672ebeefc265d39c4ebaaa5Andreas Huber mode, texture->blend, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset, 721c23f12af0394aa2f6651968a3c8840f1af317aa1Andreas Huber GL_TRIANGLES, mesh->verticesCount, false, false, mesh->meshBuffer); 72266b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber } 72366b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber} 72466b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber 72566b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Hubervoid OpenGLRenderer::drawLines(float* points, int count, const SkPaint* paint) { 7267fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber if (mSnapshot->invisible) return; 727c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 7287fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber int alpha; 7297fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber SkXfermode::Mode mode; 7307fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber getAlphaAndMode(paint, &alpha, &mode); 7317fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber 7327fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber uint32_t color = paint->getColor(); 7337fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber const GLfloat a = alpha / 255.0f; 7347fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f; 7357fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; 7367fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber const GLfloat b = a * ((color ) & 0xFF) / 255.0f; 7377fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber 7387fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber const bool isAA = paint->isAntiAlias(); 7397fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber if (isAA) { 7407fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber GLuint textureUnit = 0; 7417fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber setupTextureAlpha8(mCaches.line.getTexture(), 0, 0, textureUnit, 0.0f, 0.0f, r, g, b, a, 7427fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber mode, false, true, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset, 7437fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber mCaches.line.getMeshBuffer()); 7448650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber } else { 7458650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber setupColorRect(0.0f, 0.0f, 1.0f, 1.0f, r, g, b, a, mode, false); 7467fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber } 7478650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber 7488650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber const float strokeWidth = paint->getStrokeWidth(); 7498650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber const GLsizei elementsCount = isAA ? mCaches.line.getElementsCount() : gMeshCount; 7508650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber const GLenum drawMode = isAA ? GL_TRIANGLES : GL_TRIANGLE_STRIP; 7517fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber 7528650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber for (int i = 0; i < count; i += 4) { 7538650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber float tx = 0.0f; 7548650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber float ty = 0.0f; 7558650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber 7568650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber if (isAA) { 7578650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber mCaches.line.update(points[i], points[i + 1], points[i + 2], points[i + 3], 7588650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber strokeWidth, tx, ty); 7598650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber } else { 76034ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber ty = strokeWidth <= 1.0f ? 0.0f : -strokeWidth * 0.5f; 76134ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber } 76234ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber 76334ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber const float dx = points[i + 2] - points[i]; 76434ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber const float dy = points[i + 3] - points[i + 1]; 76534ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber const float mag = sqrtf(dx * dx + dy * dy); 76666b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber const float angle = acos(dx / mag); 76766b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber 768d29345dfa29cdcc650f3705e43950ef2500f6728Andreas Huber mModelView.loadTranslate(points[i], points[i + 1], 0.0f); 769d29345dfa29cdcc650f3705e43950ef2500f6728Andreas Huber if (angle > MIN_ANGLE || angle < -MIN_ANGLE) { 770d29345dfa29cdcc650f3705e43950ef2500f6728Andreas Huber mModelView.rotate(angle * RAD_TO_DEG, 0.0f, 0.0f, 1.0f); 77166b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber } 77266b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber mModelView.translate(tx, ty, 0.0f); 7738650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber if (!isAA) { 774c9e894872c298b25fe9d74e68aa1e7287a541ac3Andreas Huber float length = mCaches.line.getLength(points[i], points[i + 1], 7758650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber points[i + 2], points[i + 3]); 776c9e894872c298b25fe9d74e68aa1e7287a541ac3Andreas Huber mModelView.scale(length, strokeWidth, 1.0f); 7778650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber } 7788650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform); 77983977eb230d829cfe520f55d7977037a904ce548Andreas Huber 78083977eb230d829cfe520f55d7977037a904ce548Andreas Huber if (mShader) { 78183977eb230d829cfe520f55d7977037a904ce548Andreas Huber mShader->updateTransforms(mCaches.currentProgram, mModelView, *mSnapshot); 78283977eb230d829cfe520f55d7977037a904ce548Andreas Huber } 7838650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber 7847fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber glDrawArrays(drawMode, 0, elementsCount); 7857fbdb0903dfbf70b314a74e64e28fb880cdb9247Andreas Huber } 7868650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber 7878650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber if (isAA) { 788c9e894872c298b25fe9d74e68aa1e7287a541ac3Andreas Huber glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords")); 7898650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber } 7908650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber} 7918650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber 7928650e1960905097f6f1d6aa462ccb1c93c656834Andreas Hubervoid OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { 793c9e894872c298b25fe9d74e68aa1e7287a541ac3Andreas Huber const Rect& clip = *mSnapshot->clipRect; 7948650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true); 7958650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber} 7968650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber 7978650e1960905097f6f1d6aa462ccb1c93c656834Andreas Hubervoid OpenGLRenderer::drawRect(float left, float top, float right, float bottom, const SkPaint* p) { 7988650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber if (quickReject(left, top, right, bottom)) { 799bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber return; 800bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber } 8018650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber 8028650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber SkXfermode::Mode mode; 8038650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber if (!mExtensions.hasFramebufferFetch()) { 8048650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode); 8058650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber if (!isMode) { 8068650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber // Assume SRC_OVER 8078650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber mode = SkXfermode::kSrcOver_Mode; 80834ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber } 8098650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber } else { 8108650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber mode = getXfermode(p->getXfermode()); 8118650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber } 8128650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber 8138650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber // Skia draws using the color's alpha channel if < 255 8148650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber // Otherwise, it uses the paint's alpha 8158650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber int color = p->getColor(); 8168650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber if (((color >> 24) & 0xff) == 255) { 8178650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber color |= p->getAlpha() << 24; 8188650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber } 8198650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber 8208650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber drawColorRect(left, top, right, bottom, color, mode); 8218650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber} 8228650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber 8238650e1960905097f6f1d6aa462ccb1c93c656834Andreas Hubervoid OpenGLRenderer::drawText(const char* text, int bytesCount, int count, 8248650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber float x, float y, SkPaint* paint) { 8252415ecb5bb4e1459024f6d6c8ae2d6e3dc4fbdc7Andreas Huber if (text == NULL || count == 0 || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) { 8262415ecb5bb4e1459024f6d6c8ae2d6e3dc4fbdc7Andreas Huber return; 8278650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber } 8282a4b49bd3863024884a694b454e2e452752e6ea0Andreas Huber if (mSnapshot->invisible) return; 8298650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber 83034ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber paint->setAntiAlias(true); 83134ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber 83234ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber float length = -1.0f; 8338650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber switch (paint->getTextAlign()) { 8348650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber case SkPaint::kCenter_Align: 8358650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber length = paint->measureText(text, bytesCount); 8368650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber x -= length / 2.0f; 8378650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber break; 8388650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber case SkPaint::kRight_Align: 83934ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber length = paint->measureText(text, bytesCount); 8408650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber x -= length; 8418650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber break; 8428650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber default: 8438650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber break; 8448650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber } 8458650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber 8468650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber int alpha; 8478650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber SkXfermode::Mode mode; 8488650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber getAlphaAndMode(paint, &alpha, &mode); 8498650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber 8508650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber uint32_t color = paint->getColor(); 8518650e1960905097f6f1d6aa462ccb1c93c656834Andreas Huber const GLfloat a = alpha / 255.0f; 8522a4b49bd3863024884a694b454e2e452752e6ea0Andreas Huber const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f; 8532a4b49bd3863024884a694b454e2e452752e6ea0Andreas Huber const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; 8540a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber const GLfloat b = a * ((color ) & 0xFF) / 255.0f; 8550a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber 8560a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer(paint); 8570726045216f576e97672ebeefc265d39c4ebaaa5Andreas Huber fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()), 8580726045216f576e97672ebeefc265d39c4ebaaa5Andreas Huber paint->getTextSize()); 8592a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8602a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber Rect clipRect(*mSnapshot->clipRect); 8612a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber glScissor(clipRect.left, mSnapshot->height - clipRect.bottom, 8622a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber clipRect.getWidth(), clipRect.getHeight()); 8632a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8642a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (mHasShadow) { 8652a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber glActiveTexture(gTextureUnits[0]); 8662a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber mCaches.dropShadowCache.setFontRenderer(fontRenderer); 8672a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber const ShadowTexture* shadow = mCaches.dropShadowCache.get(paint, text, bytesCount, 8682a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber count, mShadowRadius); 8692a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber const AutoTexture autoCleanup(shadow); 8702a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8712a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber setupShadow(shadow, x, y, mode, a); 8722a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8732a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber // Draw the mesh 8742a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); 8752a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords")); 8762a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } 8772a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8782a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber GLuint textureUnit = 0; 8792a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber glActiveTexture(gTextureUnits[textureUnit]); 8802a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 8812a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber // Assume that the modelView matrix does not force scales, rotates, etc. 8822a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber const bool linearFilter = mSnapshot->transform->changesBounds(); 8832a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber setupTextureAlpha8(fontRenderer.getTexture(linearFilter), 0, 0, textureUnit, 884e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber x, y, r, g, b, a, mode, false, true, NULL, NULL); 885e2b1028852120bcfded33b8f06f66b780437fe92Andreas Huber 8862a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber const Rect& clip = mSnapshot->getLocalClip(); 8872a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber clearLayerRegions(); 888bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 889bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mCaches.unbindMeshBuffer(); 890bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber fontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y); 891bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 892d29345dfa29cdcc650f3705e43950ef2500f6728Andreas Huber glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 893d29345dfa29cdcc650f3705e43950ef2500f6728Andreas Huber glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords")); 894d29345dfa29cdcc650f3705e43950ef2500f6728Andreas Huber 895bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber drawTextDecorations(text, bytesCount, length, x, y, paint); 896bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 8972a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber setScissorFromClip(); 8982a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber} 8992a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 9002a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Hubervoid OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) { 9012a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (mSnapshot->invisible) return; 9022a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 9032a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber GLuint textureUnit = 0; 9042a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber glActiveTexture(gTextureUnits[textureUnit]); 9052a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 9062a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber const PathTexture* texture = mCaches.pathCache.get(path, paint); 9072a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (!texture) return; 9082a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber const AutoTexture autoCleanup(texture); 9092a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 9102a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber const float x = texture->left - texture->offset; 9112a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber const float y = texture->top - texture->offset; 9125d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber 9135d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber if (quickReject(x, y, x + texture->width, y + texture->height)) { 9145d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber return; 9155d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber } 9165d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber 917b2e3954c94717e43b3dc9b880564f166cfbbc0a2Andreas Huber int alpha; 9185d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber SkXfermode::Mode mode; 9195d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber getAlphaAndMode(paint, &alpha, &mode); 9205d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber 9215d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber uint32_t color = paint->getColor(); 9225d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber const GLfloat a = alpha / 255.0f; 9235d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f; 9245d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; 9255d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber const GLfloat b = a * ((color ) & 0xFF) / 255.0f; 9265d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber 9275d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber setupTextureAlpha8(texture, textureUnit, x, y, r, g, b, a, mode, true, true); 9285d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber 9295d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber clearLayerRegions(); 9305d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber 9318ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber // Draw the mesh 932bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); 933bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords")); 934a657f8deaf21acbe5faba7be1df9c6681d44d471Andreas Huber} 935bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 936bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber/////////////////////////////////////////////////////////////////////////////// 937bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber// Shaders 9385d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber/////////////////////////////////////////////////////////////////////////////// 9395d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber 940bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Hubervoid OpenGLRenderer::resetShader() { 941b2e3954c94717e43b3dc9b880564f166cfbbc0a2Andreas Huber mShader = NULL; 9422e8ffaf95bd35358ecd14ddf00cddaf3abefe0a9Andreas Huber} 9432e8ffaf95bd35358ecd14ddf00cddaf3abefe0a9Andreas Huber 944bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Hubervoid OpenGLRenderer::setupShader(SkiaShader* shader) { 945bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mShader = shader; 946bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (mShader) { 947bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mShader->set(&mCaches.textureCache, &mCaches.gradientCache); 948bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 9490a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber} 9500a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber 9510a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber/////////////////////////////////////////////////////////////////////////////// 9527b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber// Color filters 9537b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber/////////////////////////////////////////////////////////////////////////////// 954bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 9557b3396acc702451be9bafb19d7fe26d55d43a316Andreas Hubervoid OpenGLRenderer::resetColorFilter() { 956bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mColorFilter = NULL; 957bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber} 958bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 959bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Hubervoid OpenGLRenderer::setupColorFilter(SkiaColorFilter* filter) { 960bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber mColorFilter = filter; 961bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber} 962bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber 963bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber/////////////////////////////////////////////////////////////////////////////// 964bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber// Drop shadow 965bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber/////////////////////////////////////////////////////////////////////////////// 966bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Huber 967bd22c52280179b29eefac91ef7e7bbbc33d25904Andreas Hubervoid OpenGLRenderer::resetShadow() { 968bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mHasShadow = false; 969bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber} 970bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 971fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Hubervoid OpenGLRenderer::setupShadow(float radius, float dx, float dy, int color) { 972fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber mHasShadow = true; 973c130b5bf563d049bd391ccd96985ac278ef8ff8dGloria Wang mShadowRadius = radius; 974c130b5bf563d049bd391ccd96985ac278ef8ff8dGloria Wang mShadowDx = dx; 975c130b5bf563d049bd391ccd96985ac278ef8ff8dGloria Wang mShadowDy = dy; 976c130b5bf563d049bd391ccd96985ac278ef8ff8dGloria Wang mShadowColor = color; 977c130b5bf563d049bd391ccd96985ac278ef8ff8dGloria Wang} 978c130b5bf563d049bd391ccd96985ac278ef8ff8dGloria Wang 979c130b5bf563d049bd391ccd96985ac278ef8ff8dGloria Wang/////////////////////////////////////////////////////////////////////////////// 980bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber// Drawing implementation 981bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber/////////////////////////////////////////////////////////////////////////////// 982bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 983ed54ad0f8619ae416b0968ade6248894cbfc4dbaAndreas Hubervoid OpenGLRenderer::setupShadow(const ShadowTexture* texture, float x, float y, 984bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber SkXfermode::Mode mode, float alpha) { 985e7e3b785a0e7819db4c895a4f60e9a4dd755880cAndreas Huber const float sx = x - texture->left + mShadowDx; 986e7e3b785a0e7819db4c895a4f60e9a4dd755880cAndreas Huber const float sy = y - texture->top + mShadowDy; 987e7e3b785a0e7819db4c895a4f60e9a4dd755880cAndreas Huber 988e7e3b785a0e7819db4c895a4f60e9a4dd755880cAndreas Huber const int shadowAlpha = ((mShadowColor >> 24) & 0xFF); 989e7e3b785a0e7819db4c895a4f60e9a4dd755880cAndreas Huber const GLfloat a = shadowAlpha < 255 ? shadowAlpha / 255.0f : alpha; 99088c030e0e0152791ff74f90249f55fce01371198Andreas Huber const GLfloat r = a * ((mShadowColor >> 16) & 0xFF) / 255.0f; 99188c030e0e0152791ff74f90249f55fce01371198Andreas Huber const GLfloat g = a * ((mShadowColor >> 8) & 0xFF) / 255.0f; 99288c030e0e0152791ff74f90249f55fce01371198Andreas Huber const GLfloat b = a * ((mShadowColor ) & 0xFF) / 255.0f; 99388c030e0e0152791ff74f90249f55fce01371198Andreas Huber 99488c030e0e0152791ff74f90249f55fce01371198Andreas Huber GLuint textureUnit = 0; 99588c030e0e0152791ff74f90249f55fce01371198Andreas Huber setupTextureAlpha8(texture, textureUnit, sx, sy, r, g, b, a, mode, true, false); 99688c030e0e0152791ff74f90249f55fce01371198Andreas Huber} 997c130b5bf563d049bd391ccd96985ac278ef8ff8dGloria Wang 998c130b5bf563d049bd391ccd96985ac278ef8ff8dGloria Wangvoid OpenGLRenderer::setupTextureAlpha8(const Texture* texture, GLuint& textureUnit, 999c130b5bf563d049bd391ccd96985ac278ef8ff8dGloria Wang float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, 1000c130b5bf563d049bd391ccd96985ac278ef8ff8dGloria Wang bool transforms, bool applyFilters) { 1001c130b5bf563d049bd391ccd96985ac278ef8ff8dGloria Wang setupTextureAlpha8(texture->id, texture->width, texture->height, textureUnit, 100288c030e0e0152791ff74f90249f55fce01371198Andreas Huber x, y, r, g, b, a, mode, transforms, applyFilters, 100388c030e0e0152791ff74f90249f55fce01371198Andreas Huber (GLvoid*) 0, (GLvoid*) gMeshTextureOffset); 1004bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber} 1005bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1006bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Hubervoid OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height, 1007fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber GLuint& textureUnit, float x, float y, float r, float g, float b, float a, 10081862a33b246249630b654182afb5914da3480d4cAndreas Huber SkXfermode::Mode mode, bool transforms, bool applyFilters) { 10091862a33b246249630b654182afb5914da3480d4cAndreas Huber setupTextureAlpha8(texture, width, height, textureUnit, x, y, r, g, b, a, mode, 10101862a33b246249630b654182afb5914da3480d4cAndreas Huber transforms, applyFilters, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset); 1011bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber} 1012bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1013bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Hubervoid OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height, 1014bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber GLuint& textureUnit, float x, float y, float r, float g, float b, float a, 1015bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber SkXfermode::Mode mode, bool transforms, bool applyFilters, 1016bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber GLvoid* vertices, GLvoid* texCoords, GLuint vbo) { 1017bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // Describe the required shaders 10185d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber ProgramDescription description; 1019bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber description.hasTexture = true; 1020bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber description.hasAlpha8Texture = true; 1021bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const bool setColor = description.setAlpha8Color(r, g, b, a); 1022a657f8deaf21acbe5faba7be1df9c6681d44d471Andreas Huber 1023a657f8deaf21acbe5faba7be1df9c6681d44d471Andreas Huber if (applyFilters) { 1024bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (mShader) { 1025bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mShader->describe(description, mExtensions); 1026fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber } 1027fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber if (mColorFilter) { 1028fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber mColorFilter->describe(description, mExtensions); 1029fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber } 1030fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber } 1031fd4a8e09a54469bbccea6248f84319a1eb78765eAndreas Huber 10322e8ffaf95bd35358ecd14ddf00cddaf3abefe0a9Andreas Huber // Setup the blending mode 10332e8ffaf95bd35358ecd14ddf00cddaf3abefe0a9Andreas Huber chooseBlending(true, mode, description); 10342e8ffaf95bd35358ecd14ddf00cddaf3abefe0a9Andreas Huber 10352e8ffaf95bd35358ecd14ddf00cddaf3abefe0a9Andreas Huber // Build and use the appropriate shader 10362e8ffaf95bd35358ecd14ddf00cddaf3abefe0a9Andreas Huber useProgram(mCaches.programCache.get(description)); 10372e8ffaf95bd35358ecd14ddf00cddaf3abefe0a9Andreas Huber 1038bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber bindTexture(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit); 1039bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber glUniform1i(mCaches.currentProgram->getUniform("sampler"), textureUnit); 1040bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 10415daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber int texCoordsSlot = mCaches.currentProgram->getAttrib("texCoords"); 10425daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber glEnableVertexAttribArray(texCoordsSlot); 10435daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber 1044f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber if (texCoords) { 1045f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber // Setup attributes 1046f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber if (!vertices) { 1047f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo); 1048f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber } else { 1049f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mCaches.unbindMeshBuffer(); 1050f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber } 1051f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE, 1052f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber gMeshStride, vertices); 1053f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords); 1054f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber } 1055f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 1056f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber // Setup uniforms 1057f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber if (transforms) { 1058f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mModelView.loadTranslate(x, y, 0.0f); 1059f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mModelView.scale(width, height, 1.0f); 1060f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber } else { 1061f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mModelView.loadIdentity(); 1062f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber } 10635daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform); 1064ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (setColor) { 1065ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mCaches.currentProgram->setColor(r, g, b, a); 1066ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1067ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1068ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber textureUnit++; 1069ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (applyFilters) { 1070ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber // Setup attributes and uniforms required by the shaders 1071ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (mShader) { 1072f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mShader->setupProgram(mCaches.currentProgram, mModelView, *mSnapshot, &textureUnit); 1073ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1074ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (mColorFilter) { 1075f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mColorFilter->setupProgram(mCaches.currentProgram); 1076ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 10775daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber } 10785daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber} 1079bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 10800a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber// Same values used by Skia 10810a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber#define kStdStrikeThru_Offset (-6.0f / 21.0f) 10820a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber#define kStdUnderline_Offset (1.0f / 9.0f) 1083bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber#define kStdUnderline_Thickness (1.0f / 18.0f) 10840a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber 1085bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Hubervoid OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float length, 10860a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber float x, float y, SkPaint* paint) { 10870a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber // Handle underline and strike-through 10880a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber uint32_t flags = paint->getFlags(); 10890a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) { 10900a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber float underlineWidth = length; 10910a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber // If length is > 0.0f, we already measured the text for the text alignment 10920a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber if (length <= 0.0f) { 10934844ac54e8b5997c3b03872dbafe8ebed4787517Andreas Huber underlineWidth = paint->measureText(text, bytesCount); 1094ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1095ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1096ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber float offsetX = 0; 1097ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber switch (paint->getTextAlign()) { 1098ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber case SkPaint::kCenter_Align: 1099ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber offsetX = underlineWidth * 0.5f; 11000a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber break; 11014844ac54e8b5997c3b03872dbafe8ebed4787517Andreas Huber case SkPaint::kRight_Align: 11020a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber offsetX = underlineWidth; 11030a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber break; 11040a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber default: 11050a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber break; 11060a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber } 11070a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber 11080a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber if (underlineWidth > 0.0f) { 11090a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber const float textSize = paint->getTextSize(); 1110ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber const float strokeWidth = textSize * kStdUnderline_Thickness; 1111ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 11120a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber const float left = x - offsetX; 11130a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber float top = 0.0f; 11140a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber 11150a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber const int pointsCount = 4 * (flags & SkPaint::kStrikeThruText_Flag ? 2 : 1); 11160a5ca668c6f7d45706e9aec4a1dfec0aacc6d233Andreas Huber float points[pointsCount]; 1117f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber int currentPoint = 0; 1118bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1119bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (flags & SkPaint::kUnderlineText_Flag) { 1120bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber top = y + textSize * kStdUnderline_Offset; 1121bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber points[currentPoint++] = left; 1122bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber points[currentPoint++] = top; 11230a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber points[currentPoint++] = left + underlineWidth; 11240a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber points[currentPoint++] = top; 11250a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber } 1126bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1127bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (flags & SkPaint::kStrikeThruText_Flag) { 1128bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber top = y + textSize * kStdStrikeThru_Offset; 1129b2e3954c94717e43b3dc9b880564f166cfbbc0a2Andreas Huber points[currentPoint++] = left; 1130bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber points[currentPoint++] = top; 1131bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber points[currentPoint++] = left + underlineWidth; 1132bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber points[currentPoint++] = top; 1133bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 113466b0a35c9a4136a84c3f73b1b25fcb5220138b95Andreas Huber 1135bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber SkPaint linesPaint(*paint); 1136bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber linesPaint.setStrokeWidth(strokeWidth); 1137b2e3954c94717e43b3dc9b880564f166cfbbc0a2Andreas Huber 1138b2e3954c94717e43b3dc9b880564f166cfbbc0a2Andreas Huber drawLines(&points[0], pointsCount, &linesPaint); 1139b2e3954c94717e43b3dc9b880564f166cfbbc0a2Andreas Huber } 1140b2e3954c94717e43b3dc9b880564f166cfbbc0a2Andreas Huber } 1141b2e3954c94717e43b3dc9b880564f166cfbbc0a2Andreas Huber} 1142b2e3954c94717e43b3dc9b880564f166cfbbc0a2Andreas Huber 1143b2e3954c94717e43b3dc9b880564f166cfbbc0a2Andreas Hubervoid OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, 1144b2e3954c94717e43b3dc9b880564f166cfbbc0a2Andreas Huber int color, SkXfermode::Mode mode, bool ignoreTransform) { 1145bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber clearLayerRegions(); 1146bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1147bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // If a shader is set, preserve only the alpha 1148bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (mShader) { 1149dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang color |= 0x00ffffff; 1150dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 1151dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 1152dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang // Render using pre-multiplied alpha 1153dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang const int alpha = (color >> 24) & 0xFF; 1154bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const GLfloat a = alpha / 255.0f; 1155bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f; 1156bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; 1157bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const GLfloat b = a * ((color ) & 0xFF) / 255.0f; 11580a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber 1159bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber setupColorRect(left, top, right, bottom, r, g, b, a, mode, ignoreTransform); 1160bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 11615daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber // Draw the mesh 11625daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); 11635daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber} 11645daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber 11655daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Hubervoid OpenGLRenderer::setupColorRect(float left, float top, float right, float bottom, 11665daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber float r, float g, float b, float a, SkXfermode::Mode mode, bool ignoreTransform) { 1167bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber GLuint textureUnit = 0; 1168bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1169bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // Describe the required shaders 1170bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber ProgramDescription description; 1171bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const bool setColor = description.setColor(r, g, b, a); 1172bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1173bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (mShader) { 1174bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mShader->describe(description, mExtensions); 1175bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 1176bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (mColorFilter) { 1177bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mColorFilter->describe(description, mExtensions); 1178bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 1179bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1180bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // Setup the blending mode 1181bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber chooseBlending(a < 1.0f || (mShader && mShader->blend()), mode, description); 1182bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1183bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // Build and use the appropriate shader 1184bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber useProgram(mCaches.programCache.get(description)); 1185bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1186bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // Setup attributes 11872415ecb5bb4e1459024f6d6c8ae2d6e3dc4fbdc7Andreas Huber mCaches.bindMeshBuffer(); 1188bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE, 1189bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber gMeshStride, 0); 1190bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1191bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // Setup uniforms 1192bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mModelView.loadTranslate(left, top, 0.0f); 1193bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mModelView.scale(right - left, bottom - top, 1.0f); 1194bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (!ignoreTransform) { 1195bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform); 1196bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } else { 1197bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mat4 identity; 1198bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mCaches.currentProgram->set(mOrthoMatrix, mModelView, identity); 11998d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 12008d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mCaches.currentProgram->setColor(r, g, b, a); 12018d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 12028d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // Setup attributes and uniforms required by the shaders 1203dac4ee72bac87388a1495e098f39d73168c8078fAndreas Huber if (mShader) { 1204dac4ee72bac87388a1495e098f39d73168c8078fAndreas Huber mShader->setupProgram(mCaches.currentProgram, mModelView, *mSnapshot, &textureUnit); 12052415ecb5bb4e1459024f6d6c8ae2d6e3dc4fbdc7Andreas Huber } 1206bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (mColorFilter) { 1207bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mColorFilter->setupProgram(mCaches.currentProgram); 1208bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 1209bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber} 1210bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1211bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Hubervoid OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, 1212bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const Texture* texture, const SkPaint* paint) { 1213bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber int alpha; 1214bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber SkXfermode::Mode mode; 1215bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber getAlphaAndMode(paint, &alpha, &mode); 1216bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 121770f521de2675ce6eedf4b22beed94ea1289b0f38Andreas Huber drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode, 1218acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huber texture->blend, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset, 1219acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huber GL_TRIANGLE_STRIP, gMeshCount); 1220acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huber} 1221acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huber 1222acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Hubervoid OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, 1223bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber GLuint texture, float alpha, SkXfermode::Mode mode, bool blend) { 1224bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber drawTextureMesh(left, top, right, bottom, texture, alpha, mode, blend, 12250dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount); 12260dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber} 12270dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 12280dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Hubervoid OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom, 12290dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber GLuint texture, float alpha, SkXfermode::Mode mode, bool blend, 12300dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount, 12310dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber bool swapSrcDst, bool ignoreTransform, GLuint vbo) { 12320dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber clearLayerRegions(); 12330dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 12340dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber ProgramDescription description; 1235bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber description.hasTexture = true; 1236cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber const bool setColor = description.setColor(alpha, alpha, alpha, alpha); 12370dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber if (mColorFilter) { 1238cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mColorFilter->describe(description, mExtensions); 1239cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 1240cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 12410a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber mModelView.loadTranslate(left, top, 0.0f); 12420a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber mModelView.scale(right - left, bottom - top, 1.0f); 12430a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber 12440a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber chooseBlending(blend || alpha < 1.0f, mode, description, swapSrcDst); 12450a5baa9b411fe086013d2a5e9126ed63fbad046cAndreas Huber 1246bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber useProgram(mCaches.programCache.get(description)); 12471321fdd94d354431b930735e9f38f32ecd189a2dAndreas Huber if (!ignoreTransform) { 1248bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform); 12495d2de4da54504836e4b772b3010ac28c19f667f0Andreas Huber } else { 1250bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mat4 m; 1251bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mCaches.currentProgram->set(mOrthoMatrix, mModelView, m); 1252bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 12531321fdd94d354431b930735e9f38f32ecd189a2dAndreas Huber 12541321fdd94d354431b930735e9f38f32ecd189a2dAndreas Huber // Texture 12551321fdd94d354431b930735e9f38f32ecd189a2dAndreas Huber bindTexture(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0); 12561321fdd94d354431b930735e9f38f32ecd189a2dAndreas Huber glUniform1i(mCaches.currentProgram->getUniform("sampler"), 0); 12571321fdd94d354431b930735e9f38f32ecd189a2dAndreas Huber 12581321fdd94d354431b930735e9f38f32ecd189a2dAndreas Huber // Always premultiplied 12591321fdd94d354431b930735e9f38f32ecd189a2dAndreas Huber if (setColor) { 12601321fdd94d354431b930735e9f38f32ecd189a2dAndreas Huber mCaches.currentProgram->setColor(alpha, alpha, alpha, alpha); 1261bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 1262bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1263bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // Mesh 1264bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber int texCoordsSlot = mCaches.currentProgram->getAttrib("texCoords"); 1265a657f8deaf21acbe5faba7be1df9c6681d44d471Andreas Huber glEnableVertexAttribArray(texCoordsSlot); 1266bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1267bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (!vertices) { 12681862a33b246249630b654182afb5914da3480d4cAndreas Huber mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo); 12691862a33b246249630b654182afb5914da3480d4cAndreas Huber } else { 12701321fdd94d354431b930735e9f38f32ecd189a2dAndreas Huber mCaches.unbindMeshBuffer(); 1271dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 1272dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE, 1273dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang gMeshStride, vertices); 1274dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords); 1275dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 1276dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang // Color filter 1277dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mColorFilter) { 1278bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mColorFilter->setupProgram(mCaches.currentProgram); 1279bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 1280bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 128188d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber glDrawArrays(drawMode, 0, elementsCount); 128288d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber glDisableVertexAttribArray(texCoordsSlot); 1283bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber} 128488d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber 128588d8a83de12592635248aa1a3bd6b9ea46108501Andreas Hubervoid OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, 128688d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber ProgramDescription& description, bool swapSrcDst) { 128788d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber blend = blend || mode != SkXfermode::kSrcOver_Mode; 128888d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber if (blend) { 1289717826ececd8d39596f62418677721d70776add1Andreas Huber if (mode < SkXfermode::kPlus_Mode) { 1290717826ececd8d39596f62418677721d70776add1Andreas Huber if (!mCaches.blend) { 1291717826ececd8d39596f62418677721d70776add1Andreas Huber glEnable(GL_BLEND); 1292717826ececd8d39596f62418677721d70776add1Andreas Huber } 1293717826ececd8d39596f62418677721d70776add1Andreas Huber 129488d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber GLenum sourceMode = swapSrcDst ? gBlendsSwap[mode].src : gBlends[mode].src; 1295717826ececd8d39596f62418677721d70776add1Andreas Huber GLenum destMode = swapSrcDst ? gBlendsSwap[mode].dst : gBlends[mode].dst; 1296717826ececd8d39596f62418677721d70776add1Andreas Huber 129788d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber if (sourceMode != mCaches.lastSrcMode || destMode != mCaches.lastDstMode) { 1298717826ececd8d39596f62418677721d70776add1Andreas Huber glBlendFunc(sourceMode, destMode); 129988d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber mCaches.lastSrcMode = sourceMode; 1300717826ececd8d39596f62418677721d70776add1Andreas Huber mCaches.lastDstMode = destMode; 1301bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 1302bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } else { 1303bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // These blend modes are not supported by OpenGL directly and have 130488d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber // to be implemented using shaders. Since the shader will perform 13052415ecb5bb4e1459024f6d6c8ae2d6e3dc4fbdc7Andreas Huber // the blending, turn blending off here 1306bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (mExtensions.hasFramebufferFetch()) { 1307bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber description.framebufferMode = mode; 1308bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber description.swapSrcDst = swapSrcDst; 1309bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 1310bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1311a945bfd91aa291fba4d9201ffcb38fce40eab7feAndreas Huber if (mCaches.blend) { 1312a945bfd91aa291fba4d9201ffcb38fce40eab7feAndreas Huber glDisable(GL_BLEND); 1313a945bfd91aa291fba4d9201ffcb38fce40eab7feAndreas Huber } 1314a945bfd91aa291fba4d9201ffcb38fce40eab7feAndreas Huber blend = false; 1315a945bfd91aa291fba4d9201ffcb38fce40eab7feAndreas Huber } 1316a945bfd91aa291fba4d9201ffcb38fce40eab7feAndreas Huber } else if (mCaches.blend) { 131781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber glDisable(GL_BLEND); 131881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber } 131981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber mCaches.blend = blend; 132081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber} 132181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 132281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huberbool OpenGLRenderer::useProgram(Program* program) { 1323e7e3b785a0e7819db4c895a4f60e9a4dd755880cAndreas Huber if (!program->isInUse()) { 1324bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (mCaches.currentProgram != NULL) mCaches.currentProgram->remove(); 1325bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber program->use(); 1326bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mCaches.currentProgram = program; 132788d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber return false; 132888d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber } 1329bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return true; 133088d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber} 133188d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber 133288d8a83de12592635248aa1a3bd6b9ea46108501Andreas Hubervoid OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) { 13332a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber TextureVertex* v = &mMeshVertices[0]; 1334bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber TextureVertex::setUV(v++, u1, v1); 133588d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber TextureVertex::setUV(v++, u2, v1); 1336bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber TextureVertex::setUV(v++, u1, v2); 133739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TextureVertex::setUV(v++, u2, v2); 1338e332a9181cf6a3155ed1a0fd2afc212ccb1f2753Andreas Huber} 1339bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1340bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Hubervoid OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode) { 1341bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (paint) { 134288d8a83de12592635248aa1a3bd6b9ea46108501Andreas Huber if (!mExtensions.hasFramebufferFetch()) { 13432415ecb5bb4e1459024f6d6c8ae2d6e3dc4fbdc7Andreas Huber const bool isMode = SkXfermode::IsMode(paint->getXfermode(), mode); 1344bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (!isMode) { 1345bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // Assume SRC_OVER 1346bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber *mode = SkXfermode::kSrcOver_Mode; 1347bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 1348bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } else { 1349139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber *mode = getXfermode(paint->getXfermode()); 1350139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber } 1351139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber 1352139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber // Skia draws using the color's alpha channel if < 255 1353139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber // Otherwise, it uses the paint's alpha 1354139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber int color = paint->getColor(); 1355bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber *alpha = (color >> 24) & 0xFF; 1356bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (*alpha == 255) { 1357bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber *alpha = paint->getAlpha(); 1358bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 1359bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } else { 13604769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber *mode = SkXfermode::kSrcOver_Mode; 13614769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber *alpha = 255; 13624769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber } 13634769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber} 13644769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber 13654769cc92740e3ab58e9263d42553c12bbf79e3beAndreas HuberSkXfermode::Mode OpenGLRenderer::getXfermode(SkXfermode* mode) { 1366f83dd80384f70da1f6d36d60e831439ff7739ad7Jamie Gennis if (mode == NULL) { 13674769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber return SkXfermode::kSrcOver_Mode; 13684769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber } 13694769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber return mode->fMode; 13704769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber} 13714769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber 13724769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Hubervoid OpenGLRenderer::bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint textureUnit) { 13734769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber glActiveTexture(gTextureUnits[textureUnit]); 13744769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber glBindTexture(GL_TEXTURE_2D, texture); 13754769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); 13764769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); 13774769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber} 13784769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber 13794769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber}; // namespace uirenderer 13804769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber}; // namespace android 13814769cc92740e3ab58e9263d42553c12bbf79e3beAndreas Huber