From: Brian Paul Date: Wed, 3 Feb 2016 16:40:08 +0000 (-0700) Subject: st/mesa: new st_DrawAtlasBitmaps() function for drawing bitmap text X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=06d3b0a006f35dc232d512d09f45a6cb4f13cfdf;p=mesa.git st/mesa: new st_DrawAtlasBitmaps() function for drawing bitmap text This basically saves the current pipeline state, sets up state for rendering, constructs a set of textured quads, renders, then restores the previous pipeline state. It shouldn't be hard to implement a similar function for non-gallium drives. With some code refactoring, the vertex definition code could probably be shared. Reviewed-by: Nicolai Hähnle --- diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index 9c44458d141..4fd2dfef8cc 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -33,6 +33,7 @@ #include "main/imports.h" #include "main/image.h" #include "main/bufferobj.h" +#include "main/dlist.h" #include "main/macros.h" #include "main/pbo.h" #include "program/program.h" @@ -51,6 +52,7 @@ #include "pipe/p_shader_tokens.h" #include "util/u_inlines.h" #include "util/u_simple_shaders.h" +#include "util/u_upload_mgr.h" #include "program/prog_instruction.h" #include "cso_cache/cso_context.h" @@ -182,7 +184,8 @@ make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height, static void setup_render_state(struct gl_context *ctx, struct pipe_sampler_view *sv, - const GLfloat *color) + const GLfloat *color, + bool atlas) { struct st_context *st = st_context(ctx); struct cso_context *cso = st->cso_context; @@ -247,7 +250,10 @@ setup_render_state(struct gl_context *ctx, for (i = 0; i < st->state.num_samplers[PIPE_SHADER_FRAGMENT]; i++) { samplers[i] = &st->state.samplers[PIPE_SHADER_FRAGMENT][i]; } - samplers[fpv->bitmap_sampler] = &st->bitmap.sampler; + if (atlas) + samplers[fpv->bitmap_sampler] = &st->bitmap.atlas_sampler; + else + samplers[fpv->bitmap_sampler] = &st->bitmap.sampler; cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, num, (const struct pipe_sampler_state **) samplers); } @@ -322,7 +328,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, assert(height <= (GLsizei) maxSize); } - setup_render_state(ctx, sv, color); + setup_render_state(ctx, sv, color, false); /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */ z = z * 2.0f - 1.0f; @@ -569,6 +575,9 @@ init_bitmap_state(struct st_context *st) st->bitmap.sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; st->bitmap.sampler.normalized_coords = st->internal_target == PIPE_TEXTURE_2D; + st->bitmap.atlas_sampler = st->bitmap.sampler; + st->bitmap.atlas_sampler.normalized_coords = 0; + /* init baseline rasterizer state once */ memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer)); st->bitmap.rasterizer.half_pixel_center = 1; @@ -663,11 +672,139 @@ st_Bitmap(struct gl_context *ctx, GLint x, GLint y, } +/** + * Called via ctx->Driver.DrawAtlasBitmap() + */ +static void +st_DrawAtlasBitmaps(struct gl_context *ctx, + const struct gl_bitmap_atlas *atlas, + GLuint count, const GLubyte *ids) +{ + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; + struct st_texture_object *stObj = st_texture_object(atlas->texObj); + struct pipe_sampler_view *sv; + /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */ + const float z = ctx->Current.RasterPos[2] * 2.0f - 1.0f; + const float *color = ctx->Current.RasterColor; + const float clip_x_scale = 2.0f / st->state.framebuffer.width; + const float clip_y_scale = 2.0f / st->state.framebuffer.height; + const unsigned num_verts = count * 4; + const unsigned num_vert_bytes = num_verts * sizeof(struct st_util_vertex); + struct st_util_vertex *verts; + struct pipe_vertex_buffer vb = {0}; + unsigned i; + + if (!st->bitmap.cache) { + init_bitmap_state(st); + } + + st_flush_bitmap_cache(st); + + st_validate_state(st, ST_PIPELINE_RENDER); + + sv = st_create_texture_sampler_view(pipe, stObj->pt); + + setup_render_state(ctx, sv, color, true); + + vb.stride = sizeof(struct st_util_vertex); + + u_upload_alloc(st->uploader, 0, num_vert_bytes, 4, + &vb.buffer_offset, &vb.buffer, (void **) &verts); + + /* build quads vertex data */ + for (i = 0; i < count; i++) { + const GLfloat epsilon = 0.0001F; + const struct gl_bitmap_glyph *g = &atlas->glyphs[ids[i]]; + const float xmove = g->xmove, ymove = g->ymove; + const float xorig = g->xorig, yorig = g->yorig; + const float s0 = g->x, t0 = g->y; + const float s1 = s0 + g->w, t1 = t0 + g->h; + const float x0 = IFLOOR(ctx->Current.RasterPos[0] - xorig + epsilon); + const float y0 = IFLOOR(ctx->Current.RasterPos[1] - yorig + epsilon); + const float x1 = x0 + g->w, y1 = y0 + g->h; + const float clip_x0 = x0 * clip_x_scale - 1.0f; + const float clip_y0 = y0 * clip_y_scale - 1.0f; + const float clip_x1 = x1 * clip_x_scale - 1.0f; + const float clip_y1 = y1 * clip_y_scale - 1.0f; + + /* lower-left corner */ + verts->x = clip_x0; + verts->y = clip_y0; + verts->z = z; + verts->r = color[0]; + verts->g = color[1]; + verts->b = color[2]; + verts->a = color[3]; + verts->s = s0; + verts->t = t0; + verts++; + + /* lower-right corner */ + verts->x = clip_x1; + verts->y = clip_y0; + verts->z = z; + verts->r = color[0]; + verts->g = color[1]; + verts->b = color[2]; + verts->a = color[3]; + verts->s = s1; + verts->t = t0; + verts++; + + /* upper-right corner */ + verts->x = clip_x1; + verts->y = clip_y1; + verts->z = z; + verts->r = color[0]; + verts->g = color[1]; + verts->b = color[2]; + verts->a = color[3]; + verts->s = s1; + verts->t = t1; + verts++; + + /* upper-left corner */ + verts->x = clip_x0; + verts->y = clip_y1; + verts->z = z; + verts->r = color[0]; + verts->g = color[1]; + verts->b = color[2]; + verts->a = color[3]; + verts->s = s0; + verts->t = t1; + verts++; + + /* Update the raster position */ + ctx->Current.RasterPos[0] += xmove; + ctx->Current.RasterPos[1] += ymove; + } + + u_upload_unmap(st->uploader); + + cso_set_vertex_buffers(st->cso_context, + cso_get_aux_vertex_buffer_slot(st->cso_context), + 1, &vb); + + cso_draw_arrays(st->cso_context, PIPE_PRIM_QUADS, 0, num_verts); + + restore_render_state(ctx); + + pipe_resource_reference(&vb.buffer, NULL); + + /* We uploaded modified constants, need to invalidate them. */ + st->dirty.mesa |= _NEW_PROGRAM_CONSTANTS; +} + + + /** Per-context init */ void st_init_bitmap_functions(struct dd_function_table *functions) { functions->Bitmap = st_Bitmap; + functions->DrawAtlasBitmaps = st_DrawAtlasBitmaps; } diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 93da0e5d1d1..1701c618ebf 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -205,6 +205,7 @@ struct st_context struct { struct pipe_rasterizer_state rasterizer; struct pipe_sampler_state sampler; + struct pipe_sampler_state atlas_sampler; enum pipe_format tex_format; void *vs; struct bitmap_cache *cache;