OpenGLRenderer.cpp revision 9d5316e3f56d138504565ff311145ac01621dff4
1/*
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
17#define LOG_TAG "OpenGLRenderer"
18
19#include <stdlib.h>
20#include <stdint.h>
21#include <sys/types.h>
22
23#include <utils/Errors.h>
24#include <utils/KeyedVector.h>
25#include <utils/Log.h>
26
27#include <GLES2/gl2.h>
28#include <GLES2/gl2ext.h>
29
30#include <SkXfermode.h>
31
32#include "OpenGLRenderer.h"
33#include "Matrix.h"
34
35namespace android {
36namespace 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}
159
160///////////////////////////////////////////////////////////////////////////////
161// Constructors/destructor
162///////////////////////////////////////////////////////////////////////////////
163
164OpenGLRenderer::OpenGLRenderer() {
165    LOGD("Create OpenGLRenderer");
166
167    mDrawColorShader = new DrawColorProgram;
168}
169
170OpenGLRenderer::~OpenGLRenderer() {
171    LOGD("Destroy OpenGLRenderer");
172}
173
174///////////////////////////////////////////////////////////////////////////////
175// Setup
176///////////////////////////////////////////////////////////////////////////////
177
178void OpenGLRenderer::setViewport(int width, int height) {
179    glViewport(0, 0, width, height);
180
181    mat4 ortho;
182    ortho.loadOrtho(0, width, height, 0, 0, 1);
183    ortho.copyTo(mOrthoMatrix);
184
185    mWidth = width;
186    mHeight = height;
187}
188
189void OpenGLRenderer::prepare() {
190	mSnapshot = &mFirstSnapshot;
191	mSaveCount = 0;
192
193    glDisable(GL_SCISSOR_TEST);
194
195    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
196    glClear(GL_COLOR_BUFFER_BIT);
197
198    glEnable(GL_SCISSOR_TEST);
199
200    mSnapshot->clipRect.set(0.0f, 0.0f, mWidth, mHeight);
201}
202
203///////////////////////////////////////////////////////////////////////////////
204// State management
205///////////////////////////////////////////////////////////////////////////////
206
207int 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);
239	return ++mSaveCount;
240}
241
242bool OpenGLRenderer::restoreSnapshot() {
243	bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet;
244
245	mSaveCount--;
246
247	// Do not merge these two lines!
248	sp<Snapshot> previous = mSnapshot->previous;
249	mSnapshot = previous;
250
251	return restoreClip;
252}
253
254///////////////////////////////////////////////////////////////////////////////
255// Transforms
256///////////////////////////////////////////////////////////////////////////////
257
258void OpenGLRenderer::translate(float dx, float dy) {
259	mSnapshot->transform.translate(dx, dy, 0.0f);
260	mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
261}
262
263void OpenGLRenderer::rotate(float degrees) {
264	mSnapshot->transform.rotate(degrees, 0.0f, 0.0f, 1.0f);
265	mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
266}
267
268void OpenGLRenderer::scale(float sx, float sy) {
269	mSnapshot->transform.scale(sx, sy, 1.0f);
270	mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
271}
272
273void OpenGLRenderer::setMatrix(SkMatrix* matrix) {
274	mSnapshot->transform.load(*matrix);
275	mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
276}
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);
285	mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
286}
287
288///////////////////////////////////////////////////////////////////////////////
289// Clipping
290///////////////////////////////////////////////////////////////////////////////
291
292void OpenGLRenderer::setScissorFromClip() {
293	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;
299}
300
301bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom) {
302	bool clipped = mSnapshot->clipRect.intersect(left, top, right, bottom);
303	if (clipped) {
304		mSnapshot->flags |= Snapshot::kFlagClipSet;
305		setScissorFromClip();
306	}
307	return clipped;
308}
309
310///////////////////////////////////////////////////////////////////////////////
311// Drawing
312///////////////////////////////////////////////////////////////////////////////
313
314void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
315	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);
349}
350
351}; // namespace uirenderer
352}; // namespace android
353