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>
#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,
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;
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) {
- 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));
+ 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);
}
}
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:
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
}
-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) {
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,
}
}
- 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) {
_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);
+}
/** 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
/**
* 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;
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) {
/**
* 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;
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);
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;
- assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT);
+ struct pipe_resource *pt =
+ st_make_bitmap_texture(ctx, width, height, unpack, bitmap);
+ if (!pt)
+ return;
- if (sv) {
- draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
- width, height, sv, ctx->Current.RasterColor);
- }
+ assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT);
- /* 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);
}
}
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 */