OpenGLRenderer.cpp revision 7fac2e18339f765320d759e8d4c090f92431959e
1603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana/*
2603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * Copyright (C) 2010 The Android Open Source Project
3603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana *
4603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * Licensed under the Apache License, Version 2.0 (the "License");
5603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * you may not use this file except in compliance with the License.
6603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * You may obtain a copy of the License at
7603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana *
8603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana *      http://www.apache.org/licenses/LICENSE-2.0
9603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana *
10603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * Unless required by applicable law or agreed to in writing, software
11603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * distributed under the License is distributed on an "AS IS" BASIS,
12603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * See the License for the specific language governing permissions and
14603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * limitations under the License.
15603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana */
16603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
177a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey#define LOG_TAG "OpenGLRenderer"
18603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
197a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey#include <stdlib.h>
207a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey#include <stdint.h>
2156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana#include <sys/types.h>
2256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
2356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana#include <SkCanvas.h>
2456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
2556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana#include <cutils/properties.h>
2656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana#include <utils/Log.h>
2756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
2850cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn#include "OpenGLRenderer.h"
29603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
30603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintananamespace android {
3156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintananamespace uirenderer {
32603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
3356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana///////////////////////////////////////////////////////////////////////////////
3456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana// Defines
35603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana///////////////////////////////////////////////////////////////////////////////
3656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
3756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana// These properties are defined in mega-bytes
3856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana#define PROPERTY_TEXTURE_CACHE_SIZE "ro.hwui.texture_cache_size"
39603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana#define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size"
4056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
41603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana#define DEFAULT_TEXTURE_CACHE_SIZE 20
42603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana#define DEFAULT_LAYER_CACHE_SIZE 10
43603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana#define DEFAULT_PATCH_CACHE_SIZE 100
4456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
4556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana// Converts a number of mega-bytes into bytes
46603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana#define MB(s) s * 1024 * 1024
47603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
48603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana// Generates simple and textured vertices
49603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana#define SV(x, y) { { x, y } }
50603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana#define FV(x, y, u, v) { { x, y }, { u, v } }
5156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
52603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana///////////////////////////////////////////////////////////////////////////////
53603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana// Globals
54603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana///////////////////////////////////////////////////////////////////////////////
55603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
5656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanastatic const SimpleVertex gDrawColorVertices[] = {
5756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        SV(0.0f, 0.0f),
58603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        SV(1.0f, 0.0f),
59603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        SV(0.0f, 1.0f),
60603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        SV(1.0f, 1.0f)
61603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana};
62603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanastatic const GLsizei gDrawColorVertexStride = sizeof(SimpleVertex);
63603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanastatic const GLsizei gDrawColorVertexCount = 4;
64603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
653710f390968e683a0ad3adf0b517dfcade3564ceFred Quintana// This array is never used directly but used as a memcpy source in the
66603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana// OpenGLRenderer constructor
673710f390968e683a0ad3adf0b517dfcade3564ceFred Quintanastatic const TextureVertex gDrawTextureVertices[] = {
68603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        FV(0.0f, 0.0f, 0.0f, 0.0f),
69603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        FV(1.0f, 0.0f, 1.0f, 0.0f),
70603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        FV(0.0f, 1.0f, 0.0f, 1.0f),
71603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        FV(1.0f, 1.0f, 1.0f, 1.0f)
72603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana};
73603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanastatic const GLsizei gDrawTextureVertexStride = sizeof(TextureVertex);
74603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanastatic const GLsizei gDrawTextureVertexCount = 4;
75603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
76603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana// In this array, the index of each Blender equals the value of the first
77603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
7831c0959b1a04f4e17d7528a6e4a9296701e3ade7Amith Yamasanistatic const Blender gBlends[] = {
7931c0959b1a04f4e17d7528a6e4a9296701e3ade7Amith Yamasani        { SkXfermode::kClear_Mode,   GL_ZERO,                 GL_ZERO },
8031c0959b1a04f4e17d7528a6e4a9296701e3ade7Amith Yamasani        { SkXfermode::kSrc_Mode,     GL_ONE,                  GL_ZERO },
8131c0959b1a04f4e17d7528a6e4a9296701e3ade7Amith Yamasani        { SkXfermode::kDst_Mode,     GL_ZERO,                 GL_ONE },
8231c0959b1a04f4e17d7528a6e4a9296701e3ade7Amith Yamasani        { SkXfermode::kSrcOver_Mode, GL_ONE,                  GL_ONE_MINUS_SRC_ALPHA },
8331c0959b1a04f4e17d7528a6e4a9296701e3ade7Amith Yamasani        { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA,  GL_ONE },
8456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        { SkXfermode::kSrcIn_Mode,   GL_DST_ALPHA,            GL_ZERO },
8556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        { SkXfermode::kDstIn_Mode,   GL_ZERO,                 GL_SRC_ALPHA },
86603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        { SkXfermode::kSrcOut_Mode,  GL_ONE_MINUS_DST_ALPHA,  GL_ZERO },
87603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        { SkXfermode::kDstOut_Mode,  GL_ZERO,                 GL_ONE_MINUS_SRC_ALPHA },
88603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA,            GL_ONE_MINUS_SRC_ALPHA },
89603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA,  GL_SRC_ALPHA },
90603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        { SkXfermode::kXor_Mode,     GL_ONE_MINUS_DST_ALPHA,  GL_ONE_MINUS_SRC_ALPHA }
91603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana};
92603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
93603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanastatic const GLint gTileModes[] = {
94603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        GL_CLAMP_TO_EDGE,   // == SkShader::kClamp_TileMode
9556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        GL_REPEAT,          // == SkShader::kRepeat_Mode
96603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        GL_MIRRORED_REPEAT  // == SkShader::kMirror_TileMode
97603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana};
98603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
99603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana///////////////////////////////////////////////////////////////////////////////
100603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana// Constructors/destructor
101603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana///////////////////////////////////////////////////////////////////////////////
102f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana
103603073430bbcb1bd29db7afb9b14e2732ad589fbFred QuintanaOpenGLRenderer::OpenGLRenderer():
10456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        mBlend(false), mLastSrcMode(GL_ZERO), mLastDstMode(GL_ZERO),
105603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        mTextureCache(MB(DEFAULT_TEXTURE_CACHE_SIZE)),
106603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        mLayerCache(MB(DEFAULT_LAYER_CACHE_SIZE)),
107603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        mPatchCache(DEFAULT_PATCH_CACHE_SIZE) {
108603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    LOGD("Create OpenGLRenderer");
109603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
110603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    char property[PROPERTY_VALUE_MAX];
111603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, NULL) > 0) {
112603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        LOGD("  Setting texture cache size to %sMB", property);
113603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        mTextureCache.setMaxSize(MB(atoi(property)));
11431c0959b1a04f4e17d7528a6e4a9296701e3ade7Amith Yamasani    } else {
11531c0959b1a04f4e17d7528a6e4a9296701e3ade7Amith Yamasani        LOGD("  Using default texture cache size of %dMB", DEFAULT_TEXTURE_CACHE_SIZE);
116603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
11756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
11856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    if (property_get(PROPERTY_LAYER_CACHE_SIZE, property, NULL) > 0) {
119603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        LOGD("  Setting layer cache size to %sMB", property);
12056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        mLayerCache.setMaxSize(MB(atoi(property)));
121603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    } else {
12256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        LOGD("  Using default layer cache size of %dMB", DEFAULT_LAYER_CACHE_SIZE);
12356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
124603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
125603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    mDrawColorProgram = new DrawColorProgram;
126603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    mDrawTextureProgram = new DrawTextureProgram;
127603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    mCurrentProgram = mDrawTextureProgram;
128603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
129603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    mShader = kShaderNone;
130603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    mShaderTileX = SkShader::kClamp_TileMode;
131603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    mShaderTileY = SkShader::kClamp_TileMode;
132603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    mShaderMatrix = NULL;
133603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    mShaderBitmap = NULL;
134603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
135603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    mLastTexture = 0;
136603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
13731c0959b1a04f4e17d7528a6e4a9296701e3ade7Amith Yamasani    memcpy(mDrawTextureVertices, gDrawTextureVertices, sizeof(gDrawTextureVertices));
13831c0959b1a04f4e17d7528a6e4a9296701e3ade7Amith Yamasani}
13956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
14056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred QuintanaOpenGLRenderer::~OpenGLRenderer() {
14156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    LOGD("Destroy OpenGLRenderer");
14256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
14356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    mTextureCache.clear();
14456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    mLayerCache.clear();
14556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    mPatchCache.clear();
14656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana}
14756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
14856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana///////////////////////////////////////////////////////////////////////////////
14956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana// Setup
15056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana///////////////////////////////////////////////////////////////////////////////
15156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
15256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanavoid OpenGLRenderer::setViewport(int width, int height) {
15356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    glViewport(0, 0, width, height);
15456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
15556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
156603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
157603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    mWidth = width;
158603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    mHeight = height;
159603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    mFirstSnapshot.height = height;
160603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana}
16131c0959b1a04f4e17d7528a6e4a9296701e3ade7Amith Yamasani
16231c0959b1a04f4e17d7528a6e4a9296701e3ade7Amith Yamasanivoid OpenGLRenderer::prepare() {
16356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    mSnapshot = &mFirstSnapshot;
16456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    mSaveCount = 0;
16556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
16656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    glDisable(GL_SCISSOR_TEST);
16756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
16856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
16956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    glClear(GL_COLOR_BUFFER_BIT);
17056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
17156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    glEnable(GL_SCISSOR_TEST);
17256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    glScissor(0, 0, mWidth, mHeight);
17356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
17456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    mSnapshot->clipRect.set(0.0f, 0.0f, mWidth, mHeight);
17556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana}
17656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
17756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana///////////////////////////////////////////////////////////////////////////////
17856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana// State management
17956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana///////////////////////////////////////////////////////////////////////////////
18056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
18156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanaint OpenGLRenderer::getSaveCount() const {
18256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    return mSaveCount;
18356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana}
18456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
18556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanaint OpenGLRenderer::save(int flags) {
18656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    return saveSnapshot();
18756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana}
18856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
18956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanavoid OpenGLRenderer::restore() {
19056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    if (mSaveCount == 0) return;
19156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
19256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    if (restoreSnapshot()) {
19356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        setScissorFromClip();
19456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
19556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana}
19656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
19756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanavoid OpenGLRenderer::restoreToCount(int saveCount) {
19856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    if (saveCount <= 0 || saveCount > mSaveCount) return;
19956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
20056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    bool restoreClip = false;
20156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
2026ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    while (mSaveCount != saveCount - 1) {
2036ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        restoreClip |= restoreSnapshot();
2046ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    }
20556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
20656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    if (restoreClip) {
20756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        setScissorFromClip();
20856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
20956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana}
21056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
21156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanaint OpenGLRenderer::saveSnapshot() {
21256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    mSnapshot = new Snapshot(mSnapshot);
2136ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    return ++mSaveCount;
2146ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey}
21556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
21656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanabool OpenGLRenderer::restoreSnapshot() {
21756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet;
2186ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    bool restoreLayer = mSnapshot->flags & Snapshot::kFlagIsLayer;
2196ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    bool restoreOrtho = mSnapshot->flags & Snapshot::kFlagDirtyOrtho;
2206ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
22156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    sp<Snapshot> current = mSnapshot;
22256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    sp<Snapshot> previous = mSnapshot->previous;
2236ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
22456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    if (restoreOrtho) {
22556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        mOrthoMatrix.load(current->orthoMatrix);
22656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
22756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
2289d0791bf6a047dbf7a99034130a5c4b437510fcfJeff Sharkey    if (restoreLayer) {
2298a985d24ce9a38f40ed88fecbdcd0e75e3a68f44John Spurlock        composeLayer(current, previous);
2308a985d24ce9a38f40ed88fecbdcd0e75e3a68f44John Spurlock    }
2318a985d24ce9a38f40ed88fecbdcd0e75e3a68f44John Spurlock
23256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    mSnapshot = previous;
23356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    mSaveCount--;
23456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
23556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    return restoreClip;
23656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana}
23756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
23856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanavoid OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
23956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    if (!current->layer) {
24056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        LOGE("Attempting to compose a layer that does not exist");
24156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        return;
24256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
24356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
24456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    // Unbind current FBO and restore previous one
24556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    // Most of the time, previous->fbo will be 0 to bind the default buffer
24656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo);
24756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
24856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    // Restore the clip from the previous snapshot
24956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    const Rect& clip = previous->clipRect;
25056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight());
25156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
25256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    Layer* layer = current->layer;
25356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
25456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    // Compute the correct texture coordinates for the FBO texture
25550cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn    // The texture is currently as big as the window but drawn with
25656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    // a quad of the appropriate size
25756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    const Rect& rect = layer->layer;
25856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
25950cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn    drawTextureRect(rect.left, rect.top, rect.right, rect.bottom,
26056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            layer->texture, layer->alpha, layer->mode, layer->blend);
261603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2621a44d5dcabc18cd5ef111f732ccff91683a1a093Neal Nguyen    LayerSize size(rect.getWidth(), rect.getHeight());
263    // Failing to add the layer to the cache should happen only if the
264    // layer is too large
265    if (!mLayerCache.put(size, layer)) {
266        LAYER_LOGD("Deleting layer");
267
268        glDeleteFramebuffers(1, &layer->fbo);
269        glDeleteTextures(1, &layer->texture);
270
271        delete layer;
272    }
273}
274
275///////////////////////////////////////////////////////////////////////////////
276// Layers
277///////////////////////////////////////////////////////////////////////////////
278
279int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
280        const SkPaint* p, int flags) {
281    int count = saveSnapshot();
282
283    int alpha = 255;
284    SkXfermode::Mode mode;
285
286    if (p) {
287        alpha = p->getAlpha();
288        const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode);
289        if (!isMode) {
290            // Assume SRC_OVER
291            mode = SkXfermode::kSrcOver_Mode;
292        }
293    } else {
294        mode = SkXfermode::kSrcOver_Mode;
295    }
296
297    createLayer(mSnapshot, left, top, right, bottom, alpha, mode, flags);
298
299    return count;
300}
301
302int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
303        int alpha, int flags) {
304    int count = saveSnapshot();
305    createLayer(mSnapshot, left, top, right, bottom, alpha, SkXfermode::kSrcOver_Mode, flags);
306    return count;
307}
308
309bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
310        float right, float bottom, int alpha, SkXfermode::Mode mode,int flags) {
311
312    LAYER_LOGD("Requesting layer %fx%f", right - left, bottom - top);
313    LAYER_LOGD("Layer cache size = %d", mLayerCache.getSize());
314
315    GLuint previousFbo = snapshot->previous.get() ? snapshot->previous->fbo : 0;
316    LayerSize size(right - left, bottom - top);
317
318    Layer* layer = mLayerCache.get(size, previousFbo);
319    if (!layer) {
320        return false;
321    }
322
323    glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo);
324
325    // Clear the FBO
326    glDisable(GL_SCISSOR_TEST);
327    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
328    glClear(GL_COLOR_BUFFER_BIT);
329    glEnable(GL_SCISSOR_TEST);
330
331    // Save the layer in the snapshot
332    snapshot->flags |= Snapshot::kFlagIsLayer;
333    layer->mode = mode;
334    layer->alpha = alpha / 255.0f;
335    layer->layer.set(left, top, right, bottom);
336
337    snapshot->layer = layer;
338    snapshot->fbo = layer->fbo;
339
340    // Creates a new snapshot to draw into the FBO
341    saveSnapshot();
342    // TODO: This doesn't preserve other transformations (check Skia first)
343    mSnapshot->transform.loadTranslate(-left, -top, 0.0f);
344    mSnapshot->setClip(0.0f, 0.0f, right - left, bottom - top);
345    mSnapshot->height = bottom - top;
346    setScissorFromClip();
347
348    mSnapshot->flags = Snapshot::kFlagDirtyOrtho | Snapshot::kFlagClipSet;
349    mSnapshot->orthoMatrix.load(mOrthoMatrix);
350
351    // Change the ortho projection
352    mOrthoMatrix.loadOrtho(0.0f, right - left, bottom - top, 0.0f, 0.0f, 1.0f);
353
354    return true;
355}
356
357///////////////////////////////////////////////////////////////////////////////
358// Transforms
359///////////////////////////////////////////////////////////////////////////////
360
361void OpenGLRenderer::translate(float dx, float dy) {
362    mSnapshot->transform.translate(dx, dy, 0.0f);
363}
364
365void OpenGLRenderer::rotate(float degrees) {
366    mSnapshot->transform.rotate(degrees, 0.0f, 0.0f, 1.0f);
367}
368
369void OpenGLRenderer::scale(float sx, float sy) {
370    mSnapshot->transform.scale(sx, sy, 1.0f);
371}
372
373void OpenGLRenderer::setMatrix(SkMatrix* matrix) {
374    mSnapshot->transform.load(*matrix);
375}
376
377void OpenGLRenderer::getMatrix(SkMatrix* matrix) {
378    mSnapshot->transform.copyTo(*matrix);
379}
380
381void OpenGLRenderer::concatMatrix(SkMatrix* matrix) {
382    mat4 m(*matrix);
383    mSnapshot->transform.multiply(m);
384}
385
386///////////////////////////////////////////////////////////////////////////////
387// Clipping
388///////////////////////////////////////////////////////////////////////////////
389
390void OpenGLRenderer::setScissorFromClip() {
391    const Rect& clip = mSnapshot->clipRect;
392    glScissor(clip.left, mSnapshot->height - clip.bottom, clip.getWidth(), clip.getHeight());
393}
394
395const Rect& OpenGLRenderer::getClipBounds() {
396    return mSnapshot->getLocalClip();
397}
398
399bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
400    Rect r(left, top, right, bottom);
401    mSnapshot->transform.mapRect(r);
402    return !mSnapshot->clipRect.intersects(r);
403}
404
405bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
406    bool clipped = mSnapshot->clip(left, top, right, bottom, op);
407    if (clipped) {
408        setScissorFromClip();
409    }
410    return !mSnapshot->clipRect.isEmpty();
411}
412
413///////////////////////////////////////////////////////////////////////////////
414// Drawing
415///////////////////////////////////////////////////////////////////////////////
416
417void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) {
418    const float right = left + bitmap->width();
419    const float bottom = top + bitmap->height();
420
421    if (quickReject(left, top, right, bottom)) {
422        return;
423    }
424
425    const Texture* texture = mTextureCache.get(bitmap);
426    drawTextureRect(left, top, right, bottom, texture, paint);
427}
428
429void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint) {
430    Rect r(0.0f, 0.0f, bitmap->width(), bitmap->height());
431    const mat4 transform(*matrix);
432    transform.mapRect(r);
433
434    if (quickReject(r.left, r.top, r.right, r.bottom)) {
435        return;
436    }
437
438    const Texture* texture = mTextureCache.get(bitmap);
439    drawTextureRect(r.left, r.top, r.right, r.bottom, texture, paint);
440}
441
442void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
443         float srcLeft, float srcTop, float srcRight, float srcBottom,
444         float dstLeft, float dstTop, float dstRight, float dstBottom,
445         const SkPaint* paint) {
446    if (quickReject(dstLeft, dstTop, dstRight, dstBottom)) {
447        return;
448    }
449
450    const Texture* texture = mTextureCache.get(bitmap);
451
452    const float width = texture->width;
453    const float height = texture->height;
454
455    const float u1 = srcLeft / width;
456    const float v1 = srcTop / height;
457    const float u2 = srcRight / width;
458    const float v2 = srcBottom / height;
459
460    resetDrawTextureTexCoords(u1, v1, u2, v2);
461
462    drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture, paint);
463
464    resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
465}
466
467void OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
468        float left, float top, float right, float bottom, const SkPaint* paint) {
469    if (quickReject(left, top, right, bottom)) {
470        return;
471    }
472
473    const Texture* texture = mTextureCache.get(bitmap);
474
475    int alpha;
476    SkXfermode::Mode mode;
477    getAlphaAndMode(paint, &alpha, &mode);
478
479    Patch* mesh = mPatchCache.get(patch);
480    mesh->updateVertices(bitmap, left, top, right, bottom,
481            &patch->xDivs[0], &patch->yDivs[0], patch->numXDivs, patch->numYDivs);
482
483    // Specify right and bottom as +1.0f from left/top to prevent scaling since the
484    // patch mesh already defines the final size
485    drawTextureMesh(left, top, left + 1.0f, top + 1.0f, texture->id, alpha / 255.0f,
486            mode, texture->blend, &mesh->vertices[0].position[0],
487            &mesh->vertices[0].texture[0], mesh->indices, mesh->indicesCount);
488}
489
490void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
491    const Rect& clip = mSnapshot->clipRect;
492    drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true);
493}
494
495void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, const SkPaint* p) {
496    if (quickReject(left, top, right, bottom)) {
497        return;
498    }
499
500    SkXfermode::Mode mode;
501
502    const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode);
503    if (!isMode) {
504        // Assume SRC_OVER
505        mode = SkXfermode::kSrcOver_Mode;
506    }
507
508    // Skia draws using the color's alpha channel if < 255
509    // Otherwise, it uses the paint's alpha
510    int color = p->getColor();
511    if (((color >> 24) & 0xff) == 255) {
512        color |= p->getAlpha() << 24;
513    }
514
515    drawColorRect(left, top, right, bottom, color, mode);
516}
517
518///////////////////////////////////////////////////////////////////////////////
519// Shaders
520///////////////////////////////////////////////////////////////////////////////
521
522void OpenGLRenderer::resetShader() {
523    mShader = OpenGLRenderer::kShaderNone;
524    mShaderBlend = false;
525    mShaderTileX = SkShader::kClamp_TileMode;
526    mShaderTileY = SkShader::kClamp_TileMode;
527}
528
529void OpenGLRenderer::setupBitmapShader(SkBitmap* bitmap, SkShader::TileMode tileX,
530        SkShader::TileMode tileY, SkMatrix* matrix, bool hasAlpha) {
531    mShader = OpenGLRenderer::kShaderBitmap;
532    mShaderBlend = hasAlpha;
533    mShaderBitmap = bitmap;
534    mShaderTileX = tileX;
535    mShaderTileY = tileY;
536    mShaderMatrix = matrix;
537}
538
539void OpenGLRenderer::setupLinearGradientShader(float* bounds, uint32_t* colors,
540        float* positions, SkShader::TileMode tileMode, SkMatrix* matrix, bool hasAlpha) {
541    mShader = OpenGLRenderer::kShaderLinearGradient;
542    mShaderBlend = hasAlpha;
543    mShaderTileX = tileMode;
544    mShaderTileY = tileMode;
545    mShaderMatrix = matrix;
546    mShaderBounds = bounds;
547    mShaderColors = colors;
548    mShaderPositions = positions;
549}
550
551///////////////////////////////////////////////////////////////////////////////
552// Drawing implementation
553///////////////////////////////////////////////////////////////////////////////
554
555void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
556        int color, SkXfermode::Mode mode, bool ignoreTransform) {
557    // If a shader is set, preserve only the alpha
558    if (mShader != kShaderNone) {
559        color |= 0x00ffffff;
560    }
561
562    // Render using pre-multiplied alpha
563    const int alpha = (color >> 24) & 0xFF;
564    const GLfloat a = alpha / 255.0f;
565    const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f;
566    const GLfloat g = a * ((color >>  8) & 0xFF) / 255.0f;
567    const GLfloat b = a * ((color      ) & 0xFF) / 255.0f;
568
569    switch (mShader) {
570        case OpenGLRenderer::kShaderBitmap:
571            drawBitmapShader(left, top, right, bottom, a, mode);
572            return;
573        case OpenGLRenderer::kShaderLinearGradient:
574            // TODO: Generate gradient texture, set appropriate shader
575            break;
576        default:
577            break;
578    }
579
580    // Pre-multiplication happens when setting the shader color
581    chooseBlending(alpha < 255 || mShaderBlend, mode);
582
583    mModelView.loadTranslate(left, top, 0.0f);
584    mModelView.scale(right - left, bottom - top, 1.0f);
585
586    if (!useProgram(mDrawColorProgram)) {
587        const GLvoid* p = &gDrawColorVertices[0].position[0];
588        glVertexAttribPointer(mDrawColorProgram->position, 2, GL_FLOAT, GL_FALSE,
589                gDrawColorVertexStride, p);
590    }
591
592    if (!ignoreTransform) {
593        mDrawColorProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);
594    } else {
595        mat4 identity;
596        mDrawColorProgram->set(mOrthoMatrix, mModelView, identity);
597    }
598
599    glUniform4f(mDrawColorProgram->color, r, g, b, a);
600
601    glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawColorVertexCount);
602}
603
604void OpenGLRenderer::drawBitmapShader(float left, float top, float right, float bottom,
605        float alpha, SkXfermode::Mode mode) {
606    const Texture* texture = mTextureCache.get(mShaderBitmap);
607
608    const float width = texture->width;
609    const float height = texture->height;
610
611    // This could be done in the vertex shader but we have only 4 vertices
612    float u1 = 0.0f;
613    float v1 = 0.0f;
614    float u2 = right - left;
615    float v2 = bottom - top;
616
617    if (mShaderMatrix) {
618        SkMatrix inverse;
619        mShaderMatrix->invert(&inverse);
620        mat4 m(inverse);
621        Rect r(u1, v1, u2, v2);
622        m.mapRect(r);
623
624        u1 = r.left;
625        u2 = r.right;
626        v1 = r.top;
627        v2 = r.bottom;
628    }
629
630    u1 /= width;
631    u2 /= width;
632    v1 /= height;
633    v2 /= height;
634
635    resetDrawTextureTexCoords(u1, v1, u2, v2);
636
637    drawTextureMesh(left, top, right, bottom, texture->id, alpha, mode, texture->blend,
638            &mDrawTextureVertices[0].position[0], &mDrawTextureVertices[0].texture[0], NULL);
639
640    resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
641}
642
643void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
644        const Texture* texture, const SkPaint* paint) {
645    int alpha;
646    SkXfermode::Mode mode;
647    getAlphaAndMode(paint, &alpha, &mode);
648
649    drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode, texture->blend,
650            &mDrawTextureVertices[0].position[0], &mDrawTextureVertices[0].texture[0], NULL);
651}
652
653void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
654        GLuint texture, float alpha, SkXfermode::Mode mode, bool blend) {
655    drawTextureMesh(left, top, right, bottom, texture, alpha, mode, blend,
656            &mDrawTextureVertices[0].position[0], &mDrawTextureVertices[0].texture[0], NULL);
657}
658
659void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom,
660        GLuint texture, float alpha, SkXfermode::Mode mode, bool blend,
661        GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount) {
662    mModelView.loadTranslate(left, top, 0.0f);
663    mModelView.scale(right - left, bottom - top, 1.0f);
664
665    useProgram(mDrawTextureProgram);
666    mDrawTextureProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);
667
668    chooseBlending(blend || alpha < 1.0f, mode);
669
670    if (texture != mLastTexture) {
671        glBindTexture(GL_TEXTURE_2D, texture);
672        mLastTexture = texture;
673    }
674    // TODO: Don't set the texture parameters every time
675    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gTileModes[mShaderTileX]);
676    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gTileModes[mShaderTileY]);
677
678    // Always premultiplied
679    glUniform4f(mDrawTextureProgram->color, alpha, alpha, alpha, alpha);
680
681    glVertexAttribPointer(mDrawTextureProgram->position, 2, GL_FLOAT, GL_FALSE,
682            gDrawTextureVertexStride, vertices);
683    glVertexAttribPointer(mDrawTextureProgram->texCoords, 2, GL_FLOAT, GL_FALSE,
684            gDrawTextureVertexStride, texCoords);
685
686    if (!indices) {
687        glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawTextureVertexCount);
688    } else {
689        glDrawElements(GL_TRIANGLES, elementsCount, GL_UNSIGNED_SHORT, indices);
690    }
691}
692
693void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, bool isPremultiplied) {
694    // In theory we should not blend if the mode is Src, but it's rare enough
695    // that it's not worth it
696    blend = blend || mode != SkXfermode::kSrcOver_Mode;
697    if (blend) {
698        if (!mBlend) {
699            glEnable(GL_BLEND);
700        }
701
702        GLenum sourceMode = gBlends[mode].src;
703        GLenum destMode = gBlends[mode].dst;
704        if (!isPremultiplied && sourceMode == GL_ONE) {
705            sourceMode = GL_SRC_ALPHA;
706        }
707
708        if (sourceMode != mLastSrcMode || destMode != mLastDstMode) {
709            glBlendFunc(sourceMode, destMode);
710            mLastSrcMode = sourceMode;
711            mLastDstMode = destMode;
712        }
713    } else if (mBlend) {
714        glDisable(GL_BLEND);
715    }
716    mBlend = blend;
717}
718
719bool OpenGLRenderer::useProgram(const sp<Program>& program) {
720    if (!program->isInUse()) {
721        mCurrentProgram->remove();
722        program->use();
723        mCurrentProgram = program;
724        return false;
725    }
726    return true;
727}
728
729void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) {
730    TextureVertex* v = &mDrawTextureVertices[0];
731    TextureVertex::setUV(v++, u1, v1);
732    TextureVertex::setUV(v++, u2, v1);
733    TextureVertex::setUV(v++, u1, v2);
734    TextureVertex::setUV(v++, u2, v2);
735}
736
737void OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
738    if (paint) {
739        const bool isMode = SkXfermode::IsMode(paint->getXfermode(), mode);
740        if (!isMode) {
741            // Assume SRC_OVER
742            *mode = SkXfermode::kSrcOver_Mode;
743        }
744
745        // Skia draws using the color's alpha channel if < 255
746        // Otherwise, it uses the paint's alpha
747        int color = paint->getColor();
748        *alpha = (color >> 24) & 0xFF;
749        if (*alpha == 255) {
750            *alpha = paint->getAlpha();
751        }
752    } else {
753        *mode = SkXfermode::kSrcOver_Mode;
754        *alpha = 255;
755    }
756}
757
758}; // namespace uirenderer
759}; // namespace android
760