st_cb_drawpixels.c revision b69dad1683f092e3ce9d0f3f8fb1bdf96bdff0c7
12861e737e84e4884109b9526ac645194ba892a74Michal Krol/**************************************************************************
22861e737e84e4884109b9526ac645194ba892a74Michal Krol *
3942ee025908a95afc57990c57d6754ca1a626b04Brian * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
42861e737e84e4884109b9526ac645194ba892a74Michal Krol * All Rights Reserved.
5942ee025908a95afc57990c57d6754ca1a626b04Brian *
62861e737e84e4884109b9526ac645194ba892a74Michal Krol * Permission is hereby granted, free of charge, to any person obtaining a
72861e737e84e4884109b9526ac645194ba892a74Michal Krol * copy of this software and associated documentation files (the
82861e737e84e4884109b9526ac645194ba892a74Michal Krol * "Software"), to deal in the Software without restriction, including
92861e737e84e4884109b9526ac645194ba892a74Michal Krol * without limitation the rights to use, copy, modify, merge, publish,
102861e737e84e4884109b9526ac645194ba892a74Michal Krol * distribute, sub license, and/or sell copies of the Software, and to
112861e737e84e4884109b9526ac645194ba892a74Michal Krol * permit persons to whom the Software is furnished to do so, subject to
122861e737e84e4884109b9526ac645194ba892a74Michal Krol * the following conditions:
132861e737e84e4884109b9526ac645194ba892a74Michal Krol *
142861e737e84e4884109b9526ac645194ba892a74Michal Krol * The above copyright notice and this permission notice (including the
152861e737e84e4884109b9526ac645194ba892a74Michal Krol * next paragraph) shall be included in all copies or substantial portions
162861e737e84e4884109b9526ac645194ba892a74Michal Krol * of the Software.
172861e737e84e4884109b9526ac645194ba892a74Michal Krol *
182861e737e84e4884109b9526ac645194ba892a74Michal Krol * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
192861e737e84e4884109b9526ac645194ba892a74Michal Krol * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
202861e737e84e4884109b9526ac645194ba892a74Michal Krol * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
212861e737e84e4884109b9526ac645194ba892a74Michal Krol * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
222861e737e84e4884109b9526ac645194ba892a74Michal Krol * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
232861e737e84e4884109b9526ac645194ba892a74Michal Krol * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
242861e737e84e4884109b9526ac645194ba892a74Michal Krol * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
252861e737e84e4884109b9526ac645194ba892a74Michal Krol *
262861e737e84e4884109b9526ac645194ba892a74Michal Krol **************************************************************************/
272861e737e84e4884109b9526ac645194ba892a74Michal Krol
282861e737e84e4884109b9526ac645194ba892a74Michal Krol /*
292861e737e84e4884109b9526ac645194ba892a74Michal Krol  * Authors:
302861e737e84e4884109b9526ac645194ba892a74Michal Krol  *   Brian Paul
312861e737e84e4884109b9526ac645194ba892a74Michal Krol  */
32101d1a658a614d1e2ec02b1e697f6161291af653José Fonseca
33101d1a658a614d1e2ec02b1e697f6161291af653José Fonseca#include "main/imports.h"
34101d1a658a614d1e2ec02b1e697f6161291af653José Fonseca#include "main/image.h"
350560d81ce94d27f2162d77d981468cea1b2bbd8aBrian#include "main/bufferobj.h"
36b26aae67f5fe4194b48a5d3ddf704797b804b58cBrian#include "main/format_pack.h"
370560d81ce94d27f2162d77d981468cea1b2bbd8aBrian#include "main/macros.h"
380560d81ce94d27f2162d77d981468cea1b2bbd8aBrian#include "main/mfeatures.h"
392861e737e84e4884109b9526ac645194ba892a74Michal Krol#include "main/mtypes.h"
402861e737e84e4884109b9526ac645194ba892a74Michal Krol#include "main/pack.h"
41942ee025908a95afc57990c57d6754ca1a626b04Brian#include "main/pbo.h"
42942ee025908a95afc57990c57d6754ca1a626b04Brian#include "main/readpix.h"
43765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul#include "main/texformat.h"
44765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul#include "main/teximage.h"
45122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul#include "main/texstore.h"
46765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul#include "program/program.h"
47765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul#include "program/prog_print.h"
482861e737e84e4884109b9526ac645194ba892a74Michal Krol#include "program/prog_instruction.h"
4921841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul
502861e737e84e4884109b9526ac645194ba892a74Michal Krol#include "st_atom.h"
512861e737e84e4884109b9526ac645194ba892a74Michal Krol#include "st_atom_constbuf.h"
522861e737e84e4884109b9526ac645194ba892a74Michal Krol#include "st_cb_drawpixels.h"
532861e737e84e4884109b9526ac645194ba892a74Michal Krol#include "st_cb_readpixels.h"
542861e737e84e4884109b9526ac645194ba892a74Michal Krol#include "st_cb_fbo.h"
552861e737e84e4884109b9526ac645194ba892a74Michal Krol#include "st_context.h"
565b2f8dc01300058d43d8043aa897722f39657e93Brian Paul#include "st_debug.h"
575b2f8dc01300058d43d8043aa897722f39657e93Brian Paul#include "st_format.h"
585b2f8dc01300058d43d8043aa897722f39657e93Brian Paul#include "st_program.h"
595b2f8dc01300058d43d8043aa897722f39657e93Brian Paul#include "st_texture.h"
605b2f8dc01300058d43d8043aa897722f39657e93Brian Paul
615b2f8dc01300058d43d8043aa897722f39657e93Brian Paul#include "pipe/p_context.h"
625b2f8dc01300058d43d8043aa897722f39657e93Brian Paul#include "pipe/p_defines.h"
635b2f8dc01300058d43d8043aa897722f39657e93Brian Paul#include "tgsi/tgsi_ureg.h"
645b2f8dc01300058d43d8043aa897722f39657e93Brian Paul#include "util/u_draw_quad.h"
65dd528f0ec18cfbd6f0a5b23b8cb46a97b96ab965Brian Paul#include "util/u_format.h"
66dd528f0ec18cfbd6f0a5b23b8cb46a97b96ab965Brian Paul#include "util/u_inlines.h"
67dd528f0ec18cfbd6f0a5b23b8cb46a97b96ab965Brian Paul#include "util/u_math.h"
68dd528f0ec18cfbd6f0a5b23b8cb46a97b96ab965Brian Paul#include "util/u_tile.h"
69dd528f0ec18cfbd6f0a5b23b8cb46a97b96ab965Brian Paul#include "util/u_upload_mgr.h"
70dd528f0ec18cfbd6f0a5b23b8cb46a97b96ab965Brian Paul#include "cso_cache/cso_context.h"
712861e737e84e4884109b9526ac645194ba892a74Michal Krol
722861e737e84e4884109b9526ac645194ba892a74Michal Krol
732861e737e84e4884109b9526ac645194ba892a74Michal Krol#if FEATURE_drawpix
742861e737e84e4884109b9526ac645194ba892a74Michal Krol
752861e737e84e4884109b9526ac645194ba892a74Michal Krol/**
76af3d9dba562813ffed71691bffd7faf6665c4487Brian Paul * Check if the given program is:
77af3d9dba562813ffed71691bffd7faf6665c4487Brian Paul * 0: MOVE result.color, fragment.color;
78af3d9dba562813ffed71691bffd7faf6665c4487Brian Paul * 1: END;
792861e737e84e4884109b9526ac645194ba892a74Michal Krol */
80af3d9dba562813ffed71691bffd7faf6665c4487Brian Paulstatic GLboolean
812861e737e84e4884109b9526ac645194ba892a74Michal Krolis_passthrough_program(const struct gl_fragment_program *prog)
82df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian{
83df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   if (prog->Base.NumInstructions == 2) {
842861e737e84e4884109b9526ac645194ba892a74Michal Krol      const struct prog_instruction *inst = prog->Base.Instructions;
852861e737e84e4884109b9526ac645194ba892a74Michal Krol      if (inst[0].Opcode == OPCODE_MOV &&
862861e737e84e4884109b9526ac645194ba892a74Michal Krol          inst[1].Opcode == OPCODE_END &&
872861e737e84e4884109b9526ac645194ba892a74Michal Krol          inst[0].DstReg.File == PROGRAM_OUTPUT &&
882861e737e84e4884109b9526ac645194ba892a74Michal Krol          inst[0].DstReg.Index == FRAG_RESULT_COLOR &&
89b26aae67f5fe4194b48a5d3ddf704797b804b58cBrian          inst[0].DstReg.WriteMask == WRITEMASK_XYZW &&
902861e737e84e4884109b9526ac645194ba892a74Michal Krol          inst[0].SrcReg[0].File == PROGRAM_INPUT &&
912861e737e84e4884109b9526ac645194ba892a74Michal Krol          inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 &&
922861e737e84e4884109b9526ac645194ba892a74Michal Krol          inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) {
932861e737e84e4884109b9526ac645194ba892a74Michal Krol         return GL_TRUE;
94df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      }
95df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   }
962861e737e84e4884109b9526ac645194ba892a74Michal Krol   return GL_FALSE;
97b26aae67f5fe4194b48a5d3ddf704797b804b58cBrian}
982861e737e84e4884109b9526ac645194ba892a74Michal Krol
997f752fed993e5e9423abac200dd59141edbada56Dave Airlie
100b26aae67f5fe4194b48a5d3ddf704797b804b58cBrian/**
10163d683091fe3a9600b65ae7ef3b554168b805406Brian Paul * Returns a fragment program which implements the current pixel transfer ops.
1027f752fed993e5e9423abac200dd59141edbada56Dave Airlie */
1037f752fed993e5e9423abac200dd59141edbada56Dave Airliestatic struct gl_fragment_program *
104b7eea9a1ce9f3a28b74d77db19dcd859b6638a41Brian Paulget_glsl_pixel_transfer_program(struct st_context *st,
1057f752fed993e5e9423abac200dd59141edbada56Dave Airlie                                struct st_fragment_program *orig)
10663d683091fe3a9600b65ae7ef3b554168b805406Brian Paul{
1077f752fed993e5e9423abac200dd59141edbada56Dave Airlie   int pixelMaps = 0, scaleAndBias = 0;
1082861e737e84e4884109b9526ac645194ba892a74Michal Krol   struct gl_context *ctx = st->ctx;
1092861e737e84e4884109b9526ac645194ba892a74Michal Krol   struct st_fragment_program *fp = (struct st_fragment_program *)
1102861e737e84e4884109b9526ac645194ba892a74Michal Krol      ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
1112861e737e84e4884109b9526ac645194ba892a74Michal Krol
11221841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul   if (!fp)
11321841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul      return NULL;
11421841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul
11521841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul   if (ctx->Pixel.RedBias != 0.0 || ctx->Pixel.RedScale != 1.0 ||
11621841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul       ctx->Pixel.GreenBias != 0.0 || ctx->Pixel.GreenScale != 1.0 ||
11793da673904d4c520d3fbd2210e53777bf1598ac6Roland Scheidegger       ctx->Pixel.BlueBias != 0.0 || ctx->Pixel.BlueScale != 1.0 ||
118df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian       ctx->Pixel.AlphaBias != 0.0 || ctx->Pixel.AlphaScale != 1.0) {
1191631a9513d32ddcc5467225ad25d0e7a154af895Brian      scaleAndBias = 1;
12021841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul   }
12193da673904d4c520d3fbd2210e53777bf1598ac6Roland Scheidegger
122df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   pixelMaps = ctx->Pixel.MapColorFlag;
1231631a9513d32ddcc5467225ad25d0e7a154af895Brian
12421841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul   if (pixelMaps) {
12563d683091fe3a9600b65ae7ef3b554168b805406Brian Paul      /* create the colormap/texture now if not already done */
1267f752fed993e5e9423abac200dd59141edbada56Dave Airlie      if (!st->pixel_xfer.pixelmap_texture) {
1277f752fed993e5e9423abac200dd59141edbada56Dave Airlie         st->pixel_xfer.pixelmap_texture = st_create_color_map_texture(ctx);
12863d683091fe3a9600b65ae7ef3b554168b805406Brian Paul         st->pixel_xfer.pixelmap_sampler_view =
12963d683091fe3a9600b65ae7ef3b554168b805406Brian Paul            st_create_texture_sampler_view(st->pipe,
13063d683091fe3a9600b65ae7ef3b554168b805406Brian Paul                                           st->pixel_xfer.pixelmap_texture);
13163d683091fe3a9600b65ae7ef3b554168b805406Brian Paul      }
1327f752fed993e5e9423abac200dd59141edbada56Dave Airlie   }
1337f752fed993e5e9423abac200dd59141edbada56Dave Airlie
13421841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul   get_pixel_transfer_visitor(fp, orig->glsl_to_tgsi,
13521841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul                              scaleAndBias, pixelMaps);
13621841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul
13721841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul   return &fp->Base;
1384b654d41da08b3b5475144c027e97a3ae7ab5696Brian}
1394b654d41da08b3b5475144c027e97a3ae7ab5696Brian
140d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
1414b654d41da08b3b5475144c027e97a3ae7ab5696Brian/**
1424b654d41da08b3b5475144c027e97a3ae7ab5696Brian * Make fragment shader for glDraw/CopyPixels.  This shader is made
1434b654d41da08b3b5475144c027e97a3ae7ab5696Brian * by combining the pixel transfer shader with the user-defined shader.
1444b654d41da08b3b5475144c027e97a3ae7ab5696Brian * \param fpIn  the current/incoming fragment program
1454b654d41da08b3b5475144c027e97a3ae7ab5696Brian * \param fpOut  returns the combined fragment program
1464b654d41da08b3b5475144c027e97a3ae7ab5696Brian */
14757e222d6e5ef5744491d093475e1136aedf81810Brian Paulvoid
14857e222d6e5ef5744491d093475e1136aedf81810Brian Paulst_make_drawpix_fragment_program(struct st_context *st,
14957e222d6e5ef5744491d093475e1136aedf81810Brian Paul                                 struct gl_fragment_program *fpIn,
1504b654d41da08b3b5475144c027e97a3ae7ab5696Brian                                 struct gl_fragment_program **fpOut)
1514b654d41da08b3b5475144c027e97a3ae7ab5696Brian{
1524b654d41da08b3b5475144c027e97a3ae7ab5696Brian   struct gl_program *newProg;
1534b654d41da08b3b5475144c027e97a3ae7ab5696Brian   struct st_fragment_program *stfp = (struct st_fragment_program *) fpIn;
15457e222d6e5ef5744491d093475e1136aedf81810Brian Paul
15557e222d6e5ef5744491d093475e1136aedf81810Brian Paul   if (is_passthrough_program(fpIn)) {
15657e222d6e5ef5744491d093475e1136aedf81810Brian Paul      newProg = (struct gl_program *) _mesa_clone_fragment_program(st->ctx,
1574b654d41da08b3b5475144c027e97a3ae7ab5696Brian                                             &st->pixel_xfer.program->Base);
1584b654d41da08b3b5475144c027e97a3ae7ab5696Brian   }
1594b654d41da08b3b5475144c027e97a3ae7ab5696Brian   else if (stfp->glsl_to_tgsi != NULL) {
1604b654d41da08b3b5475144c027e97a3ae7ab5696Brian      newProg = (struct gl_program *) get_glsl_pixel_transfer_program(st, stfp);
1614b654d41da08b3b5475144c027e97a3ae7ab5696Brian   }
1624b654d41da08b3b5475144c027e97a3ae7ab5696Brian   else {
1634b654d41da08b3b5475144c027e97a3ae7ab5696Brian#if 0
1644b654d41da08b3b5475144c027e97a3ae7ab5696Brian      /* debug */
1654b654d41da08b3b5475144c027e97a3ae7ab5696Brian      printf("Base program:\n");
1664b654d41da08b3b5475144c027e97a3ae7ab5696Brian      _mesa_print_program(&fpIn->Base);
1674b654d41da08b3b5475144c027e97a3ae7ab5696Brian      printf("DrawPix program:\n");
1684b654d41da08b3b5475144c027e97a3ae7ab5696Brian      _mesa_print_program(&st->pixel_xfer.program->Base.Base);
1694b654d41da08b3b5475144c027e97a3ae7ab5696Brian#endif
1704b654d41da08b3b5475144c027e97a3ae7ab5696Brian      newProg = _mesa_combine_programs(st->ctx,
1714b654d41da08b3b5475144c027e97a3ae7ab5696Brian                                       &st->pixel_xfer.program->Base.Base,
1724b654d41da08b3b5475144c027e97a3ae7ab5696Brian                                       &fpIn->Base);
17321841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul   }
17421841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul
17521841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul#if 0
1762861e737e84e4884109b9526ac645194ba892a74Michal Krol   /* debug */
1772861e737e84e4884109b9526ac645194ba892a74Michal Krol   printf("Combined DrawPixels program:\n");
1782861e737e84e4884109b9526ac645194ba892a74Michal Krol   _mesa_print_program(newProg);
1792861e737e84e4884109b9526ac645194ba892a74Michal Krol   printf("InputsRead: 0x%x\n", newProg->InputsRead);
1802861e737e84e4884109b9526ac645194ba892a74Michal Krol   printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten);
1812861e737e84e4884109b9526ac645194ba892a74Michal Krol   _mesa_print_parameter_list(newProg->Parameters);
1822861e737e84e4884109b9526ac645194ba892a74Michal Krol#endif
1832861e737e84e4884109b9526ac645194ba892a74Michal Krol
1842861e737e84e4884109b9526ac645194ba892a74Michal Krol   *fpOut = (struct gl_fragment_program *) newProg;
1852861e737e84e4884109b9526ac645194ba892a74Michal Krol}
1862861e737e84e4884109b9526ac645194ba892a74Michal Krol
1872861e737e84e4884109b9526ac645194ba892a74Michal Krol
1882861e737e84e4884109b9526ac645194ba892a74Michal Krol/**
1892861e737e84e4884109b9526ac645194ba892a74Michal Krol * Create fragment program that does a TEX() instruction to get a Z and/or
1902861e737e84e4884109b9526ac645194ba892a74Michal Krol * stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL.
1912861e737e84e4884109b9526ac645194ba892a74Michal Krol * Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX).
1922861e737e84e4884109b9526ac645194ba892a74Michal Krol * Pass fragment color through as-is.
1932861e737e84e4884109b9526ac645194ba892a74Michal Krol * \return pointer to the gl_fragment program
1942861e737e84e4884109b9526ac645194ba892a74Michal Krol */
1952861e737e84e4884109b9526ac645194ba892a74Michal Krolstruct gl_fragment_program *
1962861e737e84e4884109b9526ac645194ba892a74Michal Krolst_make_drawpix_z_stencil_program(struct st_context *st,
1972861e737e84e4884109b9526ac645194ba892a74Michal Krol                                  GLboolean write_depth,
1982861e737e84e4884109b9526ac645194ba892a74Michal Krol                                  GLboolean write_stencil)
1992861e737e84e4884109b9526ac645194ba892a74Michal Krol{
2002861e737e84e4884109b9526ac645194ba892a74Michal Krol   struct gl_context *ctx = st->ctx;
2012861e737e84e4884109b9526ac645194ba892a74Michal Krol   struct gl_program *p;
2022861e737e84e4884109b9526ac645194ba892a74Michal Krol   struct gl_fragment_program *fp;
2032861e737e84e4884109b9526ac645194ba892a74Michal Krol   GLuint ic = 0;
2042861e737e84e4884109b9526ac645194ba892a74Michal Krol   const GLuint shaderIndex = write_depth * 2 + write_stencil;
2052861e737e84e4884109b9526ac645194ba892a74Michal Krol
2062861e737e84e4884109b9526ac645194ba892a74Michal Krol   assert(shaderIndex < Elements(st->drawpix.shaders));
2072861e737e84e4884109b9526ac645194ba892a74Michal Krol
2082861e737e84e4884109b9526ac645194ba892a74Michal Krol   if (st->drawpix.shaders[shaderIndex]) {
2092861e737e84e4884109b9526ac645194ba892a74Michal Krol      /* already have the proper shader */
2102861e737e84e4884109b9526ac645194ba892a74Michal Krol      return st->drawpix.shaders[shaderIndex];
2112861e737e84e4884109b9526ac645194ba892a74Michal Krol   }
2122861e737e84e4884109b9526ac645194ba892a74Michal Krol
2132861e737e84e4884109b9526ac645194ba892a74Michal Krol   /*
2142861e737e84e4884109b9526ac645194ba892a74Michal Krol    * Create shader now
2152861e737e84e4884109b9526ac645194ba892a74Michal Krol    */
2162861e737e84e4884109b9526ac645194ba892a74Michal Krol   p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
2172861e737e84e4884109b9526ac645194ba892a74Michal Krol   if (!p)
2182861e737e84e4884109b9526ac645194ba892a74Michal Krol      return NULL;
2192861e737e84e4884109b9526ac645194ba892a74Michal Krol
2202861e737e84e4884109b9526ac645194ba892a74Michal Krol   p->NumInstructions = write_depth ? 2 : 1;
2212861e737e84e4884109b9526ac645194ba892a74Michal Krol   p->NumInstructions += write_stencil ? 1 : 0;
2222861e737e84e4884109b9526ac645194ba892a74Michal Krol
2232861e737e84e4884109b9526ac645194ba892a74Michal Krol   p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
2242861e737e84e4884109b9526ac645194ba892a74Michal Krol   if (!p->Instructions) {
2252861e737e84e4884109b9526ac645194ba892a74Michal Krol      ctx->Driver.DeleteProgram(ctx, p);
2262861e737e84e4884109b9526ac645194ba892a74Michal Krol      return NULL;
2272861e737e84e4884109b9526ac645194ba892a74Michal Krol   }
2282861e737e84e4884109b9526ac645194ba892a74Michal Krol   _mesa_init_instructions(p->Instructions, p->NumInstructions);
2292861e737e84e4884109b9526ac645194ba892a74Michal Krol
2302861e737e84e4884109b9526ac645194ba892a74Michal Krol   if (write_depth) {
2312861e737e84e4884109b9526ac645194ba892a74Michal Krol      /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */
2322861e737e84e4884109b9526ac645194ba892a74Michal Krol      p->Instructions[ic].Opcode = OPCODE_TEX;
233765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul      p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
234765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul      p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPTH;
235765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul      p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z;
236122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul      p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
237122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul      p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
238765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul      p->Instructions[ic].TexSrcUnit = 0;
2392861e737e84e4884109b9526ac645194ba892a74Michal Krol      p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
240a6c423d95663cfd8601cf84e10e8e1b12fa6ef15Brian Paul      ic++;
2412861e737e84e4884109b9526ac645194ba892a74Michal Krol   }
2420c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul
2430c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul   if (write_stencil) {
2442861e737e84e4884109b9526ac645194ba892a74Michal Krol      /* TEX result.stencil, fragment.texcoord[0], texture[0], 2D; */
2452861e737e84e4884109b9526ac645194ba892a74Michal Krol      p->Instructions[ic].Opcode = OPCODE_TEX;
2462861e737e84e4884109b9526ac645194ba892a74Michal Krol      p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
2472861e737e84e4884109b9526ac645194ba892a74Michal Krol      p->Instructions[ic].DstReg.Index = FRAG_RESULT_STENCIL;
248308b85f29f191409e42935a3ccd5c502bdf70608Brian Paul      p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Y;
2490c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
2500c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
2510c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      p->Instructions[ic].TexSrcUnit = 1;
2520c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
2532861e737e84e4884109b9526ac645194ba892a74Michal Krol      ic++;
2542861e737e84e4884109b9526ac645194ba892a74Michal Krol   }
2552861e737e84e4884109b9526ac645194ba892a74Michal Krol
2562861e737e84e4884109b9526ac645194ba892a74Michal Krol   /* END; */
2572861e737e84e4884109b9526ac645194ba892a74Michal Krol   p->Instructions[ic++].Opcode = OPCODE_END;
258765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul
259765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul   assert(ic == p->NumInstructions);
260765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul
261765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul   p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
262122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   p->OutputsWritten = 0;
263122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   if (write_depth)
264765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul      p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_DEPTH);
2652861e737e84e4884109b9526ac645194ba892a74Michal Krol   if (write_stencil)
266d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_STENCIL);
2672861e737e84e4884109b9526ac645194ba892a74Michal Krol
2682861e737e84e4884109b9526ac645194ba892a74Michal Krol   p->SamplersUsed =  0x1;  /* sampler 0 (bit 0) is used */
2692861e737e84e4884109b9526ac645194ba892a74Michal Krol   if (write_stencil)
2702861e737e84e4884109b9526ac645194ba892a74Michal Krol      p->SamplersUsed |= 1 << 1;
2712861e737e84e4884109b9526ac645194ba892a74Michal Krol
272765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul   fp = (struct gl_fragment_program *) p;
273765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul
274765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul   /* save the new shader */
275765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul   st->drawpix.shaders[shaderIndex] = fp;
276122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul
277122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   return fp;
278765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul}
2792861e737e84e4884109b9526ac645194ba892a74Michal Krol
280d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
2812861e737e84e4884109b9526ac645194ba892a74Michal Krol/**
2822861e737e84e4884109b9526ac645194ba892a74Michal Krol * Create a simple vertex shader that just passes through the
2832861e737e84e4884109b9526ac645194ba892a74Michal Krol * vertex position and texcoord (and optionally, color).
2842861e737e84e4884109b9526ac645194ba892a74Michal Krol */
2852861e737e84e4884109b9526ac645194ba892a74Michal Krolstatic void *
2862861e737e84e4884109b9526ac645194ba892a74Michal Krolmake_passthrough_vertex_shader(struct st_context *st,
2872861e737e84e4884109b9526ac645194ba892a74Michal Krol                               GLboolean passColor)
2882861e737e84e4884109b9526ac645194ba892a74Michal Krol{
2892861e737e84e4884109b9526ac645194ba892a74Michal Krol   if (!st->drawpix.vert_shaders[passColor]) {
2902861e737e84e4884109b9526ac645194ba892a74Michal Krol      struct ureg_program *ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
2912861e737e84e4884109b9526ac645194ba892a74Michal Krol
2922861e737e84e4884109b9526ac645194ba892a74Michal Krol      if (ureg == NULL)
293d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle         return NULL;
2942861e737e84e4884109b9526ac645194ba892a74Michal Krol
2952861e737e84e4884109b9526ac645194ba892a74Michal Krol      /* MOV result.pos, vertex.pos; */
2962861e737e84e4884109b9526ac645194ba892a74Michal Krol      ureg_MOV(ureg,
2972861e737e84e4884109b9526ac645194ba892a74Michal Krol               ureg_DECL_output( ureg, TGSI_SEMANTIC_POSITION, 0 ),
2982861e737e84e4884109b9526ac645194ba892a74Michal Krol               ureg_DECL_vs_input( ureg, 0 ));
299122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul
3002861e737e84e4884109b9526ac645194ba892a74Michal Krol      /* MOV result.texcoord0, vertex.attr[1]; */
3012861e737e84e4884109b9526ac645194ba892a74Michal Krol      ureg_MOV(ureg,
302a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul               ureg_DECL_output( ureg, TGSI_SEMANTIC_GENERIC, 0 ),
3032861e737e84e4884109b9526ac645194ba892a74Michal Krol               ureg_DECL_vs_input( ureg, 1 ));
3042861e737e84e4884109b9526ac645194ba892a74Michal Krol
305c5af2ed60fa4fe3f33b53a8e252e24cfa490a156Brian Paul      if (passColor) {
306a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul         /* MOV result.color0, vertex.attr[2]; */
307122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul         ureg_MOV(ureg,
308a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul                  ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ),
3092861e737e84e4884109b9526ac645194ba892a74Michal Krol                  ureg_DECL_vs_input( ureg, 2 ));
3102861e737e84e4884109b9526ac645194ba892a74Michal Krol      }
311a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul
312122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul      ureg_END( ureg );
313122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul
314a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul      st->drawpix.vert_shaders[passColor] =
3152861e737e84e4884109b9526ac645194ba892a74Michal Krol         ureg_create_shader_and_destroy( ureg, st->pipe );
3162861e737e84e4884109b9526ac645194ba892a74Michal Krol   }
317a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul
3182861e737e84e4884109b9526ac645194ba892a74Michal Krol   return st->drawpix.vert_shaders[passColor];
319a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul}
3202861e737e84e4884109b9526ac645194ba892a74Michal Krol
3212861e737e84e4884109b9526ac645194ba892a74Michal Krol
3222861e737e84e4884109b9526ac645194ba892a74Michal Krol/**
3232861e737e84e4884109b9526ac645194ba892a74Michal Krol * Return a texture internalFormat for drawing/copying an image
3242861e737e84e4884109b9526ac645194ba892a74Michal Krol * of the given format and type.
3252861e737e84e4884109b9526ac645194ba892a74Michal Krol */
3262861e737e84e4884109b9526ac645194ba892a74Michal Krolstatic GLenum
3272861e737e84e4884109b9526ac645194ba892a74Michal Krolinternal_format(struct gl_context *ctx, GLenum format, GLenum type)
3282861e737e84e4884109b9526ac645194ba892a74Michal Krol{
3292861e737e84e4884109b9526ac645194ba892a74Michal Krol   switch (format) {
330122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   case GL_DEPTH_COMPONENT:
3312861e737e84e4884109b9526ac645194ba892a74Michal Krol      switch (type) {
332a6c423d95663cfd8601cf84e10e8e1b12fa6ef15Brian Paul      case GL_UNSIGNED_SHORT:
33357e222d6e5ef5744491d093475e1136aedf81810Brian Paul         return GL_DEPTH_COMPONENT16;
33457e222d6e5ef5744491d093475e1136aedf81810Brian Paul
3352861e737e84e4884109b9526ac645194ba892a74Michal Krol      case GL_UNSIGNED_INT:
336308b85f29f191409e42935a3ccd5c502bdf70608Brian Paul         return GL_DEPTH_COMPONENT32;
337308b85f29f191409e42935a3ccd5c502bdf70608Brian Paul
338d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      case GL_FLOAT:
3392861e737e84e4884109b9526ac645194ba892a74Michal Krol         if (ctx->Extensions.ARB_depth_buffer_float)
3402861e737e84e4884109b9526ac645194ba892a74Michal Krol            return GL_DEPTH_COMPONENT32F;
341de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul         else
34219ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul            return GL_DEPTH_COMPONENT;
343de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul
34465a51c0d6243f07491578e95b85bc483f923b817Brian Paul      default:
345de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul         return GL_DEPTH_COMPONENT;
34665a51c0d6243f07491578e95b85bc483f923b817Brian Paul      }
347fe1d01cb398cbcb5b28a0b222845d3865c4d612bBrian
348fe1d01cb398cbcb5b28a0b222845d3865c4d612bBrian   case GL_DEPTH_STENCIL:
349fe1d01cb398cbcb5b28a0b222845d3865c4d612bBrian      switch (type) {
3503493e867e9f2421425627a15eb5d2a2c554fbe8aBrian      case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
3513493e867e9f2421425627a15eb5d2a2c554fbe8aBrian         return GL_DEPTH32F_STENCIL8;
3523493e867e9f2421425627a15eb5d2a2c554fbe8aBrian
353fe1d01cb398cbcb5b28a0b222845d3865c4d612bBrian      case GL_UNSIGNED_INT_24_8:
3542861e737e84e4884109b9526ac645194ba892a74Michal Krol      default:
3552861e737e84e4884109b9526ac645194ba892a74Michal Krol         return GL_DEPTH24_STENCIL8;
3562861e737e84e4884109b9526ac645194ba892a74Michal Krol      }
3572861e737e84e4884109b9526ac645194ba892a74Michal Krol
3584d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul   case GL_STENCIL_INDEX:
3594d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul      return GL_STENCIL_INDEX;
3604d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul
3614d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul   default:
3624d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul      if (_mesa_is_integer_format(format)) {
3634d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul         switch (type) {
3644d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul         case GL_BYTE:
3654d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul            return GL_RGBA8I;
3664d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul         case GL_UNSIGNED_BYTE:
3674d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul            return GL_RGBA8UI;
3684d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul         case GL_SHORT:
3694d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul            return GL_RGBA16I;
3704d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul         case GL_UNSIGNED_SHORT:
3714d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul            return GL_RGBA16UI;
3722861e737e84e4884109b9526ac645194ba892a74Michal Krol         case GL_INT:
3733b9b8de9b0bf2f1e69a450360a812090520b2b29Brian Paul            return GL_RGBA32I;
374df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_UNSIGNED_INT:
375df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian            return GL_RGBA32UI;
376df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         default:
377df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian            assert(0 && "Unexpected type in internal_format()");
378df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian            return GL_RGBA_INTEGER;
379df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         }
380df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      }
381df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      else {
382df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         switch (type) {
383df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_UNSIGNED_BYTE:
3844bc39c58eb7fdf3a0be62bed666998a0d1789dcfBrian Paul         case GL_UNSIGNED_INT_8_8_8_8:
3854bc39c58eb7fdf3a0be62bed666998a0d1789dcfBrian Paul         case GL_UNSIGNED_INT_8_8_8_8_REV:
3864bc39c58eb7fdf3a0be62bed666998a0d1789dcfBrian Paul         default:
3874bc39c58eb7fdf3a0be62bed666998a0d1789dcfBrian Paul            return GL_RGBA8;
3884bc39c58eb7fdf3a0be62bed666998a0d1789dcfBrian Paul
389df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_UNSIGNED_BYTE_3_3_2:
390df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_UNSIGNED_BYTE_2_3_3_REV:
391df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_UNSIGNED_SHORT_4_4_4_4:
392df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_UNSIGNED_SHORT_4_4_4_4_REV:
393df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian            return GL_RGBA4;
394df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian
395df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_UNSIGNED_SHORT_5_6_5:
396df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_UNSIGNED_SHORT_5_6_5_REV:
397b4e75d6c41b2561ca86321fb775ca774c8af44ebBrian Paul         case GL_UNSIGNED_SHORT_5_5_5_1:
398a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul         case GL_UNSIGNED_SHORT_1_5_5_5_REV:
399a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul            return GL_RGB5_A1;
400a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul
401a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul         case GL_UNSIGNED_INT_10_10_10_2:
402df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_UNSIGNED_INT_2_10_10_10_REV:
403df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian            return GL_RGB10_A2;
404df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian
405df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_UNSIGNED_SHORT:
406df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_UNSIGNED_INT:
407df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian            return GL_RGBA16;
408d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
409df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_BYTE:
410df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian            return
411df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian               ctx->Extensions.EXT_texture_snorm ? GL_RGBA8_SNORM : GL_RGBA8;
412df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian
413df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_SHORT:
414df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_INT:
415df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian            return
416df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian               ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16;
417df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian
418df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_HALF_FLOAT_ARB:
419df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian            return
420df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian               ctx->Extensions.ARB_texture_float ? GL_RGBA16F :
421b4e75d6c41b2561ca86321fb775ca774c8af44ebBrian Paul               ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16;
422a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul
423a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul         case GL_FLOAT:
424a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul         case GL_DOUBLE:
425a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul            return
426df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian               ctx->Extensions.ARB_texture_float ? GL_RGBA32F :
427df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian               ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16;
428df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian
429df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_UNSIGNED_INT_5_9_9_9_REV:
430df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian            assert(ctx->Extensions.EXT_texture_shared_exponent);
431df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian            return GL_RGB9_E5;
432df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian
433df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         case GL_UNSIGNED_INT_10F_11F_11F_REV:
434df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian            assert(ctx->Extensions.EXT_packed_float);
435b2a3a8554a114d93691d5350c234d2022c2c2916Brian            return GL_R11F_G11F_B10F;
436b2a3a8554a114d93691d5350c234d2022c2c2916Brian         }
437b2a3a8554a114d93691d5350c234d2022c2c2916Brian      }
438b2a3a8554a114d93691d5350c234d2022c2c2916Brian   }
439b2a3a8554a114d93691d5350c234d2022c2c2916Brian}
440b2a3a8554a114d93691d5350c234d2022c2c2916Brian
441b2a3a8554a114d93691d5350c234d2022c2c2916Brian
442b2a3a8554a114d93691d5350c234d2022c2c2916Brian/**
443b2a3a8554a114d93691d5350c234d2022c2c2916Brian * Create a temporary texture to hold an image of the given size.
4445b6858c023fca9d8eefce78121aabd9aad108e09Brian * If width, height are not POT and the driver only handles POT textures,
445b2a3a8554a114d93691d5350c234d2022c2c2916Brian * allocate the next larger size of texture that is POT.
446b2a3a8554a114d93691d5350c234d2022c2c2916Brian */
447b2a3a8554a114d93691d5350c234d2022c2c2916Brianstatic struct pipe_resource *
448b2a3a8554a114d93691d5350c234d2022c2c2916Brianalloc_texture(struct st_context *st, GLsizei width, GLsizei height,
449df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian              enum pipe_format texFormat)
450df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian{
451b2a3a8554a114d93691d5350c234d2022c2c2916Brian   struct pipe_resource *pt;
452b2a3a8554a114d93691d5350c234d2022c2c2916Brian
453b2a3a8554a114d93691d5350c234d2022c2c2916Brian   pt = st_texture_create(st, st->internal_target, texFormat, 0,
454b2a3a8554a114d93691d5350c234d2022c2c2916Brian                          width, height, 1, 1, PIPE_BIND_SAMPLER_VIEW);
45557e222d6e5ef5744491d093475e1136aedf81810Brian Paul
456b2a3a8554a114d93691d5350c234d2022c2c2916Brian   return pt;
457b2a3a8554a114d93691d5350c234d2022c2c2916Brian}
45812229f119d754715e0315846fdd8d6e9213e8edfBrian
45912229f119d754715e0315846fdd8d6e9213e8edfBrian
460b2a3a8554a114d93691d5350c234d2022c2c2916Brian/**
461b2a3a8554a114d93691d5350c234d2022c2c2916Brian * Make texture containing an image for glDrawPixels image.
4620c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul * If 'pixels' is NULL, leave the texture image data undefined.
46382635aad4203d44648dd6e345ec2b5e21ff06510Nicolai Haehnle */
464c9db223f902ce9d7e9f3038e6baac6da7f231b34Brianstatic struct pipe_resource *
465c9db223f902ce9d7e9f3038e6baac6da7f231b34Brianmake_texture(struct st_context *st,
4662e76f0a846b8273843dca701543f1cba70284751Brian	     GLsizei width, GLsizei height, GLenum format, GLenum type,
4672e76f0a846b8273843dca701543f1cba70284751Brian	     const struct gl_pixelstore_attrib *unpack,
468b2a3a8554a114d93691d5350c234d2022c2c2916Brian	     const GLvoid *pixels)
4692e76f0a846b8273843dca701543f1cba70284751Brian{
4702e76f0a846b8273843dca701543f1cba70284751Brian   struct gl_context *ctx = st->ctx;
4713209c3ed0d82c158eed1020759aacf51ba1c1ad5Brian   struct pipe_context *pipe = st->pipe;
4723209c3ed0d82c158eed1020759aacf51ba1c1ad5Brian   gl_format mformat;
473b2a3a8554a114d93691d5350c234d2022c2c2916Brian   struct pipe_resource *pt;
474b2a3a8554a114d93691d5350c234d2022c2c2916Brian   enum pipe_format pipeFormat;
475b2a3a8554a114d93691d5350c234d2022c2c2916Brian   GLenum baseInternalFormat, intFormat;
476b2a3a8554a114d93691d5350c234d2022c2c2916Brian
477b2a3a8554a114d93691d5350c234d2022c2c2916Brian   intFormat = internal_format(ctx, format, type);
478b2a3a8554a114d93691d5350c234d2022c2c2916Brian   baseInternalFormat = _mesa_base_tex_format(ctx, intFormat);
479b2a3a8554a114d93691d5350c234d2022c2c2916Brian
480b2a3a8554a114d93691d5350c234d2022c2c2916Brian   mformat = st_ChooseTextureFormat_renderable(ctx, intFormat,
481b2a3a8554a114d93691d5350c234d2022c2c2916Brian                                               format, type, GL_FALSE);
482b2a3a8554a114d93691d5350c234d2022c2c2916Brian   assert(mformat);
483b2a3a8554a114d93691d5350c234d2022c2c2916Brian
48421f99792a916a62fcfae7c208f50f192d4ce5926Brian   pipeFormat = st_mesa_format_to_pipe_format(mformat);
48521f99792a916a62fcfae7c208f50f192d4ce5926Brian   assert(pipeFormat);
48621f99792a916a62fcfae7c208f50f192d4ce5926Brian
48721f99792a916a62fcfae7c208f50f192d4ce5926Brian   pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
48821f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (!pixels)
48921f99792a916a62fcfae7c208f50f192d4ce5926Brian      return NULL;
490b2a3a8554a114d93691d5350c234d2022c2c2916Brian
491b2a3a8554a114d93691d5350c234d2022c2c2916Brian   /* alloc temporary texture */
492b2a3a8554a114d93691d5350c234d2022c2c2916Brian   pt = alloc_texture(st, width, height, pipeFormat);
493b2a3a8554a114d93691d5350c234d2022c2c2916Brian   if (!pt) {
494b2a3a8554a114d93691d5350c234d2022c2c2916Brian      _mesa_unmap_pbo_source(ctx, unpack);
495b2a3a8554a114d93691d5350c234d2022c2c2916Brian      return NULL;
496b2a3a8554a114d93691d5350c234d2022c2c2916Brian   }
497b2a3a8554a114d93691d5350c234d2022c2c2916Brian
498736e1ae42fd61f2b9f982b0491ca7daea7e615edNicolai Hähnle   {
499b2a3a8554a114d93691d5350c234d2022c2c2916Brian      struct pipe_transfer *transfer;
500b2a3a8554a114d93691d5350c234d2022c2c2916Brian      GLboolean success;
501b2a3a8554a114d93691d5350c234d2022c2c2916Brian      GLubyte *dest;
502b2a3a8554a114d93691d5350c234d2022c2c2916Brian      const GLbitfield imageTransferStateSave = ctx->_ImageTransferState;
503b2a3a8554a114d93691d5350c234d2022c2c2916Brian
504b2a3a8554a114d93691d5350c234d2022c2c2916Brian      /* we'll do pixel transfer in a fragment shader */
505b2a3a8554a114d93691d5350c234d2022c2c2916Brian      ctx->_ImageTransferState = 0x0;
506b2a3a8554a114d93691d5350c234d2022c2c2916Brian
507b2a3a8554a114d93691d5350c234d2022c2c2916Brian      transfer = pipe_get_transfer(st->pipe, pt, 0, 0,
508b2a3a8554a114d93691d5350c234d2022c2c2916Brian                                   PIPE_TRANSFER_WRITE, 0, 0,
509b2a3a8554a114d93691d5350c234d2022c2c2916Brian                                   width, height);
510b2a3a8554a114d93691d5350c234d2022c2c2916Brian
511b2a3a8554a114d93691d5350c234d2022c2c2916Brian      /* map texture transfer */
512b2a3a8554a114d93691d5350c234d2022c2c2916Brian      dest = pipe_transfer_map(pipe, transfer);
513b2a3a8554a114d93691d5350c234d2022c2c2916Brian
514b2a3a8554a114d93691d5350c234d2022c2c2916Brian
515b2a3a8554a114d93691d5350c234d2022c2c2916Brian      /* Put image into texture transfer.
516b2a3a8554a114d93691d5350c234d2022c2c2916Brian       * Note that the image is actually going to be upside down in
517b2a3a8554a114d93691d5350c234d2022c2c2916Brian       * the texture.  We deal with that with texcoords.
51819ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul       */
51919ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      success = _mesa_texstore(ctx, 2,           /* dims */
52019ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul                               baseInternalFormat, /* baseInternalFormat */
52119ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul                               mformat,          /* gl_format */
52219ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul                               transfer->stride, /* dstRowStride, bytes */
52319ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul                               &dest,            /* destSlices */
52419ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul                               width, height, 1, /* size */
52519ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul                               format, type,     /* src format/type */
52619ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul                               pixels,           /* data source */
52719ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul                               unpack);
52819ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
52919ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      /* unmap */
53019ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      pipe_transfer_unmap(pipe, transfer);
53119ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      pipe->transfer_destroy(pipe, transfer);
53219ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
53319ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      assert(success);
534457d7218b8e0f0c21ae31564d25b7031b423b0f8José Fonseca
53519ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      /* restore */
53619ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      ctx->_ImageTransferState = imageTransferStateSave;
53719ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   }
53819ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
53919ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   _mesa_unmap_pbo_source(ctx, unpack);
54019ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
54119ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   return pt;
54219ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul}
54319ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
54419ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
54519ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul/**
54619ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul * Draw quad with texcoords and optional color.
54719ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul * Coords are gallium window coords with y=0=top.
54819ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul * \param color  may be null
54919ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul * \param invertTex  if true, flip texcoords vertically
55019ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul */
55119ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paulstatic void
55219ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Pauldraw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z,
55319ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul          GLfloat x1, GLfloat y1, const GLfloat *color,
55419ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul          GLboolean invertTex, GLfloat maxXcoord, GLfloat maxYcoord)
55519ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul{
55619ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   struct st_context *st = st_context(ctx);
55719ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   struct pipe_context *pipe = st->pipe;
55819ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */
55919ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
56019ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   /* setup vertex data */
56119ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   {
56219ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
56319ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      const GLfloat fb_width = (GLfloat) fb->Width;
56419ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      const GLfloat fb_height = (GLfloat) fb->Height;
56519ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f;
56619ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f;
567b2a3a8554a114d93691d5350c234d2022c2c2916Brian      const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f;
568d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f;
569d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      const GLfloat sLeft = 0.0f, sRight = maxXcoord;
570d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      const GLfloat tTop = invertTex ? maxYcoord : 0.0f;
571d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      const GLfloat tBot = invertTex ? 0.0f : maxYcoord;
572d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      GLuint i;
573d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
574d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      /* upper-left */
575d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[0][0][0] = clip_x0;    /* v[0].attr[0].x */
576d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[0][0][1] = clip_y0;    /* v[0].attr[0].y */
577d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
578d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      /* upper-right */
579d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[1][0][0] = clip_x1;
580d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[1][0][1] = clip_y0;
581d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
582d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      /* lower-right */
58320fbb24b67dda0679774756e4b6d98c2c66c2c42Brian Paul      verts[2][0][0] = clip_x1;
584d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[2][0][1] = clip_y1;
585d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
586d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      /* lower-left */
587d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[3][0][0] = clip_x0;
588d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[3][0][1] = clip_y1;
589d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
590d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[0][1][0] = sLeft; /* v[0].attr[1].S */
591d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[0][1][1] = tTop;  /* v[0].attr[1].T */
592d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[1][1][0] = sRight;
593d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[1][1][1] = tTop;
594d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[2][1][0] = sRight;
595d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[2][1][1] = tBot;
596d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[3][1][0] = sLeft;
597d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      verts[3][1][1] = tBot;
598d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
599d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      /* same for all verts: */
600d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      if (color) {
601d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle         for (i = 0; i < 4; i++) {
602d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle            verts[i][0][2] = z;         /* v[i].attr[0].z */
603d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle            verts[i][0][3] = 1.0f;      /* v[i].attr[0].w */
604d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle            verts[i][2][0] = color[0];  /* v[i].attr[2].r */
605d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle            verts[i][2][1] = color[1];  /* v[i].attr[2].g */
606d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle            verts[i][2][2] = color[2];  /* v[i].attr[2].b */
607d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle            verts[i][2][3] = color[3];  /* v[i].attr[2].a */
608d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle            verts[i][1][2] = 0.0f;      /* v[i].attr[1].R */
609d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle            verts[i][1][3] = 1.0f;      /* v[i].attr[1].Q */
610d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle         }
611d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      }
612d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      else {
613d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle         for (i = 0; i < 4; i++) {
614d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle            verts[i][0][2] = z;    /*Z*/
6156ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul            verts[i][0][3] = 1.0f; /*W*/
6166ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul            verts[i][1][2] = 0.0f; /*R*/
6176ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul            verts[i][1][3] = 1.0f; /*Q*/
6186ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul         }
6196ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      }
6206ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   }
6216ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
6226ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   {
6236ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      struct pipe_resource *buf = NULL;
6246ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      unsigned offset;
6250c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul
6266ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      u_upload_data(st->uploader, 0, sizeof(verts), verts, &offset, &buf);
6276ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      if (!buf) {
6286ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul         return;
6296ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      }
6306ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
6316ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      u_upload_unmap(st->uploader);
6326ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      util_draw_vertex_buffer(pipe, st->cso_context, buf, offset,
6330c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul                              PIPE_PRIM_QUADS,
6340c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul                              4,  /* verts */
6350c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul                              3); /* attribs/vert */
6360c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      pipe_resource_reference(&buf, NULL);
6370c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul   }
6386ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul}
6396ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
6406ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
6416ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
6426ca948a303e1af7ae66ea7082af741f6880887f2Brian Paulstatic void
6436ca948a303e1af7ae66ea7082af741f6880887f2Brian Pauldraw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
6446ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                   GLsizei width, GLsizei height,
6456ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                   GLfloat zoomX, GLfloat zoomY,
6466ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                   struct pipe_sampler_view **sv,
6476ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                   int num_sampler_view,
6486ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                   void *driver_vp,
6496ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                   void *driver_fp,
6506ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                   const GLfloat *color,
6516ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                   GLboolean invertTex,
6526ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                   GLboolean write_depth, GLboolean write_stencil)
6536ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul{
6546ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   struct st_context *st = st_context(ctx);
6556ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   struct pipe_context *pipe = st->pipe;
6566ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   struct cso_context *cso = st->cso_context;
6576ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   GLfloat x0, y0, x1, y1;
6586ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   GLsizei maxSize;
6596ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   boolean normalized = sv[0]->texture->target != PIPE_TEXTURE_RECT;
6606ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
6616ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   /* limit checks */
6626ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   /* XXX if DrawPixels image is larger than max texture size, break
6636ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul    * it up into chunks.
6646ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul    */
6656ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   maxSize = 1 << (pipe->screen->get_param(pipe->screen,
6666ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                                        PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
6676ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   assert(width <= maxSize);
6686ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   assert(height <= maxSize);
6696ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
6706ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   cso_save_rasterizer(cso);
6710c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul   cso_save_viewport(cso);
6720c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul   cso_save_samplers(cso);
6736ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   cso_save_fragment_sampler_views(cso);
6746ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   cso_save_fragment_shader(cso);
6756ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   cso_save_stream_outputs(cso);
6766ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   cso_save_vertex_shader(cso);
6776ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   cso_save_geometry_shader(cso);
6786ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   cso_save_vertex_elements(cso);
6796ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   cso_save_vertex_buffers(cso);
680a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   if (write_stencil) {
681a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul      cso_save_depth_stencil_alpha(cso);
6820c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      cso_save_blend(cso);
6836ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   }
6846ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
6856ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   /* rasterizer state: just scissor */
6866ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   {
6876ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      struct pipe_rasterizer_state rasterizer;
6886ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      memset(&rasterizer, 0, sizeof(rasterizer));
6896ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      rasterizer.clamp_fragment_color = !st->clamp_frag_color_in_shader &&
6906ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                                        ctx->Color._ClampFragmentColor;
6916ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      rasterizer.gl_rasterization_rules = 1;
6926ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      rasterizer.depth_clip = !ctx->Transform.DepthClamp;
6936ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      rasterizer.scissor = ctx->Scissor.Enabled;
6946ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      cso_set_rasterizer(cso, &rasterizer);
6956ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   }
6966ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
6976ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   if (write_stencil) {
6986ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      /* Stencil writing bypasses the normal fragment pipeline to
6996ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul       * disable color writing and set stencil test to always pass.
7006ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul       */
7016ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      struct pipe_depth_stencil_alpha_state dsa;
7026ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      struct pipe_blend_state blend;
703a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul
704a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul      /* depth/stencil */
705a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul      memset(&dsa, 0, sizeof(dsa));
706a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul      dsa.stencil[0].enabled = 1;
7076ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
7080c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      dsa.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
7095c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
7105c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      if (write_depth) {
7115c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul         /* writing depth+stencil: depth test always passes */
7120c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul         dsa.depth.enabled = 1;
7130c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul         dsa.depth.writemask = ctx->Depth.Mask;
7140c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul         dsa.depth.func = PIPE_FUNC_ALWAYS;
7150c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      }
7160c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      cso_set_depth_stencil_alpha(cso, &dsa);
7170c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul
7185c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      /* blend (colormask) */
7195c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      memset(&blend, 0, sizeof(blend));
7205c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      cso_set_blend(cso, &blend);
7215c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul   }
7225c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul
7235c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul   /* fragment shader state: TEX lookup program */
7245c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul   cso_set_fragment_shader_handle(cso, driver_fp);
7255c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul
7265c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul   /* vertex shader state: position + texcoord pass-through */
7275c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul   cso_set_vertex_shader_handle(cso, driver_vp);
7285c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul
7295c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul   /* geometry shader state: disabled */
7305c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul   cso_set_geometry_shader_handle(cso, NULL);
7315c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul
7325c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul   /* texture sampling state: */
7335c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul   {
7345c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      struct pipe_sampler_state sampler;
7355c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      memset(&sampler, 0, sizeof(sampler));
7365c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
7375c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
7385c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      sampler.wrap_r = PIPE_TEX_WRAP_CLAMP;
7395c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
7405c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
7415c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
7425c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      sampler.normalized_coords = normalized;
7435c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul
7445c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      cso_single_sampler(cso, 0, &sampler);
7450c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      if (num_sampler_view > 1) {
7460c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul         cso_single_sampler(cso, 1, &sampler);
7470c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      }
7488d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul      cso_single_sampler_done(cso);
7495c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul   }
750a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul
751a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   /* viewport state: viewport matching window dims */
752e469d78d33feff45f16235871ca1a3d483cdc950Brian Paul   {
7530c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      const float w = (float) ctx->DrawBuffer->Width;
7540c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      const float h = (float) ctx->DrawBuffer->Height;
7550c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      struct pipe_viewport_state vp;
7560c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      vp.scale[0] =  0.5f * w;
757a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul      vp.scale[1] = -0.5f * h;
758a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul      vp.scale[2] = 0.5f;
7590c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      vp.scale[3] = 1.0f;
7600c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      vp.translate[0] = 0.5f * w;
7618d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul      vp.translate[1] = 0.5f * h;
7620c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      vp.translate[2] = 0.5f;
7635c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      vp.translate[3] = 0.0f;
7646ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      cso_set_viewport(cso, &vp);
7655c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul   }
7665c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul
7676ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   cso_set_vertex_elements(cso, 3, st->velems_util_draw);
7686ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   cso_set_stream_outputs(st->cso_context, 0, NULL, 0);
7695c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul
7705c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul   /* texture state: */
7718d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul   cso_set_fragment_sampler_views(cso, num_sampler_view, sv);
7720c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul
7730c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul   /* Compute Gallium window coords (y=0=top) with pixel zoom.
7740c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul    * Recall that these coords are transformed by the current
7756ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul    * vertex shader and viewport transformation.
7760c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul    */
7776ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) {
7786ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      y = ctx->DrawBuffer->Height - (int) (y + height * ctx->Pixel.ZoomY);
7796ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      invertTex = !invertTex;
7806ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   }
7816ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
7826ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   x0 = (GLfloat) x;
7836ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   x1 = x + width * ctx->Pixel.ZoomX;
7846ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   y0 = (GLfloat) y;
7856ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   y1 = y + height * ctx->Pixel.ZoomY;
7866ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
7876ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
7886ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   z = z * 2.0 - 1.0;
7896ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
7906ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex,
7916ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul             normalized ? ((GLfloat) width / sv[0]->texture->width0) : (GLfloat)width,
7926ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul             normalized ? ((GLfloat) height / sv[0]->texture->height0) : (GLfloat)height);
7936ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
7946ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   /* restore state */
7956ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   cso_restore_rasterizer(cso);
7966ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   cso_restore_viewport(cso);
797a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   cso_restore_samplers(cso);
798a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   cso_restore_fragment_sampler_views(cso);
799a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   cso_restore_fragment_shader(cso);
800a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   cso_restore_vertex_shader(cso);
801a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   cso_restore_geometry_shader(cso);
8026ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   cso_restore_vertex_elements(cso);
803a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   cso_restore_vertex_buffers(cso);
804a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   cso_restore_stream_outputs(cso);
805a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   if (write_stencil) {
806a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul      cso_restore_depth_stencil_alpha(cso);
8076ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      cso_restore_blend(cso);
808a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   }
8096ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul}
810a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul
8116ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
8126ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul/**
8136ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul * Software fallback to do glDrawPixels(GL_STENCIL_INDEX) when we
8146ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul * can't use a fragment shader to write stencil values.
8156ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul */
816a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paulstatic void
8175076a4f53a2f34cc9116b45951037f639885c7a1Brian Pauldraw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
8185076a4f53a2f34cc9116b45951037f639885c7a1Brian Paul                    GLsizei width, GLsizei height, GLenum format, GLenum type,
819a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul                    const struct gl_pixelstore_attrib *unpack,
820a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul                    const GLvoid *pixels)
821a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul{
822a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   struct st_context *st = st_context(ctx);
8236ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   struct pipe_context *pipe = st->pipe;
8246ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   struct st_renderbuffer *strb;
8256ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   enum pipe_transfer_usage usage;
826a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   struct pipe_transfer *pt;
8276ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
828a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   ubyte *stmap;
829a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   struct gl_pixelstore_attrib clippedUnpack = *unpack;
830a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   GLubyte *sValues;
831a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   GLuint *zValues;
832a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul
833a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   if (!zoom) {
834a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul      if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height,
835a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul                                 &clippedUnpack)) {
836a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul         /* totally clipped */
837a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul         return;
838a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul      }
839a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   }
840a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul
841a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   strb = st_renderbuffer(ctx->DrawBuffer->
842a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul                          Attachment[BUFFER_STENCIL].Renderbuffer);
843a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul
844a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
845a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul      y = ctx->DrawBuffer->Height - y - height;
846a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   }
8476ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
8486ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   if (format == GL_STENCIL_INDEX &&
8496ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul       _mesa_is_format_packed_depth_stencil(strb->Base.Format)) {
8506ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      /* writing stencil to a combined depth+stencil buffer */
8516ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      usage = PIPE_TRANSFER_READ_WRITE;
852ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   }
853ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   else {
854ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul      usage = PIPE_TRANSFER_WRITE;
855ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   }
856ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
857ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   pt = pipe_get_transfer(pipe, strb->texture,
858ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul                          strb->rtt_level, strb->rtt_face + strb->rtt_slice,
859ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul                          usage, x, y,
860ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul                          width, height);
861ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
862ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   stmap = pipe_transfer_map(pipe, pt);
863ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
864ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels);
865ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   assert(pixels);
866ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
867ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   sValues = (GLubyte *) malloc(width * sizeof(GLubyte));
868516d20fd2688fce833b764ca21f1f1772bed0a03Brian Paul   zValues = (GLuint *) malloc(width * sizeof(GLuint));
869516d20fd2688fce833b764ca21f1f1772bed0a03Brian Paul
870ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   if (sValues && zValues) {
871ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul      GLint row;
872ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul      for (row = 0; row < height; row++) {
873ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         GLfloat *zValuesFloat = (GLfloat*)zValues;
874ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         GLenum destType = GL_UNSIGNED_BYTE;
875ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         const GLvoid *source = _mesa_image_address2d(&clippedUnpack, pixels,
876ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul                                                      width, height,
877ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul                                                      format, type,
878ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul                                                      row, 0);
879ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         _mesa_unpack_stencil_span(ctx, width, destType, sValues,
880ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul                                   type, source, &clippedUnpack,
881ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul                                   ctx->_ImageTransferState);
882ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
883ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         if (format == GL_DEPTH_STENCIL) {
884ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul            GLenum ztype =
885ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul               pt->resource->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ?
886ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul               GL_FLOAT : GL_UNSIGNED_INT;
887ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
888ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul            _mesa_unpack_depth_span(ctx, width, ztype, zValues,
889ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul                                    (1 << 24) - 1, type, source,
890ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul                                    &clippedUnpack);
891ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         }
892ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
893ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         if (zoom) {
894ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul            _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with "
895ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul                          "zoom not complete");
896ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         }
897ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
898ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         {
899ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul            GLint spanY;
900ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
901ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul            if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
902ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul               spanY = height - row - 1;
903ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul            }
904ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul            else {
905ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul               spanY = row;
906ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul            }
907ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
908ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul            /* now pack the stencil (and Z) values in the dest format */
909ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul            switch (pt->resource->format) {
910ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul            case PIPE_FORMAT_S8_UINT:
911               {
912                  ubyte *dest = stmap + spanY * pt->stride;
913                  assert(usage == PIPE_TRANSFER_WRITE);
914                  memcpy(dest, sValues, width);
915               }
916               break;
917            case PIPE_FORMAT_Z24_UNORM_S8_UINT:
918               if (format == GL_DEPTH_STENCIL) {
919                  uint *dest = (uint *) (stmap + spanY * pt->stride);
920                  GLint k;
921                  assert(usage == PIPE_TRANSFER_WRITE);
922                  for (k = 0; k < width; k++) {
923                     dest[k] = zValues[k] | (sValues[k] << 24);
924                  }
925               }
926               else {
927                  uint *dest = (uint *) (stmap + spanY * pt->stride);
928                  GLint k;
929                  assert(usage == PIPE_TRANSFER_READ_WRITE);
930                  for (k = 0; k < width; k++) {
931                     dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24);
932                  }
933               }
934               break;
935            case PIPE_FORMAT_S8_UINT_Z24_UNORM:
936               if (format == GL_DEPTH_STENCIL) {
937                  uint *dest = (uint *) (stmap + spanY * pt->stride);
938                  GLint k;
939                  assert(usage == PIPE_TRANSFER_WRITE);
940                  for (k = 0; k < width; k++) {
941                     dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff);
942                  }
943               }
944               else {
945                  uint *dest = (uint *) (stmap + spanY * pt->stride);
946                  GLint k;
947                  assert(usage == PIPE_TRANSFER_READ_WRITE);
948                  for (k = 0; k < width; k++) {
949                     dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff);
950                  }
951               }
952               break;
953            case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
954               if (format == GL_DEPTH_STENCIL) {
955                  uint *dest = (uint *) (stmap + spanY * pt->stride);
956                  GLfloat *destf = (GLfloat*)dest;
957                  GLint k;
958                  assert(usage == PIPE_TRANSFER_WRITE);
959                  for (k = 0; k < width; k++) {
960                     destf[k*2] = zValuesFloat[k];
961                     dest[k*2+1] = sValues[k] & 0xff;
962                  }
963               }
964               else {
965                  uint *dest = (uint *) (stmap + spanY * pt->stride);
966                  GLint k;
967                  assert(usage == PIPE_TRANSFER_READ_WRITE);
968                  for (k = 0; k < width; k++) {
969                     dest[k*2+1] = sValues[k] & 0xff;
970                  }
971               }
972               break;
973            default:
974               assert(0);
975            }
976         }
977      }
978   }
979   else {
980      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels()");
981   }
982
983   free(sValues);
984   free(zValues);
985
986   _mesa_unmap_pbo_source(ctx, &clippedUnpack);
987
988   /* unmap the stencil buffer */
989   pipe_transfer_unmap(pipe, pt);
990   pipe->transfer_destroy(pipe, pt);
991}
992
993
994/**
995 * Get fragment program variant for a glDrawPixels or glCopyPixels
996 * command for RGBA data.
997 */
998static struct st_fp_variant *
999get_color_fp_variant(struct st_context *st)
1000{
1001   struct gl_context *ctx = st->ctx;
1002   struct st_fp_variant_key key;
1003   struct st_fp_variant *fpv;
1004
1005   memset(&key, 0, sizeof(key));
1006
1007   key.st = st;
1008   key.drawpixels = 1;
1009   key.scaleAndBias = (ctx->Pixel.RedBias != 0.0 ||
1010                       ctx->Pixel.RedScale != 1.0 ||
1011                       ctx->Pixel.GreenBias != 0.0 ||
1012                       ctx->Pixel.GreenScale != 1.0 ||
1013                       ctx->Pixel.BlueBias != 0.0 ||
1014                       ctx->Pixel.BlueScale != 1.0 ||
1015                       ctx->Pixel.AlphaBias != 0.0 ||
1016                       ctx->Pixel.AlphaScale != 1.0);
1017   key.pixelMaps = ctx->Pixel.MapColorFlag;
1018   key.clamp_color = st->clamp_frag_color_in_shader &&
1019                     st->ctx->Color._ClampFragmentColor;
1020
1021   fpv = st_get_fp_variant(st, st->fp, &key);
1022
1023   return fpv;
1024}
1025
1026
1027/**
1028 * Get fragment program variant for a glDrawPixels or glCopyPixels
1029 * command for depth/stencil data.
1030 */
1031static struct st_fp_variant *
1032get_depth_stencil_fp_variant(struct st_context *st, GLboolean write_depth,
1033                             GLboolean write_stencil)
1034{
1035   struct st_fp_variant_key key;
1036   struct st_fp_variant *fpv;
1037
1038   memset(&key, 0, sizeof(key));
1039
1040   key.st = st;
1041   key.drawpixels = 1;
1042   key.drawpixels_z = write_depth;
1043   key.drawpixels_stencil = write_stencil;
1044
1045   fpv = st_get_fp_variant(st, st->fp, &key);
1046
1047   return fpv;
1048}
1049
1050
1051/**
1052 * Called via ctx->Driver.DrawPixels()
1053 */
1054static void
1055st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
1056              GLsizei width, GLsizei height,
1057              GLenum format, GLenum type,
1058              const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
1059{
1060   void *driver_vp, *driver_fp;
1061   struct st_context *st = st_context(ctx);
1062   const GLfloat *color;
1063   struct pipe_context *pipe = st->pipe;
1064   GLboolean write_stencil = GL_FALSE, write_depth = GL_FALSE;
1065   struct pipe_sampler_view *sv[2];
1066   int num_sampler_view = 1;
1067   struct st_fp_variant *fpv;
1068
1069   if (format == GL_DEPTH_STENCIL)
1070      write_stencil = write_depth = GL_TRUE;
1071   else if (format == GL_STENCIL_INDEX)
1072      write_stencil = GL_TRUE;
1073   else if (format == GL_DEPTH_COMPONENT)
1074      write_depth = GL_TRUE;
1075
1076   if (write_stencil &&
1077       !pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT)) {
1078      /* software fallback */
1079      draw_stencil_pixels(ctx, x, y, width, height, format, type,
1080                          unpack, pixels);
1081      return;
1082   }
1083
1084   /* Mesa state should be up to date by now */
1085   assert(ctx->NewState == 0x0);
1086
1087   st_validate_state(st);
1088
1089   /*
1090    * Get vertex/fragment shaders
1091    */
1092   if (write_depth || write_stencil) {
1093      fpv = get_depth_stencil_fp_variant(st, write_depth, write_stencil);
1094
1095      driver_fp = fpv->driver_shader;
1096
1097      driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
1098
1099      color = ctx->Current.RasterColor;
1100   }
1101   else {
1102      fpv = get_color_fp_variant(st);
1103
1104      driver_fp = fpv->driver_shader;
1105
1106      driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
1107
1108      color = NULL;
1109      if (st->pixel_xfer.pixelmap_enabled) {
1110	  sv[1] = st->pixel_xfer.pixelmap_sampler_view;
1111	  num_sampler_view++;
1112      }
1113   }
1114
1115   /* update fragment program constants */
1116   st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
1117
1118   /* draw with textured quad */
1119   {
1120      struct pipe_resource *pt
1121         = make_texture(st, width, height, format, type, unpack, pixels);
1122      if (pt) {
1123         sv[0] = st_create_texture_sampler_view(st->pipe, pt);
1124
1125         if (sv[0]) {
1126            /* Create a second sampler view to read stencil.
1127             * The stencil is written using the shader stencil export
1128             * functionality. */
1129            if (write_stencil) {
1130               enum pipe_format stencil_format = PIPE_FORMAT_NONE;
1131
1132               switch (pt->format) {
1133               case PIPE_FORMAT_Z24_UNORM_S8_UINT:
1134               case PIPE_FORMAT_X24S8_UINT:
1135                  stencil_format = PIPE_FORMAT_X24S8_UINT;
1136                  break;
1137               case PIPE_FORMAT_S8_UINT_Z24_UNORM:
1138               case PIPE_FORMAT_S8X24_UINT:
1139                  stencil_format = PIPE_FORMAT_S8X24_UINT;
1140                  break;
1141               case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
1142               case PIPE_FORMAT_X32_S8X24_UINT:
1143                  stencil_format = PIPE_FORMAT_X32_S8X24_UINT;
1144                  break;
1145               case PIPE_FORMAT_S8_UINT:
1146                  stencil_format = PIPE_FORMAT_S8_UINT;
1147                  break;
1148               default:
1149                  assert(0);
1150               }
1151
1152               sv[1] = st_create_texture_sampler_view_format(st->pipe, pt,
1153                                                             stencil_format);
1154               num_sampler_view++;
1155            }
1156
1157            draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
1158                               width, height,
1159                               ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
1160                               sv,
1161                               num_sampler_view,
1162                               driver_vp,
1163                               driver_fp,
1164                               color, GL_FALSE, write_depth, write_stencil);
1165            pipe_sampler_view_reference(&sv[0], NULL);
1166            if (num_sampler_view > 1)
1167               pipe_sampler_view_reference(&sv[1], NULL);
1168         }
1169         pipe_resource_reference(&pt, NULL);
1170      }
1171   }
1172}
1173
1174
1175
1176/**
1177 * Software fallback for glCopyPixels(GL_STENCIL).
1178 */
1179static void
1180copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
1181                    GLsizei width, GLsizei height,
1182                    GLint dstx, GLint dsty)
1183{
1184   struct st_renderbuffer *rbDraw;
1185   struct pipe_context *pipe = st_context(ctx)->pipe;
1186   enum pipe_transfer_usage usage;
1187   struct pipe_transfer *ptDraw;
1188   ubyte *drawMap;
1189   ubyte *buffer;
1190   int i;
1191
1192   buffer = malloc(width * height * sizeof(ubyte));
1193   if (!buffer) {
1194      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
1195      return;
1196   }
1197
1198   /* Get the dest renderbuffer */
1199   rbDraw = st_renderbuffer(ctx->DrawBuffer->
1200                            Attachment[BUFFER_STENCIL].Renderbuffer);
1201
1202   /* this will do stencil pixel transfer ops */
1203   _mesa_readpixels(ctx, srcx, srcy, width, height,
1204                    GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
1205                    &ctx->DefaultPacking, buffer);
1206
1207   if (0) {
1208      /* debug code: dump stencil values */
1209      GLint row, col;
1210      for (row = 0; row < height; row++) {
1211         printf("%3d: ", row);
1212         for (col = 0; col < width; col++) {
1213            printf("%02x ", buffer[col + row * width]);
1214         }
1215         printf("\n");
1216      }
1217   }
1218
1219   if (_mesa_is_format_packed_depth_stencil(rbDraw->Base.Format))
1220      usage = PIPE_TRANSFER_READ_WRITE;
1221   else
1222      usage = PIPE_TRANSFER_WRITE;
1223
1224   if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1225      dsty = rbDraw->Base.Height - dsty - height;
1226   }
1227
1228   ptDraw = pipe_get_transfer(pipe,
1229                              rbDraw->texture,
1230                              rbDraw->rtt_level,
1231                              rbDraw->rtt_face + rbDraw->rtt_slice,
1232                              usage, dstx, dsty,
1233                              width, height);
1234
1235   assert(util_format_get_blockwidth(ptDraw->resource->format) == 1);
1236   assert(util_format_get_blockheight(ptDraw->resource->format) == 1);
1237
1238   /* map the stencil buffer */
1239   drawMap = pipe_transfer_map(pipe, ptDraw);
1240
1241   /* draw */
1242   /* XXX PixelZoom not handled yet */
1243   for (i = 0; i < height; i++) {
1244      ubyte *dst;
1245      const ubyte *src;
1246      int y;
1247
1248      y = i;
1249
1250      if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1251         y = height - y - 1;
1252      }
1253
1254      dst = drawMap + y * ptDraw->stride;
1255      src = buffer + i * width;
1256
1257      _mesa_pack_ubyte_stencil_row(rbDraw->Base.Format, width, src, dst);
1258   }
1259
1260   free(buffer);
1261
1262   /* unmap the stencil buffer */
1263   pipe_transfer_unmap(pipe, ptDraw);
1264   pipe->transfer_destroy(pipe, ptDraw);
1265}
1266
1267
1268/**
1269 * Return renderbuffer to use for reading color pixels for glCopyPixels
1270 */
1271static struct st_renderbuffer *
1272st_get_color_read_renderbuffer(struct gl_context *ctx)
1273{
1274   struct gl_framebuffer *fb = ctx->ReadBuffer;
1275   struct st_renderbuffer *strb =
1276      st_renderbuffer(fb->_ColorReadBuffer);
1277
1278   return strb;
1279}
1280
1281
1282/** Do the src/dest regions overlap? */
1283static GLboolean
1284regions_overlap(GLint srcX, GLint srcY, GLint dstX, GLint dstY,
1285                GLsizei width, GLsizei height)
1286{
1287   if (srcX + width <= dstX ||
1288       dstX + width <= srcX ||
1289       srcY + height <= dstY ||
1290       dstY + height <= srcY)
1291      return GL_FALSE;
1292   else
1293      return GL_TRUE;
1294}
1295
1296
1297/**
1298 * Try to do a glCopyPixels for simple cases with a blit by calling
1299 * pipe->resource_copy_region().
1300 *
1301 * We can do this when we're copying color pixels (depth/stencil
1302 * eventually) with no pixel zoom, no pixel transfer ops, no
1303 * per-fragment ops, the src/dest regions don't overlap and the
1304 * src/dest pixel formats are the same.
1305 */
1306static GLboolean
1307blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
1308                 GLsizei width, GLsizei height,
1309                 GLint dstx, GLint dsty, GLenum type)
1310{
1311   struct st_context *st = st_context(ctx);
1312   struct pipe_context *pipe = st->pipe;
1313   struct gl_pixelstore_attrib pack, unpack;
1314   GLint readX, readY, readW, readH;
1315
1316   if (type == GL_COLOR &&
1317       ctx->Pixel.ZoomX == 1.0 &&
1318       ctx->Pixel.ZoomY == 1.0 &&
1319       ctx->_ImageTransferState == 0x0 &&
1320       !ctx->Color.BlendEnabled &&
1321       !ctx->Color.AlphaEnabled &&
1322       !ctx->Depth.Test &&
1323       !ctx->Fog.Enabled &&
1324       !ctx->Stencil.Enabled &&
1325       !ctx->FragmentProgram.Enabled &&
1326       !ctx->VertexProgram.Enabled &&
1327       !ctx->Shader.CurrentFragmentProgram &&
1328       st_fb_orientation(ctx->ReadBuffer) == st_fb_orientation(ctx->DrawBuffer) &&
1329       ctx->DrawBuffer->_NumColorDrawBuffers == 1 &&
1330       !ctx->Query.CondRenderQuery) {
1331      struct st_renderbuffer *rbRead, *rbDraw;
1332      GLint drawX, drawY;
1333
1334      /*
1335       * Clip the read region against the src buffer bounds.
1336       * We'll still allocate a temporary buffer/texture for the original
1337       * src region size but we'll only read the region which is on-screen.
1338       * This may mean that we draw garbage pixels into the dest region, but
1339       * that's expected.
1340       */
1341      readX = srcx;
1342      readY = srcy;
1343      readW = width;
1344      readH = height;
1345      pack = ctx->DefaultPacking;
1346      if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack))
1347         return GL_TRUE; /* all done */
1348
1349      /* clip against dest buffer bounds and scissor box */
1350      drawX = dstx + pack.SkipPixels;
1351      drawY = dsty + pack.SkipRows;
1352      unpack = pack;
1353      if (!_mesa_clip_drawpixels(ctx, &drawX, &drawY, &readW, &readH, &unpack))
1354         return GL_TRUE; /* all done */
1355
1356      readX = readX - pack.SkipPixels + unpack.SkipPixels;
1357      readY = readY - pack.SkipRows + unpack.SkipRows;
1358
1359      rbRead = st_get_color_read_renderbuffer(ctx);
1360      rbDraw = st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]);
1361
1362      if ((rbRead != rbDraw ||
1363           !regions_overlap(readX, readY, drawX, drawY, readW, readH)) &&
1364          rbRead->Base.Format == rbDraw->Base.Format) {
1365         struct pipe_box srcBox;
1366
1367         /* flip src/dst position if needed */
1368         if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
1369            /* both buffers will have the same orientation */
1370            readY = ctx->ReadBuffer->Height - readY - readH;
1371            drawY = ctx->DrawBuffer->Height - drawY - readH;
1372         }
1373
1374         u_box_2d(readX, readY, readW, readH, &srcBox);
1375
1376         pipe->resource_copy_region(pipe,
1377                                    rbDraw->texture,
1378                                    rbDraw->rtt_level, drawX, drawY, 0,
1379                                    rbRead->texture,
1380                                    rbRead->rtt_level, &srcBox);
1381         return GL_TRUE;
1382      }
1383   }
1384
1385   return GL_FALSE;
1386}
1387
1388
1389static void
1390st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
1391              GLsizei width, GLsizei height,
1392              GLint dstx, GLint dsty, GLenum type)
1393{
1394   struct st_context *st = st_context(ctx);
1395   struct pipe_context *pipe = st->pipe;
1396   struct pipe_screen *screen = pipe->screen;
1397   struct st_renderbuffer *rbRead;
1398   void *driver_vp, *driver_fp;
1399   struct pipe_resource *pt;
1400   struct pipe_sampler_view *sv[2];
1401   int num_sampler_view = 1;
1402   GLfloat *color;
1403   enum pipe_format srcFormat, texFormat;
1404   GLboolean invertTex = GL_FALSE;
1405   GLint readX, readY, readW, readH;
1406   GLuint sample_count;
1407   struct gl_pixelstore_attrib pack = ctx->DefaultPacking;
1408   struct st_fp_variant *fpv;
1409
1410   st_validate_state(st);
1411
1412   if (type == GL_DEPTH_STENCIL) {
1413      /* XXX make this more efficient */
1414      st_CopyPixels(ctx, srcx, srcy, width, height, dstx, dsty, GL_STENCIL);
1415      st_CopyPixels(ctx, srcx, srcy, width, height, dstx, dsty, GL_DEPTH);
1416      return;
1417   }
1418
1419   if (type == GL_STENCIL) {
1420      /* can't use texturing to do stencil */
1421      copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
1422      return;
1423   }
1424
1425   if (blit_copy_pixels(ctx, srcx, srcy, width, height, dstx, dsty, type))
1426      return;
1427
1428   /*
1429    * The subsequent code implements glCopyPixels by copying the source
1430    * pixels into a temporary texture that's then applied to a textured quad.
1431    * When we draw the textured quad, all the usual per-fragment operations
1432    * are handled.
1433    */
1434
1435
1436   /*
1437    * Get vertex/fragment shaders
1438    */
1439   if (type == GL_COLOR) {
1440      rbRead = st_get_color_read_renderbuffer(ctx);
1441      color = NULL;
1442
1443      fpv = get_color_fp_variant(st);
1444      driver_fp = fpv->driver_shader;
1445
1446      driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
1447
1448      if (st->pixel_xfer.pixelmap_enabled) {
1449	  sv[1] = st->pixel_xfer.pixelmap_sampler_view;
1450	  num_sampler_view++;
1451      }
1452   }
1453   else {
1454      assert(type == GL_DEPTH);
1455      rbRead = st_renderbuffer(ctx->ReadBuffer->
1456                               Attachment[BUFFER_DEPTH].Renderbuffer);
1457      color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
1458
1459      fpv = get_depth_stencil_fp_variant(st, GL_TRUE, GL_FALSE);
1460      driver_fp = fpv->driver_shader;
1461
1462      driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
1463   }
1464
1465   /* update fragment program constants */
1466   st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
1467
1468   sample_count = rbRead->texture->nr_samples;
1469   /* I believe this would be legal, presumably would need to do a resolve
1470      for color, and for depth/stencil spec says to just use one of the
1471      depth/stencil samples per pixel? Need some transfer clarifications. */
1472   assert(sample_count < 2);
1473
1474   srcFormat = rbRead->texture->format;
1475
1476   if (screen->is_format_supported(screen, srcFormat, st->internal_target,
1477                                   sample_count,
1478                                   PIPE_BIND_SAMPLER_VIEW)) {
1479      texFormat = srcFormat;
1480   }
1481   else {
1482      /* srcFormat can't be used as a texture format */
1483      if (type == GL_DEPTH) {
1484         texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT,
1485                                      GL_NONE, GL_NONE, st->internal_target,
1486				      sample_count, PIPE_BIND_DEPTH_STENCIL);
1487         assert(texFormat != PIPE_FORMAT_NONE);
1488      }
1489      else {
1490         /* default color format */
1491         texFormat = st_choose_format(screen, GL_RGBA,
1492                                      GL_NONE, GL_NONE, st->internal_target,
1493                                      sample_count, PIPE_BIND_SAMPLER_VIEW);
1494         assert(texFormat != PIPE_FORMAT_NONE);
1495      }
1496   }
1497
1498   /* Invert src region if needed */
1499   if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
1500      srcy = ctx->ReadBuffer->Height - srcy - height;
1501      invertTex = !invertTex;
1502   }
1503
1504   /* Clip the read region against the src buffer bounds.
1505    * We'll still allocate a temporary buffer/texture for the original
1506    * src region size but we'll only read the region which is on-screen.
1507    * This may mean that we draw garbage pixels into the dest region, but
1508    * that's expected.
1509    */
1510   readX = srcx;
1511   readY = srcy;
1512   readW = width;
1513   readH = height;
1514   _mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack);
1515   readW = MAX2(0, readW);
1516   readH = MAX2(0, readH);
1517
1518   /* alloc temporary texture */
1519   pt = alloc_texture(st, width, height, texFormat);
1520   if (!pt)
1521      return;
1522
1523   sv[0] = st_create_texture_sampler_view(st->pipe, pt);
1524   if (!sv[0]) {
1525      pipe_resource_reference(&pt, NULL);
1526      return;
1527   }
1528
1529   /* Make temporary texture which is a copy of the src region.
1530    */
1531   if (srcFormat == texFormat) {
1532      struct pipe_box src_box;
1533      u_box_2d(readX, readY, readW, readH, &src_box);
1534      /* copy source framebuffer surface into mipmap/texture */
1535      pipe->resource_copy_region(pipe,
1536                                 pt,                                /* dest tex */
1537                                 0,                                 /* dest lvl */
1538                                 pack.SkipPixels, pack.SkipRows, 0, /* dest pos */
1539                                 rbRead->texture,                   /* src tex */
1540                                 rbRead->rtt_level,                 /* src lvl */
1541                                 &src_box);
1542
1543   }
1544   else {
1545      /* CPU-based fallback/conversion */
1546      struct pipe_transfer *ptRead =
1547         pipe_get_transfer(st->pipe, rbRead->texture,
1548                           rbRead->rtt_level,
1549                           rbRead->rtt_face + rbRead->rtt_slice,
1550                           PIPE_TRANSFER_READ,
1551                           readX, readY, readW, readH);
1552      struct pipe_transfer *ptTex;
1553      enum pipe_transfer_usage transfer_usage;
1554
1555      if (ST_DEBUG & DEBUG_FALLBACK)
1556         debug_printf("%s: fallback processing\n", __FUNCTION__);
1557
1558      if (type == GL_DEPTH && util_format_is_depth_and_stencil(pt->format))
1559         transfer_usage = PIPE_TRANSFER_READ_WRITE;
1560      else
1561         transfer_usage = PIPE_TRANSFER_WRITE;
1562
1563      ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, transfer_usage,
1564                                0, 0, width, height);
1565
1566      /* copy image from ptRead surface to ptTex surface */
1567      if (type == GL_COLOR) {
1568         /* alternate path using get/put_tile() */
1569         GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
1570         enum pipe_format readFormat, drawFormat;
1571         readFormat = util_format_linear(rbRead->texture->format);
1572         drawFormat = util_format_linear(pt->format);
1573         pipe_get_tile_rgba_format(pipe, ptRead, 0, 0, readW, readH,
1574                                   readFormat, buf);
1575         pipe_put_tile_rgba_format(pipe, ptTex, pack.SkipPixels, pack.SkipRows,
1576                                   readW, readH, drawFormat, buf);
1577         free(buf);
1578      }
1579      else {
1580         /* GL_DEPTH */
1581         GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint));
1582         pipe_get_tile_z(pipe, ptRead, 0, 0, readW, readH, buf);
1583         pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows,
1584                         readW, readH, buf);
1585         free(buf);
1586      }
1587
1588      pipe->transfer_destroy(pipe, ptRead);
1589      pipe->transfer_destroy(pipe, ptTex);
1590   }
1591
1592   /* OK, the texture 'pt' contains the src image/pixels.  Now draw a
1593    * textured quad with that texture.
1594    */
1595   draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
1596                      width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
1597                      sv,
1598                      num_sampler_view,
1599                      driver_vp,
1600                      driver_fp,
1601                      color, invertTex, GL_FALSE, GL_FALSE);
1602
1603   pipe_resource_reference(&pt, NULL);
1604   pipe_sampler_view_reference(&sv[0], NULL);
1605}
1606
1607
1608
1609void st_init_drawpixels_functions(struct dd_function_table *functions)
1610{
1611   functions->DrawPixels = st_DrawPixels;
1612   functions->CopyPixels = st_CopyPixels;
1613}
1614
1615
1616void
1617st_destroy_drawpix(struct st_context *st)
1618{
1619   GLuint i;
1620
1621   for (i = 0; i < Elements(st->drawpix.shaders); i++) {
1622      if (st->drawpix.shaders[i])
1623         _mesa_reference_fragprog(st->ctx, &st->drawpix.shaders[i], NULL);
1624   }
1625
1626   st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
1627   if (st->drawpix.vert_shaders[0])
1628      cso_delete_vertex_shader(st->cso_context, st->drawpix.vert_shaders[0]);
1629   if (st->drawpix.vert_shaders[1])
1630      cso_delete_vertex_shader(st->cso_context, st->drawpix.vert_shaders[1]);
1631}
1632
1633#endif /* FEATURE_drawpix */
1634