Use VBOs to render most geometries.
Change-Id: I4360dc4fe5693ab425450c107282b2c22db4dca7
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 481e2df..5ab5f06 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -35,11 +35,6 @@
// Defines
///////////////////////////////////////////////////////////////////////////////
-#define REQUIRED_TEXTURE_UNITS_COUNT 3
-
-// Generates simple and textured vertices
-#define FV(x, y, u, v) { { x, y }, { u, v } }
-
#define RAD_TO_DEG (180.0f / 3.14159265f)
#define MIN_ANGLE 0.001f
@@ -50,17 +45,6 @@
// Globals
///////////////////////////////////////////////////////////////////////////////
-// This array is never used directly but used as a memcpy source in the
-// OpenGLRenderer constructor
-static const TextureVertex gMeshVertices[] = {
- FV(0.0f, 0.0f, 0.0f, 0.0f),
- FV(1.0f, 0.0f, 1.0f, 0.0f),
- FV(0.0f, 1.0f, 0.0f, 1.0f),
- FV(1.0f, 1.0f, 1.0f, 1.0f)
-};
-static const GLsizei gMeshStride = sizeof(TextureVertex);
-static const GLsizei gMeshCount = 4;
-
/**
* Structure mapping Skia xfermodes to OpenGL blending factors.
*/
@@ -124,12 +108,6 @@
mFirstSnapshot = new Snapshot;
- GLint maxTextureUnits;
- glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
- if (maxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) {
- LOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT);
- }
-
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
}
@@ -201,6 +179,8 @@
glDisable(GL_DITHER);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ mCaches.bindMeshBuffer();
if (mCaches.blend) {
glEnable(GL_BLEND);
@@ -514,11 +494,13 @@
}
const Rect& texCoords = layer->texCoords;
+ mCaches.unbindMeshBuffer();
resetDrawTextureTexCoords(texCoords.left, texCoords.top, texCoords.right, texCoords.bottom);
if (fboLayer) {
- drawTextureRect(rect.left, rect.top, rect.right, rect.bottom,
- layer->texture, layer->alpha / 255.0f, layer->mode, layer->blend);
+ drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
+ layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
+ &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount);
} else {
drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
1.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
@@ -698,9 +680,16 @@
const float u2 = srcRight / width;
const float v2 = srcBottom / height;
+ mCaches.unbindMeshBuffer();
resetDrawTextureTexCoords(u1, v1, u2, v2);
- drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture, paint);
+ int alpha;
+ SkXfermode::Mode mode;
+ getAlphaAndMode(paint, &alpha, &mode);
+
+ drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom, texture->id, alpha / 255.0f,
+ mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
+ GL_TRIANGLE_STRIP, gMeshCount);
resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
}
@@ -728,8 +717,8 @@
// Specify right and bottom as +1.0f from left/top to prevent scaling since the
// patch mesh already defines the final size
drawTextureMesh(left, top, left + 1.0f, top + 1.0f, texture->id, alpha / 255.0f,
- mode, texture->blend, &mesh->vertices[0].position[0],
- &mesh->vertices[0].texture[0], GL_TRIANGLES, mesh->verticesCount);
+ mode, texture->blend, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset,
+ GL_TRIANGLES, mesh->verticesCount, false, false, mesh->meshBuffer);
}
}
@@ -750,7 +739,8 @@
if (isAA) {
GLuint textureUnit = 0;
setupTextureAlpha8(mCaches.line.getTexture(), 0, 0, textureUnit, 0.0f, 0.0f, r, g, b, a,
- mode, false, true, mCaches.line.getVertices(), mCaches.line.getTexCoords());
+ mode, false, true, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset,
+ mCaches.line.getMeshBuffer());
} else {
setupColorRect(0.0f, 0.0f, 1.0f, 1.0f, r, g, b, a, mode, false);
}
@@ -891,11 +881,12 @@
// Assume that the modelView matrix does not force scales, rotates, etc.
const bool linearFilter = mSnapshot->transform->changesBounds();
setupTextureAlpha8(fontRenderer.getTexture(linearFilter), 0, 0, textureUnit,
- x, y, r, g, b, a, mode, false, true);
+ x, y, r, g, b, a, mode, false, true, NULL, NULL);
const Rect& clip = mSnapshot->getLocalClip();
clearLayerRegions();
+ mCaches.unbindMeshBuffer();
fontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@@ -1009,21 +1000,20 @@
bool transforms, bool applyFilters) {
setupTextureAlpha8(texture->id, texture->width, texture->height, textureUnit,
x, y, r, g, b, a, mode, transforms, applyFilters,
- &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
+ (GLvoid*) 0, (GLvoid*) gMeshTextureOffset);
}
void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height,
GLuint& textureUnit, float x, float y, float r, float g, float b, float a,
SkXfermode::Mode mode, bool transforms, bool applyFilters) {
- setupTextureAlpha8(texture, width, height, textureUnit,
- x, y, r, g, b, a, mode, transforms, applyFilters,
- &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
+ setupTextureAlpha8(texture, width, height, textureUnit, x, y, r, g, b, a, mode,
+ transforms, applyFilters, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset);
}
void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height,
GLuint& textureUnit, float x, float y, float r, float g, float b, float a,
SkXfermode::Mode mode, bool transforms, bool applyFilters,
- GLvoid* vertices, GLvoid* texCoords) {
+ GLvoid* vertices, GLvoid* texCoords, GLuint vbo) {
// Describe the required shaders
ProgramDescription description;
description.hasTexture = true;
@@ -1051,11 +1041,17 @@
int texCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
glEnableVertexAttribArray(texCoordsSlot);
- // Setup attributes
- glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
- gMeshStride, vertices);
- glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE,
- gMeshStride, texCoords);
+ if (texCoords) {
+ // Setup attributes
+ if (!vertices) {
+ mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
+ } else {
+ mCaches.unbindMeshBuffer();
+ }
+ glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
+ gMeshStride, vertices);
+ glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords);
+ }
// Setup uniforms
if (transforms) {
@@ -1188,8 +1184,9 @@
useProgram(mCaches.programCache.get(description));
// Setup attributes
+ mCaches.bindMeshBuffer();
glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
- gMeshStride, &mMeshVertices[0].position[0]);
+ gMeshStride, 0);
// Setup uniforms
mModelView.loadTranslate(left, top, 0.0f);
@@ -1218,21 +1215,20 @@
getAlphaAndMode(paint, &alpha, &mode);
drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode,
- texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
+ texture->blend, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset,
GL_TRIANGLE_STRIP, gMeshCount);
}
void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
GLuint texture, float alpha, SkXfermode::Mode mode, bool blend) {
drawTextureMesh(left, top, right, bottom, texture, alpha, mode, blend,
- &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
- GL_TRIANGLE_STRIP, gMeshCount);
+ (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount);
}
void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom,
GLuint texture, float alpha, SkXfermode::Mode mode, bool blend,
GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
- bool swapSrcDst, bool ignoreTransform) {
+ bool swapSrcDst, bool ignoreTransform, GLuint vbo) {
clearLayerRegions();
ProgramDescription description;
@@ -1267,6 +1263,12 @@
// Mesh
int texCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
glEnableVertexAttribArray(texCoordsSlot);
+
+ if (!vertices) {
+ mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
+ } else {
+ mCaches.unbindMeshBuffer();
+ }
glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
gMeshStride, vertices);
glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords);