mesa: create glBitmap textures while creating display lists

This makes glCallList just a textured draw, which is blazingly fast.

Reviewed-by: Brian Paul <brianp@vmware.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17780>
This commit is contained in:
Marek Olšák
2022-07-24 20:47:26 -04:00
committed by Marge Bot
parent 6da2fb81a7
commit bb860f63f6
5 changed files with 99 additions and 51 deletions

View File

@@ -52,8 +52,10 @@
#include "util/u_memory.h" #include "util/u_memory.h"
#include "api_exec_decl.h" #include "api_exec_decl.h"
#include "state_tracker/st_context.h"
#include "state_tracker/st_cb_texture.h" #include "state_tracker/st_cb_texture.h"
#include "state_tracker/st_cb_bitmap.h" #include "state_tracker/st_cb_bitmap.h"
#include "state_tracker/st_sampler_view.h"
static bool static bool
_mesa_glthread_should_execute_list(struct gl_context *ctx, _mesa_glthread_should_execute_list(struct gl_context *ctx,
@@ -860,9 +862,11 @@ _mesa_delete_list(struct gl_context *ctx, struct gl_display_list *dlist)
case OPCODE_DRAW_PIXELS: case OPCODE_DRAW_PIXELS:
free(get_pointer(&n[5])); free(get_pointer(&n[5]));
break; break;
case OPCODE_BITMAP: case OPCODE_BITMAP: {
free(get_pointer(&n[7])); struct pipe_resource *tex = get_pointer(&n[7]);
pipe_resource_reference(&tex, NULL);
break; break;
}
case OPCODE_POLYGON_STIPPLE: case OPCODE_POLYGON_STIPPLE:
free(get_pointer(&n[1])); free(get_pointer(&n[1]));
break; break;
@@ -1336,21 +1340,32 @@ save_Bitmap(GLsizei width, GLsizei height,
GET_CURRENT_CONTEXT(ctx); GET_CURRENT_CONTEXT(ctx);
Node *n; Node *n;
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
n = alloc_instruction(ctx, OPCODE_BITMAP, 6 + POINTER_DWORDS); struct pipe_resource *tex =
if (n) { st_make_bitmap_texture(ctx, width, height, &ctx->Unpack, pixels);
n[1].i = (GLint) width;
n[2].i = (GLint) height; if (!tex) {
n[3].f = xorig; _mesa_error(ctx, GL_OUT_OF_MEMORY, "glNewList -> glBitmap");
n[4].f = yorig; return;
n[5].f = xmove;
n[6].f = ymove;
save_pointer(&n[7],
unpack_image(ctx, 2, width, height, 1, GL_COLOR_INDEX,
GL_BITMAP, pixels, &ctx->Unpack));
} }
n = alloc_instruction(ctx, OPCODE_BITMAP, 6 + POINTER_DWORDS);
if (!n) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glNewList -> glBitmap (3)");
pipe_resource_reference(&tex, NULL);
return;
}
n[1].i = (GLint) width;
n[2].i = (GLint) height;
n[3].f = xorig;
n[4].f = yorig;
n[5].f = xmove;
n[6].f = ymove;
save_pointer(&n[7], tex);
if (ctx->ExecuteFlag) { if (ctx->ExecuteFlag) {
CALL_Bitmap(ctx->Exec, (width, height, ASSERT_OUTSIDE_BEGIN_END(ctx);
xorig, yorig, xmove, ymove, pixels)); _mesa_bitmap(ctx, width, height, xorig, yorig, xmove, ymove, NULL, tex);
} }
} }
@@ -10853,13 +10868,12 @@ execute_list(struct gl_context *ctx, GLuint list)
CALL_BindTexture(ctx->Exec, (n[1].e, n[2].ui)); CALL_BindTexture(ctx->Exec, (n[1].e, n[2].ui));
break; break;
case OPCODE_BITMAP: case OPCODE_BITMAP:
{ if (_mesa_inside_begin_end(ctx)) {
const struct gl_pixelstore_attrib save = ctx->Unpack; _mesa_error(ctx, GL_INVALID_OPERATION,
ctx->Unpack = ctx->DefaultPacking; "glCallList -> glBitmap inside Begin/End");
CALL_Bitmap(ctx->Exec, ((GLsizei) n[1].i, (GLsizei) n[2].i, } else {
n[3].f, n[4].f, n[5].f, n[6].f, _mesa_bitmap(ctx, n[1].i, n[2].i, n[3].f, n[4].f, n[5].f,
get_pointer(&n[7]))); n[6].f, NULL, get_pointer(&n[7]));
ctx->Unpack = save; /* restore */
} }
break; break;
case OPCODE_BLEND_COLOR: case OPCODE_BLEND_COLOR:

View File

@@ -101,6 +101,11 @@ _mesa_draw_gallium_multimode_fallback(struct gl_context *ctx,
const unsigned char *mode, const unsigned char *mode,
unsigned num_draws); unsigned num_draws);
void
_mesa_bitmap(struct gl_context *ctx, GLsizei width, GLsizei height,
GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
const GLubyte *bitmap, struct pipe_resource *tex);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

View File

@@ -316,13 +316,11 @@ end:
} }
void GLAPIENTRY void
_mesa_Bitmap( GLsizei width, GLsizei height, _mesa_bitmap(struct gl_context *ctx, GLsizei width, GLsizei height,
GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
const GLubyte *bitmap ) const GLubyte *bitmap, struct pipe_resource *tex)
{ {
GET_CURRENT_CONTEXT(ctx);
FLUSH_VERTICES(ctx, 0, 0); FLUSH_VERTICES(ctx, 0, 0);
if (width < 0 || height < 0) { if (width < 0 || height < 0) {
@@ -354,7 +352,7 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
GLint x = util_ifloor(ctx->Current.RasterPos[0] + epsilon - xorig); GLint x = util_ifloor(ctx->Current.RasterPos[0] + epsilon - xorig);
GLint y = util_ifloor(ctx->Current.RasterPos[1] + epsilon - yorig); GLint y = util_ifloor(ctx->Current.RasterPos[1] + epsilon - yorig);
if (ctx->Unpack.BufferObj) { if (!tex && ctx->Unpack.BufferObj) {
/* unpack from PBO */ /* unpack from PBO */
if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height,
1, GL_COLOR_INDEX, GL_BITMAP, 1, GL_COLOR_INDEX, GL_BITMAP,
@@ -371,7 +369,7 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
} }
} }
st_Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap ); st_Bitmap(ctx, x, y, width, height, &ctx->Unpack, bitmap, tex);
} }
} }
else if (ctx->RenderMode == GL_FEEDBACK) { else if (ctx->RenderMode == GL_FEEDBACK) {
@@ -396,3 +394,13 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
_mesa_flush(ctx); _mesa_flush(ctx);
} }
} }
void GLAPIENTRY
_mesa_Bitmap(GLsizei width, GLsizei height,
GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
const GLubyte *bitmap)
{
GET_CURRENT_CONTEXT(ctx);
_mesa_bitmap(ctx, width, height, xorig, yorig, xmove, ymove, bitmap, NULL);
}

View File

@@ -88,6 +88,8 @@ static GLboolean UseBitmapCache = GL_TRUE;
/** Epsilon for Z comparisons */ /** Epsilon for Z comparisons */
#define Z_EPSILON 1e-06 #define Z_EPSILON 1e-06
static void
init_bitmap_state(struct st_context *st);
/** /**
* Copy user-provide bitmap bits into texture buffer, expanding * Copy user-provide bitmap bits into texture buffer, expanding
@@ -114,10 +116,10 @@ unpack_bitmap(struct st_context *st,
/** /**
* Create a texture which represents a bitmap image. * Create a texture which represents a bitmap image.
*/ */
static struct pipe_resource * struct pipe_resource *
make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height, st_make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack, const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap) const GLubyte *bitmap)
{ {
struct st_context *st = st_context(ctx); struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe; struct pipe_context *pipe = st->pipe;
@@ -125,6 +127,9 @@ make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
ubyte *dest; ubyte *dest;
struct pipe_resource *pt; struct pipe_resource *pt;
if (!st->bitmap.tex_format)
init_bitmap_state(st);
/* PBO source... */ /* PBO source... */
bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap); bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap);
if (!bitmap) { if (!bitmap) {
@@ -283,12 +288,13 @@ restore_render_state(struct gl_context *ctx)
/** /**
* Render a glBitmap by drawing a textured quad * Render a glBitmap by drawing a textured quad
*
* take_ownership means the callee will be resposible for unreferencing sv.
*/ */
static void static void
draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
GLsizei width, GLsizei height, GLsizei width, GLsizei height,
struct pipe_sampler_view *sv, struct pipe_sampler_view *sv, const GLfloat *color)
const GLfloat *color)
{ {
struct st_context *st = st_context(ctx); struct st_context *st = st_context(ctx);
const float fb_width = (float) st->state.fb_width; const float fb_width = (float) st->state.fb_width;
@@ -589,15 +595,17 @@ init_bitmap_state(struct st_context *st)
void void
st_Bitmap(struct gl_context *ctx, GLint x, GLint y, st_Bitmap(struct gl_context *ctx, GLint x, GLint y,
GLsizei width, GLsizei height, GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap) const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap,
struct pipe_resource *tex)
{ {
struct st_context *st = st_context(ctx); struct st_context *st = st_context(ctx);
struct pipe_resource *pt;
assert(width > 0); assert(width > 0);
assert(height > 0); assert(height > 0);
st_invalidate_readpix_cache(st); st_invalidate_readpix_cache(st);
if (tex)
st_flush_bitmap_cache(st);
if (!st->bitmap.tex_format) { if (!st->bitmap.tex_format) {
init_bitmap_state(st); init_bitmap_state(st);
@@ -613,23 +621,30 @@ st_Bitmap(struct gl_context *ctx, GLint x, GLint y,
st_validate_state(st, ST_PIPELINE_META); st_validate_state(st, ST_PIPELINE_META);
} }
if (UseBitmapCache && accum_bitmap(ctx, x, y, width, height, unpack, bitmap)) struct pipe_sampler_view *view = NULL;
return;
pt = make_bitmap_texture(ctx, width, height, unpack, bitmap); if (!tex) {
if (pt) { if (UseBitmapCache && accum_bitmap(ctx, x, y, width, height, unpack, bitmap))
struct pipe_sampler_view *sv = return;
st_create_texture_sampler_view(st->pipe, pt);
struct pipe_resource *pt =
st_make_bitmap_texture(ctx, width, height, unpack, bitmap);
if (!pt)
return;
assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT); assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT);
if (sv) { view = st_create_texture_sampler_view(st->pipe, pt);
draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2], /* unreference the texture because it's referenced by sv */
width, height, sv, ctx->Current.RasterColor);
}
/* release/free the texture */
pipe_resource_reference(&pt, NULL); pipe_resource_reference(&pt, NULL);
} else {
/* tex comes from a display list. */
view = st_create_texture_sampler_view(st->pipe, tex);
}
if (view) {
draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
width, height, view, ctx->Current.RasterColor);
} }
} }

View File

@@ -45,8 +45,14 @@ st_destroy_bitmap(struct st_context *st);
extern void extern void
st_flush_bitmap_cache(struct st_context *st); st_flush_bitmap_cache(struct st_context *st);
struct pipe_resource *
st_make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap);
void st_Bitmap(struct gl_context *ctx, GLint x, GLint y, void st_Bitmap(struct gl_context *ctx, GLint x, GLint y,
GLsizei width, GLsizei height, GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap); const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap,
struct pipe_resource *tex);
#endif /* ST_CB_BITMAP_H */ #endif /* ST_CB_BITMAP_H */