X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_cb_bitmap.c;h=a5c7ed0ee66d27bcae6d662a25d916361e9c0349;hb=2bae451bd3fe93c47aa231ab35ae18ae86b7df5a;hp=2107ab167399083be37f0b7a42c38a56b2732cd9;hpb=2efabd9f5a711a7f6cd1846630244b7814bf25b3;p=mesa.git diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index 2107ab16739..a5c7ed0ee66 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" @@ -41,15 +42,16 @@ #include "st_context.h" #include "st_atom.h" #include "st_atom_constbuf.h" +#include "st_draw.h" #include "st_program.h" #include "st_cb_bitmap.h" +#include "st_sampler_view.h" #include "st_texture.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_shader_tokens.h" #include "util/u_inlines.h" -#include "util/u_draw_quad.h" #include "util/u_simple_shaders.h" #include "util/u_upload_mgr.h" #include "program/prog_instruction.h" @@ -81,177 +83,11 @@ static GLboolean UseBitmapCache = GL_TRUE; #define BITMAP_CACHE_WIDTH 512 #define BITMAP_CACHE_HEIGHT 32 -struct bitmap_cache -{ - /** Window pos to render the cached image */ - GLint xpos, ypos; - /** Bounds of region used in window coords */ - GLint xmin, ymin, xmax, ymax; - - GLfloat color[4]; - - /** Bitmap's Z position */ - GLfloat zpos; - - struct pipe_resource *texture; - struct pipe_transfer *trans; - - GLboolean empty; - - /** An I8 texture image: */ - ubyte *buffer; -}; - /** Epsilon for Z comparisons */ #define Z_EPSILON 1e-06 -/** - * Make fragment program for glBitmap: - * Sample the texture and kill the fragment if the bit is 0. - * This program will be combined with the user's fragment program. - */ -static struct st_fragment_program * -make_bitmap_fragment_program(struct gl_context *ctx, GLuint samplerIndex) -{ - struct st_context *st = st_context(ctx); - struct st_fragment_program *stfp; - struct gl_program *p; - GLuint ic = 0; - - p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); - if (!p) - return NULL; - - p->NumInstructions = 3; - - p->Instructions = _mesa_alloc_instructions(p->NumInstructions); - if (!p->Instructions) { - ctx->Driver.DeleteProgram(ctx, p); - return NULL; - } - _mesa_init_instructions(p->Instructions, p->NumInstructions); - - /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */ - p->Instructions[ic].Opcode = OPCODE_TEX; - p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY; - p->Instructions[ic].DstReg.Index = 0; - p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; - p->Instructions[ic].SrcReg[0].Index = VARYING_SLOT_TEX0; - p->Instructions[ic].TexSrcUnit = samplerIndex; - p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX; - ic++; - - /* KIL if -tmp0 < 0 # texel=0 -> keep / texel=0 -> discard */ - p->Instructions[ic].Opcode = OPCODE_KIL; - p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY; - - if (st->bitmap.tex_format == PIPE_FORMAT_L8_UNORM) - p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_XXXX; - - p->Instructions[ic].SrcReg[0].Index = 0; - p->Instructions[ic].SrcReg[0].Negate = NEGATE_XYZW; - ic++; - - /* END; */ - p->Instructions[ic++].Opcode = OPCODE_END; - - assert(ic == p->NumInstructions); - - p->InputsRead = VARYING_BIT_TEX0; - p->OutputsWritten = 0x0; - p->SamplersUsed = (1 << samplerIndex); - - stfp = (struct st_fragment_program *) p; - stfp->Base.UsesKill = GL_TRUE; - - return stfp; -} - - -static struct gl_program * -make_bitmap_fragment_program_glsl(struct st_context *st, - struct st_fragment_program *orig, - GLuint samplerIndex) -{ - struct gl_context *ctx = st->ctx; - struct st_fragment_program *fp = (struct st_fragment_program *) - ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); - - if (!fp) - return NULL; - - get_bitmap_visitor(fp, orig->glsl_to_tgsi, samplerIndex); - return &fp->Base.Base; -} - - -static int -find_free_bit(uint bitfield) -{ - int i; - for (i = 0; i < 32; i++) { - if ((bitfield & (1 << i)) == 0) { - return i; - } - } - return -1; -} - - -/** - * Combine basic bitmap fragment program with the user-defined program. - * \param st current context - * \param fpIn the incoming fragment program - * \param fpOut the new fragment program which does fragment culling - * \param bitmap_sampler sampler number for the bitmap texture - */ -void -st_make_bitmap_fragment_program(struct st_context *st, - struct gl_fragment_program *fpIn, - struct gl_fragment_program **fpOut, - GLuint *bitmap_sampler) -{ - struct st_fragment_program *bitmap_prog; - struct st_fragment_program *stfpIn = (struct st_fragment_program *) fpIn; - struct gl_program *newProg; - uint sampler; - - /* - * Generate new program which is the user-defined program prefixed - * with the bitmap sampler/kill instructions. - */ - sampler = find_free_bit(fpIn->Base.SamplersUsed); - - if (stfpIn->glsl_to_tgsi) - newProg = make_bitmap_fragment_program_glsl(st, stfpIn, sampler); - else { - bitmap_prog = make_bitmap_fragment_program(st->ctx, sampler); - - newProg = _mesa_combine_programs(st->ctx, - &bitmap_prog->Base.Base, - &fpIn->Base); - /* done with this after combining */ - st_reference_fragprog(st, &bitmap_prog, NULL); - } - -#if 0 - { - printf("Combined bitmap program:\n"); - _mesa_print_program(newProg); - printf("InputsRead: 0x%x\n", newProg->InputsRead); - printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten); - _mesa_print_parameter_list(newProg->Parameters); - } -#endif - - /* return results */ - *fpOut = (struct gl_fragment_program *) newProg; - *bitmap_sampler = sampler; -} - - /** * Copy user-provide bitmap bits into texture buffer, expanding * bits into texels. @@ -321,102 +157,26 @@ make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height, return pt; } -static void -setup_bitmap_vertex_data(struct st_context *st, bool normalized, - int x, int y, int width, int height, - float z, const float color[4], - struct pipe_resource **vbuf, - unsigned *vbuf_offset) -{ - const GLfloat fb_width = (GLfloat)st->state.framebuffer.width; - const GLfloat fb_height = (GLfloat)st->state.framebuffer.height; - const GLfloat x0 = (GLfloat)x; - const GLfloat x1 = (GLfloat)(x + width); - const GLfloat y0 = (GLfloat)y; - const GLfloat y1 = (GLfloat)(y + height); - GLfloat sLeft = (GLfloat)0.0, sRight = (GLfloat)1.0; - GLfloat tTop = (GLfloat)0.0, tBot = (GLfloat)1.0 - tTop; - const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0); - const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0); - const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0); - const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0); - GLuint i; - float (*vertices)[3][4]; /**< vertex pos + color + texcoord */ - - if(!normalized) - { - sRight = (GLfloat) width; - tBot = (GLfloat) height; - } - - if (u_upload_alloc(st->uploader, 0, 4 * sizeof(vertices[0]), - vbuf_offset, vbuf, (void **) &vertices) != PIPE_OK) { - return; - } - - /* Positions are in clip coords since we need to do clipping in case - * the bitmap quad goes beyond the window bounds. - */ - vertices[0][0][0] = clip_x0; - vertices[0][0][1] = clip_y0; - vertices[0][2][0] = sLeft; - vertices[0][2][1] = tTop; - - vertices[1][0][0] = clip_x1; - vertices[1][0][1] = clip_y0; - vertices[1][2][0] = sRight; - vertices[1][2][1] = tTop; - - vertices[2][0][0] = clip_x1; - vertices[2][0][1] = clip_y1; - vertices[2][2][0] = sRight; - vertices[2][2][1] = tBot; - - vertices[3][0][0] = clip_x0; - vertices[3][0][1] = clip_y1; - vertices[3][2][0] = sLeft; - vertices[3][2][1] = tBot; - - /* same for all verts: */ - for (i = 0; i < 4; i++) { - vertices[i][0][2] = z; - vertices[i][0][3] = 1.0f; - vertices[i][1][0] = color[0]; - vertices[i][1][1] = color[1]; - vertices[i][1][2] = color[2]; - vertices[i][1][3] = color[3]; - vertices[i][2][2] = 0.0; /*R*/ - vertices[i][2][3] = 1.0; /*Q*/ - } - - u_upload_unmap(st->uploader); -} - - /** - * Render a glBitmap by drawing a textured quad + * Setup pipeline state prior to rendering the bitmap textured quad. */ 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) +setup_render_state(struct gl_context *ctx, + struct pipe_sampler_view *sv, + const GLfloat *color, + bool atlas) { struct st_context *st = st_context(ctx); - struct pipe_context *pipe = st->pipe; struct cso_context *cso = st->cso_context; struct st_fp_variant *fpv; struct st_fp_variant_key key; - GLuint maxSize; - GLuint offset; - struct pipe_resource *vbuf = NULL; memset(&key, 0, sizeof(key)); - key.st = st; + key.st = st->has_shareable_shaders ? NULL : st; key.bitmap = GL_TRUE; key.clamp_color = st->clamp_frag_color_in_shader && - st->ctx->Color._ClampFragmentColor; + ctx->Color._ClampFragmentColor; fpv = st_get_fp_variant(st, st->fp, &key); @@ -431,30 +191,19 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, GLfloat colorSave[4]; COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color); - st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); + st_upload_constants(st, &st->fp->Base); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave); } + cso_save_state(cso, (CSO_BIT_RASTERIZER | + CSO_BIT_FRAGMENT_SAMPLERS | + CSO_BIT_FRAGMENT_SAMPLER_VIEWS | + CSO_BIT_VIEWPORT | + CSO_BIT_STREAM_OUTPUTS | + CSO_BIT_VERTEX_ELEMENTS | + CSO_BIT_AUX_VERTEX_BUFFER_SLOT | + CSO_BITS_ALL_SHADERS)); - /* limit checks */ - /* XXX if the bitmap is larger than the max texture size, break - * it up into chunks. - */ - maxSize = 1 << (pipe->screen->get_param(pipe->screen, - PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); - assert(width <= (GLsizei)maxSize); - assert(height <= (GLsizei)maxSize); - - cso_save_rasterizer(cso); - cso_save_samplers(cso, PIPE_SHADER_FRAGMENT); - cso_save_sampler_views(cso, PIPE_SHADER_FRAGMENT); - cso_save_viewport(cso); - cso_save_fragment_shader(cso); - cso_save_stream_outputs(cso); - cso_save_vertex_shader(cso); - cso_save_geometry_shader(cso); - cso_save_vertex_elements(cso); - cso_save_aux_vertex_buffer_slot(cso); /* rasterizer state: just scissor */ st->bitmap.rasterizer.scissor = ctx->Scissor.EnableFlags & 1; @@ -466,7 +215,9 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, /* vertex shader state: position + texcoord pass-through */ cso_set_vertex_shader_handle(cso, st->bitmap.vs); - /* geometry shader state: disabled */ + /* disable other shaders */ + cso_set_tessctrl_shader_handle(cso, NULL); + cso_set_tesseval_shader_handle(cso, NULL); cso_set_geometry_shader_handle(cso, NULL); /* user samplers, plus our bitmap sampler */ @@ -478,8 +229,10 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, 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.samplers[sv->texture->target != PIPE_TEXTURE_RECT]; + 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); } @@ -496,59 +249,92 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, } /* viewport state: viewport matching window dims */ + cso_set_viewport_dims(cso, st->state.fb_width, + st->state.fb_height, + st->state.fb_orientation == Y_0_TOP); + + cso_set_vertex_elements(cso, 3, st->util_velems); + + cso_set_stream_outputs(st->cso_context, 0, NULL, NULL); +} + + +/** + * Restore pipeline state after rendering the bitmap textured quad. + */ +static void +restore_render_state(struct gl_context *ctx) +{ + struct st_context *st = st_context(ctx); + struct cso_context *cso = st->cso_context; + + cso_restore_state(cso); +} + + +/** + * Render a glBitmap by drawing a textured quad + */ +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 st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; + const float fb_width = (float) st->state.fb_width; + const float fb_height = (float) st->state.fb_height; + const float x0 = (float) x; + const float x1 = (float) (x + width); + const float y0 = (float) y; + const float y1 = (float) (y + height); + float sLeft = 0.0f, sRight = 1.0f; + float tTop = 0.0f, tBot = 1.0f - tTop; + const float clip_x0 = x0 / fb_width * 2.0f - 1.0f; + const float clip_y0 = y0 / fb_height * 2.0f - 1.0f; + const float clip_x1 = x1 / fb_width * 2.0f - 1.0f; + const float clip_y1 = y1 / fb_height * 2.0f - 1.0f; + + /* limit checks */ { - const GLboolean invert = st->state.fb_orientation == Y_0_TOP; - const GLfloat width = (GLfloat)st->state.framebuffer.width; - const GLfloat height = (GLfloat)st->state.framebuffer.height; - struct pipe_viewport_state vp; - vp.scale[0] = 0.5f * width; - vp.scale[1] = height * (invert ? -0.5f : 0.5f); - vp.scale[2] = 0.5f; - vp.translate[0] = 0.5f * width; - vp.translate[1] = 0.5f * height; - vp.translate[2] = 0.5f; - cso_set_viewport(cso, &vp); + /* XXX if the bitmap is larger than the max texture size, break + * it up into chunks. + */ + GLuint MAYBE_UNUSED maxSize = + 1 << (pipe->screen->get_param(pipe->screen, + PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); + assert(width <= (GLsizei) maxSize); + assert(height <= (GLsizei) maxSize); } - cso_set_vertex_elements(cso, 3, st->velems_util_draw); - cso_set_stream_outputs(st->cso_context, 0, NULL, NULL); + 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; - /* draw textured quad */ - setup_bitmap_vertex_data(st, sv->texture->target != PIPE_TEXTURE_RECT, - x, y, width, height, z, color, &vbuf, &offset); - - if (vbuf) { - util_draw_vertex_buffer(pipe, st->cso_context, vbuf, - cso_get_aux_vertex_buffer_slot(st->cso_context), - offset, - PIPE_PRIM_TRIANGLE_FAN, - 4, /* verts */ - 3); /* attribs/vert */ + if (sv->texture->target == PIPE_TEXTURE_RECT) { + /* use non-normalized texcoords */ + sRight = (float) width; + tBot = (float) height; } - /* restore state */ - cso_restore_rasterizer(cso); - cso_restore_samplers(cso, PIPE_SHADER_FRAGMENT); - cso_restore_sampler_views(cso, PIPE_SHADER_FRAGMENT); - cso_restore_viewport(cso); - cso_restore_fragment_shader(cso); - cso_restore_vertex_shader(cso); - cso_restore_geometry_shader(cso); - cso_restore_vertex_elements(cso); - cso_restore_aux_vertex_buffer_slot(cso); - cso_restore_stream_outputs(cso); - - pipe_resource_reference(&vbuf, NULL); + if (!st_draw_quad(st, clip_x0, clip_y0, clip_x1, clip_y1, z, + sLeft, tBot, sRight, tTop, color, 0)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBitmap"); + } + + restore_render_state(ctx); + + /* We uploaded modified constants, need to invalidate them. */ + st->dirty |= ST_NEW_FS_CONSTANTS; } static void reset_cache(struct st_context *st) { - struct bitmap_cache *cache = st->bitmap.cache; + struct st_bitmap_cache *cache = &st->bitmap.cache; /*memset(cache->buffer, 0xff, sizeof(cache->buffer));*/ cache->empty = GL_TRUE; @@ -561,7 +347,7 @@ reset_cache(struct st_context *st) assert(!cache->texture); /* allocate a new texture */ - cache->texture = st_texture_create(st, PIPE_TEXTURE_2D, + cache->texture = st_texture_create(st, st->internal_target, st->bitmap.tex_format, 0, BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, 1, 1, 0, @@ -571,7 +357,7 @@ reset_cache(struct st_context *st) /** Print bitmap image to stdout (debug) */ static void -print_cache(const struct bitmap_cache *cache) +print_cache(const struct st_bitmap_cache *cache) { int i, j, k; @@ -596,7 +382,7 @@ static void create_cache_trans(struct st_context *st) { struct pipe_context *pipe = st->pipe; - struct bitmap_cache *cache = st->bitmap.cache; + struct st_bitmap_cache *cache = &st->bitmap.cache; if (cache->trans) return; @@ -620,23 +406,23 @@ create_cache_trans(struct st_context *st) void st_flush_bitmap_cache(struct st_context *st) { - if (!st->bitmap.cache->empty) { - struct bitmap_cache *cache = st->bitmap.cache; + struct st_bitmap_cache *cache = &st->bitmap.cache; + if (!cache->empty) { struct pipe_context *pipe = st->pipe; struct pipe_sampler_view *sv; assert(cache->xmin <= cache->xmax); -/* printf("flush size %d x %d at %d, %d\n", - cache->xmax - cache->xmin, - cache->ymax - cache->ymin, - cache->xpos, cache->ypos); -*/ + if (0) + printf("flush bitmap, size %d x %d at %d, %d\n", + cache->xmax - cache->xmin, + cache->ymax - cache->ymin, + cache->xpos, cache->ypos); /* The texture transfer has been mapped until now. - * So unmap and release the texture transfer before drawing. - */ + * So unmap and release the texture transfer before drawing. + */ if (cache->trans && cache->buffer) { if (0) print_cache(cache); @@ -677,9 +463,9 @@ accum_bitmap(struct gl_context *ctx, const GLubyte *bitmap ) { struct st_context *st = ctx->st; - struct bitmap_cache *cache = st->bitmap.cache; + struct st_bitmap_cache *cache = &st->bitmap.cache; int px = -999, py = -999; - const GLfloat z = st->ctx->Current.RasterPos[2]; + const GLfloat z = ctx->Current.RasterPos[2]; if (width > BITMAP_CACHE_WIDTH || height > BITMAP_CACHE_HEIGHT) @@ -690,7 +476,7 @@ accum_bitmap(struct gl_context *ctx, py = y - cache->ypos; if (px < 0 || px + width > BITMAP_CACHE_WIDTH || py < 0 || py + height > BITMAP_CACHE_HEIGHT || - !TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color) || + !TEST_EQ_4V(ctx->Current.RasterColor, cache->color) || ((fabs(z - cache->zpos) > Z_EPSILON))) { /* This bitmap would extend beyond cache bounds, or the bitmap * color is changing @@ -708,7 +494,7 @@ accum_bitmap(struct gl_context *ctx, cache->ypos = y - py; cache->zpos = z; cache->empty = GL_FALSE; - COPY_4FV(cache->color, st->ctx->Current.RasterColor); + COPY_4FV(cache->color, ctx->Current.RasterColor); } assert(px != -999); @@ -741,25 +527,63 @@ accum_bitmap(struct gl_context *ctx, } - /** - * Called via ctx->Driver.Bitmap() + * One-time init for drawing bitmaps. */ static void -st_Bitmap(struct gl_context *ctx, GLint x, GLint y, - GLsizei width, GLsizei height, - const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) +init_bitmap_state(struct st_context *st) { - struct st_context *st = st_context(ctx); - struct pipe_resource *pt; + struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = pipe->screen; - if (width == 0 || height == 0) - return; + /* This function should only be called once */ + assert(st->bitmap.vs == NULL); - st_validate_state(st); + assert(st->internal_target == PIPE_TEXTURE_2D || + st->internal_target == PIPE_TEXTURE_RECT); - if (!st->bitmap.vs) { - /* create pass-through vertex shader now */ + /* init sampler state once */ + memset(&st->bitmap.sampler, 0, sizeof(st->bitmap.sampler)); + st->bitmap.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP; + st->bitmap.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP; + st->bitmap.sampler.wrap_r = PIPE_TEX_WRAP_CLAMP; + st->bitmap.sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; + st->bitmap.sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + 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; + st->bitmap.rasterizer.bottom_edge_rule = 1; + st->bitmap.rasterizer.depth_clip = 1; + + /* find a usable texture format */ + if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, + st->internal_target, 0, + PIPE_BIND_SAMPLER_VIEW)) { + st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM; + } + else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM, + st->internal_target, 0, + PIPE_BIND_SAMPLER_VIEW)) { + st->bitmap.tex_format = PIPE_FORMAT_A8_UNORM; + } + else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, + st->internal_target, 0, + PIPE_BIND_SAMPLER_VIEW)) { + st->bitmap.tex_format = PIPE_FORMAT_L8_UNORM; + } + else { + /* XXX support more formats */ + assert(0); + } + + /* Create the vertex shader */ + { const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_COLOR, st->needs_texcoord_semantic ? TGSI_SEMANTIC_TEXCOORD : @@ -771,6 +595,40 @@ st_Bitmap(struct gl_context *ctx, GLint x, GLint y, FALSE); } + reset_cache(st); +} + + +/** + * Called via ctx->Driver.Bitmap() + */ +static void +st_Bitmap(struct gl_context *ctx, GLint x, GLint y, + GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) +{ + struct st_context *st = st_context(ctx); + struct pipe_resource *pt; + + assert(width > 0); + assert(height > 0); + + st_invalidate_readpix_cache(st); + + if (!st->bitmap.vs) { + init_bitmap_state(st); + } + + /* We only need to validate any non-ST_NEW_CONSTANTS state. The VS we use + * for bitmap drawing uses no constants and the FS constants are + * explicitly uploaded in the draw_bitmap_quad() function. + */ + if ((st->dirty | ctx->NewDriverState) & ~ST_NEW_CONSTANTS & + ST_PIPELINE_RENDER_STATE_MASK || + st->gfx_shaders_may_be_dirty) { + st_validate_state(st, ST_PIPELINE_RENDER); + } + if (UseBitmapCache && accum_bitmap(ctx, x, y, width, height, unpack, bitmap)) return; @@ -783,8 +641,7 @@ st_Bitmap(struct gl_context *ctx, GLint x, GLint y, if (sv) { draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2], - width, height, sv, - st->ctx->Current.RasterColor); + width, height, sv, ctx->Current.RasterColor); pipe_sampler_view_reference(&sv, NULL); } @@ -795,64 +652,152 @@ st_Bitmap(struct gl_context *ctx, GLint x, GLint y, } -/** Per-context init */ -void -st_init_bitmap_functions(struct dd_function_table *functions) -{ - functions->Bitmap = st_Bitmap; -} - - -/** Per-context init */ -void -st_init_bitmap(struct st_context *st) +/** + * 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 pipe_sampler_state *sampler = &st->bitmap.samplers[0]; + struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; + 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.fb_width; + const float clip_y_scale = 2.0f / st->state.fb_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; - /* init sampler state once */ - memset(sampler, 0, sizeof(*sampler)); - sampler->wrap_s = PIPE_TEX_WRAP_CLAMP; - sampler->wrap_t = PIPE_TEX_WRAP_CLAMP; - sampler->wrap_r = PIPE_TEX_WRAP_CLAMP; - sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST; - sampler->min_mip_filter = PIPE_TEX_MIPFILTER_NONE; - sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST; - st->bitmap.samplers[1] = *sampler; - st->bitmap.samplers[1].normalized_coords = 1; + if (!st->bitmap.vs) { + init_bitmap_state(st); + } - /* init baseline rasterizer state once */ - memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer)); - st->bitmap.rasterizer.half_pixel_center = 1; - st->bitmap.rasterizer.bottom_edge_rule = 1; - st->bitmap.rasterizer.depth_clip = 1; + st_flush_bitmap_cache(st); - /* find a usable texture format */ - if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW)) { - st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM; - } - else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW)) { - st->bitmap.tex_format = PIPE_FORMAT_A8_UNORM; + st_validate_state(st, ST_PIPELINE_RENDER); + st_invalidate_readpix_cache(st); + + sv = st_create_texture_sampler_view(pipe, stObj->pt); + if (!sv) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCallLists(bitmap text)"); + return; } - else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW)) { - st->bitmap.tex_format = PIPE_FORMAT_L8_UNORM; + + setup_render_state(ctx, sv, color, true); + + vb.stride = sizeof(struct st_util_vertex); + + u_upload_alloc(pipe->stream_uploader, 0, num_vert_bytes, 4, + &vb.buffer_offset, &vb.buffer.resource, (void **) &verts); + + if (unlikely(!verts)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCallLists(bitmap text)"); + goto out; } - else { - /* XXX support more formats */ - assert(0); + + /* 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; } - /* alloc bitmap cache object */ - st->bitmap.cache = ST_CALLOC_STRUCT(bitmap_cache); + u_upload_unmap(pipe->stream_uploader); - reset_cache(st); + 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); + +out: + restore_render_state(ctx); + + pipe_resource_reference(&vb.buffer.resource, NULL); + + pipe_sampler_view_reference(&sv, NULL); + + /* We uploaded modified constants, need to invalidate them. */ + st->dirty |= ST_NEW_FS_CONSTANTS; +} + + + +/** Per-context init */ +void +st_init_bitmap_functions(struct dd_function_table *functions) +{ + functions->Bitmap = st_Bitmap; + functions->DrawAtlasBitmaps = st_DrawAtlasBitmaps; } @@ -861,19 +806,15 @@ void st_destroy_bitmap(struct st_context *st) { struct pipe_context *pipe = st->pipe; - struct bitmap_cache *cache = st->bitmap.cache; + struct st_bitmap_cache *cache = &st->bitmap.cache; if (st->bitmap.vs) { cso_delete_vertex_shader(st->cso_context, st->bitmap.vs); st->bitmap.vs = NULL; } - if (cache) { - if (cache->trans && cache->buffer) { - pipe_transfer_unmap(pipe, cache->trans); - } - pipe_resource_reference(&st->bitmap.cache->texture, NULL); - free(st->bitmap.cache); - st->bitmap.cache = NULL; + if (cache->trans && cache->buffer) { + pipe_transfer_unmap(pipe, cache->trans); } + pipe_resource_reference(&st->bitmap.cache.texture, NULL); }