OpenGLRenderer.cpp revision c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6c
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 <SkPaint.h> 31#include <SkXfermode.h> 32 33#include "OpenGLRenderer.h" 34#include "Matrix.h" 35 36namespace android { 37namespace uirenderer { 38 39/////////////////////////////////////////////////////////////////////////////// 40// Defines 41/////////////////////////////////////////////////////////////////////////////// 42 43#define V(x, y) { { x, y } } 44 45/////////////////////////////////////////////////////////////////////////////// 46// Globals 47/////////////////////////////////////////////////////////////////////////////// 48 49const SimpleVertex gDrawColorVertices[] = { 50 V(0.0f, 0.0f), 51 V(1.0f, 0.0f), 52 V(0.0f, 1.0f), 53 V(1.0f, 1.0f) 54}; 55const GLsizei gDrawColorVertexStride = sizeof(SimpleVertex); 56const GLsizei gDrawColorVertexCount = 4; 57 58/////////////////////////////////////////////////////////////////////////////// 59// Shaders 60/////////////////////////////////////////////////////////////////////////////// 61 62#define SHADER_SOURCE(name, source) const char* name = #source 63 64#include "shaders/drawColor.vert" 65#include "shaders/drawColor.frag" 66 67Program::Program(const char* vertex, const char* fragment) { 68 vertexShader = buildShader(vertex, GL_VERTEX_SHADER); 69 fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER); 70 71 id = glCreateProgram(); 72 glAttachShader(id, vertexShader); 73 glAttachShader(id, fragmentShader); 74 glLinkProgram(id); 75 76 GLint status; 77 glGetProgramiv(id, GL_LINK_STATUS, &status); 78 if (status != GL_TRUE) { 79 GLint infoLen = 0; 80 glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen); 81 if (infoLen > 1) { 82 char* log = (char*) malloc(sizeof(char) * infoLen); 83 glGetProgramInfoLog(id, infoLen, 0, log); 84 LOGE("Error while linking shaders: %s", log); 85 delete log; 86 } 87 glDeleteProgram(id); 88 } 89} 90 91Program::~Program() { 92 glDeleteShader(vertexShader); 93 glDeleteShader(fragmentShader); 94 glDeleteProgram(id); 95} 96 97void Program::use() { 98 glUseProgram(id); 99} 100 101int Program::addAttrib(const char* name) { 102 int slot = glGetAttribLocation(id, name); 103 attributes.add(name, slot); 104 return slot; 105} 106 107int Program::getAttrib(const char* name) { 108 return attributes.valueFor(name); 109} 110 111int Program::addUniform(const char* name) { 112 int slot = glGetUniformLocation(id, name); 113 uniforms.add(name, slot); 114 return slot; 115} 116 117int Program::getUniform(const char* name) { 118 return uniforms.valueFor(name); 119} 120 121GLuint Program::buildShader(const char* source, GLenum type) { 122 GLuint shader = glCreateShader(type); 123 glShaderSource(shader, 1, &source, 0); 124 glCompileShader(shader); 125 126 GLint status; 127 glGetShaderiv(shader, GL_COMPILE_STATUS, &status); 128 if (status != GL_TRUE) { 129 // Some drivers return wrong values for GL_INFO_LOG_LENGTH 130 // use a fixed size instead 131 GLchar log[512]; 132 glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]); 133 LOGE("Error while compiling shader: %s", log); 134 glDeleteShader(shader); 135 } 136 137 return shader; 138} 139 140DrawColorProgram::DrawColorProgram(): 141 Program(gDrawColorVertexShader, gDrawColorFragmentShader) { 142 position = addAttrib("position"); 143 color = addAttrib("color"); 144 projection = addUniform("projection"); 145 modelView = addUniform("modelView"); 146 transform = addUniform("transform"); 147} 148 149void DrawColorProgram::use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix, 150 const GLfloat* transformMatrix) { 151 Program::use(); 152 glUniformMatrix4fv(projection, 1, GL_FALSE, projectionMatrix); 153 glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewMatrix); 154 glUniformMatrix4fv(transform, 1, GL_FALSE, transformMatrix); 155} 156 157/////////////////////////////////////////////////////////////////////////////// 158// Support 159/////////////////////////////////////////////////////////////////////////////// 160 161const Rect& Snapshot::getMappedClip() { 162 if (flags & kFlagDirtyTransform) { 163 flags &= ~kFlagDirtyTransform; 164 mappedClip.set(clipRect); 165 transform.mapRect(mappedClip); 166 } 167 return mappedClip; 168} 169 170/////////////////////////////////////////////////////////////////////////////// 171// Constructors/destructor 172/////////////////////////////////////////////////////////////////////////////// 173 174OpenGLRenderer::OpenGLRenderer() { 175 LOGD("Create OpenGLRenderer"); 176 177 mDrawColorShader = new DrawColorProgram; 178} 179 180OpenGLRenderer::~OpenGLRenderer() { 181 LOGD("Destroy OpenGLRenderer"); 182} 183 184/////////////////////////////////////////////////////////////////////////////// 185// Setup 186/////////////////////////////////////////////////////////////////////////////// 187 188void OpenGLRenderer::setViewport(int width, int height) { 189 glViewport(0, 0, width, height); 190 191 mat4 ortho; 192 ortho.loadOrtho(0, width, height, 0, -1, 1); 193 ortho.copyTo(mOrthoMatrix); 194 195 mWidth = width; 196 mHeight = height; 197} 198 199void OpenGLRenderer::prepare() { 200 mSnapshot = &mFirstSnapshot; 201 mSaveCount = 0; 202 203 glDisable(GL_SCISSOR_TEST); 204 205 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 206 glClear(GL_COLOR_BUFFER_BIT); 207 208 glEnable(GL_SCISSOR_TEST); 209 glScissor(0, 0, mWidth, mHeight); 210 211 mSnapshot->clipRect.set(0.0f, 0.0f, mWidth, mHeight); 212} 213 214/////////////////////////////////////////////////////////////////////////////// 215// State management 216/////////////////////////////////////////////////////////////////////////////// 217 218int OpenGLRenderer::getSaveCount() const { 219 return mSaveCount; 220} 221 222int OpenGLRenderer::save(int flags) { 223 return saveSnapshot(); 224} 225 226void OpenGLRenderer::restore() { 227 if (mSaveCount == 0) return; 228 229 if (restoreSnapshot()) { 230 setScissorFromClip(); 231 } 232} 233 234void OpenGLRenderer::restoreToCount(int saveCount) { 235 if (saveCount <= 0 || saveCount > mSaveCount) return; 236 237 bool restoreClip = false; 238 239 while (mSaveCount != saveCount - 1) { 240 restoreClip |= restoreSnapshot(); 241 } 242 243 if (restoreClip) { 244 setScissorFromClip(); 245 } 246} 247 248int OpenGLRenderer::saveSnapshot() { 249 mSnapshot = new Snapshot(mSnapshot); 250 return ++mSaveCount; 251} 252 253bool OpenGLRenderer::restoreSnapshot() { 254 bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet; 255 256 mSaveCount--; 257 258 // Do not merge these two lines! 259 sp<Snapshot> previous = mSnapshot->previous; 260 mSnapshot = previous; 261 262 return restoreClip; 263} 264 265/////////////////////////////////////////////////////////////////////////////// 266// Transforms 267/////////////////////////////////////////////////////////////////////////////// 268 269void OpenGLRenderer::translate(float dx, float dy) { 270 mSnapshot->transform.translate(dx, dy, 0.0f); 271 mSnapshot->flags |= Snapshot::kFlagDirtyTransform; 272} 273 274void OpenGLRenderer::rotate(float degrees) { 275 mSnapshot->transform.rotate(degrees, 0.0f, 0.0f, 1.0f); 276 mSnapshot->flags |= Snapshot::kFlagDirtyTransform; 277} 278 279void OpenGLRenderer::scale(float sx, float sy) { 280 mSnapshot->transform.scale(sx, sy, 1.0f); 281 mSnapshot->flags |= Snapshot::kFlagDirtyTransform; 282} 283 284void OpenGLRenderer::setMatrix(SkMatrix* matrix) { 285 mSnapshot->transform.load(*matrix); 286 mSnapshot->flags |= Snapshot::kFlagDirtyTransform; 287} 288 289void OpenGLRenderer::getMatrix(SkMatrix* matrix) { 290 mSnapshot->transform.copyTo(*matrix); 291} 292 293void OpenGLRenderer::concatMatrix(SkMatrix* matrix) { 294 mat4 m(*matrix); 295 mSnapshot->transform.multiply(m); 296 mSnapshot->flags |= Snapshot::kFlagDirtyTransform; 297} 298 299/////////////////////////////////////////////////////////////////////////////// 300// Clipping 301/////////////////////////////////////////////////////////////////////////////// 302 303void OpenGLRenderer::setScissorFromClip() { 304 const Rect& clip = mSnapshot->getMappedClip(); 305 glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight()); 306} 307 308const Rect& OpenGLRenderer::getClipBounds() { 309 return mSnapshot->clipRect; 310} 311 312bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) { 313 /* 314 * The documentation of quickReject() indicates that the specified rect 315 * is transformed before being compared to the clip rect. However, the 316 * clip rect is not stored transformed in the snapshot and can thus be 317 * compared directly 318 * 319 * The following code can be used instead to performed a mapped comparison: 320 * 321 * mSnapshot->transform.mapRect(r); 322 * const Rect& clip = mSnapshot->getMappedClip(); 323 * return !clip.intersects(r); 324 */ 325 326 Rect r(left, top, right, bottom); 327 return !mSnapshot->clipRect.intersects(r); 328} 329 330bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom) { 331 bool clipped = mSnapshot->clipRect.intersect(left, top, right, bottom); 332 if (clipped) { 333 mSnapshot->flags |= Snapshot::kFlagClipSet; 334 setScissorFromClip(); 335 } 336 return clipped; 337} 338 339/////////////////////////////////////////////////////////////////////////////// 340// Drawing 341/////////////////////////////////////////////////////////////////////////////// 342 343void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { 344 // TODO: Set the transfer mode 345 const Rect& clip = mSnapshot->clipRect; 346 drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color); 347} 348 349void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* paint) { 350 // TODO Support more than just color 351 // TODO: Set the transfer mode 352 drawColorRect(left, top, right, bottom, paint->getColor()); 353} 354 355void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, int color) { 356 GLfloat a = ((color >> 24) & 0xFF) / 255.0f; 357 GLfloat r = ((color >> 16) & 0xFF) / 255.0f; 358 GLfloat g = ((color >> 8) & 0xFF) / 255.0f; 359 GLfloat b = ((color ) & 0xFF) / 255.0f; 360 361 mModelView.loadTranslate(left, top, 0.0f); 362 mModelView.scale(right - left, bottom - top, 1.0f); 363 364 mDrawColorShader->use(&mOrthoMatrix[0], &mModelView.data[0], &mSnapshot->transform.data[0]); 365 366 const GLvoid* p = &gDrawColorVertices[0].position[0]; 367 368 glEnableVertexAttribArray(mDrawColorShader->position); 369 glVertexAttribPointer(mDrawColorShader->position, 2, GL_FLOAT, GL_FALSE, 370 gDrawColorVertexStride, p); 371 glVertexAttrib4f(mDrawColorShader->color, r, g, b, a); 372 373 glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawColorVertexCount); 374 375 glDisableVertexAttribArray(mDrawColorShader->position); 376} 377 378}; // namespace uirenderer 379}; // namespace android 380