summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Faye-Lund <erik.faye-lund@collabora.com>2020-09-08 09:35:27 +0200
committerErik Faye-Lund <erik.faye-lund@collabora.com>2020-10-08 11:24:02 +0000
commitfaaa319d704ac677c3a93caadedeb91a4a74b7a7 (patch)
treecb57a4f140c4a80cae38a42c50cdb26589564abe
parent5435fc7fbd332e171da9a71e33a9b190e9462cf0 (diff)
egl: pack all strips per gear into a single draw
We can pack multiple triangle-strips into a single draw, by inserting degenerate triangles between them. This should be a big win in terms of CPU usage. To avoid inserting needless degenerate triangles to invert face-winding, we can manually invert the order of the back-face as well as emit the inner face last. This ensures every strip starts with the right face-winding. Reviewed-by: Alexandros Frantzis <alexandros.frantzis@collbora.com>
-rw-r--r--src/egl/opengles2/es2gears.c81
1 files changed, 37 insertions, 44 deletions
diff --git a/src/egl/opengles2/es2gears.c b/src/egl/opengles2/es2gears.c
index 027cc323..e9e06c79 100644
--- a/src/egl/opengles2/es2gears.c
+++ b/src/egl/opengles2/es2gears.c
@@ -40,6 +40,7 @@
#define _GNU_SOURCE
+#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
@@ -52,19 +53,9 @@
#include "eglut.h"
#define STRIPS_PER_TOOTH 7
-#define VERTICES_PER_TOOTH 34
+#define VERTICES_PER_TOOTH 46
#define GEAR_VERTEX_STRIDE 6
-/**
- * Struct describing the vertices in triangle strip
- */
-struct vertex_strip {
- /** The first vertex in the strip */
- GLint first;
- /** The number of consecutive vertices in the strip after the first */
- GLint count;
-};
-
/* Each vertex consist of GEAR_VERTEX_STRIDE GLfloat attributes */
typedef GLfloat GearVertex[GEAR_VERTEX_STRIDE];
@@ -76,10 +67,6 @@ struct gear {
GearVertex *vertices;
/** The number of vertices comprising the gear */
int nvertices;
- /** The array of triangle strips comprising the gear */
- struct vertex_strip *strips;
- /** The number of triangle strips comprising the gear */
- int nstrips;
/** The Vertex Buffer Object holding the vertices in the graphics card */
GLuint vbo;
};
@@ -145,7 +132,7 @@ create_gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
struct gear *gear;
double s[5], c[5];
GLfloat normal[3];
- int cur_strip = 0;
+ int cur_strip_start = 0;
int i;
/* Allocate memory for the gear */
@@ -160,12 +147,13 @@ create_gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
da = 2.0 * M_PI / teeth / 4.0;
- /* Allocate memory for the triangle strip information */
- gear->nstrips = STRIPS_PER_TOOTH * teeth;
- gear->strips = calloc(gear->nstrips, sizeof (*gear->strips));
+ /* the first tooth doesn't need the first strip-restart sequence */
+ assert(teeth > 0);
+ gear->nvertices = VERTICES_PER_TOOTH +
+ (VERTICES_PER_TOOTH + 2) * (teeth - 1);
/* Allocate memory for the vertices */
- gear->vertices = calloc(VERTICES_PER_TOOTH * teeth, sizeof(*gear->vertices));
+ gear->vertices = calloc(gear->nvertices, sizeof(*gear->vertices));
v = gear->vertices;
for (i = 0; i < teeth; i++) {
@@ -185,13 +173,20 @@ create_gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
#define GEAR_VERT(v, point, sign) vert((v), p[(point)].x, p[(point)].y, (sign) * width * 0.5, normal)
#define START_STRIP do { \
- gear->strips[cur_strip].first = v - gear->vertices; \
+ cur_strip_start = (v - gear->vertices); \
+ if (cur_strip_start) \
+ v += 2; \
} while(0);
+/* emit prev last vertex
+ emit first vertex */
#define END_STRIP do { \
- int _tmp = (v - gear->vertices); \
- gear->strips[cur_strip].count = _tmp - gear->strips[cur_strip].first; \
- cur_strip++; \
+ if (cur_strip_start) { \
+ memcpy(gear->vertices + cur_strip_start, \
+ gear->vertices + (cur_strip_start - 1), sizeof(GearVertex)); \
+ memcpy(gear->vertices + cur_strip_start + 1, \
+ gear->vertices + (cur_strip_start + 2), sizeof(GearVertex)); \
+ } \
} while (0)
#define QUAD_WITH_NORMAL(p1, p2) do { \
@@ -230,26 +225,16 @@ create_gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
v = GEAR_VERT(v, 6, +1);
END_STRIP;
- /* Inner face */
- START_STRIP;
- SET_NORMAL(-c[0], -s[0], 0);
- v = GEAR_VERT(v, 4, -1);
- v = GEAR_VERT(v, 4, 1);
- SET_NORMAL(-c[4], -s[4], 0);
- v = GEAR_VERT(v, 6, -1);
- v = GEAR_VERT(v, 6, 1);
- END_STRIP;
-
/* Back face */
START_STRIP;
SET_NORMAL(0, 0, -1.0);
- v = GEAR_VERT(v, 6, -1);
- v = GEAR_VERT(v, 5, -1);
- v = GEAR_VERT(v, 4, -1);
- v = GEAR_VERT(v, 3, -1);
- v = GEAR_VERT(v, 2, -1);
- v = GEAR_VERT(v, 1, -1);
v = GEAR_VERT(v, 0, -1);
+ v = GEAR_VERT(v, 1, -1);
+ v = GEAR_VERT(v, 2, -1);
+ v = GEAR_VERT(v, 3, -1);
+ v = GEAR_VERT(v, 4, -1);
+ v = GEAR_VERT(v, 5, -1);
+ v = GEAR_VERT(v, 6, -1);
END_STRIP;
/* Outer face */
@@ -268,9 +253,19 @@ create_gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
START_STRIP;
QUAD_WITH_NORMAL(5, 3);
END_STRIP;
+
+ /* Inner face */
+ START_STRIP;
+ SET_NORMAL(-c[0], -s[0], 0);
+ v = GEAR_VERT(v, 4, -1);
+ v = GEAR_VERT(v, 4, 1);
+ SET_NORMAL(-c[4], -s[4], 0);
+ v = GEAR_VERT(v, 6, -1);
+ v = GEAR_VERT(v, 6, 1);
+ END_STRIP;
}
- gear->nvertices = (v - gear->vertices);
+ assert(gear->nvertices == (v - gear->vertices));
/* Store the vertices in a vertex buffer object (VBO) */
glGenBuffers(1, &gear->vbo);
@@ -501,9 +496,7 @@ draw_gear(struct gear *gear, GLfloat *transform,
glEnableVertexAttribArray(1);
/* Draw the triangle strips that comprise the gear */
- int n;
- for (n = 0; n < gear->nstrips; n++)
- glDrawArrays(GL_TRIANGLE_STRIP, gear->strips[n].first, gear->strips[n].count);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, gear->nvertices);
/* Disable the attributes */
glDisableVertexAttribArray(1);