aboutsummaryrefslogtreecommitdiffstats
path: root/src/mesa/main/draw.c
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2020-02-12 15:30:30 -0500
committerMarge Bot <[email protected]>2020-02-28 00:53:45 +0000
commit4c5cd113b82b798634f9a71ef98241d8917c05e1 (patch)
tree88ef7f8e0123841e33084a0367327b5e1901abd2 /src/mesa/main/draw.c
parentb78ab9c741ac758e9d1eb237f7e8ddc3b70235f5 (diff)
mesa: clean up glMultiDrawElements code, use alloca for small draw count (v2)
v2: use calloc, add reusable macros Reviewed-by: Mathias Fröhlich <[email protected]> (v1) Reviewed-by: Pierre-Eric Pelloux-Prayer <[email protected]> (v1) Reviewed-by: Ian Romanick <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3990>
Diffstat (limited to 'src/mesa/main/draw.c')
-rw-r--r--src/mesa/main/draw.c56
1 files changed, 38 insertions, 18 deletions
diff --git a/src/mesa/main/draw.c b/src/mesa/main/draw.c
index 02efab74db1..3a7c390784d 100644
--- a/src/mesa/main/draw.c
+++ b/src/mesa/main/draw.c
@@ -608,6 +608,28 @@ _mesa_exec_DrawArraysInstancedBaseInstance(GLenum mode, GLint first,
}
+#define MAX_ALLOCA_PRIMS (50000 / sizeof(*prim))
+
+/* Use calloc for large allocations and alloca for small allocations. */
+/* We have to use a macro because alloca is local within the function. */
+#define ALLOC_PRIMS(prim, primcount, func) do { \
+ if (unlikely(primcount > MAX_ALLOCA_PRIMS)) { \
+ prim = calloc(primcount, sizeof(*prim)); \
+ if (!prim) { \
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, func); \
+ return; \
+ } \
+ } else { \
+ prim = alloca(primcount * sizeof(*prim)); \
+ } \
+} while (0)
+
+#define FREE_PRIMS(prim, primcount) do { \
+ if (primcount > MAX_ALLOCA_PRIMS) \
+ free(prim); \
+} while (0)
+
+
/**
* Called from glMultiDrawArrays when in immediate mode.
*/
@@ -1158,7 +1180,6 @@ _mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
GLsizei primcount, const GLint *basevertex)
{
struct _mesa_index_buffer ib;
- struct _mesa_prim *prim;
unsigned int index_type_size = sizeof_ib_type(type);
uintptr_t min_index_ptr, max_index_ptr;
GLboolean fallback = GL_FALSE;
@@ -1167,12 +1188,6 @@ _mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
if (primcount == 0)
return;
- prim = calloc(primcount, sizeof(*prim));
- if (prim == NULL) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
- return;
- }
-
min_index_ptr = (uintptr_t) indices[0];
max_index_ptr = 0;
for (i = 0; i < primcount; i++) {
@@ -1215,6 +1230,10 @@ _mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
fallback = GL_TRUE;
if (!fallback) {
+ struct _mesa_prim *prim;
+
+ ALLOC_PRIMS(prim, primcount, "glMultiDrawElements");
+
ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
ib.index_size = sizeof_ib_type(type);
ib.obj = ctx->Array.VAO->IndexBufferObj;
@@ -1236,34 +1255,35 @@ _mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
ctx->Driver.Draw(ctx, prim, primcount, &ib,
false, 0, ~0, 1, 0, NULL, 0);
+ FREE_PRIMS(prim, primcount);
}
else {
/* render one prim at a time */
for (i = 0; i < primcount; i++) {
if (count[i] == 0)
continue;
+
ib.count = count[i];
ib.index_size = sizeof_ib_type(type);
ib.obj = ctx->Array.VAO->IndexBufferObj;
ib.ptr = indices[i];
- prim[0].begin = 1;
- prim[0].end = 1;
- prim[0].mode = mode;
- prim[0].start = 0;
- prim[0].count = count[i];
- prim[0].draw_id = i;
+ struct _mesa_prim prim;
+ prim.begin = 1;
+ prim.end = 1;
+ prim.mode = mode;
+ prim.start = 0;
+ prim.count = count[i];
+ prim.draw_id = i;
if (basevertex != NULL)
- prim[0].basevertex = basevertex[i];
+ prim.basevertex = basevertex[i];
else
- prim[0].basevertex = 0;
+ prim.basevertex = 0;
- ctx->Driver.Draw(ctx, prim, 1, &ib, false, 0, ~0, 1, 0, NULL, 0);
+ ctx->Driver.Draw(ctx, &prim, 1, &ib, false, 0, ~0, 1, 0, NULL, 0);
}
}
- free(prim);
-
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
_mesa_flush(ctx);
}