blob: 575bc20e90c22732d46f7b1cbd55507eb4fb2cad [file] [log] [blame]
Romain Guye4d01122010-06-16 18:44:05 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Romain Guy85bf02f2010-06-22 13:11:24 -070017#define LOG_TAG "OpenGLRenderer"
Romain Guye4d01122010-06-16 18:44:05 -070018
19#include <stdlib.h>
20#include <stdint.h>
21#include <sys/types.h>
22
23#include <utils/Errors.h>
Romain Guy9d5316e2010-06-24 19:30:36 -070024#include <utils/KeyedVector.h>
Romain Guye4d01122010-06-16 18:44:05 -070025#include <utils/Log.h>
26
27#include <GLES2/gl2.h>
28#include <GLES2/gl2ext.h>
29
Romain Guy85bf02f2010-06-22 13:11:24 -070030#include <SkXfermode.h>
31
32#include "OpenGLRenderer.h"
33#include "Matrix.h"
Romain Guye4d01122010-06-16 18:44:05 -070034
35namespace android {
Romain Guy9d5316e2010-06-24 19:30:36 -070036namespace uirenderer {
37
38///////////////////////////////////////////////////////////////////////////////
39// Defines
40///////////////////////////////////////////////////////////////////////////////
41
42#define SOLID_WHITE { 1.0f, 1.0f, 1.0f, 1.0f }
43
44#define P(x, y) { x, y }
45
46///////////////////////////////////////////////////////////////////////////////
47// Globals
48///////////////////////////////////////////////////////////////////////////////
49
50const Vertex gDrawColorVertices[] = {
51 { P(0.0f, 0.0f), SOLID_WHITE },
52 { P(1.0f, 0.0f), SOLID_WHITE },
53 { P(0.0f, 1.0f), SOLID_WHITE },
54 { P(1.0f, 1.0f), SOLID_WHITE }
55};
56
57///////////////////////////////////////////////////////////////////////////////
58// Shaders
59///////////////////////////////////////////////////////////////////////////////
60
61#define SHADER_SOURCE(name, source) const char* name = #source
62
63#include "shaders/drawColor.vert"
64#include "shaders/drawColor.frag"
65
66Program::Program(const char* vertex, const char* fragment) {
67 vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
68 fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
69
70 id = glCreateProgram();
71 glAttachShader(id, vertexShader);
72 glAttachShader(id, fragmentShader);
73 glLinkProgram(id);
74
75 GLint status;
76 glGetProgramiv(id, GL_LINK_STATUS, &status);
77 if (status != GL_TRUE) {
78 GLint infoLen = 0;
79 glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);
80 if (infoLen > 1) {
81 char* log = (char*) malloc(sizeof(char) * infoLen);
82 glGetProgramInfoLog(id, infoLen, 0, log);
83 LOGE("Error while linking shaders: %s", log);
84 delete log;
85 }
86 glDeleteProgram(id);
87 }
88}
89
90Program::~Program() {
91 glDeleteShader(vertexShader);
92 glDeleteShader(fragmentShader);
93 glDeleteProgram(id);
94}
95
96void Program::use() {
97 glUseProgram(id);
98}
99
100int Program::addAttrib(const char* name) {
101 int slot = glGetAttribLocation(id, name);
102 attributes.add(name, slot);
103 return slot;
104}
105
106int Program::getAttrib(const char* name) {
107 return attributes.valueFor(name);
108}
109
110int Program::addUniform(const char* name) {
111 int slot = glGetUniformLocation(id, name);
112 uniforms.add(name, slot);
113 return slot;
114}
115
116int Program::getUniform(const char* name) {
117 return uniforms.valueFor(name);
118}
119
120GLuint Program::buildShader(const char* source, GLenum type) {
121 GLuint shader = glCreateShader(type);
122 glShaderSource(shader, 1, &source, 0);
123 glCompileShader(shader);
124
125 GLint status;
126 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
127 if (status != GL_TRUE) {
128 // Some drivers return wrong values for GL_INFO_LOG_LENGTH
129 // use a fixed size instead
130 GLchar log[512];
131 glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]);
132 LOGE("Error while compiling shader: %s", log);
133 glDeleteShader(shader);
134 }
135
136 return shader;
137}
138
139DrawColorProgram::DrawColorProgram():
140 Program(gDrawColorVertexShader, gDrawColorFragmentShader) {
141 position = addAttrib("position");
142 color = addAttrib("color");
143 projection = addUniform("projection");
144 modelView = addUniform("modelView");
145}
146
147///////////////////////////////////////////////////////////////////////////////
148// Support
149///////////////////////////////////////////////////////////////////////////////
150
151const Rect& Snapshot::getMappedClip() {
152 if (flags & kFlagDirtyTransform) {
153 flags &= ~kFlagDirtyTransform;
154 mappedClip.set(clipRect);
155 transform.mapRect(mappedClip);
156 }
157 return mappedClip;
158}
Romain Guye4d01122010-06-16 18:44:05 -0700159
Romain Guyf6a11b82010-06-23 17:47:49 -0700160///////////////////////////////////////////////////////////////////////////////
161// Constructors/destructor
162///////////////////////////////////////////////////////////////////////////////
163
Romain Guy85bf02f2010-06-22 13:11:24 -0700164OpenGLRenderer::OpenGLRenderer() {
165 LOGD("Create OpenGLRenderer");
Romain Guy9d5316e2010-06-24 19:30:36 -0700166
167 mDrawColorShader = new DrawColorProgram;
Romain Guye4d01122010-06-16 18:44:05 -0700168}
169
Romain Guy85bf02f2010-06-22 13:11:24 -0700170OpenGLRenderer::~OpenGLRenderer() {
171 LOGD("Destroy OpenGLRenderer");
Romain Guye4d01122010-06-16 18:44:05 -0700172}
173
Romain Guyf6a11b82010-06-23 17:47:49 -0700174///////////////////////////////////////////////////////////////////////////////
175// Setup
176///////////////////////////////////////////////////////////////////////////////
177
Romain Guy85bf02f2010-06-22 13:11:24 -0700178void OpenGLRenderer::setViewport(int width, int height) {
Romain Guy08ae3172010-06-21 19:35:50 -0700179 glViewport(0, 0, width, height);
180
181 mat4 ortho;
182 ortho.loadOrtho(0, width, height, 0, 0, 1);
183 ortho.copyTo(mOrthoMatrix);
Romain Guybb9524b2010-06-22 18:56:38 -0700184
185 mWidth = width;
186 mHeight = height;
Romain Guye4d01122010-06-16 18:44:05 -0700187}
188
Romain Guy85bf02f2010-06-22 13:11:24 -0700189void OpenGLRenderer::prepare() {
Romain Guyf6a11b82010-06-23 17:47:49 -0700190 mSnapshot = &mFirstSnapshot;
191 mSaveCount = 0;
192
Romain Guy08ae3172010-06-21 19:35:50 -0700193 glDisable(GL_SCISSOR_TEST);
Romain Guybb9524b2010-06-22 18:56:38 -0700194
Romain Guy08ae3172010-06-21 19:35:50 -0700195 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
196 glClear(GL_COLOR_BUFFER_BIT);
Romain Guybb9524b2010-06-22 18:56:38 -0700197
Romain Guy08ae3172010-06-21 19:35:50 -0700198 glEnable(GL_SCISSOR_TEST);
Romain Guyf6a11b82010-06-23 17:47:49 -0700199
Romain Guybb9524b2010-06-22 18:56:38 -0700200 mSnapshot->clipRect.set(0.0f, 0.0f, mWidth, mHeight);
201}
202
Romain Guyf6a11b82010-06-23 17:47:49 -0700203///////////////////////////////////////////////////////////////////////////////
204// State management
205///////////////////////////////////////////////////////////////////////////////
206
Romain Guybb9524b2010-06-22 18:56:38 -0700207int OpenGLRenderer::getSaveCount() const {
208 return mSaveCount;
209}
210
211int OpenGLRenderer::save(int flags) {
212 return saveSnapshot();
213}
214
215void OpenGLRenderer::restore() {
216 if (mSaveCount == 0) return;
217
218 if (restoreSnapshot()) {
219 setScissorFromClip();
220 }
221}
222
223void OpenGLRenderer::restoreToCount(int saveCount) {
224 if (saveCount <= 0 || saveCount > mSaveCount) return;
225
226 bool restoreClip = false;
227
228 while (mSaveCount != saveCount - 1) {
229 restoreClip |= restoreSnapshot();
230 }
231
232 if (restoreClip) {
233 setScissorFromClip();
234 }
235}
236
237int OpenGLRenderer::saveSnapshot() {
238 mSnapshot = new Snapshot(mSnapshot);
Romain Guyf6a11b82010-06-23 17:47:49 -0700239 return ++mSaveCount;
Romain Guybb9524b2010-06-22 18:56:38 -0700240}
241
242bool OpenGLRenderer::restoreSnapshot() {
Romain Guybb9524b2010-06-22 18:56:38 -0700243 bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet;
244
245 mSaveCount--;
Romain Guyf6a11b82010-06-23 17:47:49 -0700246
247 // Do not merge these two lines!
248 sp<Snapshot> previous = mSnapshot->previous;
249 mSnapshot = previous;
Romain Guybb9524b2010-06-22 18:56:38 -0700250
251 return restoreClip;
252}
253
Romain Guyf6a11b82010-06-23 17:47:49 -0700254///////////////////////////////////////////////////////////////////////////////
255// Transforms
256///////////////////////////////////////////////////////////////////////////////
257
258void OpenGLRenderer::translate(float dx, float dy) {
259 mSnapshot->transform.translate(dx, dy, 0.0f);
Romain Guy9d5316e2010-06-24 19:30:36 -0700260 mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
Romain Guyf6a11b82010-06-23 17:47:49 -0700261}
262
263void OpenGLRenderer::rotate(float degrees) {
264 mSnapshot->transform.rotate(degrees, 0.0f, 0.0f, 1.0f);
Romain Guy9d5316e2010-06-24 19:30:36 -0700265 mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
Romain Guyf6a11b82010-06-23 17:47:49 -0700266}
267
268void OpenGLRenderer::scale(float sx, float sy) {
269 mSnapshot->transform.scale(sx, sy, 1.0f);
Romain Guy9d5316e2010-06-24 19:30:36 -0700270 mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
Romain Guyf6a11b82010-06-23 17:47:49 -0700271}
272
273void OpenGLRenderer::setMatrix(SkMatrix* matrix) {
274 mSnapshot->transform.load(*matrix);
Romain Guy9d5316e2010-06-24 19:30:36 -0700275 mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
Romain Guyf6a11b82010-06-23 17:47:49 -0700276}
277
278void OpenGLRenderer::getMatrix(SkMatrix* matrix) {
279 mSnapshot->transform.copyTo(*matrix);
280}
281
282void OpenGLRenderer::concatMatrix(SkMatrix* matrix) {
283 mat4 m(*matrix);
284 mSnapshot->transform.multiply(m);
Romain Guy9d5316e2010-06-24 19:30:36 -0700285 mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
Romain Guyf6a11b82010-06-23 17:47:49 -0700286}
287
288///////////////////////////////////////////////////////////////////////////////
289// Clipping
290///////////////////////////////////////////////////////////////////////////////
291
Romain Guybb9524b2010-06-22 18:56:38 -0700292void OpenGLRenderer::setScissorFromClip() {
Romain Guy9d5316e2010-06-24 19:30:36 -0700293 const Rect& clip = mSnapshot->getMappedClip();
294 glScissor(clip.left, clip.top, clip.getWidth(), clip.getHeight());
295}
296
297const Rect& OpenGLRenderer::getClipBounds() {
298 return mSnapshot->clipRect;
Romain Guybb9524b2010-06-22 18:56:38 -0700299}
300
301bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom) {
Romain Guybb9524b2010-06-22 18:56:38 -0700302 bool clipped = mSnapshot->clipRect.intersect(left, top, right, bottom);
303 if (clipped) {
304 mSnapshot->flags |= Snapshot::kFlagClipSet;
305 setScissorFromClip();
306 }
307 return clipped;
Romain Guye4d01122010-06-16 18:44:05 -0700308}
309
Romain Guyf6a11b82010-06-23 17:47:49 -0700310///////////////////////////////////////////////////////////////////////////////
311// Drawing
312///////////////////////////////////////////////////////////////////////////////
313
Romain Guy85bf02f2010-06-22 13:11:24 -0700314void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
Romain Guy9d5316e2010-06-24 19:30:36 -0700315 GLfloat a = ((color >> 24) & 0xFF) / 255.0f;
316 GLfloat r = ((color >> 16) & 0xFF) / 255.0f;
317 GLfloat g = ((color >> 8) & 0xFF) / 255.0f;
318 GLfloat b = ((color ) & 0xFF) / 255.0f;
319
320 // TODO Optimize this section
321 const Rect& clip = mSnapshot->getMappedClip();
322
323 mat4 modelView;
324 modelView.loadScale(clip.getWidth(), clip.getHeight(), 1.0f);
325 modelView.translate(clip.left, clip.top, 0.0f);
326
327 float matrix[16];
328 modelView.copyTo(matrix);
329 // TODO Optimize this section
330
331 mDrawColorShader->use();
332
333 glUniformMatrix4fv(mDrawColorShader->projection, 1, GL_FALSE, &mOrthoMatrix[0]);
334 glUniformMatrix4fv(mDrawColorShader->modelView, 1, GL_FALSE, &matrix[0]);
335
336 glEnableVertexAttribArray(mDrawColorShader->position);
337
338 GLsizei stride = sizeof(Vertex);
339 const GLvoid* p = &gDrawColorVertices[0].position[0];
340
341 glVertexAttribPointer(mDrawColorShader->position, 2, GL_FLOAT, GL_FALSE, stride, p);
342 glVertexAttrib4f(mDrawColorShader->color, r, g, b, a);
343
344 GLsizei vertexCount = sizeof(gDrawColorVertices) / sizeof(Vertex);
345 glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexCount);
346
347 glDisableVertexAttribArray(mDrawColorShader->position);
348 glDisableVertexAttribArray(mDrawColorShader->color);
Romain Guy85bf02f2010-06-22 13:11:24 -0700349}
350
Romain Guy9d5316e2010-06-24 19:30:36 -0700351}; // namespace uirenderer
Romain Guye4d01122010-06-16 18:44:05 -0700352}; // namespace android