mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 13:10:10 +01:00
mesa: add a fallback for drivers not implementing Driver.DrawGallium*
This is for classic drivers and it translates pipe_draw_info to the old interface using _mesa_prim. Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7679>
This commit is contained in:
parent
dee3f34a8e
commit
bd54e34e4f
5 changed files with 197 additions and 24 deletions
|
|
@ -121,8 +121,8 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
|
|||
|
||||
/* Draw functions */
|
||||
driver->Draw = NULL;
|
||||
driver->DrawGallium = NULL;
|
||||
driver->DrawGalliumComplex = NULL;
|
||||
driver->DrawGallium = _mesa_draw_gallium_fallback;
|
||||
driver->DrawGalliumComplex = _mesa_draw_gallium_complex_fallback;
|
||||
driver->DrawIndirect = NULL;
|
||||
driver->DrawTransformFeedback = NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "enums.h"
|
||||
#include "macros.h"
|
||||
#include "transformfeedback.h"
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
typedef struct {
|
||||
GLuint count;
|
||||
|
|
@ -57,6 +58,180 @@ typedef struct {
|
|||
} DrawElementsIndirectCommand;
|
||||
|
||||
|
||||
#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 via Driver.DrawGallium. This is a fallback invoking Driver.Draw.
|
||||
*/
|
||||
void
|
||||
_mesa_draw_gallium_fallback(struct gl_context *ctx,
|
||||
struct pipe_draw_info *info,
|
||||
const struct pipe_draw_start_count *draws,
|
||||
unsigned num_draws)
|
||||
{
|
||||
struct _mesa_index_buffer ib;
|
||||
unsigned index_size = info->index_size;
|
||||
unsigned min_index = info->index_bounds_valid ? info->min_index : 0;
|
||||
unsigned max_index = info->index_bounds_valid ? info->max_index : ~0;
|
||||
|
||||
ib.index_size_shift = util_logbase2(index_size);
|
||||
|
||||
/* Single draw or a fallback for user indices. */
|
||||
if (num_draws == 1 ||
|
||||
(info->index_size && info->has_user_indices &&
|
||||
!ctx->Const.MultiDrawWithUserIndices)) {
|
||||
for (unsigned i = 0; i < num_draws; i++) {
|
||||
if (index_size) {
|
||||
ib.count = draws[i].count;
|
||||
|
||||
if (info->has_user_indices) {
|
||||
ib.obj = NULL;
|
||||
/* User indices require start to be added here if
|
||||
* Const.MultiDrawWithUserIndices is false.
|
||||
*/
|
||||
ib.ptr = (const char*)info->index.user +
|
||||
draws[i].start * index_size;
|
||||
} else {
|
||||
ib.obj = info->index.gl_bo;
|
||||
ib.ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct _mesa_prim prim;
|
||||
prim.mode = info->mode;
|
||||
prim.begin = 1;
|
||||
prim.end = 1;
|
||||
prim.start = index_size && info->has_user_indices ? 0 : draws[i].start;
|
||||
prim.count = draws[i].count;
|
||||
prim.basevertex = index_size ? info->index_bias : 0;
|
||||
prim.draw_id = info->drawid + (info->increment_draw_id ? i : 0);
|
||||
|
||||
ctx->Driver.Draw(ctx, &prim, 1, index_size ? &ib : NULL,
|
||||
info->index_bounds_valid, info->primitive_restart,
|
||||
info->restart_index, min_index, max_index,
|
||||
info->instance_count, info->start_instance);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
struct _mesa_prim *prim;
|
||||
unsigned max_count = 0;
|
||||
|
||||
ALLOC_PRIMS(prim, num_draws, "DrawGallium");
|
||||
|
||||
for (unsigned i = 0; i < num_draws; i++) {
|
||||
prim[i].mode = info->mode;
|
||||
prim[i].begin = 1;
|
||||
prim[i].end = 1;
|
||||
prim[i].start = draws[i].start;
|
||||
prim[i].count = draws[i].count;
|
||||
prim[i].basevertex = info->index_size ? info->index_bias : 0;
|
||||
prim[i].draw_id = info->drawid + (info->increment_draw_id ? i : 0);
|
||||
|
||||
max_count = MAX2(max_count, prim[i].count);
|
||||
}
|
||||
|
||||
if (info->index_size) {
|
||||
ib.count = max_count;
|
||||
ib.index_size_shift = util_logbase2(index_size);
|
||||
|
||||
if (info->has_user_indices) {
|
||||
ib.obj = NULL;
|
||||
ib.ptr = (const char*)info->index.user;
|
||||
} else {
|
||||
ib.obj = info->index.gl_bo;
|
||||
ib.ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->Driver.Draw(ctx, prim, num_draws, index_size ? &ib : NULL,
|
||||
info->index_bounds_valid, info->primitive_restart,
|
||||
info->restart_index, min_index, max_index,
|
||||
info->instance_count, info->start_instance);
|
||||
FREE_PRIMS(prim, num_draws);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via Driver.DrawGallium. This is a fallback invoking Driver.Draw.
|
||||
*/
|
||||
void
|
||||
_mesa_draw_gallium_complex_fallback(struct gl_context *ctx,
|
||||
struct pipe_draw_info *info,
|
||||
const struct pipe_draw_start_count *draws,
|
||||
const unsigned char *mode,
|
||||
const int *base_vertex,
|
||||
unsigned num_draws)
|
||||
{
|
||||
enum {
|
||||
MODE = 1,
|
||||
BASE_VERTEX = 2,
|
||||
};
|
||||
unsigned mask = (mode ? MODE : 0) | (base_vertex ? BASE_VERTEX : 0);
|
||||
unsigned i, first;
|
||||
|
||||
/* Find consecutive draws where mode and base_vertex don't vary. */
|
||||
switch (mask) {
|
||||
case MODE:
|
||||
for (i = 0, first = 0; i <= num_draws; i++) {
|
||||
if (i == num_draws || mode[i] != mode[first]) {
|
||||
info->mode = mode[first];
|
||||
ctx->Driver.DrawGallium(ctx, info, &draws[first], i - first);
|
||||
first = i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BASE_VERTEX:
|
||||
for (i = 0, first = 0; i <= num_draws; i++) {
|
||||
if (i == num_draws || base_vertex[i] != base_vertex[first]) {
|
||||
info->index_bias = base_vertex[first];
|
||||
ctx->Driver.DrawGallium(ctx, info, &draws[first], i - first);
|
||||
first = i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MODE | BASE_VERTEX:
|
||||
for (i = 0, first = 0; i <= num_draws; i++) {
|
||||
if (i == num_draws ||
|
||||
mode[i] != mode[first] ||
|
||||
base_vertex[i] != base_vertex[first]) {
|
||||
info->mode = mode[first];
|
||||
info->index_bias = base_vertex[first];
|
||||
ctx->Driver.DrawGallium(ctx, info, &draws[first], i - first);
|
||||
first = i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(!"invalid parameters in DrawGalliumComplex");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check that element 'j' of the array has reasonable data.
|
||||
* Map VBO if needed.
|
||||
|
|
@ -662,28 +837,6 @@ _mesa_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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -81,6 +81,20 @@ void
|
|||
_mesa_initialize_exec_dispatch(const struct gl_context *ctx,
|
||||
struct _glapi_table *exec);
|
||||
|
||||
void
|
||||
_mesa_draw_gallium_fallback(struct gl_context *ctx,
|
||||
struct pipe_draw_info *info,
|
||||
const struct pipe_draw_start_count *draws,
|
||||
unsigned num_draws);
|
||||
|
||||
void
|
||||
_mesa_draw_gallium_complex_fallback(struct gl_context *ctx,
|
||||
struct pipe_draw_info *info,
|
||||
const struct pipe_draw_start_count *draws,
|
||||
const unsigned char *mode,
|
||||
const int *base_vertex,
|
||||
unsigned num_draws);
|
||||
|
||||
void GLAPIENTRY
|
||||
_mesa_EvalMesh1(GLenum mode, GLint i1, GLint i2);
|
||||
|
||||
|
|
|
|||
|
|
@ -293,6 +293,8 @@ st_RenderMode(struct gl_context *ctx, GLenum newMode )
|
|||
draw_set_rasterize_stage(draw, st->selection_stage);
|
||||
/* Plug in new vbo draw function */
|
||||
ctx->Driver.Draw = st_feedback_draw_vbo;
|
||||
ctx->Driver.DrawGallium = _mesa_draw_gallium_fallback;
|
||||
ctx->Driver.DrawGalliumComplex = _mesa_draw_gallium_complex_fallback;
|
||||
}
|
||||
else {
|
||||
struct gl_program *vp = st->ctx->VertexProgram._Current;
|
||||
|
|
@ -302,6 +304,8 @@ st_RenderMode(struct gl_context *ctx, GLenum newMode )
|
|||
draw_set_rasterize_stage(draw, st->feedback_stage);
|
||||
/* Plug in new vbo draw function */
|
||||
ctx->Driver.Draw = st_feedback_draw_vbo;
|
||||
ctx->Driver.DrawGallium = _mesa_draw_gallium_fallback;
|
||||
ctx->Driver.DrawGalliumComplex = _mesa_draw_gallium_complex_fallback;
|
||||
/* need to generate/use a vertex program that emits pos/color/tex */
|
||||
if (vp)
|
||||
st->dirty |= ST_NEW_VERTEX_PROGRAM(st, st_program(vp));
|
||||
|
|
|
|||
|
|
@ -324,6 +324,8 @@ void
|
|||
st_init_draw_functions(struct dd_function_table *functions)
|
||||
{
|
||||
functions->Draw = st_draw_vbo;
|
||||
functions->DrawGallium = _mesa_draw_gallium_fallback;
|
||||
functions->DrawGalliumComplex = _mesa_draw_gallium_complex_fallback;
|
||||
functions->DrawIndirect = st_indirect_draw_vbo;
|
||||
functions->DrawTransformFeedback = st_draw_transform_feedback;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue