gallium: use cso_save/restore_sampler_textures() functions
[mesa.git] / src / mesa / state_tracker / st_cb_bitmap.c
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 */
68 static GLboolean UseBitmapCache = GL_TRUE;
69
70
71 #define BITMAP_CACHE_WIDTH 512
72 #define BITMAP_CACHE_HEIGHT 32
73
74 struct 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 */
94 static struct st_fragment_program *
95 make_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 */
172 static struct st_fragment_program *
173 combined_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 */
226 static struct pipe_texture *
227 make_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
346 static void
347 setup_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 */
424 static void
425 draw_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_sampler_textures(cso);
448 cso_save_viewport(cso);
449
450 /* rasterizer state: just scissor */
451 st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled;
452 cso_set_rasterizer(cso, &st->bitmap.rasterizer);
453
454 /* fragment shader state: TEX lookup program */
455 pipe->bind_fs_state(pipe, stfp->driver_shader);
456
457 /* vertex shader state: position + texcoord pass-through */
458 pipe->bind_vs_state(pipe, st->bitmap.vs);
459
460 /* sampler / texture state */
461 cso_single_sampler(cso, 0, &st->bitmap.sampler);
462 cso_single_sampler_done(cso);
463 pipe->set_sampler_textures(pipe, 1, &pt);
464
465 /* viewport state: viewport matching window dims */
466 {
467 const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
468 const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
469 const float width = fb->Width;
470 const float height = fb->Height;
471 struct pipe_viewport_state vp;
472 vp.scale[0] = 0.5 * width;
473 vp.scale[1] = height * (invert ? -0.5 : 0.5);
474 vp.scale[2] = 1.0;
475 vp.scale[3] = 1.0;
476 vp.translate[0] = 0.5 * width;
477 vp.translate[1] = 0.5 * height;
478 vp.translate[2] = 0.0;
479 vp.translate[3] = 0.0;
480 cso_set_viewport(cso, &vp);
481 }
482
483 /* draw textured quad */
484 setup_bitmap_vertex_data(st, x, y, width, height,
485 ctx->Current.RasterPos[2],
486 ctx->Current.RasterColor);
487
488 util_draw_vertex_buffer(pipe, st->bitmap.vbuf,
489 PIPE_PRIM_TRIANGLE_FAN,
490 4, /* verts */
491 3); /* attribs/vert */
492
493
494 /* restore state */
495 cso_restore_rasterizer(cso);
496 cso_restore_samplers(cso);
497 cso_restore_sampler_textures(cso);
498 cso_restore_viewport(cso);
499 /* shaders don't go through cso yet */
500 pipe->bind_fs_state(pipe, st->fp->driver_shader);
501 pipe->bind_vs_state(pipe, st->vp->driver_shader);
502 }
503
504
505 static void
506 reset_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
518 static void
519 init_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 */
554 void
555 st_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 */
597 static GLboolean
598 accum_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 */
706 static void
707 st_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 */
741 void
742 st_init_bitmap_functions(struct dd_function_table *functions)
743 {
744 functions->Bitmap = st_Bitmap;
745 }
746
747
748 /** Per-context init */
749 void
750 st_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 baseline rasterizer state once */
765 memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer));
766 st->bitmap.rasterizer.bypass_vs = 1;
767
768 init_bitmap_cache(st);
769 }
770
771
772 /** Per-context tear-down */
773 void
774 st_destroy_bitmap(struct st_context *st)
775 {
776 struct pipe_context *pipe = st->pipe;
777
778 if (st->bitmap.combined_prog) {
779 st_delete_program(st->ctx, &st->bitmap.combined_prog->Base.Base);
780 }
781
782 if (st->bitmap.program) {
783 st_delete_program(st->ctx, &st->bitmap.program->Base.Base);
784 }
785
786 if (st->bitmap.vs) {
787 pipe->delete_vs_state(pipe, st->bitmap.vs);
788 st->bitmap.vs = NULL;
789 }
790
791 if (st->bitmap.vbuf) {
792 pipe->winsys->buffer_destroy(pipe->winsys, st->bitmap.vbuf);
793 st->bitmap.vbuf = NULL;
794 }
795
796 if (st->bitmap.cache) {
797 pipe_texture_release(&st->bitmap.cache->texture);
798 FREE(st->bitmap.cache);
799 st->bitmap.cache = NULL;
800 }
801 }