OpenGLRenderer.cpp revision bd6b79b40247aea7bfe13d0831c6c0472df6c636
1e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy/*
2e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Copyright (C) 2010 The Android Open Source Project
3e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
4e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * you may not use this file except in compliance with the License.
6e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * You may obtain a copy of the License at
7e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
8e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
10e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Unless required by applicable law or agreed to in writing, software
11e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * See the License for the specific language governing permissions and
14e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * limitations under the License.
15e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy */
16e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#define LOG_TAG "OpenGLRenderer"
18e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
19e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <stdlib.h>
20e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <stdint.h>
21e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <sys/types.h>
22e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
23e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <utils/Errors.h>
249d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include <utils/KeyedVector.h>
25e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <utils/Log.h>
26e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
27e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <GLES2/gl2.h>
28e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <GLES2/gl2ext.h>
29e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
30bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy#include <SkCanvas.h>
31c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy#include <SkPaint.h>
3285bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include <SkXfermode.h>
3385bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy
3485bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include "OpenGLRenderer.h"
3585bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include "Matrix.h"
36e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
37e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guynamespace android {
389d5316e3f56d138504565ff311145ac01621dff4Romain Guynamespace uirenderer {
399d5316e3f56d138504565ff311145ac01621dff4Romain Guy
409d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
419d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Defines
429d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
439d5316e3f56d138504565ff311145ac01621dff4Romain Guy
44bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy#define SV(x, y) { { x, y } }
45bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy#define FV(x, y, u, v) { { x, y }, { u, v } }
469d5316e3f56d138504565ff311145ac01621dff4Romain Guy
479d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
489d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Globals
499d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
509d5316e3f56d138504565ff311145ac01621dff4Romain Guy
51c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guyconst SimpleVertex gDrawColorVertices[] = {
52bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        SV(0.0f, 0.0f),
53bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        SV(1.0f, 0.0f),
54bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        SV(0.0f, 1.0f),
55bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        SV(1.0f, 1.0f)
569d5316e3f56d138504565ff311145ac01621dff4Romain Guy};
57c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guyconst GLsizei gDrawColorVertexStride = sizeof(SimpleVertex);
58c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guyconst GLsizei gDrawColorVertexCount = 4;
599d5316e3f56d138504565ff311145ac01621dff4Romain Guy
60bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyconst TextureVertex gDrawTextureVertices[] = {
61bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        FV(0.0f, 0.0f, 0.0f, 1.0f),
62bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        FV(1.0f, 0.0f, 1.0f, 1.0f),
63bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        FV(0.0f, 1.0f, 0.0f, 0.0f),
64bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        FV(1.0f, 1.0f, 1.0f, 0.0f)
65bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy};
66bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyconst GLsizei gDrawTextureVertexStride = sizeof(TextureVertex);
67bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyconst GLsizei gDrawTextureVertexCount = 4;
68bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
699d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
709d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Shaders
719d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
729d5316e3f56d138504565ff311145ac01621dff4Romain Guy
739d5316e3f56d138504565ff311145ac01621dff4Romain Guy#define SHADER_SOURCE(name, source) const char* name = #source
749d5316e3f56d138504565ff311145ac01621dff4Romain Guy
759d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include "shaders/drawColor.vert"
769d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include "shaders/drawColor.frag"
779d5316e3f56d138504565ff311145ac01621dff4Romain Guy
78bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy#include "shaders/drawTexture.vert"
79bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy#include "shaders/drawTexture.frag"
80bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
819d5316e3f56d138504565ff311145ac01621dff4Romain GuyProgram::Program(const char* vertex, const char* fragment) {
827ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
837ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
847ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
857ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    id = glCreateProgram();
867ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glAttachShader(id, vertexShader);
877ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glAttachShader(id, fragmentShader);
887ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glLinkProgram(id);
897ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
907ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    GLint status;
917ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glGetProgramiv(id, GL_LINK_STATUS, &status);
927ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (status != GL_TRUE) {
937ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        GLint infoLen = 0;
947ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);
957ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        if (infoLen > 1) {
967ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy            char* log = (char*) malloc(sizeof(char) * infoLen);
977ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy            glGetProgramInfoLog(id, infoLen, 0, log);
987ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy            LOGE("Error while linking shaders: %s", log);
997ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy            delete log;
1007ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        }
1017ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        glDeleteProgram(id);
1027ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
1039d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1049d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1059d5316e3f56d138504565ff311145ac01621dff4Romain GuyProgram::~Program() {
1067ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glDeleteShader(vertexShader);
1077ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glDeleteShader(fragmentShader);
1087ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glDeleteProgram(id);
1099d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1109d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1119d5316e3f56d138504565ff311145ac01621dff4Romain Guyvoid Program::use() {
1127ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glUseProgram(id);
1139d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1149d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1159d5316e3f56d138504565ff311145ac01621dff4Romain Guyint Program::addAttrib(const char* name) {
1167ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    int slot = glGetAttribLocation(id, name);
1177ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    attributes.add(name, slot);
1187ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return slot;
1199d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1209d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1219d5316e3f56d138504565ff311145ac01621dff4Romain Guyint Program::getAttrib(const char* name) {
1227ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return attributes.valueFor(name);
1239d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1249d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1259d5316e3f56d138504565ff311145ac01621dff4Romain Guyint Program::addUniform(const char* name) {
1267ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    int slot = glGetUniformLocation(id, name);
1277ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    uniforms.add(name, slot);
1287ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return slot;
1299d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1309d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1319d5316e3f56d138504565ff311145ac01621dff4Romain Guyint Program::getUniform(const char* name) {
1327ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return uniforms.valueFor(name);
1339d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1349d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1359d5316e3f56d138504565ff311145ac01621dff4Romain GuyGLuint Program::buildShader(const char* source, GLenum type) {
1367ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    GLuint shader = glCreateShader(type);
1377ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glShaderSource(shader, 1, &source, 0);
1387ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glCompileShader(shader);
1399d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1407ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    GLint status;
1417ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
1427ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (status != GL_TRUE) {
1437ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        // Some drivers return wrong values for GL_INFO_LOG_LENGTH
1447ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        // use a fixed size instead
1457ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        GLchar log[512];
1467ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]);
1477ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        LOGE("Error while compiling shader: %s", log);
1487ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        glDeleteShader(shader);
1497ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
1509d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1517ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return shader;
1529d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1539d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1549d5316e3f56d138504565ff311145ac01621dff4Romain GuyDrawColorProgram::DrawColorProgram():
1557ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        Program(gDrawColorVertexShader, gDrawColorFragmentShader) {
156bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    getAttribsAndUniforms();
157bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy}
158bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
159bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain GuyDrawColorProgram::DrawColorProgram(const char* vertex, const char* fragment):
160bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        Program(vertex, fragment) {
161bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    getAttribsAndUniforms();
162bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy}
163bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
164bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyvoid DrawColorProgram::getAttribsAndUniforms() {
1657ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    position = addAttrib("position");
1667ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    color = addAttrib("color");
1677ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    projection = addUniform("projection");
1687ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    modelView = addUniform("modelView");
1697ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    transform = addUniform("transform");
170c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy}
171c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
172c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guyvoid DrawColorProgram::use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix,
173c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy        const GLfloat* transformMatrix) {
1747ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    Program::use();
1757ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glUniformMatrix4fv(projection, 1, GL_FALSE, projectionMatrix);
1767ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewMatrix);
1777ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glUniformMatrix4fv(transform, 1, GL_FALSE, transformMatrix);
1789d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1799d5316e3f56d138504565ff311145ac01621dff4Romain Guy
180bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain GuyDrawTextureProgram::DrawTextureProgram():
181bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        DrawColorProgram(gDrawTextureVertexShader, gDrawTextureFragmentShader) {
182bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    texCoords = addAttrib("texCoords");
183bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    sampler = addUniform("sampler");
184bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy}
185bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
1869d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
1879d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Support
1889d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
1899d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1909d5316e3f56d138504565ff311145ac01621dff4Romain Guyconst Rect& Snapshot::getMappedClip() {
1917ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (flags & kFlagDirtyTransform) {
1927ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        flags &= ~kFlagDirtyTransform;
1937ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        mappedClip.set(clipRect);
1947ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        transform.mapRect(mappedClip);
1957ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
1967ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return mappedClip;
1979d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
198e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
199f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
200f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Constructors/destructor
201f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
202f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
20385bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain GuyOpenGLRenderer::OpenGLRenderer() {
20485bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy    LOGD("Create OpenGLRenderer");
2059d5316e3f56d138504565ff311145ac01621dff4Romain Guy
2069d5316e3f56d138504565ff311145ac01621dff4Romain Guy    mDrawColorShader = new DrawColorProgram;
207bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    mDrawTextureShader = new DrawTextureProgram;
208e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
209e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
21085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain GuyOpenGLRenderer::~OpenGLRenderer() {
21185bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy    LOGD("Destroy OpenGLRenderer");
212e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
213e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
214f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
215f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Setup
216f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
217f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
21885bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guyvoid OpenGLRenderer::setViewport(int width, int height) {
21908ae317c21ec3086b5017672bba87420cc38a407Romain Guy    glViewport(0, 0, width, height);
22008ae317c21ec3086b5017672bba87420cc38a407Romain Guy
22108ae317c21ec3086b5017672bba87420cc38a407Romain Guy    mat4 ortho;
222c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    ortho.loadOrtho(0, width, height, 0, -1, 1);
22308ae317c21ec3086b5017672bba87420cc38a407Romain Guy    ortho.copyTo(mOrthoMatrix);
224bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
225bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    mWidth = width;
226bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    mHeight = height;
227e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
228e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
22985bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guyvoid OpenGLRenderer::prepare() {
2307ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot = &mFirstSnapshot;
2317ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSaveCount = 0;
232f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
23308ae317c21ec3086b5017672bba87420cc38a407Romain Guy    glDisable(GL_SCISSOR_TEST);
234bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
23508ae317c21ec3086b5017672bba87420cc38a407Romain Guy    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
23608ae317c21ec3086b5017672bba87420cc38a407Romain Guy    glClear(GL_COLOR_BUFFER_BIT);
237bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
23808ae317c21ec3086b5017672bba87420cc38a407Romain Guy    glEnable(GL_SCISSOR_TEST);
239c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    glScissor(0, 0, mWidth, mHeight);
240f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
241bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    mSnapshot->clipRect.set(0.0f, 0.0f, mWidth, mHeight);
242bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
243bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
244f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
245f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// State management
246f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
247f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
248bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyint OpenGLRenderer::getSaveCount() const {
2497ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return mSaveCount;
250bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
251bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
252bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyint OpenGLRenderer::save(int flags) {
2537ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return saveSnapshot();
254bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
255bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
256bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid OpenGLRenderer::restore() {
2577ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (mSaveCount == 0) return;
258bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
2597ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (restoreSnapshot()) {
2607ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        setScissorFromClip();
2617ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
262bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
263bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
264bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid OpenGLRenderer::restoreToCount(int saveCount) {
2657ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (saveCount <= 0 || saveCount > mSaveCount) return;
266bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
2677ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    bool restoreClip = false;
268bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
2697ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    while (mSaveCount != saveCount - 1) {
2707ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        restoreClip |= restoreSnapshot();
2717ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
272bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
2737ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (restoreClip) {
2747ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        setScissorFromClip();
2757ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
276bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
277bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
278bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyint OpenGLRenderer::saveSnapshot() {
2797ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot = new Snapshot(mSnapshot);
2807ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return ++mSaveCount;
281bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
282bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
283bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guybool OpenGLRenderer::restoreSnapshot() {
2847ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet;
285bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    bool restoreLayer = mSnapshot->flags & Snapshot::kFlagIsLayer;
286bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
287bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    sp<Snapshot> current = mSnapshot;
2887ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    sp<Snapshot> previous = mSnapshot->previous;
289bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
290bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    if (restoreLayer) {
291bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        // Unbind current FBO and restore previous one
292bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        // Most of the time, previous->fbo will be 0 to bind the default buffer
293bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo);
294bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
295bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        const Rect& layer = current->layer;
296bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        clipRect(layer.left, layer.top, layer.right, layer.bottom);
297bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        mSnapshot->transform.loadIdentity();
298bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
299bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        drawTextureRect(0.0f, 0.0f, mWidth, mHeight, current->texture, current->alpha);
300bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
301bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        glDeleteFramebuffers(1, &current->fbo);
302bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        glDeleteTextures(1, &current->texture);
303bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    }
304bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
3057ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot = previous;
306bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    mSaveCount--;
307bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
3087ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return restoreClip;
309bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
310bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
311f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
312bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy// Layers
313bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy///////////////////////////////////////////////////////////////////////////////
314bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
315bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyint OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
316bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        const SkPaint* p, int flags) {
317bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    // TODO Implement
318bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    return saveSnapshot();
319bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy}
320bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
321bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyint OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
322bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        int alpha, int flags) {
323bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    int count = saveSnapshot();
324bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
325bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    mSnapshot->flags |= Snapshot::kFlagIsLayer;
326bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    mSnapshot->alpha = alpha / 255.0f;
327bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    mSnapshot->layer.set(left, top, right, bottom);
328bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
329bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    // Generate the FBO and attach the texture
330bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glGenFramebuffers(1, &mSnapshot->fbo);
331bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glBindFramebuffer(GL_FRAMEBUFFER, mSnapshot->fbo);
332bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
333bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    // Generate the texture in which the FBO will draw
334bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glGenTextures(1, &mSnapshot->texture);
335bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glBindTexture(GL_TEXTURE_2D, mSnapshot->texture);
336bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
337bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    // The FBO will not be scaled, so we can use lower quality filtering
338bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
339bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
340bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
341bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    // TODO ***** IMPORTANT *****
342bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    // Creating a texture-backed FBO works only if the texture is the same size
343bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    // as the original rendering buffer (in this case, mWidth and mHeight.)
344bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    // This is expensive and wasteful and must be fixed.
345bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
346bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    const GLsizei width = mWidth; //right - left;
347bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    const GLsizei height = mHeight; //bottom - right;
348bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
349bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    const GLint format = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) ? GL_RGBA : GL_RGB;
350bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, NULL);
351bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glBindTexture(GL_TEXTURE_2D, 0);
352bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
353bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    // Bind texture to FBO
354bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
355bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            mSnapshot->texture, 0);
356bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
357bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
358bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    if (status != GL_FRAMEBUFFER_COMPLETE) {
359bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        LOGD("Framebuffer incomplete %d", status);
360bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
361bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        glDeleteFramebuffers(1, &mSnapshot->fbo);
362bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        glDeleteTextures(1, &mSnapshot->texture);
363bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    }
364bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
365bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    return count;
366bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy}
367bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
368bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy///////////////////////////////////////////////////////////////////////////////
369f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Transforms
370f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
371f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
372f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::translate(float dx, float dy) {
3737ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->transform.translate(dx, dy, 0.0f);
3747ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
375f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
376f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
377f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::rotate(float degrees) {
3787ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->transform.rotate(degrees, 0.0f, 0.0f, 1.0f);
3797ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
380f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
381f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
382f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::scale(float sx, float sy) {
3837ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->transform.scale(sx, sy, 1.0f);
3847ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
385f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
386f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
387f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::setMatrix(SkMatrix* matrix) {
3887ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->transform.load(*matrix);
3897ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
390f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
391f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
392f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::getMatrix(SkMatrix* matrix) {
3937ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->transform.copyTo(*matrix);
394f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
395f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
396f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::concatMatrix(SkMatrix* matrix) {
3977ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mat4 m(*matrix);
3987ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->transform.multiply(m);
3997ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
400f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
401f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
402f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
403f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Clipping
404f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
405f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
406bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid OpenGLRenderer::setScissorFromClip() {
4077ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    const Rect& clip = mSnapshot->getMappedClip();
4087ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight());
4099d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
4109d5316e3f56d138504565ff311145ac01621dff4Romain Guy
4119d5316e3f56d138504565ff311145ac01621dff4Romain Guyconst Rect& OpenGLRenderer::getClipBounds() {
4127ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return mSnapshot->clipRect;
413bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
414bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
415c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guybool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
416c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    /*
417c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     * The documentation of quickReject() indicates that the specified rect
418c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     * is transformed before being compared to the clip rect. However, the
419c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     * clip rect is not stored transformed in the snapshot and can thus be
420c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     * compared directly
421c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     *
422c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     * The following code can be used instead to performed a mapped comparison:
423c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     *
424c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     *     mSnapshot->transform.mapRect(r);
425c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     *     const Rect& clip = mSnapshot->getMappedClip();
426c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     *     return !clip.intersects(r);
427c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     */
428c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
429c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    Rect r(left, top, right, bottom);
430c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    return !mSnapshot->clipRect.intersects(r);
431c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy}
432c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
433bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guybool OpenGLRenderer::clipRect(float left, float top, float right, float bottom) {
4347ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    bool clipped = mSnapshot->clipRect.intersect(left, top, right, bottom);
4357ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (clipped) {
4367ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        mSnapshot->flags |= Snapshot::kFlagClipSet;
4377ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        setScissorFromClip();
4387ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
4397ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return clipped;
440e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
441e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
442f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
443f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Drawing
444f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
445f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
44685bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guyvoid OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
447c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    // TODO: Set the transfer mode
448c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    const Rect& clip = mSnapshot->clipRect;
449c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color);
450c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy}
4519d5316e3f56d138504565ff311145ac01621dff4Romain Guy
452bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyvoid OpenGLRenderer::drawRect(float left, float top, float right, float bottom, const SkPaint* p) {
453c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    // TODO Support more than  just color
454c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    // TODO: Set the transfer mode
455bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    drawColorRect(left, top, right, bottom, p->getColor());
456c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy}
4579d5316e3f56d138504565ff311145ac01621dff4Romain Guy
458c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guyvoid OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, int color) {
459c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    GLfloat a = ((color >> 24) & 0xFF) / 255.0f;
460c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    GLfloat r = ((color >> 16) & 0xFF) / 255.0f;
461c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    GLfloat g = ((color >>  8) & 0xFF) / 255.0f;
462c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    GLfloat b = ((color      ) & 0xFF) / 255.0f;
4639d5316e3f56d138504565ff311145ac01621dff4Romain Guy
464c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mModelView.loadTranslate(left, top, 0.0f);
465c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mModelView.scale(right - left, bottom - top, 1.0f);
4669d5316e3f56d138504565ff311145ac01621dff4Romain Guy
467c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mDrawColorShader->use(&mOrthoMatrix[0], &mModelView.data[0], &mSnapshot->transform.data[0]);
4689d5316e3f56d138504565ff311145ac01621dff4Romain Guy
469c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    const GLvoid* p = &gDrawColorVertices[0].position[0];
4709d5316e3f56d138504565ff311145ac01621dff4Romain Guy
471c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    glEnableVertexAttribArray(mDrawColorShader->position);
472c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    glVertexAttribPointer(mDrawColorShader->position, 2, GL_FLOAT, GL_FALSE,
473c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy            gDrawColorVertexStride, p);
474c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    glVertexAttrib4f(mDrawColorShader->color, r, g, b, a);
4759d5316e3f56d138504565ff311145ac01621dff4Romain Guy
476c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawColorVertexCount);
4779d5316e3f56d138504565ff311145ac01621dff4Romain Guy
478c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    glDisableVertexAttribArray(mDrawColorShader->position);
47985bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy}
48085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy
481bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyvoid OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
482bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        GLuint texture, float alpha) {
483bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    mModelView.loadTranslate(left, top, 0.0f);
484bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    mModelView.scale(right - left, bottom - top, 1.0f);
485bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
486bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    mDrawTextureShader->use(&mOrthoMatrix[0], &mModelView.data[0], &mSnapshot->transform.data[0]);
487bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
488bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    // TODO Correctly set the blend function
489bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glEnable(GL_BLEND);
490bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
491bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
492bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glBindTexture(GL_TEXTURE_2D, texture);
493bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
494bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glActiveTexture(GL_TEXTURE0);
495bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glUniform1i(mDrawTextureShader->sampler, 0);
496bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
497bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    const GLvoid* p = &gDrawTextureVertices[0].position[0];
498bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    const GLvoid* t = &gDrawTextureVertices[0].texture[0];
499bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
500bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glEnableVertexAttribArray(mDrawTextureShader->position);
501bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glVertexAttribPointer(mDrawTextureShader->position, 2, GL_FLOAT, GL_FALSE,
502bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            gDrawTextureVertexStride, p);
503bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
504bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glEnableVertexAttribArray(mDrawTextureShader->texCoords);
505bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glVertexAttribPointer(mDrawTextureShader->texCoords, 2, GL_FLOAT, GL_FALSE,
506bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            gDrawTextureVertexStride, t);
507bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
508bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glVertexAttrib4f(mDrawTextureShader->color, 1.0f, 1.0f, 1.0f, alpha);
509bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
510bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawTextureVertexCount);
511bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
512bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glDisableVertexAttribArray(mDrawTextureShader->position);
513bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glDisableVertexAttribArray(mDrawTextureShader->texCoords);
514bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
515bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glBindTexture(GL_TEXTURE_2D, 0);
516bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    glDisable(GL_BLEND);
517bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy}
518bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
5199d5316e3f56d138504565ff311145ac01621dff4Romain Guy}; // namespace uirenderer
520e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}; // namespace android
521