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