OpenGLRenderer.cpp revision 7ae7ac48aa2b53453c9805075171ecd5bcafd7de
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
30c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy#include <SkPaint.h>
3185bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include <SkXfermode.h>
3285bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy
3385bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include "OpenGLRenderer.h"
3485bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include "Matrix.h"
35e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
36e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guynamespace android {
379d5316e3f56d138504565ff311145ac01621dff4Romain Guynamespace uirenderer {
389d5316e3f56d138504565ff311145ac01621dff4Romain Guy
399d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
409d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Defines
419d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
429d5316e3f56d138504565ff311145ac01621dff4Romain Guy
43c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy#define V(x, y) { { x, y } }
449d5316e3f56d138504565ff311145ac01621dff4Romain Guy
459d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
469d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Globals
479d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
489d5316e3f56d138504565ff311145ac01621dff4Romain Guy
49c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guyconst SimpleVertex gDrawColorVertices[] = {
507ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        V(0.0f, 0.0f),
517ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        V(1.0f, 0.0f),
527ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        V(0.0f, 1.0f),
537ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        V(1.0f, 1.0f)
549d5316e3f56d138504565ff311145ac01621dff4Romain Guy};
55c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guyconst GLsizei gDrawColorVertexStride = sizeof(SimpleVertex);
56c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guyconst GLsizei gDrawColorVertexCount = 4;
579d5316e3f56d138504565ff311145ac01621dff4Romain Guy
589d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
599d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Shaders
609d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
619d5316e3f56d138504565ff311145ac01621dff4Romain Guy
629d5316e3f56d138504565ff311145ac01621dff4Romain Guy#define SHADER_SOURCE(name, source) const char* name = #source
639d5316e3f56d138504565ff311145ac01621dff4Romain Guy
649d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include "shaders/drawColor.vert"
659d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include "shaders/drawColor.frag"
669d5316e3f56d138504565ff311145ac01621dff4Romain Guy
679d5316e3f56d138504565ff311145ac01621dff4Romain GuyProgram::Program(const char* vertex, const char* fragment) {
687ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
697ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
707ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
717ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    id = glCreateProgram();
727ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glAttachShader(id, vertexShader);
737ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glAttachShader(id, fragmentShader);
747ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glLinkProgram(id);
757ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
767ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    GLint status;
777ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glGetProgramiv(id, GL_LINK_STATUS, &status);
787ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (status != GL_TRUE) {
797ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        GLint infoLen = 0;
807ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);
817ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        if (infoLen > 1) {
827ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy            char* log = (char*) malloc(sizeof(char) * infoLen);
837ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy            glGetProgramInfoLog(id, infoLen, 0, log);
847ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy            LOGE("Error while linking shaders: %s", log);
857ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy            delete log;
867ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        }
877ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        glDeleteProgram(id);
887ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
899d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
909d5316e3f56d138504565ff311145ac01621dff4Romain Guy
919d5316e3f56d138504565ff311145ac01621dff4Romain GuyProgram::~Program() {
927ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glDeleteShader(vertexShader);
937ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glDeleteShader(fragmentShader);
947ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glDeleteProgram(id);
959d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
969d5316e3f56d138504565ff311145ac01621dff4Romain Guy
979d5316e3f56d138504565ff311145ac01621dff4Romain Guyvoid Program::use() {
987ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glUseProgram(id);
999d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1009d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1019d5316e3f56d138504565ff311145ac01621dff4Romain Guyint Program::addAttrib(const char* name) {
1027ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    int slot = glGetAttribLocation(id, name);
1037ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    attributes.add(name, slot);
1047ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return slot;
1059d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1069d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1079d5316e3f56d138504565ff311145ac01621dff4Romain Guyint Program::getAttrib(const char* name) {
1087ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return attributes.valueFor(name);
1099d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1109d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1119d5316e3f56d138504565ff311145ac01621dff4Romain Guyint Program::addUniform(const char* name) {
1127ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    int slot = glGetUniformLocation(id, name);
1137ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    uniforms.add(name, slot);
1147ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return slot;
1159d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1169d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1179d5316e3f56d138504565ff311145ac01621dff4Romain Guyint Program::getUniform(const char* name) {
1187ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return uniforms.valueFor(name);
1199d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1209d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1219d5316e3f56d138504565ff311145ac01621dff4Romain GuyGLuint Program::buildShader(const char* source, GLenum type) {
1227ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    GLuint shader = glCreateShader(type);
1237ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glShaderSource(shader, 1, &source, 0);
1247ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glCompileShader(shader);
1259d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1267ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    GLint status;
1277ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
1287ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (status != GL_TRUE) {
1297ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        // Some drivers return wrong values for GL_INFO_LOG_LENGTH
1307ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        // use a fixed size instead
1317ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        GLchar log[512];
1327ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]);
1337ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        LOGE("Error while compiling shader: %s", log);
1347ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        glDeleteShader(shader);
1357ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
1369d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1377ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return shader;
1389d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1399d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1409d5316e3f56d138504565ff311145ac01621dff4Romain GuyDrawColorProgram::DrawColorProgram():
1417ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        Program(gDrawColorVertexShader, gDrawColorFragmentShader) {
1427ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    position = addAttrib("position");
1437ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    color = addAttrib("color");
1447ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    projection = addUniform("projection");
1457ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    modelView = addUniform("modelView");
1467ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    transform = addUniform("transform");
147c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy}
148c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
149c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guyvoid DrawColorProgram::use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix,
150c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy        const GLfloat* transformMatrix) {
1517ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    Program::use();
1527ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glUniformMatrix4fv(projection, 1, GL_FALSE, projectionMatrix);
1537ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewMatrix);
1547ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glUniformMatrix4fv(transform, 1, GL_FALSE, transformMatrix);
1559d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1569d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1579d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
1589d5316e3f56d138504565ff311145ac01621dff4Romain Guy// Support
1599d5316e3f56d138504565ff311145ac01621dff4Romain Guy///////////////////////////////////////////////////////////////////////////////
1609d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1619d5316e3f56d138504565ff311145ac01621dff4Romain Guyconst Rect& Snapshot::getMappedClip() {
1627ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (flags & kFlagDirtyTransform) {
1637ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        flags &= ~kFlagDirtyTransform;
1647ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        mappedClip.set(clipRect);
1657ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        transform.mapRect(mappedClip);
1667ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
1677ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return mappedClip;
1689d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
169e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
170f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
171f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Constructors/destructor
172f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
173f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
17485bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain GuyOpenGLRenderer::OpenGLRenderer() {
17585bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy    LOGD("Create OpenGLRenderer");
1769d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1779d5316e3f56d138504565ff311145ac01621dff4Romain Guy    mDrawColorShader = new DrawColorProgram;
178e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
179e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
18085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain GuyOpenGLRenderer::~OpenGLRenderer() {
18185bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy    LOGD("Destroy OpenGLRenderer");
182e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
183e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
184f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
185f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Setup
186f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
187f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
18885bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guyvoid OpenGLRenderer::setViewport(int width, int height) {
18908ae317c21ec3086b5017672bba87420cc38a407Romain Guy    glViewport(0, 0, width, height);
19008ae317c21ec3086b5017672bba87420cc38a407Romain Guy
19108ae317c21ec3086b5017672bba87420cc38a407Romain Guy    mat4 ortho;
192c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    ortho.loadOrtho(0, width, height, 0, -1, 1);
19308ae317c21ec3086b5017672bba87420cc38a407Romain Guy    ortho.copyTo(mOrthoMatrix);
194bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
195bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    mWidth = width;
196bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    mHeight = height;
197e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
198e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
19985bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guyvoid OpenGLRenderer::prepare() {
2007ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot = &mFirstSnapshot;
2017ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSaveCount = 0;
202f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
20308ae317c21ec3086b5017672bba87420cc38a407Romain Guy    glDisable(GL_SCISSOR_TEST);
204bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
20508ae317c21ec3086b5017672bba87420cc38a407Romain Guy    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
20608ae317c21ec3086b5017672bba87420cc38a407Romain Guy    glClear(GL_COLOR_BUFFER_BIT);
207bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
20808ae317c21ec3086b5017672bba87420cc38a407Romain Guy    glEnable(GL_SCISSOR_TEST);
209c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    glScissor(0, 0, mWidth, mHeight);
210f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
211bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    mSnapshot->clipRect.set(0.0f, 0.0f, mWidth, mHeight);
212bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
213bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
214f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
215f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// State management
216f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
217f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
218bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyint OpenGLRenderer::getSaveCount() const {
2197ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return mSaveCount;
220bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
221bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
222bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyint OpenGLRenderer::save(int flags) {
2237ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return saveSnapshot();
224bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
225bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
226bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid OpenGLRenderer::restore() {
2277ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (mSaveCount == 0) return;
228bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
2297ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (restoreSnapshot()) {
2307ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        setScissorFromClip();
2317ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
232bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
233bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
234bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid OpenGLRenderer::restoreToCount(int saveCount) {
2357ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (saveCount <= 0 || saveCount > mSaveCount) return;
236bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
2377ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    bool restoreClip = false;
238bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
2397ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    while (mSaveCount != saveCount - 1) {
2407ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        restoreClip |= restoreSnapshot();
2417ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
242bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
2437ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (restoreClip) {
2447ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        setScissorFromClip();
2457ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
246bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
247bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
248bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyint OpenGLRenderer::saveSnapshot() {
2497ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot = new Snapshot(mSnapshot);
2507ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return ++mSaveCount;
251bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
252bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
253bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guybool OpenGLRenderer::restoreSnapshot() {
2547ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet;
255bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
2567ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSaveCount--;
257f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
2587ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    // Do not merge these two lines!
2597ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    sp<Snapshot> previous = mSnapshot->previous;
2607ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot = previous;
261bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
2627ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return restoreClip;
263bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
264bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
265f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
266f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Transforms
267f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
268f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
269f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::translate(float dx, float dy) {
2707ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->transform.translate(dx, dy, 0.0f);
2717ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
272f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
273f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
274f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::rotate(float degrees) {
2757ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->transform.rotate(degrees, 0.0f, 0.0f, 1.0f);
2767ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
277f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
278f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
279f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::scale(float sx, float sy) {
2807ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->transform.scale(sx, sy, 1.0f);
2817ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
282f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
283f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
284f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::setMatrix(SkMatrix* matrix) {
2857ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->transform.load(*matrix);
2867ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
287f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
288f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
289f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::getMatrix(SkMatrix* matrix) {
2907ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->transform.copyTo(*matrix);
291f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
292f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
293f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid OpenGLRenderer::concatMatrix(SkMatrix* matrix) {
2947ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mat4 m(*matrix);
2957ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->transform.multiply(m);
2967ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
297f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
298f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
299f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
300f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Clipping
301f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
302f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
303bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyvoid OpenGLRenderer::setScissorFromClip() {
3047ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    const Rect& clip = mSnapshot->getMappedClip();
3057ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight());
3069d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
3079d5316e3f56d138504565ff311145ac01621dff4Romain Guy
3089d5316e3f56d138504565ff311145ac01621dff4Romain Guyconst Rect& OpenGLRenderer::getClipBounds() {
3097ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return mSnapshot->clipRect;
310bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
311bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
312c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guybool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
313c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    /*
314c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     * The documentation of quickReject() indicates that the specified rect
315c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     * is transformed before being compared to the clip rect. However, the
316c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     * clip rect is not stored transformed in the snapshot and can thus be
317c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     * compared directly
318c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     *
319c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     * The following code can be used instead to performed a mapped comparison:
320c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     *
321c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     *     mSnapshot->transform.mapRect(r);
322c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     *     const Rect& clip = mSnapshot->getMappedClip();
323c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     *     return !clip.intersects(r);
324c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy     */
325c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
326c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    Rect r(left, top, right, bottom);
327c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    return !mSnapshot->clipRect.intersects(r);
328c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy}
329c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
330bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guybool OpenGLRenderer::clipRect(float left, float top, float right, float bottom) {
3317ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    bool clipped = mSnapshot->clipRect.intersect(left, top, right, bottom);
3327ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    if (clipped) {
3337ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        mSnapshot->flags |= Snapshot::kFlagClipSet;
3347ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        setScissorFromClip();
3357ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
3367ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    return clipped;
337e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
338e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
339f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
340f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// Drawing
341f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy///////////////////////////////////////////////////////////////////////////////
342f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
34385bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guyvoid OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
344c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    // TODO: Set the transfer mode
345c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    const Rect& clip = mSnapshot->clipRect;
346c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color);
347c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy}
3489d5316e3f56d138504565ff311145ac01621dff4Romain Guy
349c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guyvoid OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* paint) {
350c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    // TODO Support more than  just color
351c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    // TODO: Set the transfer mode
352c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    drawColorRect(left, top, right, bottom, paint->getColor());
353c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy}
3549d5316e3f56d138504565ff311145ac01621dff4Romain Guy
355c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guyvoid OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, int color) {
356c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    GLfloat a = ((color >> 24) & 0xFF) / 255.0f;
357c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    GLfloat r = ((color >> 16) & 0xFF) / 255.0f;
358c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    GLfloat g = ((color >>  8) & 0xFF) / 255.0f;
359c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    GLfloat b = ((color      ) & 0xFF) / 255.0f;
3609d5316e3f56d138504565ff311145ac01621dff4Romain Guy
361c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mModelView.loadTranslate(left, top, 0.0f);
362c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mModelView.scale(right - left, bottom - top, 1.0f);
3639d5316e3f56d138504565ff311145ac01621dff4Romain Guy
364c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mDrawColorShader->use(&mOrthoMatrix[0], &mModelView.data[0], &mSnapshot->transform.data[0]);
3659d5316e3f56d138504565ff311145ac01621dff4Romain Guy
366c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    const GLvoid* p = &gDrawColorVertices[0].position[0];
3679d5316e3f56d138504565ff311145ac01621dff4Romain Guy
368c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    glEnableVertexAttribArray(mDrawColorShader->position);
369c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    glVertexAttribPointer(mDrawColorShader->position, 2, GL_FLOAT, GL_FALSE,
370c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy            gDrawColorVertexStride, p);
371c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    glVertexAttrib4f(mDrawColorShader->color, r, g, b, a);
3729d5316e3f56d138504565ff311145ac01621dff4Romain Guy
373c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawColorVertexCount);
3749d5316e3f56d138504565ff311145ac01621dff4Romain Guy
375c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    glDisableVertexAttribArray(mDrawColorShader->position);
37685bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy}
37785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy
3789d5316e3f56d138504565ff311145ac01621dff4Romain Guy}; // namespace uirenderer
379e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}; // namespace android
380