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:
@@ -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);
|
||||
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) {
|
||||
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],
|
||||
unpack_image(ctx, 2, width, height, 1, GL_COLOR_INDEX,
|
||||
GL_BITMAP, pixels, &ctx->Unpack));
|
||||
}
|
||||
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:
|
||||
|
@@ -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
|
||||
|
@@ -316,13 +316,11 @@ end:
|
||||
}
|
||||
|
||||
|
||||
void GLAPIENTRY
|
||||
_mesa_Bitmap( GLsizei width, GLsizei height,
|
||||
void
|
||||
_mesa_bitmap(struct gl_context *ctx, GLsizei width, GLsizei height,
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
@@ -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,8 +116,8 @@ 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,
|
||||
struct pipe_resource *
|
||||
st_make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLubyte *bitmap)
|
||||
{
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
struct pipe_sampler_view *view = NULL;
|
||||
|
||||
if (!tex) {
|
||||
if (UseBitmapCache && accum_bitmap(ctx, x, y, width, height, unpack, bitmap))
|
||||
return;
|
||||
|
||||
pt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
|
||||
if (pt) {
|
||||
struct pipe_sampler_view *sv =
|
||||
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);
|
||||
|
||||
if (sv) {
|
||||
draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
|
||||
width, height, sv, ctx->Current.RasterColor);
|
||||
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);
|
||||
}
|
||||
|
||||
/* release/free the texture */
|
||||
pipe_resource_reference(&pt, NULL);
|
||||
if (view) {
|
||||
draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
|
||||
width, height, view, ctx->Current.RasterColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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 */
|
||||
|
Reference in New Issue
Block a user