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 "api_exec_decl.h"
#include "state_tracker/st_context.h"
#include "state_tracker/st_cb_texture.h"
#include "state_tracker/st_cb_bitmap.h"
#include "state_tracker/st_sampler_view.h"
static bool
_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:
free(get_pointer(&n[5]));
break;
case OPCODE_BITMAP:
free(get_pointer(&n[7]));
case OPCODE_BITMAP: {
struct pipe_resource *tex = get_pointer(&n[7]);
pipe_resource_reference(&tex, NULL);
break;
}
case OPCODE_POLYGON_STIPPLE:
free(get_pointer(&n[1]));
break;
@@ -1336,21 +1340,32 @@ save_Bitmap(GLsizei width, GLsizei height,
GET_CURRENT_CONTEXT(ctx);
Node *n;
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
n = alloc_instruction(ctx, OPCODE_BITMAP, 6 + POINTER_DWORDS);
if (n) {
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],
unpack_image(ctx, 2, width, height, 1, GL_COLOR_INDEX,
GL_BITMAP, pixels, &ctx->Unpack));
struct pipe_resource *tex =
st_make_bitmap_texture(ctx, width, height, &ctx->Unpack, pixels);
if (!tex) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glNewList -> glBitmap");
return;
}
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) {
CALL_Bitmap(ctx->Exec, (width, height,
xorig, yorig, xmove, ymove, pixels));
ASSERT_OUTSIDE_BEGIN_END(ctx);
_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));
break;
case OPCODE_BITMAP:
{
const struct gl_pixelstore_attrib save = ctx->Unpack;
ctx->Unpack = ctx->DefaultPacking;
CALL_Bitmap(ctx->Exec, ((GLsizei) n[1].i, (GLsizei) n[2].i,
n[3].f, n[4].f, n[5].f, n[6].f,
get_pointer(&n[7])));
ctx->Unpack = save; /* restore */
if (_mesa_inside_begin_end(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glCallList -> glBitmap inside Begin/End");
} else {
_mesa_bitmap(ctx, n[1].i, n[2].i, n[3].f, n[4].f, n[5].f,
n[6].f, NULL, get_pointer(&n[7]));
}
break;
case OPCODE_BLEND_COLOR:

View File

@@ -101,6 +101,11 @@ _mesa_draw_gallium_multimode_fallback(struct gl_context *ctx,
const unsigned char *mode,
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
} // extern "C"
#endif

View File

@@ -316,13 +316,11 @@ end:
}
void GLAPIENTRY
_mesa_Bitmap( GLsizei width, GLsizei height,
GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
const GLubyte *bitmap )
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)
{
GET_CURRENT_CONTEXT(ctx);
FLUSH_VERTICES(ctx, 0, 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 y = util_ifloor(ctx->Current.RasterPos[1] + epsilon - yorig);
if (ctx->Unpack.BufferObj) {
if (!tex && ctx->Unpack.BufferObj) {
/* unpack from PBO */
if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height,
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) {
@@ -396,3 +394,13 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
_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 */
#define Z_EPSILON 1e-06
static void
init_bitmap_state(struct st_context *st);
/**
* 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.
*/
static struct pipe_resource *
make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap)
struct pipe_resource *
st_make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
@@ -125,6 +127,9 @@ make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
ubyte *dest;
struct pipe_resource *pt;
if (!st->bitmap.tex_format)
init_bitmap_state(st);
/* PBO source... */
bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap);
if (!bitmap) {
@@ -283,12 +288,13 @@ restore_render_state(struct gl_context *ctx)
/**
* Render a glBitmap by drawing a textured quad
*
* take_ownership means the callee will be resposible for unreferencing sv.
*/
static void
draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
GLsizei width, GLsizei height,
struct pipe_sampler_view *sv,
const GLfloat *color)
struct pipe_sampler_view *sv, const GLfloat *color)
{
struct st_context *st = st_context(ctx);
const float fb_width = (float) st->state.fb_width;
@@ -589,15 +595,17 @@ init_bitmap_state(struct st_context *st)
void
st_Bitmap(struct gl_context *ctx, GLint x, GLint y,
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 pipe_resource *pt;
assert(width > 0);
assert(height > 0);
st_invalidate_readpix_cache(st);
if (tex)
st_flush_bitmap_cache(st);
if (!st->bitmap.tex_format) {
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);
}
if (UseBitmapCache && accum_bitmap(ctx, x, y, width, height, unpack, bitmap))
return;
struct pipe_sampler_view *view = NULL;
pt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
if (pt) {
struct pipe_sampler_view *sv =
st_create_texture_sampler_view(st->pipe, pt);
if (!tex) {
if (UseBitmapCache && accum_bitmap(ctx, x, y, width, height, unpack, bitmap))
return;
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);
if (sv) {
draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
width, height, sv, ctx->Current.RasterColor);
}
/* release/free the texture */
view = st_create_texture_sampler_view(st->pipe, pt);
/* unreference the texture because it's referenced by sv */
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
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,
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 */