Use write posting in the kickoff function too.
[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 #include "shader/program.h"
37 #include "shader/prog_parameter.h"
38 #include "shader/prog_print.h"
39
40 #include "st_context.h"
41 #include "st_atom.h"
42 #include "st_atom_constbuf.h"
43 #include "st_cache.h"
44 #include "st_draw.h"
45 #include "st_program.h"
46 #include "st_cb_drawpixels.h"
47 #include "st_cb_readpixels.h"
48 #include "st_cb_fbo.h"
49 #include "st_cb_texture.h"
50 #include "st_draw.h"
51 #include "st_format.h"
52 #include "st_mesa_to_tgsi.h"
53 #include "pipe/p_context.h"
54 #include "pipe/p_defines.h"
55 #include "pipe/p_inlines.h"
56 #include "pipe/p_winsys.h"
57 #include "shader/prog_instruction.h"
58
59
60 /**
61 * Check if the given program is:
62 * 0: MOVE result.color, fragment.color;
63 * 1: END;
64 */
65 static GLboolean
66 is_passthrough_program(const struct gl_fragment_program *prog)
67 {
68 if (prog->Base.NumInstructions == 2) {
69 const struct prog_instruction *inst = prog->Base.Instructions;
70 if (inst[0].Opcode == OPCODE_MOV &&
71 inst[1].Opcode == OPCODE_END &&
72 inst[0].DstReg.File == PROGRAM_OUTPUT &&
73 inst[0].DstReg.Index == FRAG_RESULT_COLR &&
74 inst[0].DstReg.WriteMask == WRITEMASK_XYZW &&
75 inst[0].SrcReg[0].File == PROGRAM_INPUT &&
76 inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 &&
77 inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) {
78 return GL_TRUE;
79 }
80 }
81 return GL_FALSE;
82 }
83
84
85 /**
86 * Make fragment program for glBitmap:
87 * Sample the texture and kill the fragment if the bit is 0.
88 * This program will be combined with the user's fragment program.
89 */
90 static struct st_fragment_program *
91 make_bitmap_fragment_program(GLcontext *ctx)
92 {
93 struct st_fragment_program *stfp;
94 struct gl_program *p;
95 GLuint ic = 0;
96
97 p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
98 if (!p)
99 return NULL;
100
101 p->NumInstructions = 5;
102
103 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
104 if (!p->Instructions) {
105 ctx->Driver.DeleteProgram(ctx, p);
106 return NULL;
107 }
108 _mesa_init_instructions(p->Instructions, p->NumInstructions);
109
110 /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
111 p->Instructions[ic].Opcode = OPCODE_TEX;
112 p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
113 p->Instructions[ic].DstReg.Index = 0;
114 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
115 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
116 p->Instructions[ic].TexSrcUnit = 0;
117 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
118 ic++;
119
120 /* SWZ tmp0.x, tmp0.x, 1111; # tmp0.x = 1.0 */
121 p->Instructions[ic].Opcode = OPCODE_SWZ;
122 p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
123 p->Instructions[ic].DstReg.Index = 0;
124 p->Instructions[ic].DstReg.WriteMask = WRITEMASK_X;
125 p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
126 p->Instructions[ic].SrcReg[0].Index = 0;
127 p->Instructions[ic].SrcReg[0].Swizzle
128 = MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE );
129 ic++;
130
131 /* SUB tmp0, tmp0.wwww, tmp0.xxxx; # tmp0.w -= 1 */
132 p->Instructions[ic].Opcode = OPCODE_SUB;
133 p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
134 p->Instructions[ic].DstReg.Index = 0;
135 p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
136 p->Instructions[ic].SrcReg[0].Index = 0;
137 p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_WWWW;
138 p->Instructions[ic].SrcReg[1].File = PROGRAM_TEMPORARY;
139 p->Instructions[ic].SrcReg[1].Index = 0;
140 p->Instructions[ic].SrcReg[1].Swizzle = SWIZZLE_XXXX; /* 1.0 */
141 ic++;
142
143 /* KIL if tmp0 < 0 */
144 p->Instructions[ic].Opcode = OPCODE_KIL;
145 p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
146 p->Instructions[ic].SrcReg[0].Index = 0;
147 ic++;
148
149 /* END; */
150 p->Instructions[ic++].Opcode = OPCODE_END;
151
152 assert(ic == p->NumInstructions);
153
154 p->InputsRead = FRAG_BIT_TEX0;
155 p->OutputsWritten = 0x0;
156
157 stfp = (struct st_fragment_program *) p;
158 st_translate_fragment_program(ctx->st, stfp, NULL,
159 stfp->tokens, ST_MAX_SHADER_TOKENS);
160
161 return stfp;
162 }
163
164
165 /**
166 * Combine basic bitmap fragment program with the user-defined program.
167 */
168 static struct st_fragment_program *
169 combined_bitmap_fragment_program(GLcontext *ctx)
170 {
171 struct st_context *st = ctx->st;
172 struct st_fragment_program *stfp;
173
174 if (!st->bitmap.program) {
175 /* create the basic bitmap fragment program */
176 st->bitmap.program = make_bitmap_fragment_program(ctx);
177 }
178
179 if (st->bitmap.user_prog_sn == st->fp->serialNo) {
180 /* re-use */
181 stfp = st->bitmap.combined_prog;
182 }
183 else {
184 /* Concatenate the bitmap program with the current user-defined program.
185 */
186 stfp = (struct st_fragment_program *)
187 _mesa_combine_programs(ctx,
188 &st->bitmap.program->Base.Base,
189 &st->fp->Base.Base);
190
191 #if 0
192 {
193 struct gl_program *p = &stfp->Base.Base;
194 printf("Combined bitmap program:\n");
195 _mesa_print_program(p);
196 printf("InputsRead: 0x%x\n", p->InputsRead);
197 printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
198 _mesa_print_parameter_list(p->Parameters);
199 }
200 #endif
201
202 /* translate to TGSI tokens */
203 st_translate_fragment_program(st, stfp, NULL,
204 stfp->tokens, ST_MAX_SHADER_TOKENS);
205
206 /* save new program, update serial numbers */
207 st->bitmap.user_prog_sn = st->fp->serialNo;
208 st->bitmap.combined_prog = stfp;
209 }
210
211 /* Ideally we'd have updated the pipe constants during the normal
212 * st/atom mechanism. But we can't since this is specific to glBitmap.
213 */
214 st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
215
216 return stfp;
217 }
218
219
220
221 /**
222 * Make fragment shader for glDraw/CopyPixels. This shader is made
223 * by combining the pixel transfer shader with the user-defined shader.
224 */
225 static struct st_fragment_program *
226 combined_drawpix_fragment_program(GLcontext *ctx)
227 {
228 struct st_context *st = ctx->st;
229 struct st_fragment_program *stfp;
230
231 if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn
232 && st->fp->serialNo == st->pixel_xfer.user_prog_sn) {
233 /* the pixel tranfer program has not changed and the user-defined
234 * program has not changed, so re-use the combined program.
235 */
236 stfp = st->pixel_xfer.combined_prog;
237 }
238 else {
239 /* Concatenate the pixel transfer program with the current user-
240 * defined program.
241 */
242 if (is_passthrough_program(&st->fp->Base)) {
243 stfp = (struct st_fragment_program *)
244 _mesa_clone_program(ctx, &st->pixel_xfer.program->Base.Base);
245 }
246 else {
247 stfp = (struct st_fragment_program *)
248 _mesa_combine_programs(ctx,
249 &st->pixel_xfer.program->Base.Base,
250 &st->fp->Base.Base);
251 }
252
253 #if 0
254 {
255 struct gl_program *p = &stfp->Base.Base;
256 printf("Combined DrawPixels program:\n");
257 _mesa_print_program(p);
258 printf("InputsRead: 0x%x\n", p->InputsRead);
259 printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
260 _mesa_print_parameter_list(p->Parameters);
261 }
262 #endif
263
264 /* translate to TGSI tokens */
265 st_translate_fragment_program(st, stfp, NULL,
266 stfp->tokens, ST_MAX_SHADER_TOKENS);
267
268 /* save new program, update serial numbers */
269 st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
270 st->pixel_xfer.user_prog_sn = st->fp->serialNo;
271 st->pixel_xfer.combined_prog_sn = stfp->serialNo;
272 st->pixel_xfer.combined_prog = stfp;
273 }
274
275 /* Ideally we'd have updated the pipe constants during the normal
276 * st/atom mechanism. But we can't since this is specific to glDrawPixels.
277 */
278 st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
279
280 return stfp;
281 }
282
283
284 /**
285 * Create fragment shader that does a TEX() instruction to get a Z
286 * value, then writes to FRAG_RESULT_DEPR.
287 * Pass fragment color through as-is.
288 */
289 static struct st_fragment_program *
290 make_fragment_shader_z(struct st_context *st)
291 {
292 GLcontext *ctx = st->ctx;
293 /* only make programs once and re-use */
294 static struct st_fragment_program *stfp = NULL;
295 struct gl_program *p;
296 GLuint ic = 0;
297
298 if (stfp)
299 return stfp;
300
301 p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
302 if (!p)
303 return NULL;
304
305 p->NumInstructions = 3;
306
307 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
308 if (!p->Instructions) {
309 ctx->Driver.DeleteProgram(ctx, p);
310 return NULL;
311 }
312 _mesa_init_instructions(p->Instructions, p->NumInstructions);
313
314 /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */
315 p->Instructions[ic].Opcode = OPCODE_TEX;
316 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
317 p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPR;
318 p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z;
319 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
320 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
321 p->Instructions[ic].TexSrcUnit = 0;
322 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
323 ic++;
324
325 /* MOV result.color, fragment.color */
326 p->Instructions[ic].Opcode = OPCODE_MOV;
327 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
328 p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLR;
329 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
330 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0;
331 ic++;
332
333 /* END; */
334 p->Instructions[ic++].Opcode = OPCODE_END;
335
336 assert(ic == p->NumInstructions);
337
338 p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
339 p->OutputsWritten = (1 << FRAG_RESULT_COLR) | (1 << FRAG_RESULT_DEPR);
340
341 stfp = (struct st_fragment_program *) p;
342 st_translate_fragment_program(st, stfp, NULL,
343 stfp->tokens, ST_MAX_SHADER_TOKENS);
344
345 return stfp;
346 }
347
348
349
350 /**
351 * Create a simple vertex shader that just passes through the
352 * vertex position and texcoord (and optionally, color).
353 */
354 static struct st_vertex_program *
355 make_vertex_shader(struct st_context *st, GLboolean passColor)
356 {
357 /* only make programs once and re-use */
358 static struct st_vertex_program *progs[2] = { NULL, NULL };
359 GLcontext *ctx = st->ctx;
360 struct st_vertex_program *stvp;
361 struct gl_program *p;
362 GLuint ic = 0;
363
364 if (progs[passColor])
365 return progs[passColor];
366
367 p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
368 if (!p)
369 return NULL;
370
371 if (passColor)
372 p->NumInstructions = 4;
373 else
374 p->NumInstructions = 3;
375
376 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
377 if (!p->Instructions) {
378 ctx->Driver.DeleteProgram(ctx, p);
379 return NULL;
380 }
381 _mesa_init_instructions(p->Instructions, p->NumInstructions);
382 /* MOV result.pos, vertex.pos; */
383 p->Instructions[0].Opcode = OPCODE_MOV;
384 p->Instructions[0].DstReg.File = PROGRAM_OUTPUT;
385 p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS;
386 p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT;
387 p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS;
388 /* MOV result.texcoord0, vertex.texcoord0; */
389 p->Instructions[1].Opcode = OPCODE_MOV;
390 p->Instructions[1].DstReg.File = PROGRAM_OUTPUT;
391 p->Instructions[1].DstReg.Index = VERT_RESULT_TEX0;
392 p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT;
393 p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_TEX0;
394 ic = 2;
395 if (passColor) {
396 /* MOV result.color0, vertex.color0; */
397 p->Instructions[ic].Opcode = OPCODE_MOV;
398 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
399 p->Instructions[ic].DstReg.Index = VERT_RESULT_COL0;
400 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
401 p->Instructions[ic].SrcReg[0].Index = VERT_ATTRIB_COLOR0;
402 ic++;
403 }
404
405 /* END; */
406 p->Instructions[ic].Opcode = OPCODE_END;
407 ic++;
408
409 assert(ic == p->NumInstructions);
410
411 p->InputsRead = VERT_BIT_POS | VERT_BIT_TEX0;
412 p->OutputsWritten = ((1 << VERT_RESULT_TEX0) |
413 (1 << VERT_RESULT_HPOS));
414 if (passColor) {
415 p->InputsRead |= VERT_BIT_COLOR0;
416 p->OutputsWritten |= (1 << VERT_RESULT_COL0);
417 }
418
419 stvp = (struct st_vertex_program *) p;
420 st_translate_vertex_program(st, stvp, NULL,
421 stvp->tokens, ST_MAX_SHADER_TOKENS);
422
423 progs[passColor] = stvp;
424
425 return stvp;
426 }
427
428
429 static GLenum
430 _mesa_base_format(GLenum format)
431 {
432 switch (format) {
433 case GL_DEPTH_COMPONENT:
434 return GL_DEPTH_COMPONENT;
435 case GL_STENCIL_INDEX:
436 return GL_STENCIL_INDEX;
437 default:
438 return GL_RGBA;
439 }
440 }
441
442
443
444 static struct pipe_mipmap_tree *
445 alloc_mipmap_tree(struct st_context *st,
446 GLsizei width, GLsizei height, uint pipeFormat)
447 {
448 const GLbitfield flags = PIPE_SURFACE_FLAG_TEXTURE;
449 struct pipe_mipmap_tree *mt;
450 GLuint cpp;
451
452 mt = CALLOC_STRUCT(pipe_mipmap_tree);
453 if (!mt)
454 return NULL;
455
456 cpp = st_sizeof_format(pipeFormat);
457
458 /* allocate texture region/storage */
459 mt->region = st->pipe->winsys->region_alloc(st->pipe->winsys,
460 cpp, width, height, flags);
461
462 mt->target = PIPE_TEXTURE_2D;
463 mt->internal_format = GL_RGBA;
464 mt->format = pipeFormat;
465 mt->first_level = 0;
466 mt->last_level = 0;
467 mt->width0 = width;
468 mt->height0 = height;
469 mt->depth0 = 1;
470 mt->cpp = cpp;
471 mt->compressed = 0;
472 mt->pitch = mt->region->pitch;
473 mt->depth_pitch = 0;
474 mt->total_height = height;
475 mt->level[0].level_offset = 0;
476 mt->level[0].width = width;
477 mt->level[0].height = height;
478 mt->level[0].depth = 1;
479 mt->level[0].nr_images = 1;
480 mt->level[0].image_offset = NULL;
481 mt->refcount = 1;
482
483 return mt;
484 }
485
486
487 /**
488 * Make mipmap tree containing an image for glDrawPixels image.
489 * If 'pixels' is NULL, leave the texture image data undefined.
490 */
491 static struct pipe_mipmap_tree *
492 make_mipmap_tree(struct st_context *st,
493 GLsizei width, GLsizei height, GLenum format, GLenum type,
494 const struct gl_pixelstore_attrib *unpack,
495 const GLvoid *pixels)
496 {
497 GLcontext *ctx = st->ctx;
498 struct pipe_context *pipe = st->pipe;
499 const struct gl_texture_format *mformat;
500 struct pipe_mipmap_tree *mt;
501 GLuint pipeFormat, cpp;
502 GLenum baseFormat;
503
504 baseFormat = _mesa_base_format(format);
505
506 mformat = st_ChooseTextureFormat(ctx, baseFormat, format, type);
507 assert(mformat);
508
509 pipeFormat = st_mesa_format_to_pipe_format(mformat->MesaFormat);
510 assert(pipeFormat);
511 cpp = st_sizeof_format(pipeFormat);
512
513 mt = alloc_mipmap_tree(st, width, height, pipeFormat);
514 if (!mt)
515 return NULL;
516
517 if (unpack->BufferObj && unpack->BufferObj->Name) {
518 /*
519 mt->region = buffer_object_region(unpack->BufferObj);
520 */
521 printf("st_DrawPixels (sourcing from PBO not implemented yet)\n");
522 }
523
524 {
525 static const GLuint dstImageOffsets = 0;
526 GLboolean success;
527 GLuint pitch = mt->region->pitch;
528 GLubyte *dest;
529 const GLbitfield imageTransferStateSave = ctx->_ImageTransferState;
530
531 /* we'll do pixel transfer in a fragment shader */
532 ctx->_ImageTransferState = 0x0;
533
534 /* map texture region */
535 dest = pipe->region_map(pipe, mt->region);
536
537 /* Put image into texture region.
538 * Note that the image is actually going to be upside down in
539 * the texture. We deal with that with texcoords.
540 */
541 success = mformat->StoreImage(ctx, 2, /* dims */
542 baseFormat, /* baseInternalFormat */
543 mformat, /* gl_texture_format */
544 dest, /* dest */
545 0, 0, 0, /* dstX/Y/Zoffset */
546 pitch * cpp, /* dstRowStride, bytes */
547 &dstImageOffsets, /* dstImageOffsets */
548 width, height, 1, /* size */
549 format, type, /* src format/type */
550 pixels, /* data source */
551 unpack);
552
553 /* unmap */
554 pipe->region_unmap(pipe, mt->region);
555 assert(success);
556
557 /* restore */
558 ctx->_ImageTransferState = imageTransferStateSave;
559 }
560
561 #if 0
562 mt->target = PIPE_TEXTURE_2D;
563 mt->internal_format = GL_RGBA;
564 mt->format = pipeFormat;
565 mt->first_level = 0;
566 mt->last_level = 0;
567 mt->width0 = width;
568 mt->height0 = height;
569 mt->depth0 = 1;
570 mt->cpp = cpp;
571 mt->compressed = 0;
572 mt->pitch = mt->region->pitch;
573 mt->depth_pitch = 0;
574 mt->total_height = height;
575 mt->level[0].level_offset = 0;
576 mt->level[0].width = width;
577 mt->level[0].height = height;
578 mt->level[0].depth = 1;
579 mt->level[0].nr_images = 1;
580 mt->level[0].image_offset = NULL;
581 mt->refcount = 1;
582 #endif
583 return mt;
584 }
585
586
587 static void
588 free_mipmap_tree(struct pipe_context *pipe, struct pipe_mipmap_tree *mt)
589 {
590 pipe->winsys->region_release(pipe->winsys, &mt->region);
591 free(mt);
592 }
593
594
595 /**
596 * Draw textured quad.
597 * Coords are window coords with y=0=bottom.
598 */
599 static void
600 draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
601 GLfloat x1, GLfloat y1, GLboolean invertTex)
602 {
603 GLfloat verts[4][2][4]; /* four verts, two attribs, XYZW */
604 GLuint i;
605 GLfloat tTop = invertTex, tBot = 1.0 - tTop;
606
607 /* upper-left */
608 verts[0][0][0] = x0; /* attr[0].x */
609 verts[0][0][1] = y0; /* attr[0].x */
610 verts[0][1][0] = 0.0; /* attr[1].s */
611 verts[0][1][1] = tTop; /* attr[1].t */
612
613 /* upper-right */
614 verts[1][0][0] = x1;
615 verts[1][0][1] = y0;
616 verts[1][1][0] = 1.0;
617 verts[1][1][1] = tTop;
618
619 /* lower-right */
620 verts[2][0][0] = x1;
621 verts[2][0][1] = y1;
622 verts[2][1][0] = 1.0;
623 verts[2][1][1] = tBot;
624
625 /* lower-left */
626 verts[3][0][0] = x0;
627 verts[3][0][1] = y1;
628 verts[3][1][0] = 0.0;
629 verts[3][1][1] = tBot;
630
631 /* same for all verts: */
632 for (i = 0; i < 4; i++) {
633 verts[i][0][2] = z; /*Z*/
634 verts[i][0][3] = 1.0; /*W*/
635 verts[i][1][2] = 0.0; /*R*/
636 verts[i][1][3] = 1.0; /*Q*/
637 }
638
639 st_draw_vertices(ctx, PIPE_PRIM_QUADS, 4, (float *) verts, 2);
640 }
641
642
643 static void
644 draw_quad_colored(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
645 GLfloat x1, GLfloat y1, const GLfloat *color,
646 GLboolean invertTex)
647 {
648 GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */
649 GLuint i;
650 GLfloat tTop = invertTex, tBot = 1.0 - tTop;
651
652 /* upper-left */
653 verts[0][0][0] = x0; /* attr[0].x */
654 verts[0][0][1] = y0; /* attr[0].y */
655 verts[0][2][0] = 0.0; /* attr[2].s */
656 verts[0][2][1] = tTop; /* attr[2].t */
657
658 /* upper-right */
659 verts[1][0][0] = x1;
660 verts[1][0][1] = y0;
661 verts[1][2][0] = 1.0;
662 verts[1][2][1] = tTop;
663
664 /* lower-right */
665 verts[2][0][0] = x1;
666 verts[2][0][1] = y1;
667 verts[2][2][0] = 1.0;
668 verts[2][2][1] = tBot;
669
670 /* lower-left */
671 verts[3][0][0] = x0;
672 verts[3][0][1] = y1;
673 verts[3][2][0] = 0.0;
674 verts[3][2][1] = tBot;
675
676 /* same for all verts: */
677 for (i = 0; i < 4; i++) {
678 verts[i][0][2] = z; /*Z*/
679 verts[i][0][3] = 1.0; /*W*/
680 verts[i][1][0] = color[0];
681 verts[i][1][1] = color[1];
682 verts[i][1][2] = color[2];
683 verts[i][1][3] = color[3];
684 verts[i][2][2] = 0.0; /*R*/
685 verts[i][2][3] = 1.0; /*Q*/
686 }
687
688 st_draw_vertices(ctx, PIPE_PRIM_QUADS, 4, (float *) verts, 3);
689 }
690
691
692
693 static void
694 draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
695 GLsizei width, GLsizei height,
696 GLfloat zoomX, GLfloat zoomY,
697 struct pipe_mipmap_tree *mt,
698 struct st_vertex_program *stvp,
699 struct st_fragment_program *stfp,
700 const GLfloat *color,
701 GLboolean invertTex)
702 {
703 const GLuint unit = 0;
704 struct pipe_context *pipe = ctx->st->pipe;
705 GLfloat x0, y0, x1, y1;
706 GLuint maxSize;
707
708 /* limit checks */
709 /* XXX if DrawPixels image is larger than max texture size, break
710 * it up into chunks.
711 */
712 maxSize = 1 << (pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
713 assert(width <= maxSize);
714 assert(height <= maxSize);
715
716 /* setup state: just scissor */
717 {
718 struct pipe_rasterizer_state setup;
719 const struct cso_rasterizer *cso;
720 memset(&setup, 0, sizeof(setup));
721 if (ctx->Scissor.Enabled)
722 setup.scissor = 1;
723 cso = st_cached_rasterizer_state(ctx->st, &setup);
724 pipe->bind_rasterizer_state(pipe, cso->data);
725 }
726
727 /* fragment shader state: TEX lookup program */
728 pipe->bind_fs_state(pipe, stfp->fs->data);
729
730 /* vertex shader state: position + texcoord pass-through */
731 pipe->bind_vs_state(pipe, stvp->vs->data);
732
733 /* texture sampling state: */
734 {
735 struct pipe_sampler_state sampler;
736 const struct cso_sampler *cso;
737 memset(&sampler, 0, sizeof(sampler));
738 sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
739 sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
740 sampler.wrap_r = PIPE_TEX_WRAP_REPEAT;
741 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
742 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
743 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
744 sampler.normalized_coords = 1;
745 cso = st_cached_sampler_state(ctx->st, &sampler);
746 pipe->bind_sampler_state(pipe, unit, cso->data);
747 }
748
749 /* viewport state: viewport matching window dims */
750 {
751 const float width = ctx->DrawBuffer->Width;
752 const float height = ctx->DrawBuffer->Height;
753 struct pipe_viewport_state vp;
754 vp.scale[0] = 0.5 * width;
755 vp.scale[1] = -0.5 * height;
756 vp.scale[2] = 1.0;
757 vp.scale[3] = 1.0;
758 vp.translate[0] = 0.5 * width;
759 vp.translate[1] = 0.5 * height;
760 vp.translate[2] = 0.0;
761 vp.translate[3] = 0.0;
762 pipe->set_viewport_state(pipe, &vp);
763 }
764
765 /* mipmap tree state: */
766 {
767 pipe->set_texture_state(pipe, unit, mt);
768 }
769
770 /* Compute window coords (y=0=bottom) with pixel zoom.
771 * Recall that these coords are transformed by the current
772 * vertex shader and viewport transformation.
773 */
774 x0 = x;
775 x1 = x + width * ctx->Pixel.ZoomX;
776 y0 = y;
777 y1 = y + height * ctx->Pixel.ZoomY;
778
779 /* draw textured quad */
780 if (color)
781 draw_quad_colored(ctx, x0, y0, z, x1, y1, color, invertTex);
782 else
783 draw_quad(ctx, x0, y0, z, x1, y1, invertTex);
784
785 /* restore GL state */
786 pipe->bind_rasterizer_state(pipe, ctx->st->state.rasterizer->data);
787 pipe->bind_fs_state(pipe, ctx->st->state.fs->data);
788 pipe->bind_vs_state(pipe, ctx->st->state.vs->data);
789 pipe->set_texture_state(pipe, unit, ctx->st->state.texture[unit]);
790 pipe->bind_sampler_state(pipe, unit, ctx->st->state.sampler[unit]->data);
791 pipe->set_viewport_state(pipe, &ctx->st->state.viewport);
792 }
793
794
795 /**
796 * Check if a GL format/type combination is a match to the given pipe format.
797 * XXX probably move this to a re-usable place.
798 */
799 static GLboolean
800 compatible_formats(GLenum format, GLenum type, GLuint pipeFormat)
801 {
802 static const GLuint one = 1;
803 GLubyte littleEndian = *((GLubyte *) &one);
804
805 if (pipeFormat == PIPE_FORMAT_U_R8_G8_B8_A8 &&
806 format == GL_RGBA &&
807 type == GL_UNSIGNED_BYTE &&
808 !littleEndian) {
809 return GL_TRUE;
810 }
811 else if (pipeFormat == PIPE_FORMAT_U_R8_G8_B8_A8 &&
812 format == GL_ABGR_EXT &&
813 type == GL_UNSIGNED_BYTE &&
814 littleEndian) {
815 return GL_TRUE;
816 }
817 else if (pipeFormat == PIPE_FORMAT_U_A8_R8_G8_B8 &&
818 format == GL_BGRA &&
819 type == GL_UNSIGNED_BYTE &&
820 littleEndian) {
821 return GL_TRUE;
822 }
823 else if (pipeFormat == PIPE_FORMAT_U_R5_G6_B5 &&
824 format == GL_RGB &&
825 type == GL_UNSIGNED_SHORT_5_6_5) {
826 /* endian don't care */
827 return GL_TRUE;
828 }
829 else if (pipeFormat == PIPE_FORMAT_U_R5_G6_B5 &&
830 format == GL_BGR &&
831 type == GL_UNSIGNED_SHORT_5_6_5_REV) {
832 /* endian don't care */
833 return GL_TRUE;
834 }
835 else if (pipeFormat == PIPE_FORMAT_U_S8 &&
836 format == GL_STENCIL_INDEX &&
837 type == GL_UNSIGNED_BYTE) {
838 return GL_TRUE;
839 }
840 else if (pipeFormat == PIPE_FORMAT_U_Z32 &&
841 format == GL_DEPTH_COMPONENT &&
842 type == GL_UNSIGNED_INT) {
843 return GL_TRUE;
844 }
845 /* XXX add more cases */
846 else {
847 return GL_FALSE;
848 }
849 }
850
851
852 /**
853 * Check if any per-fragment ops are enabled.
854 * XXX probably move this to a re-usable place.
855 */
856 static GLboolean
857 any_fragment_ops(const struct st_context *st)
858 {
859 if (st->state.alpha_test->state.enabled ||
860 st->state.blend->state.blend_enable ||
861 st->state.blend->state.logicop_enable ||
862 st->state.depth_stencil->state.depth.enabled)
863 /* XXX more checks */
864 return GL_TRUE;
865 else
866 return GL_FALSE;
867 }
868
869
870 /**
871 * Check if any pixel transfer ops are enabled.
872 * XXX probably move this to a re-usable place.
873 */
874 static GLboolean
875 any_pixel_transfer_ops(const struct st_context *st)
876 {
877 if (st->ctx->Pixel.RedScale != 1.0 ||
878 st->ctx->Pixel.RedBias != 0.0 ||
879 st->ctx->Pixel.GreenScale != 1.0 ||
880 st->ctx->Pixel.GreenBias != 0.0 ||
881 st->ctx->Pixel.BlueScale != 1.0 ||
882 st->ctx->Pixel.BlueBias != 0.0 ||
883 st->ctx->Pixel.AlphaScale != 1.0 ||
884 st->ctx->Pixel.AlphaBias != 0.0 ||
885 st->ctx->Pixel.MapColorFlag)
886 /* XXX more checks */
887 return GL_TRUE;
888 else
889 return GL_FALSE;
890 }
891
892
893 /**
894 * Draw image with a blit, or other non-textured quad method.
895 */
896 static void
897 draw_blit(struct st_context *st,
898 GLsizei width, GLsizei height,
899 GLenum format, GLenum type, const GLvoid *pixels)
900 {
901
902
903 }
904
905
906 static void
907 draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
908 GLsizei width, GLsizei height, GLenum type,
909 const struct gl_pixelstore_attrib *unpack,
910 const GLvoid *pixels)
911 {
912 struct st_context *st = ctx->st;
913 struct pipe_context *pipe = st->pipe;
914 struct pipe_surface *ps = st->state.framebuffer.sbuf;
915 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
916 GLint skipPixels;
917 ubyte *stmap;
918
919 pipe->flush(pipe, 0);
920
921 /* map the stencil buffer */
922 stmap = pipe->region_map(pipe, ps->region);
923
924 /* if width > MAX_WIDTH, have to process image in chunks */
925 skipPixels = 0;
926 while (skipPixels < width) {
927 const GLint spanX = x + skipPixels;
928 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
929 GLint row;
930 for (row = 0; row < height; row++) {
931 GLint spanY = y + row;
932 GLubyte values[MAX_WIDTH];
933 GLenum destType = GL_UNSIGNED_BYTE;
934 const GLvoid *source = _mesa_image_address2d(unpack, pixels,
935 width, height,
936 GL_COLOR_INDEX, type,
937 row, skipPixels);
938 _mesa_unpack_stencil_span(ctx, spanWidth, destType, values,
939 type, source, unpack,
940 ctx->_ImageTransferState);
941 if (zoom) {
942 /*
943 _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth,
944 spanX, spanY, values);
945 */
946 }
947 else {
948 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
949 spanY = ctx->DrawBuffer->Height - spanY - 1;
950 }
951
952 switch (ps->format) {
953 case PIPE_FORMAT_U_S8:
954 {
955 ubyte *dest = stmap + spanY * ps->region->pitch + spanX;
956 memcpy(dest, values, spanWidth);
957 }
958 break;
959 case PIPE_FORMAT_S8_Z24:
960 {
961 uint *dest = (uint *) stmap + spanY * ps->region->pitch + spanX;
962 GLint k;
963 for (k = 0; k < spanWidth; k++) {
964 uint p = dest[k];
965 p = (p & 0xffffff) | (values[k] << 24);
966 dest[k] = p;
967 }
968 }
969 break;
970 default:
971 assert(0);
972 }
973 }
974 }
975 skipPixels += spanWidth;
976 }
977
978 /* unmap the stencil buffer */
979 pipe->region_unmap(pipe, ps->region);
980 }
981
982
983 /**
984 * Called via ctx->Driver.DrawPixels()
985 */
986 static void
987 st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
988 GLenum format, GLenum type,
989 const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
990 {
991 struct st_fragment_program *stfp;
992 struct st_vertex_program *stvp;
993 struct st_context *st = ctx->st;
994 struct pipe_surface *ps;
995 GLuint bufferFormat;
996 const GLfloat *color;
997
998 if (format == GL_STENCIL_INDEX) {
999 draw_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels);
1000 return;
1001 }
1002
1003 st_validate_state(st);
1004
1005 if (format == GL_DEPTH_COMPONENT) {
1006 ps = st->state.framebuffer.zbuf;
1007 stfp = make_fragment_shader_z(ctx->st);
1008 stvp = make_vertex_shader(ctx->st, GL_TRUE);
1009 color = ctx->Current.RasterColor;
1010 }
1011 else if (format == GL_STENCIL_INDEX) {
1012 ps = st->state.framebuffer.sbuf;
1013 /* XXX special case - can't use texture map */
1014 color = NULL;
1015 }
1016 else {
1017 ps = st->state.framebuffer.cbufs[0];
1018 stfp = combined_drawpix_fragment_program(ctx);
1019 stvp = make_vertex_shader(ctx->st, GL_FALSE);
1020 color = NULL;
1021 }
1022
1023 bufferFormat = ps->format;
1024
1025 if (any_fragment_ops(st) ||
1026 any_pixel_transfer_ops(st) ||
1027 !compatible_formats(format, type, ps->format)) {
1028 /* textured quad */
1029 struct pipe_mipmap_tree *mt
1030 = make_mipmap_tree(ctx->st, width, height, format, type,
1031 unpack, pixels);
1032 if (mt) {
1033 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
1034 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
1035 mt, stvp, stfp, color, GL_FALSE);
1036 free_mipmap_tree(st->pipe, mt);
1037 }
1038 }
1039 else {
1040 /* blit */
1041 draw_blit(st, width, height, format, type, pixels);
1042 }
1043 }
1044
1045
1046
1047 /**
1048 * Create a texture which represents a bitmap image.
1049 */
1050 static struct pipe_mipmap_tree *
1051 make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
1052 const struct gl_pixelstore_attrib *unpack,
1053 const GLubyte *bitmap)
1054 {
1055 struct pipe_context *pipe = ctx->st->pipe;
1056 const uint flags = PIPE_SURFACE_FLAG_TEXTURE;
1057 uint format = 0, cpp, comp, pitch;
1058 ubyte *dest;
1059 struct pipe_mipmap_tree *mt;
1060 int row, col;
1061
1062 /* find a texture format we know */
1063 if (pipe->is_format_supported( pipe, PIPE_FORMAT_U_I8 )) {
1064 format = PIPE_FORMAT_U_I8;
1065 cpp = 1;
1066 comp = 0;
1067 }
1068 else if (pipe->is_format_supported( pipe, PIPE_FORMAT_U_A8_R8_G8_B8 )) {
1069 format = PIPE_FORMAT_U_A8_R8_G8_B8;
1070 cpp = 4;
1071 comp = 3; /* alpha channel */ /*XXX little-endian dependency */
1072 }
1073 else {
1074 /* XXX support more formats */
1075 assert( 0 );
1076 }
1077
1078 /**
1079 * Create a mipmap tree.
1080 */
1081 mt = CALLOC_STRUCT(pipe_mipmap_tree);
1082 if (!mt)
1083 return NULL;
1084
1085 if (unpack->BufferObj && unpack->BufferObj->Name) {
1086 /*
1087 mt->region = buffer_object_region(unpack->BufferObj);
1088 */
1089 printf("st_Bitmap (sourcing from PBO not implemented yet)\n");
1090 }
1091
1092
1093 /* allocate texture region/storage */
1094 mt->region = pipe->winsys->region_alloc(pipe->winsys,
1095 cpp, width, height, flags);
1096 pitch = mt->region->pitch;
1097
1098 /* map texture region */
1099 dest = pipe->region_map(pipe, mt->region);
1100 if (!dest) {
1101 printf("st_Bitmap region_map() failed!?!");
1102 return NULL;
1103 }
1104
1105 /* Put image into texture region.
1106 * Note that the image is actually going to be upside down in
1107 * the texture. We deal with that with texcoords.
1108 */
1109
1110 for (row = 0; row < height; row++) {
1111 const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
1112 bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
1113 ubyte *destRow = dest + row * pitch * cpp;
1114
1115 if (unpack->LsbFirst) {
1116 /* Lsb first */
1117 GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
1118 for (col = 0; col < width; col++) {
1119
1120 /* set texel to 255 if bit is set */
1121 destRow[comp] = (*src & mask) ? 255 : 0;
1122 destRow += cpp;
1123
1124 if (mask == 128U) {
1125 src++;
1126 mask = 1U;
1127 }
1128 else {
1129 mask = mask << 1;
1130 }
1131 }
1132
1133 /* get ready for next row */
1134 if (mask != 1)
1135 src++;
1136 }
1137 else {
1138 /* Msb first */
1139 GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
1140 for (col = 0; col < width; col++) {
1141
1142 /* set texel to 255 if bit is set */
1143 destRow[comp] =(*src & mask) ? 255 : 0;
1144 destRow += cpp;
1145
1146 if (mask == 1U) {
1147 src++;
1148 mask = 128U;
1149 }
1150 else {
1151 mask = mask >> 1;
1152 }
1153 }
1154
1155 /* get ready for next row */
1156 if (mask != 128)
1157 src++;
1158 }
1159
1160 } /* row */
1161
1162 /* unmap */
1163 pipe->region_unmap(pipe, mt->region);
1164
1165 mt->target = PIPE_TEXTURE_2D;
1166 mt->internal_format = GL_RGBA;
1167 mt->format = format;
1168 mt->first_level = 0;
1169 mt->last_level = 0;
1170 mt->width0 = width;
1171 mt->height0 = height;
1172 mt->depth0 = 1;
1173 mt->cpp = cpp;
1174 mt->compressed = 0;
1175 mt->pitch = mt->region->pitch;
1176 mt->depth_pitch = 0;
1177 mt->total_height = height;
1178 mt->level[0].level_offset = 0;
1179 mt->level[0].width = width;
1180 mt->level[0].height = height;
1181 mt->level[0].depth = 1;
1182 mt->level[0].nr_images = 1;
1183 mt->level[0].image_offset = NULL;
1184 mt->refcount = 1;
1185
1186 return mt;
1187 }
1188
1189
1190
1191 static void
1192 st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
1193 const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
1194 {
1195 struct st_fragment_program *stfp;
1196 struct st_vertex_program *stvp;
1197 struct st_context *st = ctx->st;
1198 struct pipe_mipmap_tree *mt;
1199
1200 stvp = make_vertex_shader(ctx->st, GL_TRUE);
1201 stfp = combined_bitmap_fragment_program(ctx);
1202
1203 st_validate_state(st);
1204
1205 mt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
1206 if (mt) {
1207 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
1208 width, height, 1.0, 1.0,
1209 mt, stvp, stfp,
1210 ctx->Current.RasterColor, GL_FALSE);
1211
1212 free_mipmap_tree(st->pipe, mt);
1213 }
1214 }
1215
1216
1217 static void
1218 copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
1219 GLsizei width, GLsizei height,
1220 GLint dstx, GLint dsty)
1221 {
1222 struct st_context *st = ctx->st;
1223 struct pipe_context *pipe = st->pipe;
1224 struct st_renderbuffer *rbRead = st_renderbuffer(ctx->ReadBuffer->_StencilBuffer);
1225 struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer);
1226 struct pipe_surface *psRead = rbRead->surface;
1227 struct pipe_surface *psDraw = rbDraw->surface;
1228 ubyte *readMap, *drawMap;
1229 ubyte *buffer;
1230 int i;
1231
1232 buffer = malloc(width * height * sizeof(ubyte));
1233 if (!buffer) {
1234 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
1235 return;
1236 }
1237
1238 /* map the stencil buffers */
1239 readMap = pipe->region_map(pipe, psRead->region);
1240 drawMap = pipe->region_map(pipe, psDraw->region);
1241
1242 /* this will do stencil pixel transfer ops */
1243 st_read_stencil_pixels(ctx, srcx, srcy, width, height, GL_UNSIGNED_BYTE,
1244 &ctx->DefaultPacking, buffer);
1245
1246 /* draw */
1247 /* XXX PixelZoom not handled yet */
1248 for (i = 0; i < height; i++) {
1249 ubyte *dst;
1250 const ubyte *src;
1251 int y;
1252
1253 y = dsty + i;
1254
1255 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1256 y = ctx->DrawBuffer->Height - y - 1;
1257 }
1258
1259 dst = drawMap + (y * psDraw->region->pitch + dstx) * psDraw->region->cpp;
1260 src = buffer + i * width;
1261
1262 switch (psDraw->format) {
1263 case PIPE_FORMAT_S8_Z24:
1264 {
1265 uint *dst4 = (uint *) dst;
1266 int j;
1267 for (j = 0; j < width; j++) {
1268 *dst4 = (*dst4 & 0xffffff) | (src[j] << 24);
1269 dst4++;
1270 }
1271 }
1272 break;
1273 case PIPE_FORMAT_U_S8:
1274 memcpy(dst, src, width);
1275 break;
1276 default:
1277 assert(0);
1278 }
1279 }
1280
1281 free(buffer);
1282
1283 /* unmap the stencil buffers */
1284 pipe->region_unmap(pipe, psRead->region);
1285 pipe->region_unmap(pipe, psDraw->region);
1286 }
1287
1288
1289 static void
1290 st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
1291 GLsizei width, GLsizei height,
1292 GLint dstx, GLint dsty, GLenum type)
1293 {
1294 struct st_context *st = ctx->st;
1295 struct pipe_context *pipe = st->pipe;
1296 struct st_renderbuffer *rbRead;
1297 struct st_vertex_program *stvp;
1298 struct st_fragment_program *stfp;
1299 struct pipe_surface *psRead;
1300 struct pipe_mipmap_tree *mt;
1301 GLfloat *color;
1302 uint format;
1303
1304 /* make sure rendering has completed */
1305 pipe->flush(pipe, 0x0);
1306
1307 st_validate_state(st);
1308
1309 if (type == GL_STENCIL) {
1310 /* can't use texturing to do stencil */
1311 copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
1312 return;
1313 }
1314
1315 if (type == GL_COLOR) {
1316 rbRead = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
1317 color = NULL;
1318 stfp = combined_drawpix_fragment_program(ctx);
1319 stvp = make_vertex_shader(ctx->st, GL_FALSE);
1320 }
1321 else {
1322 rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
1323 color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
1324 stfp = make_fragment_shader_z(ctx->st);
1325 stvp = make_vertex_shader(ctx->st, GL_TRUE);
1326 }
1327
1328 psRead = rbRead->surface;
1329 format = psRead->format;
1330
1331 mt = alloc_mipmap_tree(ctx->st, width, height, format);
1332 if (!mt)
1333 return;
1334
1335 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1336 srcy = ctx->DrawBuffer->Height - srcy - height;
1337 }
1338
1339 /* For some drivers (like Xlib) it's not possible to treat the
1340 * front/back color buffers as regions (they're XImages and Pixmaps).
1341 * So, this var tells us if we can use region_copy here...
1342 */
1343 if (st->haveFramebufferRegions) {
1344 /* copy source framebuffer region into mipmap/texture */
1345 pipe->region_copy(pipe,
1346 mt->region, /* dest */
1347 0, /* dest_offset */
1348 0, 0, /* destx/y */
1349 psRead->region,
1350 0, /* src_offset */
1351 srcx, srcy, width, height);
1352 }
1353 else {
1354 /* alternate path using get/put_tile() */
1355 struct pipe_surface *psTex;
1356 GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
1357
1358 psTex = pipe->get_tex_surface(pipe, mt, 0, 0, 0);
1359
1360 (void) pipe->region_map(pipe, psRead->region);
1361 (void) pipe->region_map(pipe, psTex->region);
1362
1363 pipe->get_tile_rgba(pipe, psRead, srcx, srcy, width, height, buf);
1364 pipe->put_tile_rgba(pipe, psTex, 0, 0, width, height, buf);
1365
1366 pipe->region_unmap(pipe, psRead->region);
1367 pipe->region_unmap(pipe, psTex->region);
1368
1369 pipe_surface_reference(&psTex, NULL);
1370
1371 free(buf);
1372 }
1373
1374
1375 /* draw textured quad */
1376 draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
1377 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
1378 mt, stvp, stfp, color, GL_TRUE);
1379
1380 free_mipmap_tree(st->pipe, mt);
1381 }
1382
1383
1384
1385 void st_init_drawpixels_functions(struct dd_function_table *functions)
1386 {
1387 functions->DrawPixels = st_DrawPixels;
1388 functions->CopyPixels = st_CopyPixels;
1389 functions->Bitmap = st_Bitmap;
1390 }