remove #include vf.h
[mesa.git] / src / mesa / state_tracker / st_cb_drawpixels.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/macros.h"
36
37 #include "st_context.h"
38 #include "st_atom.h"
39 #include "st_cache.h"
40 #include "st_draw.h"
41 #include "st_program.h"
42 #include "st_cb_drawpixels.h"
43 #include "st_cb_texture.h"
44 #include "st_draw.h"
45 #include "st_format.h"
46 #include "pipe/p_context.h"
47 #include "pipe/p_defines.h"
48 #include "pipe/tgsi/mesa/mesa_to_tgsi.h"
49 #include "shader/prog_instruction.h"
50
51
52
53 /**
54 * Create a simple fragment shader that does a TEX() instruction to get
55 * the fragment color.
56 */
57 static struct st_fragment_program *
58 make_fragment_shader(struct st_context *st, GLboolean bitmapMode)
59 {
60 GLcontext *ctx = st->ctx;
61 struct st_fragment_program *stfp;
62 struct gl_program *p;
63 GLuint ic = 0;
64
65 p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
66 if (!p)
67 return NULL;
68
69 if (bitmapMode)
70 p->NumInstructions = 6;
71 else
72 p->NumInstructions = 2;
73
74 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
75 if (!p->Instructions) {
76 ctx->Driver.DeleteProgram(ctx, p);
77 return NULL;
78 }
79 _mesa_init_instructions(p->Instructions, p->NumInstructions);
80 if (bitmapMode) {
81 /*
82 * XXX, we need to compose this fragment shader with the current
83 * user-provided fragment shader so the fragment program is applied
84 * to the fragments which aren't culled.
85 */
86 /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
87 p->Instructions[ic].Opcode = OPCODE_TEX;
88 p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
89 p->Instructions[ic].DstReg.Index = 0;
90 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
91 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
92 p->Instructions[ic].TexSrcUnit = 0;
93 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
94 ic++;
95
96 /* SWZ tmp0.x, tmp0.x, 1111; # tmp0.x = 1.0 */
97 p->Instructions[ic].Opcode = OPCODE_SWZ;
98 p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
99 p->Instructions[ic].DstReg.Index = 0;
100 p->Instructions[ic].DstReg.WriteMask = WRITEMASK_X;
101 p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
102 p->Instructions[ic].SrcReg[0].Index = 0;
103 p->Instructions[ic].SrcReg[0].Swizzle
104 = MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE );
105 ic++;
106
107 /* SUB tmp0, tmp0.wwww, tmp0.xxxx; # tmp0.w -= 1 */
108 p->Instructions[ic].Opcode = OPCODE_SUB;
109 p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
110 p->Instructions[ic].DstReg.Index = 0;
111 p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
112 p->Instructions[ic].SrcReg[0].Index = 0;
113 p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_WWWW;
114 p->Instructions[ic].SrcReg[1].File = PROGRAM_TEMPORARY;
115 p->Instructions[ic].SrcReg[1].Index = 0;
116 p->Instructions[ic].SrcReg[1].Swizzle = SWIZZLE_XXXX; /* 1.0 */
117 ic++;
118
119 /* KIL if tmp0 < 0 */
120 p->Instructions[ic].Opcode = OPCODE_KIL;
121 p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
122 p->Instructions[ic].SrcReg[0].Index = 0;
123 ic++;
124
125 /* MOV result.color, fragment.color */
126 p->Instructions[ic].Opcode = OPCODE_MOV;
127 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
128 p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLR;
129 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
130 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0;
131 ic++;
132 }
133 else {
134 /* DrawPixels mode */
135 /* TEX result.color, fragment.texcoord[0], texture[0], 2D; */
136 p->Instructions[ic].Opcode = OPCODE_TEX;
137 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
138 p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLR;
139 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
140 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
141 p->Instructions[ic].TexSrcUnit = 0;
142 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
143 ic++;
144 }
145 /* END; */
146 p->Instructions[ic++].Opcode = OPCODE_END;
147
148 assert(ic == p->NumInstructions);
149
150 p->InputsRead = FRAG_BIT_TEX0;
151 p->OutputsWritten = (1 << FRAG_RESULT_COLR);
152 if (bitmapMode) {
153 p->InputsRead |= FRAG_BIT_COL0;
154 }
155
156 stfp = (struct st_fragment_program *) p;
157 st_translate_fragment_program(st, stfp, NULL,
158 stfp->tokens, ST_MAX_SHADER_TOKENS);
159
160 return stfp;
161 }
162
163
164 /**
165 * Create fragment shader that does a TEX() instruction to get a Z
166 * value, then writes to FRAG_RESULT_DEPR.
167 */
168 static struct st_fragment_program *
169 make_fragment_shader_z(struct st_context *st)
170 {
171 GLcontext *ctx = st->ctx;
172 struct st_fragment_program *stfp;
173 struct gl_program *p;
174 GLuint ic = 0;
175
176 p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
177 if (!p)
178 return NULL;
179
180 p->NumInstructions = 3;
181
182 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
183 if (!p->Instructions) {
184 ctx->Driver.DeleteProgram(ctx, p);
185 return NULL;
186 }
187 _mesa_init_instructions(p->Instructions, p->NumInstructions);
188
189 /* TEX result.color, fragment.texcoord[0], texture[0], 2D; */
190 p->Instructions[ic].Opcode = OPCODE_TEX;
191 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
192 p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPR;
193 p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z;
194 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
195 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
196 p->Instructions[ic].TexSrcUnit = 0;
197 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
198 ic++;
199
200 /* MOV result.color, fragment.color */
201 p->Instructions[ic].Opcode = OPCODE_MOV;
202 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
203 p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLR;
204 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
205 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0;
206 ic++;
207
208 /* END; */
209 p->Instructions[ic++].Opcode = OPCODE_END;
210
211 assert(ic == p->NumInstructions);
212
213 p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
214 p->OutputsWritten = (1 << FRAG_RESULT_COLR) | (1 << FRAG_RESULT_DEPR);
215
216 stfp = (struct st_fragment_program *) p;
217 st_translate_fragment_program(st, stfp, NULL,
218 stfp->tokens, ST_MAX_SHADER_TOKENS);
219
220 return stfp;
221 }
222
223
224
225 /**
226 * Create a simple vertex shader that just passes through the
227 * vertex position and texcoord (and color).
228 */
229 static struct st_vertex_program *
230 make_vertex_shader(struct st_context *st, GLboolean passColor)
231 {
232 GLcontext *ctx = st->ctx;
233 struct st_vertex_program *stvp;
234 struct gl_program *p;
235 GLuint ic = 0;
236
237 p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
238 if (!p)
239 return NULL;
240
241 if (passColor)
242 p->NumInstructions = 4;
243 else
244 p->NumInstructions = 3;
245
246 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
247 if (!p->Instructions) {
248 ctx->Driver.DeleteProgram(ctx, p);
249 return NULL;
250 }
251 _mesa_init_instructions(p->Instructions, p->NumInstructions);
252 /* MOV result.pos, vertex.pos; */
253 p->Instructions[0].Opcode = OPCODE_MOV;
254 p->Instructions[0].DstReg.File = PROGRAM_OUTPUT;
255 p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS;
256 p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT;
257 p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS;
258 /* MOV result.texcoord0, vertex.texcoord0; */
259 p->Instructions[1].Opcode = OPCODE_MOV;
260 p->Instructions[1].DstReg.File = PROGRAM_OUTPUT;
261 p->Instructions[1].DstReg.Index = VERT_RESULT_TEX0;
262 p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT;
263 p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_TEX0;
264 ic = 2;
265 if (passColor) {
266 /* MOV result.color0, vertex.color0; */
267 p->Instructions[ic].Opcode = OPCODE_MOV;
268 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
269 p->Instructions[ic].DstReg.Index = VERT_RESULT_COL0;
270 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
271 p->Instructions[ic].SrcReg[0].Index = VERT_ATTRIB_COLOR0;
272 ic++;
273 }
274
275 /* END; */
276 p->Instructions[ic].Opcode = OPCODE_END;
277 ic++;
278
279 assert(ic == p->NumInstructions);
280
281 p->InputsRead = VERT_BIT_POS | VERT_BIT_TEX0;
282 p->OutputsWritten = ((1 << VERT_RESULT_TEX0) |
283 (1 << VERT_RESULT_HPOS));
284 if (passColor) {
285 p->InputsRead |= VERT_BIT_COLOR0;
286 p->OutputsWritten |= (1 << VERT_RESULT_COL0);
287 }
288
289 stvp = (struct st_vertex_program *) p;
290 st_translate_vertex_program(st, stvp, NULL,
291 stvp->tokens, ST_MAX_SHADER_TOKENS);
292
293 return stvp;
294 }
295
296
297 static GLenum
298 _mesa_base_format(GLenum format)
299 {
300 switch (format) {
301 case GL_DEPTH_COMPONENT:
302 return GL_DEPTH_COMPONENT;
303 case GL_STENCIL_INDEX:
304 return GL_STENCIL_INDEX;
305 default:
306 return GL_RGBA;
307 }
308 }
309
310
311
312 /**
313 * Make mipmap tree containing the glDrawPixels image.
314 */
315 static struct pipe_mipmap_tree *
316 make_mipmap_tree(struct st_context *st,
317 GLsizei width, GLsizei height, GLenum format, GLenum type,
318 const struct gl_pixelstore_attrib *unpack,
319 const GLvoid *pixels)
320 {
321 struct pipe_context *pipe = st->pipe;
322 const struct gl_texture_format *mformat;
323 const GLbitfield flags = PIPE_SURFACE_FLAG_TEXTURE;
324 struct pipe_mipmap_tree *mt;
325 GLuint pipeFormat, cpp;
326 GLenum baseFormat;
327
328 baseFormat = _mesa_base_format(format);
329
330 mformat = st_ChooseTextureFormat(st->ctx, baseFormat, format, type);
331 assert(mformat);
332
333 pipeFormat = st_mesa_format_to_pipe_format(mformat->MesaFormat);
334 assert(pipeFormat);
335 cpp = st_sizeof_format(pipeFormat);
336
337 mt = CALLOC_STRUCT(pipe_mipmap_tree);
338 if (!mt)
339 return NULL;
340
341 if (unpack->BufferObj && unpack->BufferObj->Name) {
342 /*
343 mt->region = buffer_object_region(unpack->BufferObj);
344 */
345 printf("st_DrawPixels (sourcing from PBO not implemented yet)\n");
346 }
347 else {
348 static const GLuint dstImageOffsets = 0;
349 GLboolean success;
350 GLubyte *dest;
351 GLuint pitch;
352
353 /* allocate texture region/storage */
354 mt->region = st->pipe->region_alloc(st->pipe, cpp, width, height, flags);
355 pitch = mt->region->pitch;
356
357 /* map texture region */
358 dest = pipe->region_map(pipe, mt->region);
359
360 /* Put image into texture region.
361 * Note that the image is actually going to be upside down in
362 * the texture. We deal with that with texcoords.
363 */
364 success = mformat->StoreImage(st->ctx, 2, /* dims */
365 baseFormat, /* baseInternalFormat */
366 mformat, /* gl_texture_format */
367 dest, /* dest */
368 0, 0, 0, /* dstX/Y/Zoffset */
369 pitch * cpp, /* dstRowStride, bytes */
370 &dstImageOffsets, /* dstImageOffsets */
371 width, height, 1, /* size */
372 format, type, /* src format/type */
373 pixels, /* data source */
374 unpack);
375
376 /* unmap */
377 pipe->region_unmap(pipe, mt->region);
378
379 assert(success);
380 }
381
382 mt->target = PIPE_TEXTURE_2D;
383 mt->internal_format = GL_RGBA;
384 mt->format = pipeFormat;
385 mt->first_level = 0;
386 mt->last_level = 0;
387 mt->width0 = width;
388 mt->height0 = height;
389 mt->depth0 = 1;
390 mt->cpp = cpp;
391 mt->compressed = 0;
392 mt->pitch = mt->region->pitch;
393 mt->depth_pitch = 0;
394 mt->total_height = height;
395 mt->level[0].level_offset = 0;
396 mt->level[0].width = width;
397 mt->level[0].height = height;
398 mt->level[0].depth = 1;
399 mt->level[0].nr_images = 1;
400 mt->level[0].image_offset = NULL;
401 mt->refcount = 1;
402
403 return mt;
404 }
405
406
407 static void
408 free_mipmap_tree(struct pipe_context *pipe, struct pipe_mipmap_tree *mt)
409 {
410 pipe->region_release(pipe, &mt->region);
411 free(mt);
412 }
413
414
415 /**
416 * Draw textured quad.
417 * Coords are window coords with y=0=bottom.
418 */
419 static void
420 draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
421 GLfloat x1, GLfloat y1)
422 {
423 GLfloat verts[4][2][4]; /* four verts, two attribs, XYZW */
424 GLuint i;
425
426 /* upper-left */
427 verts[0][0][0] = x0; /* attr[0].x */
428 verts[0][0][1] = y0; /* attr[0].x */
429 verts[0][1][0] = 0.0; /* attr[1].s */
430 verts[0][1][1] = 0.0; /* attr[1].t */
431
432 /* upper-right */
433 verts[1][0][0] = x1;
434 verts[1][0][1] = y0;
435 verts[1][1][0] = 1.0;
436 verts[1][1][1] = 0.0;
437
438 /* lower-right */
439 verts[2][0][0] = x1;
440 verts[2][0][1] = y1;
441 verts[2][1][0] = 1.0;
442 verts[2][1][1] = 1.0;
443
444 /* lower-left */
445 verts[3][0][0] = x0;
446 verts[3][0][1] = y1;
447 verts[3][1][0] = 0.0;
448 verts[3][1][1] = 1.0;
449
450 /* same for all verts: */
451 for (i = 0; i < 4; i++) {
452 verts[i][0][2] = z; /*Z*/
453 verts[i][0][3] = 1.0; /*W*/
454 verts[i][1][2] = 0.0; /*R*/
455 verts[i][1][3] = 1.0; /*Q*/
456 }
457
458 st_draw_vertices(ctx, PIPE_PRIM_QUADS, 4, (float *) verts, 2);
459 }
460
461
462 static void
463 draw_quad_colored(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
464 GLfloat x1, GLfloat y1, const GLfloat *color)
465 {
466 GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */
467 GLuint i;
468
469 /* upper-left */
470 verts[0][0][0] = x0; /* attr[0].x */
471 verts[0][0][1] = y0; /* attr[0].x */
472 verts[0][2][0] = 0.0; /* attr[2].s */
473 verts[0][2][1] = 0.0; /* attr[2].t */
474
475 /* upper-right */
476 verts[1][0][0] = x1;
477 verts[1][0][1] = y0;
478 verts[1][2][0] = 1.0;
479 verts[1][2][1] = 0.0;
480
481 /* lower-right */
482 verts[2][0][0] = x1;
483 verts[2][0][1] = y1;
484 verts[2][2][0] = 1.0;
485 verts[2][2][1] = 1.0;
486
487 /* lower-left */
488 verts[3][0][0] = x0;
489 verts[3][0][1] = y1;
490 verts[3][2][0] = 0.0;
491 verts[3][2][1] = 1.0;
492
493 /* same for all verts: */
494 for (i = 0; i < 4; i++) {
495 verts[i][0][2] = z; /*Z*/
496 verts[i][0][3] = 1.0; /*W*/
497 verts[i][1][0] = color[0];
498 verts[i][1][1] = color[1];
499 verts[i][1][2] = color[2];
500 verts[i][1][3] = color[3];
501 verts[i][2][2] = 0.0; /*R*/
502 verts[i][2][3] = 1.0; /*Q*/
503 }
504
505 st_draw_vertices(ctx, PIPE_PRIM_QUADS, 4, (float *) verts, 3);
506 }
507
508
509
510 static void
511 draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
512 GLsizei width, GLsizei height,
513 GLfloat zoomX, GLfloat zoomY,
514 struct pipe_mipmap_tree *mt,
515 struct st_vertex_program *stvp,
516 struct st_fragment_program *stfp,
517 const GLfloat *color)
518 {
519 const GLuint unit = 0;
520 struct pipe_context *pipe = ctx->st->pipe;
521 GLfloat x0, y0, x1, y1;
522 GLuint maxWidth, maxHeight;
523
524 /* limit checks */
525 /* XXX if DrawPixels image is larger than max texture size, break
526 * it up into chunks.
527 */
528 pipe->max_texture_size(pipe, PIPE_TEXTURE_2D, &maxWidth, &maxHeight, NULL);
529 assert(width <= maxWidth);
530 assert(height <= maxHeight);
531
532 /* setup state: just scissor */
533 {
534 struct pipe_rasterizer_state setup;
535 const struct cso_rasterizer *cso;
536 memset(&setup, 0, sizeof(setup));
537 if (ctx->Scissor.Enabled)
538 setup.scissor = 1;
539 cso = st_cached_rasterizer_state(ctx->st, &setup);
540 pipe->bind_rasterizer_state(pipe, cso->data);
541 }
542
543 /* fragment shader state: TEX lookup program */
544 pipe->bind_fs_state(pipe, stfp->fs->data);
545
546 /* vertex shader state: position + texcoord pass-through */
547 pipe->bind_vs_state(pipe, stvp->vs->data);
548
549 /* texture sampling state: */
550 {
551 struct pipe_sampler_state sampler;
552 const struct cso_sampler *cso;
553 memset(&sampler, 0, sizeof(sampler));
554 sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
555 sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
556 sampler.wrap_r = PIPE_TEX_WRAP_REPEAT;
557 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
558 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
559 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
560 sampler.normalized_coords = 1;
561 cso = st_cached_sampler_state(ctx->st, &sampler);
562 pipe->bind_sampler_state(pipe, unit, cso->data);
563 }
564
565 /* viewport state: viewport matching window dims */
566 {
567 const float width = ctx->DrawBuffer->Width;
568 const float height = ctx->DrawBuffer->Height;
569 struct pipe_viewport_state vp;
570 vp.scale[0] = 0.5 * width;
571 vp.scale[1] = -0.5 * height;
572 vp.scale[2] = 1.0;
573 vp.scale[3] = 1.0;
574 vp.translate[0] = 0.5 * width;
575 vp.translate[1] = 0.5 * height;
576 vp.translate[2] = 0.0;
577 vp.translate[3] = 0.0;
578 pipe->set_viewport_state(pipe, &vp);
579 }
580
581 /* mipmap tree state: */
582 {
583 pipe->set_texture_state(pipe, unit, mt);
584 }
585
586 /* Compute window coords (y=0=bottom) with pixel zoom.
587 * Recall that these coords are transformed by the current
588 * vertex shader and viewport transformation.
589 */
590 x0 = x;
591 x1 = x + width * ctx->Pixel.ZoomX;
592 y0 = y;
593 y1 = y + height * ctx->Pixel.ZoomY;
594
595 /* draw textured quad */
596 if (color)
597 draw_quad_colored(ctx, x0, y0, z, x1, y1, color);
598 else
599 draw_quad(ctx, x0, y0, z, x1, y1);
600
601 /* restore GL state */
602 pipe->bind_rasterizer_state(pipe, ctx->st->state.rasterizer->data);
603 pipe->bind_fs_state(pipe, ctx->st->state.fs->data);
604 pipe->bind_vs_state(pipe, ctx->st->state.vs->data);
605 pipe->set_texture_state(pipe, unit, ctx->st->state.texture[unit]);
606 pipe->bind_sampler_state(pipe, unit, ctx->st->state.sampler[unit]->data);
607 pipe->set_viewport_state(pipe, &ctx->st->state.viewport);
608 }
609
610
611 /**
612 * Check if a GL format/type combination is a match to the given pipe format.
613 * XXX probably move this to a re-usable place.
614 */
615 static GLboolean
616 compatible_formats(GLenum format, GLenum type, GLuint pipeFormat)
617 {
618 static const GLuint one = 1;
619 GLubyte littleEndian = *((GLubyte *) &one);
620
621 if (pipeFormat == PIPE_FORMAT_U_R8_G8_B8_A8 &&
622 format == GL_RGBA &&
623 type == GL_UNSIGNED_BYTE &&
624 !littleEndian) {
625 return GL_TRUE;
626 }
627 else if (pipeFormat == PIPE_FORMAT_U_R8_G8_B8_A8 &&
628 format == GL_ABGR_EXT &&
629 type == GL_UNSIGNED_BYTE &&
630 littleEndian) {
631 return GL_TRUE;
632 }
633 else if (pipeFormat == PIPE_FORMAT_U_A8_R8_G8_B8 &&
634 format == GL_BGRA &&
635 type == GL_UNSIGNED_BYTE &&
636 littleEndian) {
637 return GL_TRUE;
638 }
639 else if (pipeFormat == PIPE_FORMAT_U_R5_G6_B5 &&
640 format == GL_RGB &&
641 type == GL_UNSIGNED_SHORT_5_6_5) {
642 /* endian don't care */
643 return GL_TRUE;
644 }
645 else if (pipeFormat == PIPE_FORMAT_U_R5_G6_B5 &&
646 format == GL_BGR &&
647 type == GL_UNSIGNED_SHORT_5_6_5_REV) {
648 /* endian don't care */
649 return GL_TRUE;
650 }
651 else if (pipeFormat == PIPE_FORMAT_U_S8 &&
652 format == GL_STENCIL_INDEX &&
653 type == GL_UNSIGNED_BYTE) {
654 return GL_TRUE;
655 }
656 else if (pipeFormat == PIPE_FORMAT_U_Z32 &&
657 format == GL_DEPTH_COMPONENT &&
658 type == GL_UNSIGNED_INT) {
659 return GL_TRUE;
660 }
661 /* XXX add more cases */
662 else {
663 return GL_FALSE;
664 }
665 }
666
667
668 /**
669 * Check if any per-fragment ops are enabled.
670 * XXX probably move this to a re-usable place.
671 */
672 static GLboolean
673 any_fragment_ops(const struct st_context *st)
674 {
675 if (st->state.alpha_test->state.enabled ||
676 st->state.blend->state.blend_enable ||
677 st->state.blend->state.logicop_enable ||
678 st->state.depth_stencil->state.depth.enabled)
679 /* XXX more checks */
680 return GL_TRUE;
681 else
682 return GL_FALSE;
683 }
684
685
686 /**
687 * Check if any pixel transfer ops are enabled.
688 * XXX probably move this to a re-usable place.
689 */
690 static GLboolean
691 any_pixel_transfer_ops(const struct st_context *st)
692 {
693 if (st->ctx->Pixel.RedScale != 1.0 ||
694 st->ctx->Pixel.RedBias != 0.0 ||
695 st->ctx->Pixel.GreenScale != 1.0 ||
696 st->ctx->Pixel.GreenBias != 0.0 ||
697 st->ctx->Pixel.BlueScale != 1.0 ||
698 st->ctx->Pixel.BlueBias != 0.0 ||
699 st->ctx->Pixel.AlphaScale != 1.0 ||
700 st->ctx->Pixel.AlphaBias != 0.0 ||
701 st->ctx->Pixel.MapColorFlag)
702 /* XXX more checks */
703 return GL_TRUE;
704 else
705 return GL_FALSE;
706 }
707
708
709 /**
710 * Draw image with a blit, or other non-textured quad method.
711 */
712 static void
713 draw_blit(struct st_context *st,
714 GLsizei width, GLsizei height,
715 GLenum format, GLenum type, const GLvoid *pixels)
716 {
717
718
719 }
720
721
722 static void
723 draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
724 GLsizei width, GLsizei height, GLenum type,
725 const struct gl_pixelstore_attrib *unpack,
726 const GLvoid *pixels)
727 {
728 struct st_context *st = ctx->st;
729 struct pipe_context *pipe = st->pipe;
730 struct pipe_surface *ps = st->state.framebuffer.sbuf;
731 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
732 GLint skipPixels;
733 ubyte *stmap;
734
735 /* map the stencil buffer */
736 stmap = pipe->region_map(pipe, ps->region);
737
738 /* if width > MAX_WIDTH, have to process image in chunks */
739 skipPixels = 0;
740 while (skipPixels < width) {
741 const GLint spanX = x + skipPixels;
742 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
743 GLint row;
744 for (row = 0; row < height; row++) {
745 GLint spanY = y + row;
746 GLubyte values[MAX_WIDTH];
747 GLenum destType = GL_UNSIGNED_BYTE;
748 const GLvoid *source = _mesa_image_address2d(unpack, pixels,
749 width, height,
750 GL_COLOR_INDEX, type,
751 row, skipPixels);
752 _mesa_unpack_stencil_span(ctx, spanWidth, destType, values,
753 type, source, unpack,
754 ctx->_ImageTransferState);
755 if (zoom) {
756 /*
757 _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth,
758 spanX, spanY, values);
759 */
760 }
761 else {
762 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
763 spanY = ctx->DrawBuffer->Height - spanY - 1;
764 }
765
766 switch (ps->format) {
767 case PIPE_FORMAT_U_S8:
768 {
769 ubyte *dest = stmap + spanY * ps->region->pitch + spanX;
770 memcpy(dest, values, spanWidth);
771 }
772 break;
773 case PIPE_FORMAT_S8_Z24:
774 {
775 uint *dest = (uint *) stmap + spanY * ps->region->pitch + spanX;
776 GLint k;
777 for (k = 0; k < spanWidth; k++) {
778 uint p = dest[k];
779 p = (p & 0xffffff) | (values[k] << 24);
780 dest[k] = p;
781 }
782 }
783 break;
784 default:
785 assert(0);
786 }
787 }
788 }
789 skipPixels += spanWidth;
790 }
791
792 /* unmap the stencil buffer */
793 pipe->region_unmap(pipe, ps->region);
794 }
795
796
797 /**
798 * Called via ctx->Driver.DrawPixels()
799 */
800 static void
801 st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
802 GLenum format, GLenum type,
803 const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
804 {
805 static struct st_fragment_program *stfp_c = NULL; /* color */
806 static struct st_fragment_program *stfp_z = NULL; /* z */
807 static struct st_vertex_program *stvp_t = NULL; /* just emit texcoord */
808 static struct st_vertex_program *stvp_c = NULL; /* emit color too */
809 struct st_fragment_program *stfp;
810 struct st_vertex_program *stvp;
811 struct st_context *st = ctx->st;
812 struct pipe_surface *ps;
813 GLuint bufferFormat;
814 const GLfloat *color;
815
816 if (format == GL_STENCIL_INDEX) {
817 draw_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels);
818 return;
819 }
820
821 /* create the fragment programs if needed */
822 if (!stfp_c) {
823 stfp_c = make_fragment_shader(ctx->st, GL_FALSE);
824 }
825 if (!stfp_z) {
826 stfp_z = make_fragment_shader_z(ctx->st);
827 }
828
829 /* and vertex programs */
830 if (!stvp_t) {
831 stvp_t = make_vertex_shader(ctx->st, GL_FALSE);
832 }
833 if (!stvp_c) {
834 stvp_c = make_vertex_shader(ctx->st, GL_TRUE);
835 }
836
837 st_validate_state(st);
838
839 if (format == GL_DEPTH_COMPONENT) {
840 ps = st->state.framebuffer.zbuf;
841 stfp = stfp_z;
842 stvp = stvp_c;
843 color = ctx->Current.RasterColor;
844 }
845 else if (format == GL_STENCIL_INDEX) {
846 ps = st->state.framebuffer.sbuf;
847 /* XXX special case - can't use texture map */
848 color = NULL;
849 }
850 else {
851 ps = st->state.framebuffer.cbufs[0];
852 stfp = stfp_c;
853 stvp = stvp_t;
854 color = NULL;
855 }
856
857 bufferFormat = ps->format;
858
859 if (any_fragment_ops(st) ||
860 any_pixel_transfer_ops(st) ||
861 !compatible_formats(format, type, ps->format)) {
862 /* textured quad */
863 struct pipe_mipmap_tree *mt
864 = make_mipmap_tree(ctx->st, width, height, format, type,
865 unpack, pixels);
866 if (mt) {
867 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
868 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
869 mt, stvp, stfp, color);
870 free_mipmap_tree(st->pipe, mt);
871 }
872 }
873 else {
874 /* blit */
875 draw_blit(st, width, height, format, type, pixels);
876 }
877 }
878
879
880
881 /**
882 * Create a texture which represents a bitmap image.
883 */
884 static struct pipe_mipmap_tree *
885 make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
886 const struct gl_pixelstore_attrib *unpack,
887 const GLubyte *bitmap)
888 {
889 struct pipe_context *pipe = ctx->st->pipe;
890 const uint flags = PIPE_SURFACE_FLAG_TEXTURE;
891 uint numFormats, i, format = 0, cpp, comp, pitch;
892 const uint *formats = ctx->st->pipe->supported_formats(pipe, &numFormats);
893 ubyte *dest;
894 struct pipe_mipmap_tree *mt;
895 int row, col;
896
897 /* find a texture format we know */
898 for (i = 0; i < numFormats; i++) {
899 switch (formats[i]) {
900 case PIPE_FORMAT_U_I8:
901 format = formats[i];
902 cpp = 1;
903 comp = 0;
904 break;
905 case PIPE_FORMAT_U_A8_R8_G8_B8:
906 format = formats[i];
907 cpp = 4;
908 comp = 3; /* alpha channel */ /*XXX little-endian dependency */
909 break;
910 default:
911 /* XXX support more formats */
912 ;
913 }
914 }
915 assert(format);
916
917 /**
918 * Create a mipmap tree.
919 */
920 mt = CALLOC_STRUCT(pipe_mipmap_tree);
921 if (!mt)
922 return NULL;
923
924 if (unpack->BufferObj && unpack->BufferObj->Name) {
925 /*
926 mt->region = buffer_object_region(unpack->BufferObj);
927 */
928 printf("st_Bitmap (sourcing from PBO not implemented yet)\n");
929 }
930
931
932 /* allocate texture region/storage */
933 mt->region = pipe->region_alloc(pipe, cpp, width, height, flags);
934 pitch = mt->region->pitch;
935
936 /* map texture region */
937 dest = pipe->region_map(pipe, mt->region);
938 if (!dest) {
939 printf("st_Bitmap region_map() failed!?!");
940 return NULL;
941 }
942
943 /* Put image into texture region.
944 * Note that the image is actually going to be upside down in
945 * the texture. We deal with that with texcoords.
946 */
947
948 for (row = 0; row < height; row++) {
949 const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
950 bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
951 ubyte *destRow = dest + row * pitch * cpp;
952
953 if (unpack->LsbFirst) {
954 /* Lsb first */
955 GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
956 for (col = 0; col < width; col++) {
957
958 /* set texel to 255 if bit is set */
959 destRow[comp] = (*src & mask) ? 255 : 0;
960 destRow += cpp;
961
962 if (mask == 128U) {
963 src++;
964 mask = 1U;
965 }
966 else {
967 mask = mask << 1;
968 }
969 }
970
971 /* get ready for next row */
972 if (mask != 1)
973 src++;
974 }
975 else {
976 /* Msb first */
977 GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
978 for (col = 0; col < width; col++) {
979
980 /* set texel to 255 if bit is set */
981 destRow[comp] =(*src & mask) ? 255 : 0;
982 destRow += cpp;
983
984 if (mask == 1U) {
985 src++;
986 mask = 128U;
987 }
988 else {
989 mask = mask >> 1;
990 }
991 }
992
993 /* get ready for next row */
994 if (mask != 128)
995 src++;
996 }
997
998 } /* row */
999
1000 /* unmap */
1001 pipe->region_unmap(pipe, mt->region);
1002
1003 mt->target = PIPE_TEXTURE_2D;
1004 mt->internal_format = GL_RGBA;
1005 mt->format = format;
1006 mt->first_level = 0;
1007 mt->last_level = 0;
1008 mt->width0 = width;
1009 mt->height0 = height;
1010 mt->depth0 = 1;
1011 mt->cpp = cpp;
1012 mt->compressed = 0;
1013 mt->pitch = mt->region->pitch;
1014 mt->depth_pitch = 0;
1015 mt->total_height = height;
1016 mt->level[0].level_offset = 0;
1017 mt->level[0].width = width;
1018 mt->level[0].height = height;
1019 mt->level[0].depth = 1;
1020 mt->level[0].nr_images = 1;
1021 mt->level[0].image_offset = NULL;
1022 mt->refcount = 1;
1023
1024 return mt;
1025 }
1026
1027
1028
1029 static void
1030 st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
1031 const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
1032 {
1033 static struct st_vertex_program *stvp = NULL;
1034 static struct st_fragment_program *stfp = NULL;
1035 struct st_context *st = ctx->st;
1036 struct pipe_mipmap_tree *mt;
1037
1038 /* create the fragment program if needed */
1039 if (!stfp) {
1040 stfp = make_fragment_shader(ctx->st, GL_TRUE);
1041 }
1042 /* and vertex program */
1043 if (!stvp) {
1044 stvp = make_vertex_shader(ctx->st, GL_TRUE);
1045 }
1046
1047 st_validate_state(st);
1048
1049 mt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
1050 if (mt) {
1051 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
1052 width, height, 1.0, 1.0,
1053 mt, stvp, stfp,
1054 ctx->Current.RasterColor);
1055
1056 free_mipmap_tree(st->pipe, mt);
1057 }
1058 }
1059
1060
1061 static void
1062 st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
1063 GLsizei width, GLsizei height,
1064 GLint dstx, GLint dsty, GLenum type)
1065 {
1066 struct st_context *st = ctx->st;
1067
1068 st_validate_state(st);
1069
1070 /* allocate a texture of size width x height */
1071
1072 /* blit/copy framebuffer region into texture */
1073
1074 /* draw textured quad */
1075
1076
1077 fprintf(stderr, "st_CopyPixels not implemented yet\n");
1078 }
1079
1080
1081
1082 void st_init_drawpixels_functions(struct dd_function_table *functions)
1083 {
1084 functions->DrawPixels = st_DrawPixels;
1085 functions->CopyPixels = st_CopyPixels;
1086 functions->Bitmap = st_Bitmap;
1087 }