st_cb_bitmap.c revision e66cb602b79f52bd1f01b1c3f7af039eeff283a6
1/************************************************************************** 2 * 3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 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 TUNGSTEN GRAPHICS 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/macros.h" 37#include "main/texformat.h" 38#include "shader/program.h" 39#include "shader/prog_parameter.h" 40#include "shader/prog_print.h" 41 42#include "st_context.h" 43#include "st_atom.h" 44#include "st_atom_constbuf.h" 45#include "st_program.h" 46#include "st_cb_bitmap.h" 47#include "st_cb_program.h" 48#include "st_mesa_to_tgsi.h" 49#include "st_texture.h" 50#include "pipe/p_context.h" 51#include "pipe/p_defines.h" 52#include "pipe/p_inlines.h" 53#include "pipe/p_winsys.h" 54#include "util/p_tile.h" 55#include "util/u_draw_quad.h" 56#include "util/u_simple_shaders.h" 57#include "shader/prog_instruction.h" 58#include "cso_cache/cso_context.h" 59 60 61 62/** 63 * The bitmap cache attempts to accumulate multiple glBitmap calls in a 64 * buffer which is then rendered en mass upon a flush, state change, etc. 65 * A wide, short buffer is used to target the common case of a series 66 * of glBitmap calls being used to draw text. 67 */ 68static GLboolean UseBitmapCache = GL_TRUE; 69 70 71#define BITMAP_CACHE_WIDTH 512 72#define BITMAP_CACHE_HEIGHT 32 73 74struct bitmap_cache 75{ 76 /** Window pos to render the cached image */ 77 GLint xpos, ypos; 78 /** Bounds of region used in window coords */ 79 GLint xmin, ymin, xmax, ymax; 80 struct pipe_texture *texture; 81 GLboolean empty; 82 /** An I8 texture image: */ 83 GLubyte buffer[BITMAP_CACHE_HEIGHT][BITMAP_CACHE_WIDTH]; 84}; 85 86 87 88 89/** 90 * Make fragment program for glBitmap: 91 * Sample the texture and kill the fragment if the bit is 0. 92 * This program will be combined with the user's fragment program. 93 */ 94static struct st_fragment_program * 95make_bitmap_fragment_program(GLcontext *ctx) 96{ 97 struct st_fragment_program *stfp; 98 struct gl_program *p; 99 GLuint ic = 0; 100 101 p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); 102 if (!p) 103 return NULL; 104 105 p->NumInstructions = 5; 106 107 p->Instructions = _mesa_alloc_instructions(p->NumInstructions); 108 if (!p->Instructions) { 109 ctx->Driver.DeleteProgram(ctx, p); 110 return NULL; 111 } 112 _mesa_init_instructions(p->Instructions, p->NumInstructions); 113 114 /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */ 115 p->Instructions[ic].Opcode = OPCODE_TEX; 116 p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY; 117 p->Instructions[ic].DstReg.Index = 0; 118 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; 119 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0; 120 p->Instructions[ic].TexSrcUnit = 0; 121 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX; 122 ic++; 123 124 /* SWZ tmp0.x, tmp0.x, 1111; # tmp0.x = 1.0 */ 125 p->Instructions[ic].Opcode = OPCODE_SWZ; 126 p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY; 127 p->Instructions[ic].DstReg.Index = 0; 128 p->Instructions[ic].DstReg.WriteMask = WRITEMASK_X; 129 p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY; 130 p->Instructions[ic].SrcReg[0].Index = 0; 131 p->Instructions[ic].SrcReg[0].Swizzle 132 = MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE ); 133 ic++; 134 135 /* SUB tmp0, tmp0.wwww, tmp0.xxxx; # tmp0.w -= 1 */ 136 p->Instructions[ic].Opcode = OPCODE_SUB; 137 p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY; 138 p->Instructions[ic].DstReg.Index = 0; 139 p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY; 140 p->Instructions[ic].SrcReg[0].Index = 0; 141 p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_WWWW; 142 p->Instructions[ic].SrcReg[1].File = PROGRAM_TEMPORARY; 143 p->Instructions[ic].SrcReg[1].Index = 0; 144 p->Instructions[ic].SrcReg[1].Swizzle = SWIZZLE_XXXX; /* 1.0 */ 145 ic++; 146 147 /* KIL if tmp0 < 0 */ 148 p->Instructions[ic].Opcode = OPCODE_KIL; 149 p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY; 150 p->Instructions[ic].SrcReg[0].Index = 0; 151 ic++; 152 153 /* END; */ 154 p->Instructions[ic++].Opcode = OPCODE_END; 155 156 assert(ic == p->NumInstructions); 157 158 p->InputsRead = FRAG_BIT_TEX0; 159 p->OutputsWritten = 0x0; 160 161 stfp = (struct st_fragment_program *) p; 162 stfp->Base.UsesKill = GL_TRUE; 163 st_translate_fragment_program(ctx->st, stfp, NULL); 164 165 return stfp; 166} 167 168 169/** 170 * Combine basic bitmap fragment program with the user-defined program. 171 */ 172static struct st_fragment_program * 173combined_bitmap_fragment_program(GLcontext *ctx) 174{ 175 struct st_context *st = ctx->st; 176 struct st_fragment_program *stfp; 177 178 if (!st->bitmap.program) { 179 /* create the basic bitmap fragment program */ 180 st->bitmap.program = make_bitmap_fragment_program(ctx); 181 } 182 183 if (st->bitmap.user_prog_sn == st->fp->serialNo) { 184 /* re-use */ 185 stfp = st->bitmap.combined_prog; 186 } 187 else { 188 /* Concatenate the bitmap program with the current user-defined program. 189 */ 190 stfp = (struct st_fragment_program *) 191 _mesa_combine_programs(ctx, 192 &st->bitmap.program->Base.Base, 193 &st->fp->Base.Base); 194 195#if 0 196 { 197 struct gl_program *p = &stfp->Base.Base; 198 printf("Combined bitmap program:\n"); 199 _mesa_print_program(p); 200 printf("InputsRead: 0x%x\n", p->InputsRead); 201 printf("OutputsWritten: 0x%x\n", p->OutputsWritten); 202 _mesa_print_parameter_list(p->Parameters); 203 } 204#endif 205 206 /* translate to TGSI tokens */ 207 st_translate_fragment_program(st, stfp, NULL); 208 209 /* save new program, update serial numbers */ 210 st->bitmap.user_prog_sn = st->fp->serialNo; 211 st->bitmap.combined_prog = stfp; 212 } 213 214 /* Ideally we'd have updated the pipe constants during the normal 215 * st/atom mechanism. But we can't since this is specific to glBitmap. 216 */ 217 st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); 218 219 return stfp; 220} 221 222 223/** 224 * Create a texture which represents a bitmap image. 225 */ 226static struct pipe_texture * 227make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height, 228 const struct gl_pixelstore_attrib *unpack, 229 const GLubyte *bitmap) 230{ 231 struct pipe_context *pipe = ctx->st->pipe; 232 struct pipe_screen *screen = pipe->screen; 233 struct pipe_surface *surface; 234 uint format = 0, cpp, comp; 235 ubyte *dest; 236 struct pipe_texture *pt; 237 int row, col; 238 239 /* find a texture format we know */ 240 if (screen->is_format_supported( screen, PIPE_FORMAT_U_I8, PIPE_TEXTURE )) { 241 format = PIPE_FORMAT_U_I8; 242 cpp = 1; 243 comp = 0; 244 } 245 else if (screen->is_format_supported( screen, PIPE_FORMAT_A8R8G8B8_UNORM, PIPE_TEXTURE )) { 246 format = PIPE_FORMAT_A8R8G8B8_UNORM; 247 cpp = 4; 248 comp = 3; /* alpha channel */ /*XXX little-endian dependency */ 249 } 250 else { 251 /* XXX support more formats */ 252 assert( 0 ); 253 } 254 255 /* PBO source... */ 256 bitmap = _mesa_map_bitmap_pbo(ctx, unpack, bitmap); 257 if (!bitmap) { 258 return NULL; 259 } 260 261 /** 262 * Create texture to hold bitmap pattern. 263 */ 264 pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0, width, height, 265 1, 0); 266 if (!pt) { 267 _mesa_unmap_bitmap_pbo(ctx, unpack); 268 return NULL; 269 } 270 271 surface = screen->get_tex_surface(screen, pt, 0, 0, 0); 272 273 /* map texture surface */ 274 dest = pipe_surface_map(surface); 275 276 /* Put image into texture surface. 277 * Note that the image is actually going to be upside down in 278 * the texture. We deal with that with texcoords. 279 */ 280 281 for (row = 0; row < height; row++) { 282 const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack, 283 bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0); 284 ubyte *destRow = dest + row * surface->pitch * cpp; 285 286 if (unpack->LsbFirst) { 287 /* Lsb first */ 288 GLubyte mask = 1U << (unpack->SkipPixels & 0x7); 289 for (col = 0; col < width; col++) { 290 291 /* set texel to 255 if bit is set */ 292 destRow[comp] = (*src & mask) ? 255 : 0; 293 destRow += cpp; 294 295 if (mask == 128U) { 296 src++; 297 mask = 1U; 298 } 299 else { 300 mask = mask << 1; 301 } 302 } 303 304 /* get ready for next row */ 305 if (mask != 1) 306 src++; 307 } 308 else { 309 /* Msb first */ 310 GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); 311 for (col = 0; col < width; col++) { 312 313 /* set texel to 255 if bit is set */ 314 destRow[comp] =(*src & mask) ? 255 : 0; 315 destRow += cpp; 316 317 if (mask == 1U) { 318 src++; 319 mask = 128U; 320 } 321 else { 322 mask = mask >> 1; 323 } 324 } 325 326 /* get ready for next row */ 327 if (mask != 128) 328 src++; 329 } 330 331 } /* row */ 332 333 _mesa_unmap_bitmap_pbo(ctx, unpack); 334 335 /* Release surface */ 336 pipe_surface_unmap(surface); 337 pipe_surface_reference(&surface, NULL); 338 pipe->texture_update(pipe, pt, 0, 0x1); 339 340 pt->format = format; 341 342 return pt; 343} 344 345 346static void 347setup_bitmap_vertex_data(struct st_context *st, 348 int x, int y, int width, int height, 349 float z, const float color[4]) 350{ 351 struct pipe_context *pipe = st->pipe; 352 const struct gl_framebuffer *fb = st->ctx->DrawBuffer; 353 const GLfloat fb_width = fb->Width; 354 const GLfloat fb_height = fb->Height; 355 const GLfloat x0 = x; 356 const GLfloat x1 = x + width; 357 const GLfloat y0 = y; 358 const GLfloat y1 = y + height; 359 const GLfloat bias = st->bitmap_texcoord_bias; 360 const GLfloat xBias = bias / (x1-x0); 361 const GLfloat yBias = bias / (y1-y0); 362 const GLfloat sLeft = 0.0 + xBias, sRight = 1.0 + xBias; 363 const GLfloat tTop = yBias, tBot = 1.0 - tTop - yBias; 364 const GLfloat clip_x0 = x0 / fb_width * 2.0 - 1.0; 365 const GLfloat clip_y0 = y0 / fb_height * 2.0 - 1.0; 366 const GLfloat clip_x1 = x1 / fb_width * 2.0 - 1.0; 367 const GLfloat clip_y1 = y1 / fb_height * 2.0 - 1.0; 368 GLuint i; 369 void *buf; 370 371 if (!st->bitmap.vbuf) { 372 st->bitmap.vbuf = pipe->winsys->buffer_create(pipe->winsys, 32, 373 PIPE_BUFFER_USAGE_VERTEX, 374 sizeof(st->bitmap.vertices)); 375 } 376 377 /* Positions are in clip coords since we need to do clipping in case 378 * the bitmap quad goes beyond the window bounds. 379 */ 380 st->bitmap.vertices[0][0][0] = clip_x0; 381 st->bitmap.vertices[0][0][1] = clip_y0; 382 st->bitmap.vertices[0][2][0] = sLeft; 383 st->bitmap.vertices[0][2][1] = tTop; 384 385 st->bitmap.vertices[1][0][0] = clip_x1; 386 st->bitmap.vertices[1][0][1] = clip_y0; 387 st->bitmap.vertices[1][2][0] = sRight; 388 st->bitmap.vertices[1][2][1] = tTop; 389 390 st->bitmap.vertices[2][0][0] = clip_x1; 391 st->bitmap.vertices[2][0][1] = clip_y1; 392 st->bitmap.vertices[2][2][0] = sRight; 393 st->bitmap.vertices[2][2][1] = tBot; 394 395 st->bitmap.vertices[3][0][0] = clip_x0; 396 st->bitmap.vertices[3][0][1] = clip_y1; 397 st->bitmap.vertices[3][2][0] = sLeft; 398 st->bitmap.vertices[3][2][1] = tBot; 399 400 /* same for all verts: */ 401 for (i = 0; i < 4; i++) { 402 st->bitmap.vertices[i][0][2] = z; 403 st->bitmap.vertices[i][0][3] = 1.0; 404 st->bitmap.vertices[i][1][0] = color[0]; 405 st->bitmap.vertices[i][1][1] = color[1]; 406 st->bitmap.vertices[i][1][2] = color[2]; 407 st->bitmap.vertices[i][1][3] = color[3]; 408 st->bitmap.vertices[i][2][2] = 0.0; /*R*/ 409 st->bitmap.vertices[i][2][3] = 1.0; /*Q*/ 410 } 411 412 /* put vertex data into vbuf */ 413 buf = pipe->winsys->buffer_map(pipe->winsys, st->bitmap.vbuf, 414 PIPE_BUFFER_USAGE_CPU_WRITE); 415 memcpy(buf, st->bitmap.vertices, sizeof(st->bitmap.vertices)); 416 pipe->winsys->buffer_unmap(pipe->winsys, st->bitmap.vbuf); 417} 418 419 420 421/** 422 * Render a glBitmap by drawing a textured quad 423 */ 424static void 425draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, 426 GLsizei width, GLsizei height, 427 struct pipe_texture *pt) 428{ 429 struct st_context *st = ctx->st; 430 struct pipe_context *pipe = ctx->st->pipe; 431 struct cso_context *cso = ctx->st->cso_context; 432 struct st_fragment_program *stfp; 433 GLuint maxSize; 434 435 stfp = combined_bitmap_fragment_program(ctx); 436 437 /* limit checks */ 438 /* XXX if the bitmap is larger than the max texture size, break 439 * it up into chunks. 440 */ 441 maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); 442 assert(width <= maxSize); 443 assert(height <= maxSize); 444 445 cso_save_rasterizer(cso); 446 cso_save_samplers(cso); 447 cso_save_viewport(cso); 448 449 /* rasterizer state: just scissor */ 450 st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled; 451 cso_set_rasterizer(cso, &st->bitmap.rasterizer); 452 453 /* fragment shader state: TEX lookup program */ 454 pipe->bind_fs_state(pipe, stfp->driver_shader); 455 456 /* vertex shader state: position + texcoord pass-through */ 457 pipe->bind_vs_state(pipe, st->bitmap.vs); 458 459 /* sampler / texture state */ 460 cso_single_sampler(cso, 0, &st->bitmap.sampler); 461 cso_single_sampler_done(cso); 462 pipe->set_sampler_textures(pipe, 1, &pt); 463 464 /* viewport state: viewport matching window dims */ 465 { 466 const struct gl_framebuffer *fb = st->ctx->DrawBuffer; 467 const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP); 468 const float width = fb->Width; 469 const float height = fb->Height; 470 struct pipe_viewport_state vp; 471 vp.scale[0] = 0.5 * width; 472 vp.scale[1] = height * (invert ? -0.5 : 0.5); 473 vp.scale[2] = 1.0; 474 vp.scale[3] = 1.0; 475 vp.translate[0] = 0.5 * width; 476 vp.translate[1] = 0.5 * height; 477 vp.translate[2] = 0.0; 478 vp.translate[3] = 0.0; 479 cso_set_viewport(cso, &vp); 480 } 481 482 /* draw textured quad */ 483 setup_bitmap_vertex_data(st, x, y, width, height, 484 ctx->Current.RasterPos[2], 485 ctx->Current.RasterColor); 486 487 util_draw_vertex_buffer(pipe, st->bitmap.vbuf, 488 PIPE_PRIM_TRIANGLE_FAN, 489 4, /* verts */ 490 3); /* attribs/vert */ 491 492 493 /* restore state */ 494 cso_restore_rasterizer(cso); 495 cso_restore_samplers(cso); 496 cso_restore_viewport(cso); 497 /* shaders don't go through cso yet */ 498 pipe->bind_fs_state(pipe, st->fp->driver_shader); 499 pipe->bind_vs_state(pipe, st->vp->driver_shader); 500 pipe->set_sampler_textures(pipe, ctx->st->state.num_textures, 501 ctx->st->state.sampler_texture); 502} 503 504 505static void 506reset_cache(struct st_context *st) 507{ 508 memset(st->bitmap.cache->buffer, 0, sizeof(st->bitmap.cache->buffer)); 509 st->bitmap.cache->empty = GL_TRUE; 510 511 st->bitmap.cache->xmin = 1000000; 512 st->bitmap.cache->xmax = -1000000; 513 st->bitmap.cache->ymin = 1000000; 514 st->bitmap.cache->ymax = -1000000; 515} 516 517 518static void 519init_bitmap_cache(struct st_context *st) 520{ 521 struct pipe_context *pipe = st->pipe; 522 struct pipe_screen *screen = pipe->screen; 523 enum pipe_format format; 524 525 st->bitmap.cache = CALLOC_STRUCT(bitmap_cache); 526 if (!st->bitmap.cache) 527 return; 528 529 /* find a usable texture format */ 530 if (screen->is_format_supported(screen, PIPE_FORMAT_U_I8, PIPE_TEXTURE)) { 531 format = PIPE_FORMAT_U_I8; 532 } 533 else { 534 /* XXX support more formats */ 535 assert(0); 536 } 537 538 st->bitmap.cache->texture 539 = st_texture_create(st, PIPE_TEXTURE_2D, format, 0, 540 BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, 1, 0); 541 if (!st->bitmap.cache->texture) { 542 FREE(st->bitmap.cache); 543 st->bitmap.cache = NULL; 544 return; 545 } 546 547 reset_cache(st); 548} 549 550 551/** 552 * If there's anything in the bitmap cache, draw/flush it now. 553 */ 554void 555st_flush_bitmap_cache(struct st_context *st) 556{ 557 if (!st->bitmap.cache->empty) { 558 struct bitmap_cache *cache = st->bitmap.cache; 559 struct pipe_context *pipe = st->pipe; 560 struct pipe_screen *screen = pipe->screen; 561 struct pipe_surface *surf; 562 void *dest; 563 564 assert(cache->xmin <= cache->xmax); 565 /* 566 printf("flush size %d x %d at %d, %d\n", 567 cache->xmax - cache->xmin, 568 cache->ymax - cache->ymin, 569 cache->xpos, cache->ypos); 570 */ 571 572 /* update the texture map image */ 573 surf = screen->get_tex_surface(screen, cache->texture, 0, 0, 0); 574 dest = pipe_surface_map(surf); 575 memcpy(dest, cache->buffer, sizeof(cache->buffer)); 576 pipe_surface_unmap(surf); 577 pipe_surface_reference(&surf, NULL); 578 579 pipe->texture_update(pipe, cache->texture, 0, 0x1); 580 581 draw_bitmap_quad(st->ctx, 582 cache->xpos, 583 cache->ypos, 584 st->ctx->Current.RasterPos[2], 585 BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, 586 cache->texture); 587 588 reset_cache(st); 589 } 590} 591 592 593/** 594 * Try to accumulate this glBitmap call in the bitmap cache. 595 * \return GL_TRUE for success, GL_FALSE if bitmap is too large, etc. 596 */ 597static GLboolean 598accum_bitmap(struct st_context *st, 599 GLint x, GLint y, GLsizei width, GLsizei height, 600 const struct gl_pixelstore_attrib *unpack, 601 const GLubyte *bitmap ) 602{ 603 struct bitmap_cache *cache = st->bitmap.cache; 604 int row, col; 605 int px = -999, py; 606 607 if (width > BITMAP_CACHE_WIDTH || 608 height > BITMAP_CACHE_HEIGHT) 609 return GL_FALSE; /* too big to cache */ 610 611 if (!cache->empty) { 612 px = x - cache->xpos; /* pos in buffer */ 613 py = y - cache->ypos; 614 if (px < 0 || px + width > BITMAP_CACHE_WIDTH || 615 py < 0 || py + height > BITMAP_CACHE_HEIGHT) { 616 /* This bitmap would extend beyond cache bounds, 617 * so flush and continue. 618 */ 619 st_flush_bitmap_cache(st); 620 } 621 } 622 623 if (cache->empty) { 624 /* Initialize. Center bitmap vertically in the buffer. */ 625 px = 0; 626 py = (BITMAP_CACHE_HEIGHT - height) / 2; 627 cache->xpos = x; 628 cache->ypos = y - py; 629 cache->empty = GL_FALSE; 630 } 631 632 assert(px != -999); 633 634 if (x < cache->xmin) 635 cache->xmin = x; 636 if (y < cache->ymin) 637 cache->ymin = y; 638 if (x + width > cache->xmax) 639 cache->xmax = x + width; 640 if (y + height > cache->ymax) 641 cache->ymax = y + height; 642 643 /* XXX try to combine this code with code in make_bitmap_texture() */ 644#define SET_PIXEL(COL, ROW) \ 645 cache->buffer[py + (ROW)][px + (COL)] = 0xff; 646 647 for (row = 0; row < height; row++) { 648 const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack, 649 bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0); 650 651 if (unpack->LsbFirst) { 652 /* Lsb first */ 653 GLubyte mask = 1U << (unpack->SkipPixels & 0x7); 654 for (col = 0; col < width; col++) { 655 656 if (*src & mask) { 657 SET_PIXEL(col, row); 658 } 659 660 if (mask == 128U) { 661 src++; 662 mask = 1U; 663 } 664 else { 665 mask = mask << 1; 666 } 667 } 668 669 /* get ready for next row */ 670 if (mask != 1) 671 src++; 672 } 673 else { 674 /* Msb first */ 675 GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); 676 for (col = 0; col < width; col++) { 677 678 if (*src & mask) { 679 SET_PIXEL(col, row); 680 } 681 682 if (mask == 1U) { 683 src++; 684 mask = 128U; 685 } 686 else { 687 mask = mask >> 1; 688 } 689 } 690 691 /* get ready for next row */ 692 if (mask != 128) 693 src++; 694 } 695 696 } /* row */ 697 698 return GL_TRUE; /* accumulated */ 699} 700 701 702 703/** 704 * Called via ctx->Driver.Bitmap() 705 */ 706static void 707st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, 708 const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) 709{ 710 struct st_context *st = ctx->st; 711 struct pipe_texture *pt; 712 713 st_validate_state(st); 714 715 if (!st->bitmap.vs) { 716 /* create pass-through vertex shader now */ 717 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, 718 TGSI_SEMANTIC_COLOR, 719 TGSI_SEMANTIC_GENERIC }; 720 const uint semantic_indexes[] = { 0, 0, 0 }; 721 st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3, 722 semantic_names, 723 semantic_indexes, 724 &st->bitmap.vert_shader); 725 } 726 727 if (UseBitmapCache && accum_bitmap(st, x, y, width, height, unpack, bitmap)) 728 return; 729 730 pt = make_bitmap_texture(ctx, width, height, unpack, bitmap); 731 if (pt) { 732 assert(pt->target == PIPE_TEXTURE_2D); 733 draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2], 734 width, height, pt); 735 pipe_texture_reference(&pt, NULL); 736 } 737} 738 739 740/** Per-context init */ 741void 742st_init_bitmap_functions(struct dd_function_table *functions) 743{ 744 functions->Bitmap = st_Bitmap; 745} 746 747 748/** Per-context init */ 749void 750st_init_bitmap(struct st_context *st) 751{ 752 struct pipe_sampler_state *sampler = &st->bitmap.sampler; 753 754 /* init sampler state once */ 755 memset(sampler, 0, sizeof(*sampler)); 756 sampler->wrap_s = PIPE_TEX_WRAP_CLAMP; 757 sampler->wrap_t = PIPE_TEX_WRAP_CLAMP; 758 sampler->wrap_r = PIPE_TEX_WRAP_CLAMP; 759 sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST; 760 sampler->min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 761 sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST; 762 sampler->normalized_coords = 1; 763 764 /* init scissor state once */ 765 memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer)); 766 767 init_bitmap_cache(st); 768} 769 770 771/** Per-context tear-down */ 772void 773st_destroy_bitmap(struct st_context *st) 774{ 775 struct pipe_context *pipe = st->pipe; 776 777 if (st->bitmap.combined_prog) { 778 st_delete_program(st->ctx, &st->bitmap.combined_prog->Base.Base); 779 } 780 781 if (st->bitmap.program) { 782 st_delete_program(st->ctx, &st->bitmap.program->Base.Base); 783 } 784 785 if (st->bitmap.vs) { 786 pipe->delete_vs_state(pipe, st->bitmap.vs); 787 st->bitmap.vs = NULL; 788 } 789 790 if (st->bitmap.vbuf) { 791 pipe->winsys->buffer_destroy(pipe->winsys, st->bitmap.vbuf); 792 st->bitmap.vbuf = NULL; 793 } 794 795 if (st->bitmap.cache) { 796 pipe_texture_release(&st->bitmap.cache->texture); 797 FREE(st->bitmap.cache); 798 st->bitmap.cache = NULL; 799 } 800} 801