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