1/************************************************************************** 2 * 3 * Copyright 2007 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /* 29 * Authors: 30 * Brian Paul 31 */ 32 33#include "main/errors.h" 34 35#include "main/image.h" 36#include "main/bufferobj.h" 37#include "main/dlist.h" 38#include "main/framebuffer.h" 39#include "main/macros.h" 40#include "main/pbo.h" 41#include "program/program.h" 42#include "program/prog_print.h" 43 44#include "st_context.h" 45#include "st_atom.h" 46#include "st_atom_constbuf.h" 47#include "st_draw.h" 48#include "st_program.h" 49#include "st_cb_bitmap.h" 50#include "st_cb_drawpixels.h" 51#include "st_sampler_view.h" 52#include "st_texture.h" 53#include "st_util.h" 54 55#include "pipe/p_context.h" 56#include "pipe/p_defines.h" 57#include "pipe/p_shader_tokens.h" 58#include "util/u_inlines.h" 59#include "util/u_upload_mgr.h" 60#include "program/prog_instruction.h" 61#include "cso_cache/cso_context.h" 62 63 64/** 65 * glBitmaps are drawn as textured quads. The user's bitmap pattern 66 * is stored in a texture image. An alpha8 texture format is used. 67 * The fragment shader samples a bit (texel) from the texture, then 68 * discards the fragment if the bit is off. 69 * 70 * Note that we actually store the inverse image of the bitmap to 71 * simplify the fragment program. An "on" bit gets stored as texel=0x0 72 * and an "off" bit is stored as texel=0xff. Then we kill the 73 * fragment if the negated texel value is less than zero. 74 */ 75 76 77/** 78 * The bitmap cache attempts to accumulate multiple glBitmap calls in a 79 * buffer which is then rendered en mass upon a flush, state change, etc. 80 * A wide, short buffer is used to target the common case of a series 81 * of glBitmap calls being used to draw text. 82 */ 83static GLboolean UseBitmapCache = GL_TRUE; 84 85 86#define BITMAP_CACHE_WIDTH 512 87#define BITMAP_CACHE_HEIGHT 32 88 89 90/** Epsilon for Z comparisons */ 91#define Z_EPSILON 1e-06 92 93 94/** 95 * Copy user-provide bitmap bits into texture buffer, expanding 96 * bits into texels. 97 * "On" bits will set texels to 0x0. 98 * "Off" bits will not modify texels. 99 * Note that the image is actually going to be upside down in 100 * the texture. We deal with that with texcoords. 101 */ 102static void 103unpack_bitmap(struct st_context *st, 104 GLint px, GLint py, GLsizei width, GLsizei height, 105 const struct gl_pixelstore_attrib *unpack, 106 const GLubyte *bitmap, 107 ubyte *destBuffer, uint destStride) 108{ 109 destBuffer += py * destStride + px; 110 111 _mesa_expand_bitmap(width, height, unpack, bitmap, 112 destBuffer, destStride, 0x0); 113} 114 115 116/** 117 * Create a texture which represents a bitmap image. 118 */ 119static struct pipe_resource * 120make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height, 121 const struct gl_pixelstore_attrib *unpack, 122 const GLubyte *bitmap) 123{ 124 struct st_context *st = st_context(ctx); 125 struct pipe_context *pipe = st->pipe; 126 struct pipe_transfer *transfer; 127 ubyte *dest; 128 struct pipe_resource *pt; 129 130 /* PBO source... */ 131 bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap); 132 if (!bitmap) { 133 return NULL; 134 } 135 136 /** 137 * Create texture to hold bitmap pattern. 138 */ 139 pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format, 140 0, width, height, 1, 1, 0, 141 PIPE_BIND_SAMPLER_VIEW, false); 142 if (!pt) { 143 _mesa_unmap_pbo_source(ctx, unpack); 144 return NULL; 145 } 146 147 dest = pipe_texture_map(st->pipe, pt, 0, 0, 148 PIPE_MAP_WRITE, 149 0, 0, width, height, &transfer); 150 151 /* Put image into texture transfer */ 152 memset(dest, 0xff, height * transfer->stride); 153 unpack_bitmap(st, 0, 0, width, height, unpack, bitmap, 154 dest, transfer->stride); 155 156 _mesa_unmap_pbo_source(ctx, unpack); 157 158 /* Release transfer */ 159 pipe_texture_unmap(pipe, transfer); 160 return pt; 161} 162 163 164/** 165 * Setup pipeline state prior to rendering the bitmap textured quad. 166 */ 167static void 168setup_render_state(struct gl_context *ctx, 169 struct pipe_sampler_view *sv, 170 const GLfloat *color, 171 bool atlas) 172{ 173 struct st_context *st = st_context(ctx); 174 struct pipe_context *pipe = st->pipe; 175 struct cso_context *cso = st->cso_context; 176 struct st_fp_variant *fpv; 177 struct st_fp_variant_key key; 178 179 memset(&key, 0, sizeof(key)); 180 key.st = st->has_shareable_shaders ? NULL : st; 181 key.bitmap = GL_TRUE; 182 key.clamp_color = st->clamp_frag_color_in_shader && 183 ctx->Color._ClampFragmentColor; 184 key.lower_alpha_func = COMPARE_FUNC_ALWAYS; 185 186 fpv = st_get_fp_variant(st, st->fp, &key); 187 188 /* As an optimization, Mesa's fragment programs will sometimes get the 189 * primary color from a statevar/constant rather than a varying variable. 190 * when that's the case, we need to ensure that we use the 'color' 191 * parameter and not the current attribute color (which may have changed 192 * through glRasterPos and state validation. 193 * So, we force the proper color here. Not elegant, but it works. 194 */ 195 { 196 GLfloat colorSave[4]; 197 COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); 198 COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color); 199 st_upload_constants(st, st->fp, MESA_SHADER_FRAGMENT); 200 COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave); 201 } 202 203 cso_save_state(cso, (CSO_BIT_RASTERIZER | 204 CSO_BIT_FRAGMENT_SAMPLERS | 205 CSO_BIT_VIEWPORT | 206 CSO_BIT_STREAM_OUTPUTS | 207 CSO_BIT_VERTEX_ELEMENTS | 208 CSO_BITS_ALL_SHADERS)); 209 210 211 /* rasterizer state: just scissor */ 212 st->bitmap.rasterizer.scissor = ctx->Scissor.EnableFlags & 1; 213 cso_set_rasterizer(cso, &st->bitmap.rasterizer); 214 215 /* fragment shader state: TEX lookup program */ 216 cso_set_fragment_shader_handle(cso, fpv->base.driver_shader); 217 218 /* vertex shader state: position + texcoord pass-through */ 219 cso_set_vertex_shader_handle(cso, st->passthrough_vs); 220 221 /* disable other shaders */ 222 cso_set_tessctrl_shader_handle(cso, NULL); 223 cso_set_tesseval_shader_handle(cso, NULL); 224 cso_set_geometry_shader_handle(cso, NULL); 225 226 /* user samplers, plus our bitmap sampler */ 227 { 228 struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; 229 uint num = MAX2(fpv->bitmap_sampler + 1, 230 st->state.num_frag_samplers); 231 uint i; 232 for (i = 0; i < st->state.num_frag_samplers; i++) { 233 samplers[i] = &st->state.frag_samplers[i]; 234 } 235 if (atlas) 236 samplers[fpv->bitmap_sampler] = &st->bitmap.atlas_sampler; 237 else 238 samplers[fpv->bitmap_sampler] = &st->bitmap.sampler; 239 cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, num, 240 (const struct pipe_sampler_state **) samplers); 241 } 242 243 /* user textures, plus the bitmap texture */ 244 { 245 struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; 246 unsigned num_views = 247 st_get_sampler_views(st, PIPE_SHADER_FRAGMENT, 248 ctx->FragmentProgram._Current, sampler_views); 249 250 num_views = MAX2(fpv->bitmap_sampler + 1, num_views); 251 sampler_views[fpv->bitmap_sampler] = sv; 252 pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num_views, 0, 253 true, sampler_views); 254 st->state.num_sampler_views[PIPE_SHADER_FRAGMENT] = num_views; 255 } 256 257 /* viewport state: viewport matching window dims */ 258 cso_set_viewport_dims(cso, st->state.fb_width, 259 st->state.fb_height, 260 st->state.fb_orientation == Y_0_TOP); 261 262 st->util_velems.count = 3; 263 cso_set_vertex_elements(cso, &st->util_velems); 264 265 cso_set_stream_outputs(st->cso_context, 0, NULL, NULL); 266} 267 268 269/** 270 * Restore pipeline state after rendering the bitmap textured quad. 271 */ 272static void 273restore_render_state(struct gl_context *ctx) 274{ 275 struct st_context *st = st_context(ctx); 276 struct cso_context *cso = st->cso_context; 277 278 /* Unbind all because st/mesa won't do it if the current shader doesn't 279 * use them. 280 */ 281 cso_restore_state(cso, CSO_UNBIND_FS_SAMPLERVIEWS); 282 st->state.num_sampler_views[PIPE_SHADER_FRAGMENT] = 0; 283 284 ctx->Array.NewVertexElements = true; 285 st->dirty |= ST_NEW_VERTEX_ARRAYS | 286 ST_NEW_FS_SAMPLER_VIEWS; 287} 288 289 290/** 291 * Render a glBitmap by drawing a textured quad 292 */ 293static void 294draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, 295 GLsizei width, GLsizei height, 296 struct pipe_sampler_view *sv, 297 const GLfloat *color) 298{ 299 struct st_context *st = st_context(ctx); 300 const float fb_width = (float) st->state.fb_width; 301 const float fb_height = (float) st->state.fb_height; 302 const float x0 = (float) x; 303 const float x1 = (float) (x + width); 304 const float y0 = (float) y; 305 const float y1 = (float) (y + height); 306 float sLeft = 0.0f, sRight = 1.0f; 307 float tTop = 0.0f, tBot = 1.0f - tTop; 308 const float clip_x0 = x0 / fb_width * 2.0f - 1.0f; 309 const float clip_y0 = y0 / fb_height * 2.0f - 1.0f; 310 const float clip_x1 = x1 / fb_width * 2.0f - 1.0f; 311 const float clip_y1 = y1 / fb_height * 2.0f - 1.0f; 312 313 /* limit checks */ 314 { 315 /* XXX if the bitmap is larger than the max texture size, break 316 * it up into chunks. 317 */ 318 ASSERTED GLuint maxSize = 319 st->screen->get_param(st->screen, PIPE_CAP_MAX_TEXTURE_2D_SIZE); 320 assert(width <= (GLsizei) maxSize); 321 assert(height <= (GLsizei) maxSize); 322 } 323 324 setup_render_state(ctx, sv, color, false); 325 326 /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */ 327 z = z * 2.0f - 1.0f; 328 329 if (sv->texture->target == PIPE_TEXTURE_RECT) { 330 /* use non-normalized texcoords */ 331 sRight = (float) width; 332 tBot = (float) height; 333 } 334 335 if (!st_draw_quad(st, clip_x0, clip_y0, clip_x1, clip_y1, z, 336 sLeft, tBot, sRight, tTop, color, 0)) { 337 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBitmap"); 338 } 339 340 restore_render_state(ctx); 341 342 /* We uploaded modified constants, need to invalidate them. */ 343 st->dirty |= ST_NEW_FS_CONSTANTS; 344} 345 346 347static void 348reset_cache(struct st_context *st) 349{ 350 struct st_bitmap_cache *cache = &st->bitmap.cache; 351 352 /*memset(cache->buffer, 0xff, sizeof(cache->buffer));*/ 353 cache->empty = GL_TRUE; 354 355 cache->xmin = 1000000; 356 cache->xmax = -1000000; 357 cache->ymin = 1000000; 358 cache->ymax = -1000000; 359 360 assert(!cache->texture); 361 362 /* allocate a new texture */ 363 cache->texture = st_texture_create(st, st->internal_target, 364 st->bitmap.tex_format, 0, 365 BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, 366 1, 1, 0, 367 PIPE_BIND_SAMPLER_VIEW, 368 false); 369} 370 371 372/** Print bitmap image to stdout (debug) */ 373static void 374print_cache(const struct st_bitmap_cache *cache) 375{ 376 int i, j, k; 377 378 for (i = 0; i < BITMAP_CACHE_HEIGHT; i++) { 379 k = BITMAP_CACHE_WIDTH * (BITMAP_CACHE_HEIGHT - i - 1); 380 for (j = 0; j < BITMAP_CACHE_WIDTH; j++) { 381 if (cache->buffer[k]) 382 printf("X"); 383 else 384 printf(" "); 385 k++; 386 } 387 printf("\n"); 388 } 389} 390 391 392/** 393 * Create gallium pipe_transfer object for the bitmap cache. 394 */ 395static void 396create_cache_trans(struct st_context *st) 397{ 398 struct pipe_context *pipe = st->pipe; 399 struct st_bitmap_cache *cache = &st->bitmap.cache; 400 401 if (cache->trans) 402 return; 403 404 /* Map the texture transfer. 405 * Subsequent glBitmap calls will write into the texture image. 406 */ 407 cache->buffer = pipe_texture_map(pipe, cache->texture, 0, 0, 408 PIPE_MAP_WRITE, 0, 0, 409 BITMAP_CACHE_WIDTH, 410 BITMAP_CACHE_HEIGHT, &cache->trans); 411 412 /* init image to all 0xff */ 413 memset(cache->buffer, 0xff, cache->trans->stride * BITMAP_CACHE_HEIGHT); 414} 415 416 417/** 418 * If there's anything in the bitmap cache, draw/flush it now. 419 */ 420void 421st_flush_bitmap_cache(struct st_context *st) 422{ 423 struct st_bitmap_cache *cache = &st->bitmap.cache; 424 425 if (!cache->empty) { 426 struct pipe_context *pipe = st->pipe; 427 struct pipe_sampler_view *sv; 428 429 assert(cache->xmin <= cache->xmax); 430 431 if (0) 432 printf("flush bitmap, size %d x %d at %d, %d\n", 433 cache->xmax - cache->xmin, 434 cache->ymax - cache->ymin, 435 cache->xpos, cache->ypos); 436 437 /* The texture transfer has been mapped until now. 438 * So unmap and release the texture transfer before drawing. 439 */ 440 if (cache->trans && cache->buffer) { 441 if (0) 442 print_cache(cache); 443 pipe_texture_unmap(pipe, cache->trans); 444 cache->buffer = NULL; 445 cache->trans = NULL; 446 } 447 448 sv = st_create_texture_sampler_view(st->pipe, cache->texture); 449 if (sv) { 450 draw_bitmap_quad(st->ctx, 451 cache->xpos, 452 cache->ypos, 453 cache->zpos, 454 BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, 455 sv, 456 cache->color); 457 } 458 459 /* release/free the texture */ 460 pipe_resource_reference(&cache->texture, NULL); 461 462 reset_cache(st); 463 } 464} 465 466 467/** 468 * Try to accumulate this glBitmap call in the bitmap cache. 469 * \return GL_TRUE for success, GL_FALSE if bitmap is too large, etc. 470 */ 471static GLboolean 472accum_bitmap(struct gl_context *ctx, 473 GLint x, GLint y, GLsizei width, GLsizei height, 474 const struct gl_pixelstore_attrib *unpack, 475 const GLubyte *bitmap ) 476{ 477 struct st_context *st = ctx->st; 478 struct st_bitmap_cache *cache = &st->bitmap.cache; 479 int px = -999, py = -999; 480 const GLfloat z = ctx->Current.RasterPos[2]; 481 482 if (width > BITMAP_CACHE_WIDTH || 483 height > BITMAP_CACHE_HEIGHT) 484 return GL_FALSE; /* too big to cache */ 485 486 if (!cache->empty) { 487 px = x - cache->xpos; /* pos in buffer */ 488 py = y - cache->ypos; 489 if (px < 0 || px + width > BITMAP_CACHE_WIDTH || 490 py < 0 || py + height > BITMAP_CACHE_HEIGHT || 491 !TEST_EQ_4V(ctx->Current.RasterColor, cache->color) || 492 ((fabsf(z - cache->zpos) > Z_EPSILON))) { 493 /* This bitmap would extend beyond cache bounds, or the bitmap 494 * color is changing 495 * so flush and continue. 496 */ 497 st_flush_bitmap_cache(st); 498 } 499 } 500 501 if (cache->empty) { 502 /* Initialize. Center bitmap vertically in the buffer. */ 503 px = 0; 504 py = (BITMAP_CACHE_HEIGHT - height) / 2; 505 cache->xpos = x; 506 cache->ypos = y - py; 507 cache->zpos = z; 508 cache->empty = GL_FALSE; 509 COPY_4FV(cache->color, ctx->Current.RasterColor); 510 } 511 512 assert(px != -999); 513 assert(py != -999); 514 515 if (x < cache->xmin) 516 cache->xmin = x; 517 if (y < cache->ymin) 518 cache->ymin = y; 519 if (x + width > cache->xmax) 520 cache->xmax = x + width; 521 if (y + height > cache->ymax) 522 cache->ymax = y + height; 523 524 /* create the transfer if needed */ 525 create_cache_trans(st); 526 527 /* PBO source... */ 528 bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap); 529 if (!bitmap) { 530 return FALSE; 531 } 532 533 unpack_bitmap(st, px, py, width, height, unpack, bitmap, 534 cache->buffer, BITMAP_CACHE_WIDTH); 535 536 _mesa_unmap_pbo_source(ctx, unpack); 537 538 return GL_TRUE; /* accumulated */ 539} 540 541 542/** 543 * One-time init for drawing bitmaps. 544 */ 545static void 546init_bitmap_state(struct st_context *st) 547{ 548 struct pipe_screen *screen = st->screen; 549 550 /* This function should only be called once */ 551 assert(!st->bitmap.tex_format); 552 553 assert(st->internal_target == PIPE_TEXTURE_2D || 554 st->internal_target == PIPE_TEXTURE_RECT); 555 556 /* init sampler state once */ 557 memset(&st->bitmap.sampler, 0, sizeof(st->bitmap.sampler)); 558 st->bitmap.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 559 st->bitmap.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 560 st->bitmap.sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 561 st->bitmap.sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 562 st->bitmap.sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 563 st->bitmap.sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 564 st->bitmap.sampler.normalized_coords = st->internal_target == PIPE_TEXTURE_2D || 565 (st->internal_target == PIPE_TEXTURE_RECT && st->lower_rect_tex); 566 567 st->bitmap.atlas_sampler = st->bitmap.sampler; 568 st->bitmap.atlas_sampler.normalized_coords = 0; 569 570 /* init baseline rasterizer state once */ 571 memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer)); 572 st->bitmap.rasterizer.half_pixel_center = 1; 573 st->bitmap.rasterizer.bottom_edge_rule = 1; 574 st->bitmap.rasterizer.depth_clip_near = 1; 575 st->bitmap.rasterizer.depth_clip_far = 1; 576 577 /* find a usable texture format */ 578 if (screen->is_format_supported(screen, PIPE_FORMAT_R8_UNORM, 579 st->internal_target, 0, 0, 580 PIPE_BIND_SAMPLER_VIEW)) { 581 st->bitmap.tex_format = PIPE_FORMAT_R8_UNORM; 582 } 583 else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM, 584 st->internal_target, 0, 0, 585 PIPE_BIND_SAMPLER_VIEW)) { 586 st->bitmap.tex_format = PIPE_FORMAT_A8_UNORM; 587 } 588 else { 589 /* XXX support more formats */ 590 assert(0); 591 } 592 593 /* Create the vertex shader */ 594 st_make_passthrough_vertex_shader(st); 595 596 reset_cache(st); 597} 598 599void 600st_Bitmap(struct gl_context *ctx, GLint x, GLint y, 601 GLsizei width, GLsizei height, 602 const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap) 603{ 604 struct st_context *st = st_context(ctx); 605 struct pipe_resource *pt; 606 607 assert(width > 0); 608 assert(height > 0); 609 610 st_invalidate_readpix_cache(st); 611 612 if (!st->bitmap.tex_format) { 613 init_bitmap_state(st); 614 } 615 616 /* We only need to validate any non-ST_NEW_CONSTANTS state. The VS we use 617 * for bitmap drawing uses no constants and the FS constants are 618 * explicitly uploaded in the draw_bitmap_quad() function. 619 */ 620 if ((st->dirty | ctx->NewDriverState) & st->active_states & 621 ~ST_NEW_CONSTANTS & ST_PIPELINE_RENDER_STATE_MASK || 622 st->gfx_shaders_may_be_dirty) { 623 st_validate_state(st, ST_PIPELINE_META); 624 } 625 626 if (UseBitmapCache && accum_bitmap(ctx, x, y, width, height, unpack, bitmap)) 627 return; 628 629 pt = make_bitmap_texture(ctx, width, height, unpack, bitmap); 630 if (pt) { 631 struct pipe_sampler_view *sv = 632 st_create_texture_sampler_view(st->pipe, pt); 633 634 assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT); 635 636 if (sv) { 637 draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2], 638 width, height, sv, ctx->Current.RasterColor); 639 } 640 641 /* release/free the texture */ 642 pipe_resource_reference(&pt, NULL); 643 } 644} 645 646void 647st_DrawAtlasBitmaps(struct gl_context *ctx, 648 const struct gl_bitmap_atlas *atlas, 649 GLuint count, const GLubyte *ids) 650{ 651 struct st_context *st = st_context(ctx); 652 struct pipe_context *pipe = st->pipe; 653 struct gl_texture_object *stObj = atlas->texObj; 654 struct pipe_sampler_view *sv; 655 /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */ 656 const float z = ctx->Current.RasterPos[2] * 2.0f - 1.0f; 657 const float *color = ctx->Current.RasterColor; 658 const float clip_x_scale = 2.0f / st->state.fb_width; 659 const float clip_y_scale = 2.0f / st->state.fb_height; 660 const unsigned num_verts = count * 4; 661 const unsigned num_vert_bytes = num_verts * sizeof(struct st_util_vertex); 662 struct st_util_vertex *verts; 663 struct pipe_vertex_buffer vb = {0}; 664 unsigned i; 665 666 if (!st->bitmap.tex_format) { 667 init_bitmap_state(st); 668 } 669 670 st_flush_bitmap_cache(st); 671 672 st_validate_state(st, ST_PIPELINE_META); 673 st_invalidate_readpix_cache(st); 674 675 sv = st_create_texture_sampler_view(pipe, stObj->pt); 676 if (!sv) { 677 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCallLists(bitmap text)"); 678 return; 679 } 680 681 setup_render_state(ctx, sv, color, true); 682 683 vb.stride = sizeof(struct st_util_vertex); 684 685 u_upload_alloc(pipe->stream_uploader, 0, num_vert_bytes, 4, 686 &vb.buffer_offset, &vb.buffer.resource, (void **) &verts); 687 688 if (unlikely(!verts)) { 689 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCallLists(bitmap text)"); 690 goto out; 691 } 692 693 /* build quads vertex data */ 694 for (i = 0; i < count; i++) { 695 const GLfloat epsilon = 0.0001F; 696 const struct gl_bitmap_glyph *g = &atlas->glyphs[ids[i]]; 697 const float xmove = g->xmove, ymove = g->ymove; 698 const float xorig = g->xorig, yorig = g->yorig; 699 const float s0 = g->x, t0 = g->y; 700 const float s1 = s0 + g->w, t1 = t0 + g->h; 701 const float x0 = util_ifloor(ctx->Current.RasterPos[0] - xorig + epsilon); 702 const float y0 = util_ifloor(ctx->Current.RasterPos[1] - yorig + epsilon); 703 const float x1 = x0 + g->w, y1 = y0 + g->h; 704 const float clip_x0 = x0 * clip_x_scale - 1.0f; 705 const float clip_y0 = y0 * clip_y_scale - 1.0f; 706 const float clip_x1 = x1 * clip_x_scale - 1.0f; 707 const float clip_y1 = y1 * clip_y_scale - 1.0f; 708 709 /* lower-left corner */ 710 verts->x = clip_x0; 711 verts->y = clip_y0; 712 verts->z = z; 713 verts->r = color[0]; 714 verts->g = color[1]; 715 verts->b = color[2]; 716 verts->a = color[3]; 717 verts->s = s0; 718 verts->t = t0; 719 verts++; 720 721 /* lower-right corner */ 722 verts->x = clip_x1; 723 verts->y = clip_y0; 724 verts->z = z; 725 verts->r = color[0]; 726 verts->g = color[1]; 727 verts->b = color[2]; 728 verts->a = color[3]; 729 verts->s = s1; 730 verts->t = t0; 731 verts++; 732 733 /* upper-right corner */ 734 verts->x = clip_x1; 735 verts->y = clip_y1; 736 verts->z = z; 737 verts->r = color[0]; 738 verts->g = color[1]; 739 verts->b = color[2]; 740 verts->a = color[3]; 741 verts->s = s1; 742 verts->t = t1; 743 verts++; 744 745 /* upper-left corner */ 746 verts->x = clip_x0; 747 verts->y = clip_y1; 748 verts->z = z; 749 verts->r = color[0]; 750 verts->g = color[1]; 751 verts->b = color[2]; 752 verts->a = color[3]; 753 verts->s = s0; 754 verts->t = t1; 755 verts++; 756 757 /* Update the raster position */ 758 ctx->Current.RasterPos[0] += xmove; 759 ctx->Current.RasterPos[1] += ymove; 760 ctx->PopAttribState |= GL_CURRENT_BIT; 761 } 762 763 u_upload_unmap(pipe->stream_uploader); 764 765 cso_set_vertex_buffers(st->cso_context, 0, 1, 0, false, &vb); 766 st->last_num_vbuffers = MAX2(st->last_num_vbuffers, 1); 767 768 cso_draw_arrays(st->cso_context, PIPE_PRIM_QUADS, 0, num_verts); 769 770out: 771 restore_render_state(ctx); 772 773 pipe_resource_reference(&vb.buffer.resource, NULL); 774 775 /* We uploaded modified constants, need to invalidate them. */ 776 st->dirty |= ST_NEW_FS_CONSTANTS; 777} 778 779/** Per-context tear-down */ 780void 781st_destroy_bitmap(struct st_context *st) 782{ 783 struct pipe_context *pipe = st->pipe; 784 struct st_bitmap_cache *cache = &st->bitmap.cache; 785 786 if (cache->trans && cache->buffer) { 787 pipe_texture_unmap(pipe, cache->trans); 788 } 789 pipe_resource_reference(&st->bitmap.cache.texture, NULL); 790} 791