summaryrefslogtreecommitdiff
path: root/libs/hwui/OpenGLRenderer.cpp
diff options
context:
space:
mode:
author Romain Guy <romainguy@google.com> 2010-12-08 18:34:42 -0800
committer Romain Guy <romainguy@google.com> 2010-12-08 19:06:58 -0800
commita957eea78557cb47a91d44d9e6ee641c58cf1c07 (patch)
treebc6ee438bdb116feee2fef40ada876367544dcbb /libs/hwui/OpenGLRenderer.cpp
parent1e8b5fea90e6160f8cdd101767d0a8f6842751fd (diff)
New, better line drawing implementation.
Bug #3207544 Bug #3225875 Change-Id: Ibdd1dfc64e01625d5c441f39eb0aa3ee647f6ff5
Diffstat (limited to 'libs/hwui/OpenGLRenderer.cpp')
-rw-r--r--libs/hwui/OpenGLRenderer.cpp139
1 files changed, 96 insertions, 43 deletions
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 1a89ca0eb993..b3579736eb64 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -30,6 +30,7 @@
#include "OpenGLRenderer.h"
#include "DisplayListRenderer.h"
+#include "Vector.h"
namespace android {
namespace uirenderer {
@@ -989,6 +990,12 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
// TODO: Should do quickReject for each line
if (mSnapshot->invisible) return;
+ const bool isAA = paint->isAntiAlias();
+ const float strokeWidth = paint->getStrokeWidth() * 0.5f;
+ // A stroke width of 0 has a special meaningin Skia:
+ // it draws an unscaled 1px wide line
+ const bool isHairLine = paint->getStrokeWidth() == 0.0f;
+
setupDraw();
int alpha;
@@ -1001,59 +1008,105 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f;
const GLfloat b = a * ((color ) & 0xFF) / 255.0f;
- const bool isAA = paint->isAntiAlias();
- if (isAA) {
- GLuint textureUnit = 0;
- glActiveTexture(gTextureUnits[textureUnit]);
- setupTextureAlpha8(mCaches.line.getTexture(), 0, 0, textureUnit, 0.0f, 0.0f, r, g, b, a,
- 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, true);
+ // Used only with AA lines
+ GLuint textureUnit = 0;
+
+ // Describe the required shaders
+ ProgramDescription description;
+ const bool setColor = description.setColor(r, g, b, a);
+
+ if (mShader) {
+ mShader->describe(description, mCaches.extensions);
+ }
+ if (mColorFilter) {
+ mColorFilter->describe(description, mCaches.extensions);
}
- const float strokeWidth = paint->getStrokeWidth();
- const GLsizei elementsCount = isAA ? mCaches.line.getElementsCount() : gMeshCount;
- const GLenum drawMode = isAA ? GL_TRIANGLES : GL_TRIANGLE_STRIP;
+ // Setup the blending mode
+ chooseBlending(a < 1.0f || (mShader && mShader->blend()), mode, description);
- for (int i = 0; i < count; i += 4) {
- float tx = 0.0f;
- float ty = 0.0f;
+ // We're not drawing with VBOs here
+ mCaches.unbindMeshBuffer();
- if (isAA) {
- mCaches.line.update(points[i], points[i + 1], points[i + 2], points[i + 3],
- strokeWidth, tx, ty);
- } else {
- ty = strokeWidth <= 1.0f ? 0.0f : -strokeWidth * 0.5f;
- }
+ int verticesCount = count >> 2;
+ if (!isHairLine) {
+ // TODO: AA needs more vertices
+ verticesCount *= 6;
+ } else {
+ // TODO: AA will be different
+ verticesCount *= 2;
+ }
- const float dx = points[i + 2] - points[i];
- const float dy = points[i + 3] - points[i + 1];
- const float mag = sqrtf(dx * dx + dy * dy);
- const float angle = acos(dx / mag);
+ TextureVertex lines[verticesCount];
+ TextureVertex* vertex = &lines[0];
- mModelView.loadTranslate(points[i], points[i + 1], 0.0f);
- if (angle > MIN_ANGLE || angle < -MIN_ANGLE) {
- mModelView.rotate(angle * RAD_TO_DEG, 0.0f, 0.0f, 1.0f);
- }
- mModelView.translate(tx, ty, 0.0f);
- if (!isAA) {
- float length = mCaches.line.getLength(points[i], points[i + 1],
- points[i + 2], points[i + 3]);
- mModelView.scale(length, strokeWidth, 1.0f);
- }
- mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
- // TODO: Add bounds to the layer's region
+ glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
+ gMeshStride, vertex);
- if (mShader) {
- mShader->updateTransforms(mCaches.currentProgram, mModelView, *mSnapshot);
- }
+ mModelView.loadIdentity();
- glDrawArrays(drawMode, 0, elementsCount);
+ // Build and use the appropriate shader
+ useProgram(mCaches.programCache.get(description));
+ mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
+
+ if (!mShader || (mShader && setColor)) {
+ mCaches.currentProgram->setColor(r, g, b, a);
}
- if (isAA) {
- glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords"));
+ if (mShader) {
+ mShader->setupProgram(mCaches.currentProgram, mModelView, *mSnapshot, &textureUnit);
+ }
+ if (mColorFilter) {
+ mColorFilter->setupProgram(mCaches.currentProgram);
+ }
+
+ if (!isHairLine) {
+ // TODO: Handle the AA case
+ for (int i = 0; i < count; i += 4) {
+ // a = start point, b = end point
+ vec2 a(points[i], points[i + 1]);
+ vec2 b(points[i + 2], points[i + 3]);
+
+ // Bias to snap to the same pixels as Skia
+ a += 0.375;
+ b += 0.375;
+
+ // Find the normal to the line
+ vec2 n = (b - a).copyNormalized() * strokeWidth;
+ float x = n.x;
+ n.x = -n.y;
+ n.y = x;
+
+ // Four corners of the rectangle defining a thick line
+ vec2 p1 = a - n;
+ vec2 p2 = a + n;
+ vec2 p3 = b + n;
+ vec2 p4 = b - n;
+
+ // Draw the line as 2 triangles, could be optimized
+ // by using only 4 vertices and the correct indices
+ // Also we should probably used non textured vertices
+ // when line AA is disabled to save on bandwidth
+ TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
+ TextureVertex::set(vertex++, p2.x, p2.y, 0.0f, 0.0f);
+ TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
+ TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
+ TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
+ TextureVertex::set(vertex++, p4.x, p4.y, 0.0f, 0.0f);
+
+ // TODO: Mark the dirty regions when RENDER_LAYERS_AS_REGIONS is set
+ }
+
+ // GL_LINE does not give the result we want to match Skia
+ glDrawArrays(GL_TRIANGLES, 0, verticesCount);
+ } else {
+ // TODO: Handle the AA case
+ for (int i = 0; i < count; i += 4) {
+ TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f);
+ TextureVertex::set(vertex++, points[i + 2], points[i + 3], 0.0f, 0.0f);
+ }
+ glLineWidth(1.0f);
+ glDrawArrays(GL_LINES, 0, verticesCount);
}
}