Merge master and fix conflicts
[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/bufferobj.h"
36 #include "main/macros.h"
37 #include "main/texformat.h"
38 #include "main/state.h"
39 #include "shader/program.h"
40 #include "shader/prog_parameter.h"
41 #include "shader/prog_print.h"
42
43 #include "st_context.h"
44 #include "st_atom.h"
45 #include "st_atom_constbuf.h"
46 #include "st_draw.h"
47 #include "st_program.h"
48 #include "st_cb_drawpixels.h"
49 #include "st_cb_readpixels.h"
50 #include "st_cb_fbo.h"
51 #include "st_cb_texture.h"
52 #include "st_draw.h"
53 #include "st_format.h"
54 #include "st_mesa_to_tgsi.h"
55 #include "st_texture.h"
56 #include "st_inlines.h"
57
58 #include "pipe/p_context.h"
59 #include "pipe/p_defines.h"
60 #include "pipe/p_inlines.h"
61 #include "util/u_tile.h"
62 #include "util/u_draw_quad.h"
63 #include "shader/prog_instruction.h"
64 #include "cso_cache/cso_context.h"
65
66
67 /**
68 * Check if the given program is:
69 * 0: MOVE result.color, fragment.color;
70 * 1: END;
71 */
72 static GLboolean
73 is_passthrough_program(const struct gl_fragment_program *prog)
74 {
75 if (prog->Base.NumInstructions == 2) {
76 const struct prog_instruction *inst = prog->Base.Instructions;
77 if (inst[0].Opcode == OPCODE_MOV &&
78 inst[1].Opcode == OPCODE_END &&
79 inst[0].DstReg.File == PROGRAM_OUTPUT &&
80 inst[0].DstReg.Index == FRAG_RESULT_COLOR &&
81 inst[0].DstReg.WriteMask == WRITEMASK_XYZW &&
82 inst[0].SrcReg[0].File == PROGRAM_INPUT &&
83 inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 &&
84 inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) {
85 return GL_TRUE;
86 }
87 }
88 return GL_FALSE;
89 }
90
91
92
93 /**
94 * Make fragment shader for glDraw/CopyPixels. This shader is made
95 * by combining the pixel transfer shader with the user-defined shader.
96 */
97 static struct st_fragment_program *
98 combined_drawpix_fragment_program(GLcontext *ctx)
99 {
100 struct st_context *st = ctx->st;
101 struct st_fragment_program *stfp;
102
103 if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn
104 && st->fp->serialNo == st->pixel_xfer.user_prog_sn) {
105 /* the pixel tranfer program has not changed and the user-defined
106 * program has not changed, so re-use the combined program.
107 */
108 stfp = st->pixel_xfer.combined_prog;
109 }
110 else {
111 /* Concatenate the pixel transfer program with the current user-
112 * defined program.
113 */
114 if (is_passthrough_program(&st->fp->Base)) {
115 stfp = (struct st_fragment_program *)
116 _mesa_clone_program(ctx, &st->pixel_xfer.program->Base.Base);
117 }
118 else {
119 #if 0
120 printf("Base program:\n");
121 _mesa_print_program(&st->fp->Base.Base);
122 printf("DrawPix program:\n");
123 _mesa_print_program(&st->pixel_xfer.program->Base.Base);
124 #endif
125 stfp = (struct st_fragment_program *)
126 _mesa_combine_programs(ctx,
127 &st->pixel_xfer.program->Base.Base,
128 &st->fp->Base.Base);
129 }
130
131 #if 0
132 {
133 struct gl_program *p = &stfp->Base.Base;
134 printf("Combined DrawPixels program:\n");
135 _mesa_print_program(p);
136 printf("InputsRead: 0x%x\n", p->InputsRead);
137 printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
138 _mesa_print_parameter_list(p->Parameters);
139 }
140 #endif
141
142 /* translate to TGSI tokens */
143 st_translate_fragment_program(st, stfp, NULL);
144
145 /* save new program, update serial numbers */
146 st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
147 st->pixel_xfer.user_prog_sn = st->fp->serialNo;
148 st->pixel_xfer.combined_prog_sn = stfp->serialNo;
149 /* can't reference new program directly, already have a reference on it */
150 st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
151 st->pixel_xfer.combined_prog = stfp;
152 }
153
154 /* Ideally we'd have updated the pipe constants during the normal
155 * st/atom mechanism. But we can't since this is specific to glDrawPixels.
156 */
157 st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
158
159 return stfp;
160 }
161
162
163 /**
164 * Create fragment shader that does a TEX() instruction to get a Z
165 * value, then writes to FRAG_RESULT_DEPTH.
166 * Pass fragment color through as-is.
167 */
168 static struct st_fragment_program *
169 make_fragment_shader_z(struct st_context *st)
170 {
171 GLcontext *ctx = st->ctx;
172 struct gl_program *p;
173 GLuint ic = 0;
174
175 if (st->drawpix.z_shader) {
176 return st->drawpix.z_shader;
177 }
178
179 /*
180 * Create shader now
181 */
182 p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
183 if (!p)
184 return NULL;
185
186 p->NumInstructions = 3;
187
188 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
189 if (!p->Instructions) {
190 ctx->Driver.DeleteProgram(ctx, p);
191 return NULL;
192 }
193 _mesa_init_instructions(p->Instructions, p->NumInstructions);
194
195 /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */
196 p->Instructions[ic].Opcode = OPCODE_TEX;
197 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
198 p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPTH;
199 p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z;
200 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
201 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
202 p->Instructions[ic].TexSrcUnit = 0;
203 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
204 ic++;
205
206 /* MOV result.color, fragment.color */
207 p->Instructions[ic].Opcode = OPCODE_MOV;
208 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
209 p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLOR;
210 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
211 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0;
212 ic++;
213
214 /* END; */
215 p->Instructions[ic++].Opcode = OPCODE_END;
216
217 assert(ic == p->NumInstructions);
218
219 p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
220 p->OutputsWritten = (1 << FRAG_RESULT_COLOR) | (1 << FRAG_RESULT_DEPTH);
221 p->SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */
222
223 st->drawpix.z_shader = (struct st_fragment_program *) p;
224 st_translate_fragment_program(st, st->drawpix.z_shader, NULL);
225
226 return st->drawpix.z_shader;
227 }
228
229
230
231 /**
232 * Create a simple vertex shader that just passes through the
233 * vertex position and texcoord (and optionally, color).
234 */
235 static struct st_vertex_program *
236 st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor)
237 {
238 GLcontext *ctx = st->ctx;
239 struct st_vertex_program *stvp;
240 struct gl_program *p;
241 GLuint ic = 0;
242
243 if (st->drawpix.vert_shaders[passColor])
244 return st->drawpix.vert_shaders[passColor];
245
246 /*
247 * Create shader now
248 */
249 p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
250 if (!p)
251 return NULL;
252
253 if (passColor)
254 p->NumInstructions = 4;
255 else
256 p->NumInstructions = 3;
257
258 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
259 if (!p->Instructions) {
260 ctx->Driver.DeleteProgram(ctx, p);
261 return NULL;
262 }
263 _mesa_init_instructions(p->Instructions, p->NumInstructions);
264 /* MOV result.pos, vertex.pos; */
265 p->Instructions[0].Opcode = OPCODE_MOV;
266 p->Instructions[0].DstReg.File = PROGRAM_OUTPUT;
267 p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS;
268 p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT;
269 p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS;
270 /* MOV result.texcoord0, vertex.texcoord0; */
271 p->Instructions[1].Opcode = OPCODE_MOV;
272 p->Instructions[1].DstReg.File = PROGRAM_OUTPUT;
273 p->Instructions[1].DstReg.Index = VERT_RESULT_TEX0;
274 p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT;
275 p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_TEX0;
276 ic = 2;
277 if (passColor) {
278 /* MOV result.color0, vertex.color0; */
279 p->Instructions[ic].Opcode = OPCODE_MOV;
280 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
281 p->Instructions[ic].DstReg.Index = VERT_RESULT_COL0;
282 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
283 p->Instructions[ic].SrcReg[0].Index = VERT_ATTRIB_COLOR0;
284 ic++;
285 }
286
287 /* END; */
288 p->Instructions[ic].Opcode = OPCODE_END;
289 ic++;
290
291 assert(ic == p->NumInstructions);
292
293 p->InputsRead = VERT_BIT_POS | VERT_BIT_TEX0;
294 p->OutputsWritten = ((1 << VERT_RESULT_TEX0) |
295 (1 << VERT_RESULT_HPOS));
296 if (passColor) {
297 p->InputsRead |= VERT_BIT_COLOR0;
298 p->OutputsWritten |= (1 << VERT_RESULT_COL0);
299 }
300
301 stvp = (struct st_vertex_program *) p;
302 st_translate_vertex_program(st, stvp, NULL, NULL, NULL);
303
304 st->drawpix.vert_shaders[passColor] = stvp;
305
306 return stvp;
307 }
308
309
310 static GLenum
311 _mesa_base_format(GLenum format)
312 {
313 switch (format) {
314 case GL_DEPTH_COMPONENT:
315 return GL_DEPTH_COMPONENT;
316 case GL_DEPTH_STENCIL:
317 return GL_DEPTH_STENCIL;
318 case GL_STENCIL_INDEX:
319 return GL_STENCIL_INDEX;
320 default:
321 return GL_RGBA;
322 }
323 }
324
325
326 /**
327 * Make texture containing an image for glDrawPixels image.
328 * If 'pixels' is NULL, leave the texture image data undefined.
329 */
330 static struct pipe_texture *
331 make_texture(struct st_context *st,
332 GLsizei width, GLsizei height, GLenum format, GLenum type,
333 const struct gl_pixelstore_attrib *unpack,
334 const GLvoid *pixels)
335 {
336 GLcontext *ctx = st->ctx;
337 struct pipe_context *pipe = st->pipe;
338 struct pipe_screen *screen = pipe->screen;
339 const struct gl_texture_format *mformat;
340 struct pipe_texture *pt;
341 enum pipe_format pipeFormat;
342 GLuint cpp;
343 GLenum baseFormat;
344
345 baseFormat = _mesa_base_format(format);
346
347 mformat = st_ChooseTextureFormat(ctx, baseFormat, format, type);
348 assert(mformat);
349
350 pipeFormat = st_mesa_format_to_pipe_format(mformat->MesaFormat);
351 assert(pipeFormat);
352 cpp = st_sizeof_format(pipeFormat);
353
354 pixels = _mesa_map_drawpix_pbo(ctx, unpack, pixels);
355 if (!pixels)
356 return NULL;
357
358 pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height, 1,
359 PIPE_TEXTURE_USAGE_SAMPLER);
360 if (!pt) {
361 _mesa_unmap_drawpix_pbo(ctx, unpack);
362 return NULL;
363 }
364
365 {
366 struct pipe_transfer *transfer;
367 static const GLuint dstImageOffsets = 0;
368 GLboolean success;
369 GLubyte *dest;
370 const GLbitfield imageTransferStateSave = ctx->_ImageTransferState;
371
372 /* we'll do pixel transfer in a fragment shader */
373 ctx->_ImageTransferState = 0x0;
374
375 transfer = st_no_flush_get_tex_transfer(st, pt, 0, 0, 0,
376 PIPE_TRANSFER_WRITE, 0, 0,
377 width, height);
378
379 /* map texture transfer */
380 dest = screen->transfer_map(screen, transfer);
381
382 /* Put image into texture transfer.
383 * Note that the image is actually going to be upside down in
384 * the texture. We deal with that with texcoords.
385 */
386 success = mformat->StoreImage(ctx, 2, /* dims */
387 baseFormat, /* baseInternalFormat */
388 mformat, /* gl_texture_format */
389 dest, /* dest */
390 0, 0, 0, /* dstX/Y/Zoffset */
391 transfer->stride, /* dstRowStride, bytes */
392 &dstImageOffsets, /* dstImageOffsets */
393 width, height, 1, /* size */
394 format, type, /* src format/type */
395 pixels, /* data source */
396 unpack);
397
398 /* unmap */
399 screen->transfer_unmap(screen, transfer);
400 screen->tex_transfer_destroy(transfer);
401
402 assert(success);
403
404 /* restore */
405 ctx->_ImageTransferState = imageTransferStateSave;
406 }
407
408 _mesa_unmap_drawpix_pbo(ctx, unpack);
409
410 return pt;
411 }
412
413
414 /**
415 * Draw quad with texcoords and optional color.
416 * Coords are window coords with y=0=bottom.
417 * \param color may be null
418 * \param invertTex if true, flip texcoords vertically
419 */
420 static void
421 draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
422 GLfloat x1, GLfloat y1, const GLfloat *color,
423 GLboolean invertTex)
424 {
425 struct st_context *st = ctx->st;
426 struct pipe_context *pipe = ctx->st->pipe;
427 GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */
428
429 /* setup vertex data */
430 {
431 const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
432 const GLfloat fb_width = (GLfloat) fb->Width;
433 const GLfloat fb_height = (GLfloat) fb->Height;
434 const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f;
435 const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f;
436 const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f;
437 const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f;
438 const GLfloat sLeft = 0.0f, sRight = 1.0f;
439 const GLfloat tTop = invertTex, tBot = 1.0f - tTop;
440 GLuint tex, i;
441
442 /* upper-left */
443 verts[0][0][0] = clip_x0; /* v[0].attr[0].x */
444 verts[0][0][1] = clip_y0; /* v[0].attr[0].y */
445
446 /* upper-right */
447 verts[1][0][0] = clip_x1;
448 verts[1][0][1] = clip_y0;
449
450 /* lower-right */
451 verts[2][0][0] = clip_x1;
452 verts[2][0][1] = clip_y1;
453
454 /* lower-left */
455 verts[3][0][0] = clip_x0;
456 verts[3][0][1] = clip_y1;
457
458 tex = color ? 2 : 1;
459 verts[0][tex][0] = sLeft; /* v[0].attr[tex].s */
460 verts[0][tex][1] = tTop; /* v[0].attr[tex].t */
461 verts[1][tex][0] = sRight;
462 verts[1][tex][1] = tTop;
463 verts[2][tex][0] = sRight;
464 verts[2][tex][1] = tBot;
465 verts[3][tex][0] = sLeft;
466 verts[3][tex][1] = tBot;
467
468 /* same for all verts: */
469 if (color) {
470 for (i = 0; i < 4; i++) {
471 verts[i][0][2] = z; /*Z*/
472 verts[i][0][3] = 1.0f; /*W*/
473 verts[i][1][0] = color[0];
474 verts[i][1][1] = color[1];
475 verts[i][1][2] = color[2];
476 verts[i][1][3] = color[3];
477 verts[i][2][2] = 0.0f; /*R*/
478 verts[i][2][3] = 1.0f; /*Q*/
479 }
480 }
481 else {
482 for (i = 0; i < 4; i++) {
483 verts[i][0][2] = z; /*Z*/
484 verts[i][0][3] = 1.0f; /*W*/
485 verts[i][1][2] = 0.0f; /*R*/
486 verts[i][1][3] = 1.0f; /*Q*/
487 }
488 }
489 }
490
491 {
492 struct pipe_buffer *buf;
493
494 /* allocate/load buffer object with vertex data */
495 buf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
496 sizeof(verts));
497 st_no_flush_pipe_buffer_write(st, buf, 0, sizeof(verts), verts);
498
499 util_draw_vertex_buffer(pipe, buf, 0,
500 PIPE_PRIM_QUADS,
501 4, /* verts */
502 3); /* attribs/vert */
503 pipe_buffer_reference(&buf, NULL);
504 }
505 }
506
507
508
509 static void
510 draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
511 GLsizei width, GLsizei height,
512 GLfloat zoomX, GLfloat zoomY,
513 struct pipe_texture *pt,
514 struct st_vertex_program *stvp,
515 struct st_fragment_program *stfp,
516 const GLfloat *color,
517 GLboolean invertTex)
518 {
519 struct st_context *st = ctx->st;
520 struct pipe_context *pipe = ctx->st->pipe;
521 struct cso_context *cso = ctx->st->cso_context;
522 GLfloat x0, y0, x1, y1;
523 GLsizei maxSize;
524
525 /* limit checks */
526 /* XXX if DrawPixels image is larger than max texture size, break
527 * it up into chunks.
528 */
529 maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
530 assert(width <= maxSize);
531 assert(height <= maxSize);
532
533 cso_save_rasterizer(cso);
534 cso_save_viewport(cso);
535 cso_save_samplers(cso);
536 cso_save_sampler_textures(cso);
537 cso_save_fragment_shader(cso);
538 cso_save_vertex_shader(cso);
539
540 /* rasterizer state: just scissor */
541 {
542 struct pipe_rasterizer_state rasterizer;
543 memset(&rasterizer, 0, sizeof(rasterizer));
544 rasterizer.gl_rasterization_rules = 1;
545 rasterizer.scissor = ctx->Scissor.Enabled;
546 cso_set_rasterizer(cso, &rasterizer);
547 }
548
549 /* fragment shader state: TEX lookup program */
550 cso_set_fragment_shader_handle(cso, stfp->driver_shader);
551
552 /* vertex shader state: position + texcoord pass-through */
553 cso_set_vertex_shader_handle(cso, stvp->driver_shader);
554
555
556 /* texture sampling state: */
557 {
558 struct pipe_sampler_state sampler;
559 memset(&sampler, 0, sizeof(sampler));
560 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
561 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
562 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP;
563 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
564 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
565 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
566 sampler.normalized_coords = 1;
567
568 cso_single_sampler(cso, 0, &sampler);
569 if (st->pixel_xfer.pixelmap_enabled) {
570 cso_single_sampler(cso, 1, &sampler);
571 }
572 cso_single_sampler_done(cso);
573 }
574
575 /* viewport state: viewport matching window dims */
576 {
577 const float width = (float) ctx->DrawBuffer->Width;
578 const float height = (float) ctx->DrawBuffer->Height;
579 struct pipe_viewport_state vp;
580 vp.scale[0] = 0.5f * width;
581 vp.scale[1] = -0.5f * height;
582 vp.scale[2] = 1.0f;
583 vp.scale[3] = 1.0f;
584 vp.translate[0] = 0.5f * width;
585 vp.translate[1] = 0.5f * height;
586 vp.translate[2] = 0.0f;
587 vp.translate[3] = 0.0f;
588 cso_set_viewport(cso, &vp);
589 }
590
591 /* texture state: */
592 if (st->pixel_xfer.pixelmap_enabled) {
593 struct pipe_texture *textures[2];
594 textures[0] = pt;
595 textures[1] = st->pixel_xfer.pixelmap_texture;
596 pipe->set_sampler_textures(pipe, 2, textures);
597 }
598 else {
599 pipe->set_sampler_textures(pipe, 1, &pt);
600 }
601
602 /* Compute window coords (y=0=bottom) with pixel zoom.
603 * Recall that these coords are transformed by the current
604 * vertex shader and viewport transformation.
605 */
606 x0 = (GLfloat) x;
607 x1 = x + width * ctx->Pixel.ZoomX;
608 y0 = (GLfloat) y;
609 y1 = y + height * ctx->Pixel.ZoomY;
610
611 draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex);
612
613 /* restore state */
614 cso_restore_rasterizer(cso);
615 cso_restore_viewport(cso);
616 cso_restore_samplers(cso);
617 cso_restore_sampler_textures(cso);
618 cso_restore_fragment_shader(cso);
619 cso_restore_vertex_shader(cso);
620 }
621
622
623 static void
624 draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
625 GLsizei width, GLsizei height, GLenum format, GLenum type,
626 const struct gl_pixelstore_attrib *unpack,
627 const GLvoid *pixels)
628 {
629 struct st_context *st = ctx->st;
630 struct pipe_context *pipe = st->pipe;
631 struct pipe_screen *screen = pipe->screen;
632 struct st_renderbuffer *strb;
633 enum pipe_transfer_usage usage;
634 struct pipe_transfer *pt;
635 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
636 GLint skipPixels;
637 ubyte *stmap;
638
639 strb = st_renderbuffer(ctx->DrawBuffer->
640 Attachment[BUFFER_STENCIL].Renderbuffer);
641
642 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
643 y = ctx->DrawBuffer->Height - y - height;
644 }
645
646 if(format != GL_DEPTH_STENCIL &&
647 pf_get_component_bits( strb->format, PIPE_FORMAT_COMP_Z ) != 0)
648 usage = PIPE_TRANSFER_READ_WRITE;
649 else
650 usage = PIPE_TRANSFER_WRITE;
651
652 pt = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture, 0, 0, 0,
653 usage, x, y,
654 width, height);
655
656 stmap = screen->transfer_map(screen, pt);
657
658 pixels = _mesa_map_drawpix_pbo(ctx, unpack, pixels);
659 assert(pixels);
660
661 /* if width > MAX_WIDTH, have to process image in chunks */
662 skipPixels = 0;
663 while (skipPixels < width) {
664 const GLint spanX = skipPixels;
665 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
666 GLint row;
667 for (row = 0; row < height; row++) {
668 GLubyte sValues[MAX_WIDTH];
669 GLuint zValues[MAX_WIDTH];
670 GLenum destType = GL_UNSIGNED_BYTE;
671 const GLvoid *source = _mesa_image_address2d(unpack, pixels,
672 width, height,
673 format, type,
674 row, skipPixels);
675 _mesa_unpack_stencil_span(ctx, spanWidth, destType, sValues,
676 type, source, unpack,
677 ctx->_ImageTransferState);
678
679 if (format == GL_DEPTH_STENCIL) {
680 _mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues,
681 (1 << 24) - 1, type, source, unpack);
682 }
683
684 if (zoom) {
685 _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with "
686 "zoom not complete");
687 }
688
689 {
690 GLint spanY;
691
692 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
693 spanY = height - row - 1;
694 }
695 else {
696 spanY = row;
697 }
698
699 /* now pack the stencil (and Z) values in the dest format */
700 switch (pt->format) {
701 case PIPE_FORMAT_S8_UNORM:
702 {
703 ubyte *dest = stmap + spanY * pt->stride + spanX;
704 assert(usage == PIPE_TRANSFER_WRITE);
705 memcpy(dest, sValues, spanWidth);
706 }
707 break;
708 case PIPE_FORMAT_S8Z24_UNORM:
709 if (format == GL_DEPTH_STENCIL) {
710 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
711 GLint k;
712 assert(usage == PIPE_TRANSFER_WRITE);
713 for (k = 0; k < spanWidth; k++) {
714 dest[k] = zValues[k] | (sValues[k] << 24);
715 }
716 }
717 else {
718 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
719 GLint k;
720 assert(usage == PIPE_TRANSFER_READ_WRITE);
721 for (k = 0; k < spanWidth; k++) {
722 dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24);
723 }
724 }
725 break;
726 case PIPE_FORMAT_Z24S8_UNORM:
727 if (format == GL_DEPTH_STENCIL) {
728 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
729 GLint k;
730 assert(usage == PIPE_TRANSFER_WRITE);
731 for (k = 0; k < spanWidth; k++) {
732 dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff);
733 }
734 }
735 else {
736 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
737 GLint k;
738 assert(usage == PIPE_TRANSFER_READ_WRITE);
739 for (k = 0; k < spanWidth; k++) {
740 dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff);
741 }
742 }
743 break;
744 default:
745 assert(0);
746 }
747 }
748 }
749 skipPixels += spanWidth;
750 }
751
752 _mesa_unmap_drawpix_pbo(ctx, unpack);
753
754 /* unmap the stencil buffer */
755 screen->transfer_unmap(screen, pt);
756 screen->tex_transfer_destroy(pt);
757 }
758
759
760 /**
761 * Called via ctx->Driver.DrawPixels()
762 */
763 static void
764 st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
765 GLenum format, GLenum type,
766 const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
767 {
768 struct st_fragment_program *stfp;
769 struct st_vertex_program *stvp;
770 struct st_context *st = ctx->st;
771 struct pipe_surface *ps;
772 const GLfloat *color;
773
774 if (format == GL_STENCIL_INDEX ||
775 format == GL_DEPTH_STENCIL) {
776 draw_stencil_pixels(ctx, x, y, width, height, format, type,
777 unpack, pixels);
778 return;
779 }
780
781 _mesa_set_vp_override( ctx, TRUE );
782 _mesa_update_state( ctx );
783
784 st_validate_state(st);
785
786 if (format == GL_DEPTH_COMPONENT) {
787 ps = st->state.framebuffer.zsbuf;
788 stfp = make_fragment_shader_z(ctx->st);
789 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE);
790 color = ctx->Current.RasterColor;
791 }
792 else {
793 ps = st->state.framebuffer.cbufs[0];
794 stfp = combined_drawpix_fragment_program(ctx);
795 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE);
796 color = NULL;
797 }
798
799 /* draw with textured quad */
800 {
801 struct pipe_texture *pt
802 = make_texture(ctx->st, width, height, format, type, unpack, pixels);
803 if (pt) {
804 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
805 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
806 pt, stvp, stfp, color, GL_FALSE);
807 pipe_texture_reference(&pt, NULL);
808 }
809 }
810
811 _mesa_set_vp_override( ctx, FALSE );
812 }
813
814
815
816 static void
817 copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
818 GLsizei width, GLsizei height,
819 GLint dstx, GLint dsty)
820 {
821 struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer);
822 struct pipe_screen *screen = ctx->st->pipe->screen;
823 enum pipe_transfer_usage usage;
824 struct pipe_transfer *ptDraw;
825 ubyte *drawMap;
826 ubyte *buffer;
827 int i;
828
829 buffer = _mesa_malloc(width * height * sizeof(ubyte));
830 if (!buffer) {
831 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
832 return;
833 }
834
835 /* this will do stencil pixel transfer ops */
836 st_read_stencil_pixels(ctx, srcx, srcy, width, height,
837 GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
838 &ctx->DefaultPacking, buffer);
839
840 if(pf_get_component_bits( rbDraw->format, PIPE_FORMAT_COMP_Z ) != 0)
841 usage = PIPE_TRANSFER_READ_WRITE;
842 else
843 usage = PIPE_TRANSFER_WRITE;
844
845 ptDraw = st_cond_flush_get_tex_transfer(st_context(ctx),
846 rbDraw->texture, 0, 0, 0,
847 usage, dstx, dsty,
848 width, height);
849
850 assert(ptDraw->block.width == 1);
851 assert(ptDraw->block.height == 1);
852
853 /* map the stencil buffer */
854 drawMap = screen->transfer_map(screen, ptDraw);
855
856 /* draw */
857 /* XXX PixelZoom not handled yet */
858 for (i = 0; i < height; i++) {
859 ubyte *dst;
860 const ubyte *src;
861 int y;
862
863 y = i;
864
865 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
866 y = height - y - 1;
867 }
868
869 dst = drawMap + y * ptDraw->stride;
870 src = buffer + i * width;
871
872 switch (ptDraw->format) {
873 case PIPE_FORMAT_S8Z24_UNORM:
874 {
875 uint *dst4 = (uint *) dst;
876 int j;
877 assert(usage == PIPE_TRANSFER_READ_WRITE);
878 for (j = 0; j < width; j++) {
879 *dst4 = (*dst4 & 0xffffff) | (src[j] << 24);
880 dst4++;
881 }
882 }
883 break;
884 case PIPE_FORMAT_Z24S8_UNORM:
885 {
886 uint *dst4 = (uint *) dst;
887 int j;
888 assert(usage == PIPE_TRANSFER_READ_WRITE);
889 for (j = 0; j < width; j++) {
890 *dst4 = (*dst4 & 0xffffff00) | (src[j] & 0xff);
891 dst4++;
892 }
893 }
894 break;
895 case PIPE_FORMAT_S8_UNORM:
896 assert(usage == PIPE_TRANSFER_WRITE);
897 memcpy(dst, src, width);
898 break;
899 default:
900 assert(0);
901 }
902 }
903
904 _mesa_free(buffer);
905
906 /* unmap the stencil buffer */
907 screen->transfer_unmap(screen, ptDraw);
908 screen->tex_transfer_destroy(ptDraw);
909 }
910
911
912 static void
913 st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
914 GLsizei width, GLsizei height,
915 GLint dstx, GLint dsty, GLenum type)
916 {
917 struct st_context *st = ctx->st;
918 struct pipe_context *pipe = st->pipe;
919 struct pipe_screen *screen = pipe->screen;
920 struct st_renderbuffer *rbRead;
921 struct st_vertex_program *stvp;
922 struct st_fragment_program *stfp;
923 struct pipe_texture *pt;
924 GLfloat *color;
925 enum pipe_format srcFormat, texFormat;
926
927 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
928
929 st_validate_state(st);
930
931 if (srcx < 0) {
932 width -= -srcx;
933 dstx += -srcx;
934 srcx = 0;
935 }
936
937 if (srcy < 0) {
938 height -= -srcy;
939 dsty += -srcy;
940 srcy = 0;
941 }
942
943 if (dstx < 0) {
944 width -= -dstx;
945 srcx += -dstx;
946 dstx = 0;
947 }
948
949 if (dsty < 0) {
950 height -= -dsty;
951 srcy += -dsty;
952 dsty = 0;
953 }
954
955 if (width < 0 || height < 0)
956 return;
957
958
959 if (type == GL_STENCIL) {
960 /* can't use texturing to do stencil */
961 copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
962 return;
963 }
964
965 if (type == GL_COLOR) {
966 rbRead = st_get_color_read_renderbuffer(ctx);
967 color = NULL;
968 stfp = combined_drawpix_fragment_program(ctx);
969 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE);
970 }
971 else {
972 assert(type == GL_DEPTH);
973 rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
974 color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
975 stfp = make_fragment_shader_z(ctx->st);
976 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE);
977 }
978
979 srcFormat = rbRead->texture->format;
980
981 if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE_2D,
982 PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
983 texFormat = srcFormat;
984 }
985 else {
986 /* srcFormat can't be used as a texture format */
987 if (type == GL_DEPTH) {
988 texFormat = st_choose_format(pipe, GL_DEPTH_COMPONENT, PIPE_TEXTURE_2D,
989 PIPE_TEXTURE_USAGE_DEPTH_STENCIL);
990 assert(texFormat != PIPE_FORMAT_NONE); /* XXX no depth texture formats??? */
991 }
992 else {
993 /* default color format */
994 texFormat = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D,
995 PIPE_TEXTURE_USAGE_SAMPLER);
996 assert(texFormat != PIPE_FORMAT_NONE);
997 }
998 }
999
1000 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1001 srcy = ctx->DrawBuffer->Height - srcy - height;
1002
1003 if (srcy < 0) {
1004 height -= -srcy;
1005 srcy = 0;
1006 }
1007
1008 if (height < 0)
1009 return;
1010 }
1011
1012 pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0,
1013 width, height, 1,
1014 PIPE_TEXTURE_USAGE_SAMPLER);
1015 if (!pt)
1016 return;
1017
1018
1019 if (srcFormat == texFormat) {
1020 /* copy source framebuffer surface into mipmap/texture */
1021 struct pipe_surface *psRead = screen->get_tex_surface(screen,
1022 rbRead->texture, 0, 0, 0,
1023 PIPE_BUFFER_USAGE_GPU_READ);
1024 struct pipe_surface *psTex = screen->get_tex_surface(screen, pt, 0, 0, 0,
1025 PIPE_BUFFER_USAGE_GPU_WRITE );
1026 pipe->surface_copy(pipe,
1027 psTex, /* dest */
1028 0, 0, /* destx/y */
1029 psRead,
1030 srcx, srcy, width, height);
1031 pipe_surface_reference(&psRead, NULL);
1032 pipe_surface_reference(&psTex, NULL);
1033 }
1034 else {
1035 /* CPU-based fallback/conversion */
1036 struct pipe_transfer *ptRead =
1037 st_cond_flush_get_tex_transfer(st, rbRead->texture, 0, 0, 0,
1038 PIPE_TRANSFER_READ, srcx, srcy, width,
1039 height);
1040
1041 struct pipe_transfer *ptTex =
1042 st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, PIPE_TRANSFER_WRITE,
1043 0, 0, width, height);
1044
1045 if (type == GL_COLOR) {
1046 /* alternate path using get/put_tile() */
1047 GLfloat *buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
1048
1049 pipe_get_tile_rgba(ptRead, 0, 0, width, height, buf);
1050 pipe_put_tile_rgba(ptTex, 0, 0, width, height, buf);
1051
1052 _mesa_free(buf);
1053 }
1054 else {
1055 /* GL_DEPTH */
1056 GLuint *buf = (GLuint *) _mesa_malloc(width * height * sizeof(GLuint));
1057 pipe_get_tile_z(ptRead, 0, 0, width, height, buf);
1058 pipe_put_tile_z(ptTex, 0, 0, width, height, buf);
1059 _mesa_free(buf);
1060 }
1061
1062 screen->tex_transfer_destroy(ptRead);
1063 screen->tex_transfer_destroy(ptTex);
1064 }
1065
1066 /* draw textured quad */
1067 draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
1068 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
1069 pt, stvp, stfp, color, GL_TRUE);
1070
1071 pipe_texture_reference(&pt, NULL);
1072 }
1073
1074
1075
1076 void st_init_drawpixels_functions(struct dd_function_table *functions)
1077 {
1078 functions->DrawPixels = st_DrawPixels;
1079 functions->CopyPixels = st_CopyPixels;
1080 }
1081
1082
1083 void
1084 st_destroy_drawpix(struct st_context *st)
1085 {
1086 st_reference_fragprog(st, &st->drawpix.z_shader, NULL);
1087 st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
1088 st_reference_vertprog(st, &st->drawpix.vert_shaders[0], NULL);
1089 st_reference_vertprog(st, &st->drawpix.vert_shaders[1], NULL);
1090 }