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