OSDN Git Service

i965/vec4: Fix confusion between SWIZZLE and BRW_SWIZZLE macros.
[android-x86/external-mesa.git] / src / mesa / state_tracker / st_cb_drawpixels.c
1 /**************************************************************************
2  * 
3  * Copyright 2007 VMware, Inc.
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 VMWARE 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/format_pack.h"
37 #include "main/macros.h"
38 #include "main/mtypes.h"
39 #include "main/pack.h"
40 #include "main/pbo.h"
41 #include "main/readpix.h"
42 #include "main/texformat.h"
43 #include "main/teximage.h"
44 #include "main/texstore.h"
45 #include "main/glformats.h"
46 #include "program/program.h"
47 #include "program/prog_print.h"
48 #include "program/prog_instruction.h"
49
50 #include "st_atom.h"
51 #include "st_atom_constbuf.h"
52 #include "st_cb_drawpixels.h"
53 #include "st_cb_readpixels.h"
54 #include "st_cb_fbo.h"
55 #include "st_context.h"
56 #include "st_debug.h"
57 #include "st_format.h"
58 #include "st_program.h"
59 #include "st_texture.h"
60
61 #include "pipe/p_context.h"
62 #include "pipe/p_defines.h"
63 #include "tgsi/tgsi_ureg.h"
64 #include "util/u_draw_quad.h"
65 #include "util/u_format.h"
66 #include "util/u_inlines.h"
67 #include "util/u_math.h"
68 #include "util/u_tile.h"
69 #include "util/u_upload_mgr.h"
70 #include "cso_cache/cso_context.h"
71
72
73 /**
74  * Check if the given program is:
75  * 0: MOVE result.color, fragment.color;
76  * 1: END;
77  */
78 static GLboolean
79 is_passthrough_program(const struct gl_fragment_program *prog)
80 {
81    if (prog->Base.NumInstructions == 2) {
82       const struct prog_instruction *inst = prog->Base.Instructions;
83       if (inst[0].Opcode == OPCODE_MOV &&
84           inst[1].Opcode == OPCODE_END &&
85           inst[0].DstReg.File == PROGRAM_OUTPUT &&
86           inst[0].DstReg.Index == FRAG_RESULT_COLOR &&
87           inst[0].DstReg.WriteMask == WRITEMASK_XYZW &&
88           inst[0].SrcReg[0].File == PROGRAM_INPUT &&
89           inst[0].SrcReg[0].Index == VARYING_SLOT_COL0 &&
90           inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) {
91          return GL_TRUE;
92       }
93    }
94    return GL_FALSE;
95 }
96
97
98 /**
99  * Returns a fragment program which implements the current pixel transfer ops.
100  */
101 static struct gl_fragment_program *
102 get_glsl_pixel_transfer_program(struct st_context *st,
103                                 struct st_fragment_program *orig)
104 {
105    int pixelMaps = 0, scaleAndBias = 0;
106    struct gl_context *ctx = st->ctx;
107    struct st_fragment_program *fp = (struct st_fragment_program *)
108       ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
109
110    if (!fp)
111       return NULL;
112
113    if (ctx->Pixel.RedBias != 0.0 || ctx->Pixel.RedScale != 1.0 ||
114        ctx->Pixel.GreenBias != 0.0 || ctx->Pixel.GreenScale != 1.0 ||
115        ctx->Pixel.BlueBias != 0.0 || ctx->Pixel.BlueScale != 1.0 ||
116        ctx->Pixel.AlphaBias != 0.0 || ctx->Pixel.AlphaScale != 1.0) {
117       scaleAndBias = 1;
118    }
119
120    pixelMaps = ctx->Pixel.MapColorFlag;
121
122    if (pixelMaps) {
123       /* create the colormap/texture now if not already done */
124       if (!st->pixel_xfer.pixelmap_texture) {
125          st->pixel_xfer.pixelmap_texture = st_create_color_map_texture(ctx);
126          st->pixel_xfer.pixelmap_sampler_view =
127             st_create_texture_sampler_view(st->pipe,
128                                            st->pixel_xfer.pixelmap_texture);
129       }
130    }
131
132    get_pixel_transfer_visitor(fp, orig->glsl_to_tgsi,
133                               scaleAndBias, pixelMaps);
134
135    return &fp->Base;
136 }
137
138
139 /**
140  * Make fragment shader for glDraw/CopyPixels.  This shader is made
141  * by combining the pixel transfer shader with the user-defined shader.
142  * \param fpIn  the current/incoming fragment program
143  * \param fpOut  returns the combined fragment program
144  */
145 void
146 st_make_drawpix_fragment_program(struct st_context *st,
147                                  struct gl_fragment_program *fpIn,
148                                  struct gl_fragment_program **fpOut)
149 {
150    struct gl_program *newProg;
151    struct st_fragment_program *stfp = (struct st_fragment_program *) fpIn;
152
153    if (is_passthrough_program(fpIn)) {
154       newProg = (struct gl_program *) _mesa_clone_fragment_program(st->ctx,
155                                              &st->pixel_xfer.program->Base);
156    }
157    else if (stfp->glsl_to_tgsi != NULL) {
158       newProg = (struct gl_program *) get_glsl_pixel_transfer_program(st, stfp);
159    }
160    else {
161 #if 0
162       /* debug */
163       printf("Base program:\n");
164       _mesa_print_program(&fpIn->Base);
165       printf("DrawPix program:\n");
166       _mesa_print_program(&st->pixel_xfer.program->Base.Base);
167 #endif
168       newProg = _mesa_combine_programs(st->ctx,
169                                        &st->pixel_xfer.program->Base.Base,
170                                        &fpIn->Base);
171    }
172
173 #if 0
174    /* debug */
175    printf("Combined DrawPixels program:\n");
176    _mesa_print_program(newProg);
177    printf("InputsRead: 0x%x\n", newProg->InputsRead);
178    printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten);
179    _mesa_print_parameter_list(newProg->Parameters);
180 #endif
181
182    *fpOut = (struct gl_fragment_program *) newProg;
183 }
184
185
186 /**
187  * Create fragment program that does a TEX() instruction to get a Z and/or
188  * stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL.
189  * Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX).
190  * Pass fragment color through as-is.
191  * \return pointer to the gl_fragment program
192  */
193 struct gl_fragment_program *
194 st_make_drawpix_z_stencil_program(struct st_context *st,
195                                   GLboolean write_depth,
196                                   GLboolean write_stencil)
197 {
198    struct gl_context *ctx = st->ctx;
199    struct gl_program *p;
200    struct gl_fragment_program *fp;
201    GLuint ic = 0;
202    const GLuint shaderIndex = write_depth * 2 + write_stencil;
203
204    assert(shaderIndex < Elements(st->drawpix.shaders));
205
206    if (st->drawpix.shaders[shaderIndex]) {
207       /* already have the proper shader */
208       return st->drawpix.shaders[shaderIndex];
209    }
210
211    /*
212     * Create shader now
213     */
214    p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
215    if (!p)
216       return NULL;
217
218    p->NumInstructions = write_depth ? 3 : 1;
219    p->NumInstructions += write_stencil ? 1 : 0;
220
221    p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
222    if (!p->Instructions) {
223       ctx->Driver.DeleteProgram(ctx, p);
224       return NULL;
225    }
226    _mesa_init_instructions(p->Instructions, p->NumInstructions);
227
228    if (write_depth) {
229       /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */
230       p->Instructions[ic].Opcode = OPCODE_TEX;
231       p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
232       p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPTH;
233       p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z;
234       p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
235       p->Instructions[ic].SrcReg[0].Index = VARYING_SLOT_TEX0;
236       p->Instructions[ic].TexSrcUnit = 0;
237       p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
238       ic++;
239       /* MOV result.color, fragment.color; */
240       p->Instructions[ic].Opcode = OPCODE_MOV;
241       p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
242       p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLOR;
243       p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
244       p->Instructions[ic].SrcReg[0].Index = VARYING_SLOT_COL0;
245       ic++;
246    }
247
248    if (write_stencil) {
249       /* TEX result.stencil, fragment.texcoord[0], texture[0], 2D; */
250       p->Instructions[ic].Opcode = OPCODE_TEX;
251       p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
252       p->Instructions[ic].DstReg.Index = FRAG_RESULT_STENCIL;
253       p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Y;
254       p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
255       p->Instructions[ic].SrcReg[0].Index = VARYING_SLOT_TEX0;
256       p->Instructions[ic].TexSrcUnit = 1;
257       p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
258       ic++;
259    }
260
261    /* END; */
262    p->Instructions[ic++].Opcode = OPCODE_END;
263
264    assert(ic == p->NumInstructions);
265
266    p->InputsRead = VARYING_BIT_TEX0 | VARYING_BIT_COL0;
267    p->OutputsWritten = 0;
268    if (write_depth) {
269       p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_DEPTH);
270       p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_COLOR);
271    }
272    if (write_stencil)
273       p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_STENCIL);
274
275    p->SamplersUsed =  0x1;  /* sampler 0 (bit 0) is used */
276    if (write_stencil)
277       p->SamplersUsed |= 1 << 1;
278
279    fp = (struct gl_fragment_program *) p;
280
281    /* save the new shader */
282    st->drawpix.shaders[shaderIndex] = fp;
283
284    return fp;
285 }
286
287
288 /**
289  * Create a simple vertex shader that just passes through the
290  * vertex position and texcoord (and optionally, color).
291  */
292 static void *
293 make_passthrough_vertex_shader(struct st_context *st, 
294                                GLboolean passColor)
295 {
296    const unsigned texcoord_semantic = st->needs_texcoord_semantic ?
297       TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC;
298
299    if (!st->drawpix.vert_shaders[passColor]) {
300       struct ureg_program *ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
301
302       if (ureg == NULL)
303          return NULL;
304
305       /* MOV result.pos, vertex.pos; */
306       ureg_MOV(ureg, 
307                ureg_DECL_output( ureg, TGSI_SEMANTIC_POSITION, 0 ),
308                ureg_DECL_vs_input( ureg, 0 ));
309       
310       /* MOV result.texcoord0, vertex.attr[1]; */
311       ureg_MOV(ureg, 
312                ureg_DECL_output( ureg, texcoord_semantic, 0 ),
313                ureg_DECL_vs_input( ureg, 1 ));
314       
315       if (passColor) {
316          /* MOV result.color0, vertex.attr[2]; */
317          ureg_MOV(ureg, 
318                   ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ),
319                   ureg_DECL_vs_input( ureg, 2 ));
320       }
321
322       ureg_END( ureg );
323       
324       st->drawpix.vert_shaders[passColor] = 
325          ureg_create_shader_and_destroy( ureg, st->pipe );
326    }
327
328    return st->drawpix.vert_shaders[passColor];
329 }
330
331
332 /**
333  * Return a texture internalFormat for drawing/copying an image
334  * of the given format and type.
335  */
336 static GLenum
337 internal_format(struct gl_context *ctx, GLenum format, GLenum type)
338 {
339    switch (format) {
340    case GL_DEPTH_COMPONENT:
341       switch (type) {
342       case GL_UNSIGNED_SHORT:
343          return GL_DEPTH_COMPONENT16;
344
345       case GL_UNSIGNED_INT:
346          return GL_DEPTH_COMPONENT32;
347
348       case GL_FLOAT:
349          if (ctx->Extensions.ARB_depth_buffer_float)
350             return GL_DEPTH_COMPONENT32F;
351          else
352             return GL_DEPTH_COMPONENT;
353
354       default:
355          return GL_DEPTH_COMPONENT;
356       }
357
358    case GL_DEPTH_STENCIL:
359       switch (type) {
360       case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
361          return GL_DEPTH32F_STENCIL8;
362
363       case GL_UNSIGNED_INT_24_8:
364       default:
365          return GL_DEPTH24_STENCIL8;
366       }
367
368    case GL_STENCIL_INDEX:
369       return GL_STENCIL_INDEX;
370
371    default:
372       if (_mesa_is_enum_format_integer(format)) {
373          switch (type) {
374          case GL_BYTE:
375             return GL_RGBA8I;
376          case GL_UNSIGNED_BYTE:
377             return GL_RGBA8UI;
378          case GL_SHORT:
379             return GL_RGBA16I;
380          case GL_UNSIGNED_SHORT:
381             return GL_RGBA16UI;
382          case GL_INT:
383             return GL_RGBA32I;
384          case GL_UNSIGNED_INT:
385             return GL_RGBA32UI;
386          default:
387             assert(0 && "Unexpected type in internal_format()");
388             return GL_RGBA_INTEGER;
389          }
390       }
391       else {
392          switch (type) {
393          case GL_UNSIGNED_BYTE:
394          case GL_UNSIGNED_INT_8_8_8_8:
395          case GL_UNSIGNED_INT_8_8_8_8_REV:
396          default:
397             return GL_RGBA8;
398
399          case GL_UNSIGNED_BYTE_3_3_2:
400          case GL_UNSIGNED_BYTE_2_3_3_REV:
401             return GL_R3_G3_B2;
402
403          case GL_UNSIGNED_SHORT_4_4_4_4:
404          case GL_UNSIGNED_SHORT_4_4_4_4_REV:
405             return GL_RGBA4;
406
407          case GL_UNSIGNED_SHORT_5_6_5:
408          case GL_UNSIGNED_SHORT_5_6_5_REV:
409             return GL_RGB565;
410
411          case GL_UNSIGNED_SHORT_5_5_5_1:
412          case GL_UNSIGNED_SHORT_1_5_5_5_REV:
413             return GL_RGB5_A1;
414
415          case GL_UNSIGNED_INT_10_10_10_2:
416          case GL_UNSIGNED_INT_2_10_10_10_REV:
417             return GL_RGB10_A2;
418
419          case GL_UNSIGNED_SHORT:
420          case GL_UNSIGNED_INT:
421             return GL_RGBA16;
422
423          case GL_BYTE:
424             return
425                ctx->Extensions.EXT_texture_snorm ? GL_RGBA8_SNORM : GL_RGBA8;
426
427          case GL_SHORT:
428          case GL_INT:
429             return
430                ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16;
431
432          case GL_HALF_FLOAT_ARB:
433             return
434                ctx->Extensions.ARB_texture_float ? GL_RGBA16F :
435                ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16;
436
437          case GL_FLOAT:
438          case GL_DOUBLE:
439             return
440                ctx->Extensions.ARB_texture_float ? GL_RGBA32F :
441                ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16;
442
443          case GL_UNSIGNED_INT_5_9_9_9_REV:
444             assert(ctx->Extensions.EXT_texture_shared_exponent);
445             return GL_RGB9_E5;
446
447          case GL_UNSIGNED_INT_10F_11F_11F_REV:
448             assert(ctx->Extensions.EXT_packed_float);
449             return GL_R11F_G11F_B10F;
450          }
451       }
452    }
453 }
454
455
456 /**
457  * Create a temporary texture to hold an image of the given size.
458  * If width, height are not POT and the driver only handles POT textures,
459  * allocate the next larger size of texture that is POT.
460  */
461 static struct pipe_resource *
462 alloc_texture(struct st_context *st, GLsizei width, GLsizei height,
463               enum pipe_format texFormat, unsigned bind)
464 {
465    struct pipe_resource *pt;
466
467    pt = st_texture_create(st, st->internal_target, texFormat, 0,
468                           width, height, 1, 1, 0, bind);
469
470    return pt;
471 }
472
473
474 /**
475  * Make texture containing an image for glDrawPixels image.
476  * If 'pixels' is NULL, leave the texture image data undefined.
477  */
478 static struct pipe_resource *
479 make_texture(struct st_context *st,
480              GLsizei width, GLsizei height, GLenum format, GLenum type,
481              const struct gl_pixelstore_attrib *unpack,
482              const GLvoid *pixels)
483 {
484    struct gl_context *ctx = st->ctx;
485    struct pipe_context *pipe = st->pipe;
486    mesa_format mformat;
487    struct pipe_resource *pt;
488    enum pipe_format pipeFormat;
489    GLenum baseInternalFormat;
490
491    /* Choose a pixel format for the temp texture which will hold the
492     * image to draw.
493     */
494    pipeFormat = st_choose_matching_format(pipe->screen, PIPE_BIND_SAMPLER_VIEW,
495                                           format, type, unpack->SwapBytes);
496
497    if (pipeFormat != PIPE_FORMAT_NONE) {
498       mformat = st_pipe_format_to_mesa_format(pipeFormat);
499       baseInternalFormat = _mesa_get_format_base_format(mformat);
500    }
501    else {
502       /* Use the generic approach. */
503       GLenum intFormat = internal_format(ctx, format, type);
504
505       baseInternalFormat = _mesa_base_tex_format(ctx, intFormat);
506       pipeFormat = st_choose_format(st, intFormat, format, type,
507                                     PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW,
508                                     FALSE);
509       assert(pipeFormat != PIPE_FORMAT_NONE);
510       mformat = st_pipe_format_to_mesa_format(pipeFormat);
511    }
512
513    pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
514    if (!pixels)
515       return NULL;
516
517    /* alloc temporary texture */
518    pt = alloc_texture(st, width, height, pipeFormat, PIPE_BIND_SAMPLER_VIEW);
519    if (!pt) {
520       _mesa_unmap_pbo_source(ctx, unpack);
521       return NULL;
522    }
523
524    {
525       struct pipe_transfer *transfer;
526       GLboolean success;
527       GLubyte *dest;
528       const GLbitfield imageTransferStateSave = ctx->_ImageTransferState;
529
530       /* we'll do pixel transfer in a fragment shader */
531       ctx->_ImageTransferState = 0x0;
532
533       /* map texture transfer */
534       dest = pipe_transfer_map(pipe, pt, 0, 0,
535                                PIPE_TRANSFER_WRITE, 0, 0,
536                                width, height, &transfer);
537
538
539       /* Put image into texture transfer.
540        * Note that the image is actually going to be upside down in
541        * the texture.  We deal with that with texcoords.
542        */
543       success = _mesa_texstore(ctx, 2,           /* dims */
544                                baseInternalFormat, /* baseInternalFormat */
545                                mformat,          /* mesa_format */
546                                transfer->stride, /* dstRowStride, bytes */
547                                &dest,            /* destSlices */
548                                width, height, 1, /* size */
549                                format, type,     /* src format/type */
550                                pixels,           /* data source */
551                                unpack);
552
553       /* unmap */
554       pipe_transfer_unmap(pipe, transfer);
555
556       assert(success);
557
558       /* restore */
559       ctx->_ImageTransferState = imageTransferStateSave;
560    }
561
562    _mesa_unmap_pbo_source(ctx, unpack);
563
564    return pt;
565 }
566
567
568 /**
569  * Draw quad with texcoords and optional color.
570  * Coords are gallium window coords with y=0=top.
571  * \param color  may be null
572  * \param invertTex  if true, flip texcoords vertically
573  */
574 static void
575 draw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z,
576           GLfloat x1, GLfloat y1, const GLfloat *color,
577           GLboolean invertTex, GLfloat maxXcoord, GLfloat maxYcoord)
578 {
579    struct st_context *st = st_context(ctx);
580    struct pipe_context *pipe = st->pipe;
581    GLfloat (*verts)[3][4]; /* four verts, three attribs, XYZW */
582    struct pipe_resource *buf = NULL;
583    unsigned offset;
584
585    if (u_upload_alloc(st->uploader, 0, 4 * sizeof(verts[0]), &offset,
586                       &buf, (void **) &verts) != PIPE_OK) {
587       return;
588    }
589
590    /* setup vertex data */
591    {
592       const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
593       const GLfloat fb_width = (GLfloat) fb->Width;
594       const GLfloat fb_height = (GLfloat) fb->Height;
595       const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f;
596       const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f;
597       const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f;
598       const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f;
599       const GLfloat sLeft = 0.0f, sRight = maxXcoord;
600       const GLfloat tTop = invertTex ? maxYcoord : 0.0f;
601       const GLfloat tBot = invertTex ? 0.0f : maxYcoord;
602       GLuint i;
603
604       /* upper-left */
605       verts[0][0][0] = clip_x0;    /* v[0].attr[0].x */
606       verts[0][0][1] = clip_y0;    /* v[0].attr[0].y */
607
608       /* upper-right */
609       verts[1][0][0] = clip_x1;
610       verts[1][0][1] = clip_y0;
611
612       /* lower-right */
613       verts[2][0][0] = clip_x1;
614       verts[2][0][1] = clip_y1;
615
616       /* lower-left */
617       verts[3][0][0] = clip_x0;
618       verts[3][0][1] = clip_y1;
619
620       verts[0][1][0] = sLeft; /* v[0].attr[1].S */
621       verts[0][1][1] = tTop;  /* v[0].attr[1].T */
622       verts[1][1][0] = sRight;
623       verts[1][1][1] = tTop;
624       verts[2][1][0] = sRight;
625       verts[2][1][1] = tBot;
626       verts[3][1][0] = sLeft;
627       verts[3][1][1] = tBot;
628
629       /* same for all verts: */
630       if (color) {
631          for (i = 0; i < 4; i++) {
632             verts[i][0][2] = z;         /* v[i].attr[0].z */
633             verts[i][0][3] = 1.0f;      /* v[i].attr[0].w */
634             verts[i][2][0] = color[0];  /* v[i].attr[2].r */
635             verts[i][2][1] = color[1];  /* v[i].attr[2].g */
636             verts[i][2][2] = color[2];  /* v[i].attr[2].b */
637             verts[i][2][3] = color[3];  /* v[i].attr[2].a */
638             verts[i][1][2] = 0.0f;      /* v[i].attr[1].R */
639             verts[i][1][3] = 1.0f;      /* v[i].attr[1].Q */
640          }
641       }
642       else {
643          for (i = 0; i < 4; i++) {
644             verts[i][0][2] = z;    /*Z*/
645             verts[i][0][3] = 1.0f; /*W*/
646             verts[i][1][2] = 0.0f; /*R*/
647             verts[i][1][3] = 1.0f; /*Q*/
648          }
649       }
650    }
651
652    u_upload_unmap(st->uploader);
653    util_draw_vertex_buffer(pipe, st->cso_context, buf,
654                            cso_get_aux_vertex_buffer_slot(st->cso_context),
655                            offset,
656                            PIPE_PRIM_QUADS,
657                            4,  /* verts */
658                            3); /* attribs/vert */
659    pipe_resource_reference(&buf, NULL);
660 }
661
662
663
664 static void
665 draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
666                    GLsizei width, GLsizei height,
667                    GLfloat zoomX, GLfloat zoomY,
668                    struct pipe_sampler_view **sv,
669                    int num_sampler_view,
670                    void *driver_vp,
671                    void *driver_fp,
672                    const GLfloat *color,
673                    GLboolean invertTex,
674                    GLboolean write_depth, GLboolean write_stencil)
675 {
676    struct st_context *st = st_context(ctx);
677    struct pipe_context *pipe = st->pipe;
678    struct cso_context *cso = st->cso_context;
679    GLfloat x0, y0, x1, y1;
680    GLsizei maxSize;
681    boolean normalized = sv[0]->texture->target != PIPE_TEXTURE_RECT;
682
683    /* limit checks */
684    /* XXX if DrawPixels image is larger than max texture size, break
685     * it up into chunks.
686     */
687    maxSize = 1 << (pipe->screen->get_param(pipe->screen,
688                                         PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
689    assert(width <= maxSize);
690    assert(height <= maxSize);
691
692    cso_save_rasterizer(cso);
693    cso_save_viewport(cso);
694    cso_save_samplers(cso, PIPE_SHADER_FRAGMENT);
695    cso_save_sampler_views(cso, PIPE_SHADER_FRAGMENT);
696    cso_save_fragment_shader(cso);
697    cso_save_stream_outputs(cso);
698    cso_save_vertex_shader(cso);
699    cso_save_geometry_shader(cso);
700    cso_save_vertex_elements(cso);
701    cso_save_aux_vertex_buffer_slot(cso);
702    if (write_stencil) {
703       cso_save_depth_stencil_alpha(cso);
704       cso_save_blend(cso);
705    }
706
707    /* rasterizer state: just scissor */
708    {
709       struct pipe_rasterizer_state rasterizer;
710       memset(&rasterizer, 0, sizeof(rasterizer));
711       rasterizer.clamp_fragment_color = !st->clamp_frag_color_in_shader &&
712                                         ctx->Color._ClampFragmentColor;
713       rasterizer.half_pixel_center = 1;
714       rasterizer.bottom_edge_rule = 1;
715       rasterizer.depth_clip = !ctx->Transform.DepthClamp;
716       rasterizer.scissor = ctx->Scissor.EnableFlags;
717       cso_set_rasterizer(cso, &rasterizer);
718    }
719
720    if (write_stencil) {
721       /* Stencil writing bypasses the normal fragment pipeline to
722        * disable color writing and set stencil test to always pass.
723        */
724       struct pipe_depth_stencil_alpha_state dsa;
725       struct pipe_blend_state blend;
726
727       /* depth/stencil */
728       memset(&dsa, 0, sizeof(dsa));
729       dsa.stencil[0].enabled = 1;
730       dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
731       dsa.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
732       dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
733       if (write_depth) {
734          /* writing depth+stencil: depth test always passes */
735          dsa.depth.enabled = 1;
736          dsa.depth.writemask = ctx->Depth.Mask;
737          dsa.depth.func = PIPE_FUNC_ALWAYS;
738       }
739       cso_set_depth_stencil_alpha(cso, &dsa);
740
741       /* blend (colormask) */
742       memset(&blend, 0, sizeof(blend));
743       cso_set_blend(cso, &blend);
744    }
745
746    /* fragment shader state: TEX lookup program */
747    cso_set_fragment_shader_handle(cso, driver_fp);
748
749    /* vertex shader state: position + texcoord pass-through */
750    cso_set_vertex_shader_handle(cso, driver_vp);
751
752    /* geometry shader state: disabled */
753    cso_set_geometry_shader_handle(cso, NULL);
754
755    /* texture sampling state: */
756    {
757       struct pipe_sampler_state sampler;
758       memset(&sampler, 0, sizeof(sampler));
759       sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
760       sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
761       sampler.wrap_r = PIPE_TEX_WRAP_CLAMP;
762       sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
763       sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
764       sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
765       sampler.normalized_coords = normalized;
766
767       cso_single_sampler(cso, PIPE_SHADER_FRAGMENT, 0, &sampler);
768       if (num_sampler_view > 1) {
769          cso_single_sampler(cso, PIPE_SHADER_FRAGMENT, 1, &sampler);
770       }
771       cso_single_sampler_done(cso, PIPE_SHADER_FRAGMENT);
772    }
773
774    /* viewport state: viewport matching window dims */
775    {
776       const float w = (float) ctx->DrawBuffer->Width;
777       const float h = (float) ctx->DrawBuffer->Height;
778       struct pipe_viewport_state vp;
779       vp.scale[0] =  0.5f * w;
780       vp.scale[1] = -0.5f * h;
781       vp.scale[2] = 0.5f;
782       vp.scale[3] = 1.0f;
783       vp.translate[0] = 0.5f * w;
784       vp.translate[1] = 0.5f * h;
785       vp.translate[2] = 0.5f;
786       vp.translate[3] = 0.0f;
787       cso_set_viewport(cso, &vp);
788    }
789
790    cso_set_vertex_elements(cso, 3, st->velems_util_draw);
791    cso_set_stream_outputs(st->cso_context, 0, NULL, 0);
792
793    /* texture state: */
794    cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num_sampler_view, sv);
795
796    /* Compute Gallium window coords (y=0=top) with pixel zoom.
797     * Recall that these coords are transformed by the current
798     * vertex shader and viewport transformation.
799     */
800    if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) {
801       y = ctx->DrawBuffer->Height - (int) (y + height * ctx->Pixel.ZoomY);
802       invertTex = !invertTex;
803    }
804
805    x0 = (GLfloat) x;
806    x1 = x + width * ctx->Pixel.ZoomX;
807    y0 = (GLfloat) y;
808    y1 = y + height * ctx->Pixel.ZoomY;
809
810    /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
811    z = z * 2.0f - 1.0f;
812
813    draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex,
814              normalized ? ((GLfloat) width / sv[0]->texture->width0) : (GLfloat)width,
815              normalized ? ((GLfloat) height / sv[0]->texture->height0) : (GLfloat)height);
816
817    /* restore state */
818    cso_restore_rasterizer(cso);
819    cso_restore_viewport(cso);
820    cso_restore_samplers(cso, PIPE_SHADER_FRAGMENT);
821    cso_restore_sampler_views(cso, PIPE_SHADER_FRAGMENT);
822    cso_restore_fragment_shader(cso);
823    cso_restore_vertex_shader(cso);
824    cso_restore_geometry_shader(cso);
825    cso_restore_vertex_elements(cso);
826    cso_restore_aux_vertex_buffer_slot(cso);
827    cso_restore_stream_outputs(cso);
828    if (write_stencil) {
829       cso_restore_depth_stencil_alpha(cso);
830       cso_restore_blend(cso);
831    }
832 }
833
834
835 /**
836  * Software fallback to do glDrawPixels(GL_STENCIL_INDEX) when we
837  * can't use a fragment shader to write stencil values.
838  */
839 static void
840 draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
841                     GLsizei width, GLsizei height, GLenum format, GLenum type,
842                     const struct gl_pixelstore_attrib *unpack,
843                     const GLvoid *pixels)
844 {
845    struct st_context *st = st_context(ctx);
846    struct pipe_context *pipe = st->pipe;
847    struct st_renderbuffer *strb;
848    enum pipe_transfer_usage usage;
849    struct pipe_transfer *pt;
850    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
851    ubyte *stmap;
852    struct gl_pixelstore_attrib clippedUnpack = *unpack;
853    GLubyte *sValues;
854    GLuint *zValues;
855
856    if (!zoom) {
857       if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height,
858                                  &clippedUnpack)) {
859          /* totally clipped */
860          return;
861       }
862    }
863
864    strb = st_renderbuffer(ctx->DrawBuffer->
865                           Attachment[BUFFER_STENCIL].Renderbuffer);
866
867    if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
868       y = ctx->DrawBuffer->Height - y - height;
869    }
870
871    if (format == GL_STENCIL_INDEX && 
872        _mesa_is_format_packed_depth_stencil(strb->Base.Format)) {
873       /* writing stencil to a combined depth+stencil buffer */
874       usage = PIPE_TRANSFER_READ_WRITE;
875    }
876    else {
877       usage = PIPE_TRANSFER_WRITE;
878    }
879
880    stmap = pipe_transfer_map(pipe, strb->texture,
881                              strb->surface->u.tex.level,
882                              strb->surface->u.tex.first_layer,
883                              usage, x, y,
884                              width, height, &pt);
885
886    pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels);
887    assert(pixels);
888
889    sValues = malloc(width * sizeof(GLubyte));
890    zValues = malloc(width * sizeof(GLuint));
891
892    if (sValues && zValues) {
893       GLint row;
894       for (row = 0; row < height; row++) {
895          GLfloat *zValuesFloat = (GLfloat*)zValues;
896          GLenum destType = GL_UNSIGNED_BYTE;
897          const GLvoid *source = _mesa_image_address2d(&clippedUnpack, pixels,
898                                                       width, height,
899                                                       format, type,
900                                                       row, 0);
901          _mesa_unpack_stencil_span(ctx, width, destType, sValues,
902                                    type, source, &clippedUnpack,
903                                    ctx->_ImageTransferState);
904
905          if (format == GL_DEPTH_STENCIL) {
906             GLenum ztype =
907                pt->resource->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ?
908                GL_FLOAT : GL_UNSIGNED_INT;
909
910             _mesa_unpack_depth_span(ctx, width, ztype, zValues,
911                                     (1 << 24) - 1, type, source,
912                                     &clippedUnpack);
913          }
914
915          if (zoom) {
916             _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with "
917                           "zoom not complete");
918          }
919
920          {
921             GLint spanY;
922
923             if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
924                spanY = height - row - 1;
925             }
926             else {
927                spanY = row;
928             }
929
930             /* now pack the stencil (and Z) values in the dest format */
931             switch (pt->resource->format) {
932             case PIPE_FORMAT_S8_UINT:
933                {
934                   ubyte *dest = stmap + spanY * pt->stride;
935                   assert(usage == PIPE_TRANSFER_WRITE);
936                   memcpy(dest, sValues, width);
937                }
938                break;
939             case PIPE_FORMAT_Z24_UNORM_S8_UINT:
940                if (format == GL_DEPTH_STENCIL) {
941                   uint *dest = (uint *) (stmap + spanY * pt->stride);
942                   GLint k;
943                   assert(usage == PIPE_TRANSFER_WRITE);
944                   for (k = 0; k < width; k++) {
945                      dest[k] = zValues[k] | (sValues[k] << 24);
946                   }
947                }
948                else {
949                   uint *dest = (uint *) (stmap + spanY * pt->stride);
950                   GLint k;
951                   assert(usage == PIPE_TRANSFER_READ_WRITE);
952                   for (k = 0; k < width; k++) {
953                      dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24);
954                   }
955                }
956                break;
957             case PIPE_FORMAT_S8_UINT_Z24_UNORM:
958                if (format == GL_DEPTH_STENCIL) {
959                   uint *dest = (uint *) (stmap + spanY * pt->stride);
960                   GLint k;
961                   assert(usage == PIPE_TRANSFER_WRITE);
962                   for (k = 0; k < width; k++) {
963                      dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff);
964                   }
965                }
966                else {
967                   uint *dest = (uint *) (stmap + spanY * pt->stride);
968                   GLint k;
969                   assert(usage == PIPE_TRANSFER_READ_WRITE);
970                   for (k = 0; k < width; k++) {
971                      dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff);
972                   }
973                }
974                break;
975             case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
976                if (format == GL_DEPTH_STENCIL) {
977                   uint *dest = (uint *) (stmap + spanY * pt->stride);
978                   GLfloat *destf = (GLfloat*)dest;
979                   GLint k;
980                   assert(usage == PIPE_TRANSFER_WRITE);
981                   for (k = 0; k < width; k++) {
982                      destf[k*2] = zValuesFloat[k];
983                      dest[k*2+1] = sValues[k] & 0xff;
984                   }
985                }
986                else {
987                   uint *dest = (uint *) (stmap + spanY * pt->stride);
988                   GLint k;
989                   assert(usage == PIPE_TRANSFER_READ_WRITE);
990                   for (k = 0; k < width; k++) {
991                      dest[k*2+1] = sValues[k] & 0xff;
992                   }
993                }
994                break;
995             default:
996                assert(0);
997             }
998          }
999       }
1000    }
1001    else {
1002       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels()");
1003    }
1004
1005    free(sValues);
1006    free(zValues);
1007
1008    _mesa_unmap_pbo_source(ctx, &clippedUnpack);
1009
1010    /* unmap the stencil buffer */
1011    pipe_transfer_unmap(pipe, pt);
1012 }
1013
1014
1015 /**
1016  * Get fragment program variant for a glDrawPixels or glCopyPixels
1017  * command for RGBA data.
1018  */
1019 static struct st_fp_variant *
1020 get_color_fp_variant(struct st_context *st)
1021 {
1022    struct gl_context *ctx = st->ctx;
1023    struct st_fp_variant_key key;
1024    struct st_fp_variant *fpv;
1025
1026    memset(&key, 0, sizeof(key));
1027
1028    key.st = st;
1029    key.drawpixels = 1;
1030    key.scaleAndBias = (ctx->Pixel.RedBias != 0.0 ||
1031                        ctx->Pixel.RedScale != 1.0 ||
1032                        ctx->Pixel.GreenBias != 0.0 ||
1033                        ctx->Pixel.GreenScale != 1.0 ||
1034                        ctx->Pixel.BlueBias != 0.0 ||
1035                        ctx->Pixel.BlueScale != 1.0 ||
1036                        ctx->Pixel.AlphaBias != 0.0 ||
1037                        ctx->Pixel.AlphaScale != 1.0);
1038    key.pixelMaps = ctx->Pixel.MapColorFlag;
1039    key.clamp_color = st->clamp_frag_color_in_shader &&
1040                      st->ctx->Color._ClampFragmentColor;
1041
1042    fpv = st_get_fp_variant(st, st->fp, &key);
1043
1044    return fpv;
1045 }
1046
1047
1048 /**
1049  * Get fragment program variant for a glDrawPixels or glCopyPixels
1050  * command for depth/stencil data.
1051  */
1052 static struct st_fp_variant *
1053 get_depth_stencil_fp_variant(struct st_context *st, GLboolean write_depth,
1054                              GLboolean write_stencil)
1055 {
1056    struct st_fp_variant_key key;
1057    struct st_fp_variant *fpv;
1058
1059    memset(&key, 0, sizeof(key));
1060
1061    key.st = st;
1062    key.drawpixels = 1;
1063    key.drawpixels_z = write_depth;
1064    key.drawpixels_stencil = write_stencil;
1065
1066    fpv = st_get_fp_variant(st, st->fp, &key);
1067
1068    return fpv;
1069 }
1070
1071
1072 /**
1073  * Clamp glDrawPixels width and height to the maximum texture size.
1074  */
1075 static void
1076 clamp_size(struct pipe_context *pipe, GLsizei *width, GLsizei *height,
1077            struct gl_pixelstore_attrib *unpack)
1078 {
1079    const int maxSize =
1080       1 << (pipe->screen->get_param(pipe->screen,
1081                                     PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
1082
1083    if (*width > maxSize) {
1084       if (unpack->RowLength == 0)
1085          unpack->RowLength = *width;
1086       *width = maxSize;
1087    }
1088    if (*height > maxSize) {
1089       *height = maxSize;
1090    }
1091 }
1092
1093
1094 /**
1095  * Called via ctx->Driver.DrawPixels()
1096  */
1097 static void
1098 st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
1099               GLsizei width, GLsizei height,
1100               GLenum format, GLenum type,
1101               const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
1102 {
1103    void *driver_vp, *driver_fp;
1104    struct st_context *st = st_context(ctx);
1105    const GLfloat *color;
1106    struct pipe_context *pipe = st->pipe;
1107    GLboolean write_stencil = GL_FALSE, write_depth = GL_FALSE;
1108    struct pipe_sampler_view *sv[2];
1109    int num_sampler_view = 1;
1110    struct st_fp_variant *fpv;
1111    struct gl_pixelstore_attrib clippedUnpack;
1112
1113    /* Mesa state should be up to date by now */
1114    assert(ctx->NewState == 0x0);
1115
1116    st_validate_state(st);
1117
1118    /* Limit the size of the glDrawPixels to the max texture size.
1119     * Strictly speaking, that's not correct but since we don't handle
1120     * larger images yet, this is better than crashing.
1121     */
1122    clippedUnpack = *unpack;
1123    unpack = &clippedUnpack;
1124    clamp_size(st->pipe, &width, &height, &clippedUnpack);
1125
1126    if (format == GL_DEPTH_STENCIL)
1127       write_stencil = write_depth = GL_TRUE;
1128    else if (format == GL_STENCIL_INDEX)
1129       write_stencil = GL_TRUE;
1130    else if (format == GL_DEPTH_COMPONENT)
1131       write_depth = GL_TRUE;
1132
1133    if (write_stencil &&
1134        !pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT)) {
1135       /* software fallback */
1136       draw_stencil_pixels(ctx, x, y, width, height, format, type,
1137                           unpack, pixels);
1138       return;
1139    }
1140
1141    /*
1142     * Get vertex/fragment shaders
1143     */
1144    if (write_depth || write_stencil) {
1145       fpv = get_depth_stencil_fp_variant(st, write_depth, write_stencil);
1146
1147       driver_fp = fpv->driver_shader;
1148
1149       driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
1150
1151       color = ctx->Current.RasterColor;
1152    }
1153    else {
1154       fpv = get_color_fp_variant(st);
1155
1156       driver_fp = fpv->driver_shader;
1157
1158       driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
1159
1160       color = NULL;
1161       if (st->pixel_xfer.pixelmap_enabled) {
1162           sv[1] = st->pixel_xfer.pixelmap_sampler_view;
1163           num_sampler_view++;
1164       }
1165    }
1166
1167    /* update fragment program constants */
1168    st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
1169
1170    /* draw with textured quad */
1171    {
1172       struct pipe_resource *pt
1173          = make_texture(st, width, height, format, type, unpack, pixels);
1174       if (pt) {
1175          sv[0] = st_create_texture_sampler_view(st->pipe, pt);
1176
1177          if (sv[0]) {
1178             /* Create a second sampler view to read stencil.
1179              * The stencil is written using the shader stencil export
1180              * functionality. */
1181             if (write_stencil) {
1182                enum pipe_format stencil_format =
1183                      util_format_stencil_only(pt->format);
1184
1185                sv[1] = st_create_texture_sampler_view_format(st->pipe, pt,
1186                                                              stencil_format);
1187                num_sampler_view++;
1188             }
1189
1190             draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
1191                                width, height,
1192                                ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
1193                                sv,
1194                                num_sampler_view,
1195                                driver_vp,
1196                                driver_fp,
1197                                color, GL_FALSE, write_depth, write_stencil);
1198             pipe_sampler_view_reference(&sv[0], NULL);
1199             if (num_sampler_view > 1)
1200                pipe_sampler_view_reference(&sv[1], NULL);
1201          }
1202          pipe_resource_reference(&pt, NULL);
1203       }
1204    }
1205 }
1206
1207
1208
1209 /**
1210  * Software fallback for glCopyPixels(GL_STENCIL).
1211  */
1212 static void
1213 copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
1214                     GLsizei width, GLsizei height,
1215                     GLint dstx, GLint dsty)
1216 {
1217    struct st_renderbuffer *rbDraw;
1218    struct pipe_context *pipe = st_context(ctx)->pipe;
1219    enum pipe_transfer_usage usage;
1220    struct pipe_transfer *ptDraw;
1221    ubyte *drawMap;
1222    ubyte *buffer;
1223    int i;
1224
1225    buffer = malloc(width * height * sizeof(ubyte));
1226    if (!buffer) {
1227       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
1228       return;
1229    }
1230
1231    /* Get the dest renderbuffer */
1232    rbDraw = st_renderbuffer(ctx->DrawBuffer->
1233                             Attachment[BUFFER_STENCIL].Renderbuffer);
1234
1235    /* this will do stencil pixel transfer ops */
1236    _mesa_readpixels(ctx, srcx, srcy, width, height,
1237                     GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
1238                     &ctx->DefaultPacking, buffer);
1239
1240    if (0) {
1241       /* debug code: dump stencil values */
1242       GLint row, col;
1243       for (row = 0; row < height; row++) {
1244          printf("%3d: ", row);
1245          for (col = 0; col < width; col++) {
1246             printf("%02x ", buffer[col + row * width]);
1247          }
1248          printf("\n");
1249       }
1250    }
1251
1252    if (_mesa_is_format_packed_depth_stencil(rbDraw->Base.Format))
1253       usage = PIPE_TRANSFER_READ_WRITE;
1254    else
1255       usage = PIPE_TRANSFER_WRITE;
1256
1257    if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1258       dsty = rbDraw->Base.Height - dsty - height;
1259    }
1260
1261    assert(util_format_get_blockwidth(rbDraw->texture->format) == 1);
1262    assert(util_format_get_blockheight(rbDraw->texture->format) == 1);
1263
1264    /* map the stencil buffer */
1265    drawMap = pipe_transfer_map(pipe,
1266                                rbDraw->texture,
1267                                rbDraw->surface->u.tex.level,
1268                                rbDraw->surface->u.tex.first_layer,
1269                                usage, dstx, dsty,
1270                                width, height, &ptDraw);
1271
1272    /* draw */
1273    /* XXX PixelZoom not handled yet */
1274    for (i = 0; i < height; i++) {
1275       ubyte *dst;
1276       const ubyte *src;
1277       int y;
1278
1279       y = i;
1280
1281       if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1282          y = height - y - 1;
1283       }
1284
1285       dst = drawMap + y * ptDraw->stride;
1286       src = buffer + i * width;
1287
1288       _mesa_pack_ubyte_stencil_row(rbDraw->Base.Format, width, src, dst);
1289    }
1290
1291    free(buffer);
1292
1293    /* unmap the stencil buffer */
1294    pipe_transfer_unmap(pipe, ptDraw);
1295 }
1296
1297
1298 /**
1299  * Return renderbuffer to use for reading color pixels for glCopyPixels
1300  */
1301 static struct st_renderbuffer *
1302 st_get_color_read_renderbuffer(struct gl_context *ctx)
1303 {
1304    struct gl_framebuffer *fb = ctx->ReadBuffer;
1305    struct st_renderbuffer *strb =
1306       st_renderbuffer(fb->_ColorReadBuffer);
1307
1308    return strb;
1309 }
1310
1311
1312 /**
1313  * \return TRUE if two regions overlap, FALSE otherwise
1314  */
1315 static boolean
1316 regions_overlap(int srcX0, int srcY0,
1317                 int srcX1, int srcY1,
1318                 int dstX0, int dstY0,
1319                 int dstX1, int dstY1)
1320 {
1321    if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1))
1322       return FALSE; /* src completely left of dst */
1323
1324    if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1))
1325       return FALSE; /* dst completely left of src */
1326
1327    if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1))
1328       return FALSE; /* src completely above dst */
1329
1330    if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1))
1331       return FALSE; /* dst completely above src */
1332
1333    return TRUE; /* some overlap */
1334 }
1335
1336
1337 /**
1338  * Try to do a glCopyPixels for simple cases with a blit by calling
1339  * pipe->blit().
1340  *
1341  * We can do this when we're copying color pixels (depth/stencil
1342  * eventually) with no pixel zoom, no pixel transfer ops, no
1343  * per-fragment ops, and the src/dest regions don't overlap.
1344  */
1345 static GLboolean
1346 blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
1347                  GLsizei width, GLsizei height,
1348                  GLint dstx, GLint dsty, GLenum type)
1349 {
1350    struct st_context *st = st_context(ctx);
1351    struct pipe_context *pipe = st->pipe;
1352    struct pipe_screen *screen = pipe->screen;
1353    struct gl_pixelstore_attrib pack, unpack;
1354    GLint readX, readY, readW, readH, drawX, drawY, drawW, drawH;
1355
1356    if (type == GL_COLOR &&
1357        ctx->Pixel.ZoomX == 1.0 &&
1358        ctx->Pixel.ZoomY == 1.0 &&
1359        ctx->_ImageTransferState == 0x0 &&
1360        !ctx->Color.BlendEnabled &&
1361        !ctx->Color.AlphaEnabled &&
1362        !ctx->Depth.Test &&
1363        !ctx->Fog.Enabled &&
1364        !ctx->Stencil.Enabled &&
1365        !ctx->FragmentProgram.Enabled &&
1366        !ctx->VertexProgram.Enabled &&
1367        !ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT] &&
1368        ctx->DrawBuffer->_NumColorDrawBuffers == 1 &&
1369        !ctx->Query.CondRenderQuery &&
1370        !ctx->Query.CurrentOcclusionObject) {
1371       struct st_renderbuffer *rbRead, *rbDraw;
1372
1373       /*
1374        * Clip the read region against the src buffer bounds.
1375        * We'll still allocate a temporary buffer/texture for the original
1376        * src region size but we'll only read the region which is on-screen.
1377        * This may mean that we draw garbage pixels into the dest region, but
1378        * that's expected.
1379        */
1380       readX = srcx;
1381       readY = srcy;
1382       readW = width;
1383       readH = height;
1384       pack = ctx->DefaultPacking;
1385       if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack))
1386          return GL_TRUE; /* all done */
1387
1388       /* clip against dest buffer bounds and scissor box */
1389       drawX = dstx + pack.SkipPixels;
1390       drawY = dsty + pack.SkipRows;
1391       unpack = pack;
1392       if (!_mesa_clip_drawpixels(ctx, &drawX, &drawY, &readW, &readH, &unpack))
1393          return GL_TRUE; /* all done */
1394
1395       readX = readX - pack.SkipPixels + unpack.SkipPixels;
1396       readY = readY - pack.SkipRows + unpack.SkipRows;
1397
1398       drawW = readW;
1399       drawH = readH;
1400
1401       rbRead = st_get_color_read_renderbuffer(ctx);
1402       rbDraw = st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]);
1403
1404       /* Flip src/dst position depending on the orientation of buffers. */
1405       if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
1406          readY = rbRead->Base.Height - readY;
1407          readH = -readH;
1408       }
1409
1410       if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1411          /* We can't flip the destination for pipe->blit, so we only adjust
1412           * its position and flip the source.
1413           */
1414          drawY = rbDraw->Base.Height - drawY - drawH;
1415          readY += readH;
1416          readH = -readH;
1417       }
1418
1419       if (rbRead != rbDraw ||
1420           !regions_overlap(readX, readY, readX + readW, readY + readH,
1421                            drawX, drawY, drawX + drawW, drawY + drawH)) {
1422          struct pipe_blit_info blit;
1423
1424          memset(&blit, 0, sizeof(blit));
1425          blit.src.resource = rbRead->texture;
1426          blit.src.level = rbRead->surface->u.tex.level;
1427          blit.src.format = rbRead->texture->format;
1428          blit.src.box.x = readX;
1429          blit.src.box.y = readY;
1430          blit.src.box.z = rbRead->surface->u.tex.first_layer;
1431          blit.src.box.width = readW;
1432          blit.src.box.height = readH;
1433          blit.src.box.depth = 1;
1434          blit.dst.resource = rbDraw->texture;
1435          blit.dst.level = rbDraw->surface->u.tex.level;
1436          blit.dst.format = rbDraw->texture->format;
1437          blit.dst.box.x = drawX;
1438          blit.dst.box.y = drawY;
1439          blit.dst.box.z = rbDraw->surface->u.tex.first_layer;
1440          blit.dst.box.width = drawW;
1441          blit.dst.box.height = drawH;
1442          blit.dst.box.depth = 1;
1443          blit.mask = PIPE_MASK_RGBA;
1444          blit.filter = PIPE_TEX_FILTER_NEAREST;
1445
1446          if (screen->is_format_supported(screen, blit.src.format,
1447                                          blit.src.resource->target,
1448                                          blit.src.resource->nr_samples,
1449                                          PIPE_BIND_SAMPLER_VIEW) &&
1450              screen->is_format_supported(screen, blit.dst.format,
1451                                          blit.dst.resource->target,
1452                                          blit.dst.resource->nr_samples,
1453                                          PIPE_BIND_RENDER_TARGET)) {
1454             pipe->blit(pipe, &blit);
1455             return GL_TRUE;
1456          }
1457       }
1458    }
1459
1460    return GL_FALSE;
1461 }
1462
1463
1464 static void
1465 st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
1466               GLsizei width, GLsizei height,
1467               GLint dstx, GLint dsty, GLenum type)
1468 {
1469    struct st_context *st = st_context(ctx);
1470    struct pipe_context *pipe = st->pipe;
1471    struct pipe_screen *screen = pipe->screen;
1472    struct st_renderbuffer *rbRead;
1473    void *driver_vp, *driver_fp;
1474    struct pipe_resource *pt;
1475    struct pipe_sampler_view *sv[2];
1476    int num_sampler_view = 1;
1477    GLfloat *color;
1478    enum pipe_format srcFormat;
1479    unsigned srcBind;
1480    GLboolean invertTex = GL_FALSE;
1481    GLint readX, readY, readW, readH;
1482    struct gl_pixelstore_attrib pack = ctx->DefaultPacking;
1483    struct st_fp_variant *fpv;
1484
1485    st_validate_state(st);
1486
1487    if (type == GL_DEPTH_STENCIL) {
1488       /* XXX make this more efficient */
1489       st_CopyPixels(ctx, srcx, srcy, width, height, dstx, dsty, GL_STENCIL);
1490       st_CopyPixels(ctx, srcx, srcy, width, height, dstx, dsty, GL_DEPTH);
1491       return;
1492    }
1493
1494    if (type == GL_STENCIL) {
1495       /* can't use texturing to do stencil */
1496       copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
1497       return;
1498    }
1499
1500    if (blit_copy_pixels(ctx, srcx, srcy, width, height, dstx, dsty, type))
1501       return;
1502
1503    /*
1504     * The subsequent code implements glCopyPixels by copying the source
1505     * pixels into a temporary texture that's then applied to a textured quad.
1506     * When we draw the textured quad, all the usual per-fragment operations
1507     * are handled.
1508     */
1509
1510
1511    /*
1512     * Get vertex/fragment shaders
1513     */
1514    if (type == GL_COLOR) {
1515       rbRead = st_get_color_read_renderbuffer(ctx);
1516       color = NULL;
1517
1518       fpv = get_color_fp_variant(st);
1519       driver_fp = fpv->driver_shader;
1520
1521       driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
1522
1523       if (st->pixel_xfer.pixelmap_enabled) {
1524          sv[1] = st->pixel_xfer.pixelmap_sampler_view;
1525          num_sampler_view++;
1526       }
1527    }
1528    else {
1529       assert(type == GL_DEPTH);
1530       rbRead = st_renderbuffer(ctx->ReadBuffer->
1531                                Attachment[BUFFER_DEPTH].Renderbuffer);
1532       color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
1533
1534       fpv = get_depth_stencil_fp_variant(st, GL_TRUE, GL_FALSE);
1535       driver_fp = fpv->driver_shader;
1536
1537       driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
1538    }
1539
1540    /* update fragment program constants */
1541    st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
1542
1543    /* Choose the format for the temporary texture. */
1544    srcFormat = rbRead->texture->format;
1545    srcBind = PIPE_BIND_SAMPLER_VIEW |
1546       (type == GL_COLOR ? PIPE_BIND_RENDER_TARGET : PIPE_BIND_DEPTH_STENCIL);
1547
1548    if (!screen->is_format_supported(screen, srcFormat, st->internal_target, 0,
1549                                     srcBind)) {
1550       /* srcFormat is non-renderable. Find a compatible renderable format. */
1551       if (type == GL_DEPTH) {
1552          srcFormat = st_choose_format(st, GL_DEPTH_COMPONENT, GL_NONE,
1553                                       GL_NONE, st->internal_target, 0,
1554                                       srcBind, FALSE);
1555       }
1556       else {
1557          assert(type == GL_COLOR);
1558
1559          if (util_format_is_float(srcFormat)) {
1560             srcFormat = st_choose_format(st, GL_RGBA32F, GL_NONE,
1561                                          GL_NONE, st->internal_target, 0,
1562                                          srcBind, FALSE);
1563          }
1564          else if (util_format_is_pure_sint(srcFormat)) {
1565             srcFormat = st_choose_format(st, GL_RGBA32I, GL_NONE,
1566                                          GL_NONE, st->internal_target, 0,
1567                                          srcBind, FALSE);
1568          }
1569          else if (util_format_is_pure_uint(srcFormat)) {
1570             srcFormat = st_choose_format(st, GL_RGBA32UI, GL_NONE,
1571                                          GL_NONE, st->internal_target, 0,
1572                                          srcBind, FALSE);
1573          }
1574          else if (util_format_is_snorm(srcFormat)) {
1575             srcFormat = st_choose_format(st, GL_RGBA16_SNORM, GL_NONE,
1576                                          GL_NONE, st->internal_target, 0,
1577                                          srcBind, FALSE);
1578          }
1579          else {
1580             srcFormat = st_choose_format(st, GL_RGBA, GL_NONE,
1581                                          GL_NONE, st->internal_target, 0,
1582                                          srcBind, FALSE);
1583          }
1584       }
1585
1586       if (srcFormat == PIPE_FORMAT_NONE) {
1587          assert(0 && "cannot choose a format for src of CopyPixels");
1588          return;
1589       }
1590    }
1591
1592    /* Invert src region if needed */
1593    if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
1594       srcy = ctx->ReadBuffer->Height - srcy - height;
1595       invertTex = !invertTex;
1596    }
1597
1598    /* Clip the read region against the src buffer bounds.
1599     * We'll still allocate a temporary buffer/texture for the original
1600     * src region size but we'll only read the region which is on-screen.
1601     * This may mean that we draw garbage pixels into the dest region, but
1602     * that's expected.
1603     */
1604    readX = srcx;
1605    readY = srcy;
1606    readW = width;
1607    readH = height;
1608    if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack)) {
1609       /* The source region is completely out of bounds.  Do nothing.
1610        * The GL spec says "Results of copies from outside the window,
1611        * or from regions of the window that are not exposed, are
1612        * hardware dependent and undefined."
1613        */
1614       return;
1615    }
1616
1617    readW = MAX2(0, readW);
1618    readH = MAX2(0, readH);
1619
1620    /* Allocate the temporary texture. */
1621    pt = alloc_texture(st, width, height, srcFormat, srcBind);
1622    if (!pt)
1623       return;
1624
1625    sv[0] = st_create_texture_sampler_view(st->pipe, pt);
1626    if (!sv[0]) {
1627       pipe_resource_reference(&pt, NULL);
1628       return;
1629    }
1630
1631    /* Copy the src region to the temporary texture. */
1632    {
1633       struct pipe_blit_info blit;
1634
1635       memset(&blit, 0, sizeof(blit));
1636       blit.src.resource = rbRead->texture;
1637       blit.src.level = rbRead->surface->u.tex.level;
1638       blit.src.format = rbRead->texture->format;
1639       blit.src.box.x = readX;
1640       blit.src.box.y = readY;
1641       blit.src.box.z = rbRead->surface->u.tex.first_layer;
1642       blit.src.box.width = readW;
1643       blit.src.box.height = readH;
1644       blit.src.box.depth = 1;
1645       blit.dst.resource = pt;
1646       blit.dst.level = 0;
1647       blit.dst.format = pt->format;
1648       blit.dst.box.x = pack.SkipPixels;
1649       blit.dst.box.y = pack.SkipRows;
1650       blit.dst.box.z = 0;
1651       blit.dst.box.width = readW;
1652       blit.dst.box.height = readH;
1653       blit.dst.box.depth = 1;
1654       blit.mask = util_format_get_mask(pt->format) & ~PIPE_MASK_S;
1655       blit.filter = PIPE_TEX_FILTER_NEAREST;
1656
1657       pipe->blit(pipe, &blit);
1658    }
1659
1660    /* OK, the texture 'pt' contains the src image/pixels.  Now draw a
1661     * textured quad with that texture.
1662     */
1663    draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
1664                       width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
1665                       sv,
1666                       num_sampler_view,
1667                       driver_vp, 
1668                       driver_fp,
1669                       color, invertTex, GL_FALSE, GL_FALSE);
1670
1671    pipe_resource_reference(&pt, NULL);
1672    pipe_sampler_view_reference(&sv[0], NULL);
1673 }
1674
1675
1676
1677 void st_init_drawpixels_functions(struct dd_function_table *functions)
1678 {
1679    functions->DrawPixels = st_DrawPixels;
1680    functions->CopyPixels = st_CopyPixels;
1681 }
1682
1683
1684 void
1685 st_destroy_drawpix(struct st_context *st)
1686 {
1687    GLuint i;
1688
1689    for (i = 0; i < Elements(st->drawpix.shaders); i++) {
1690       if (st->drawpix.shaders[i])
1691          _mesa_reference_fragprog(st->ctx, &st->drawpix.shaders[i], NULL);
1692    }
1693
1694    st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
1695    if (st->drawpix.vert_shaders[0])
1696       cso_delete_vertex_shader(st->cso_context, st->drawpix.vert_shaders[0]);
1697    if (st->drawpix.vert_shaders[1])
1698       cso_delete_vertex_shader(st->cso_context, st->drawpix.vert_shaders[1]);
1699 }