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