st_cb_drawpixels.c revision edbc302ad678e1a4a8803ba0e827a13dd27105d2
1cf5933a716e7eb6bd5ff49aa62f3e76379ebaf51Chris Lattner/**************************************************************************
2fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman *
3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell * All Rights Reserved.
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner *
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner * Permission is hereby granted, free of charge, to any person obtaining a
7fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman * copy of this software and associated documentation files (the
8b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell * "Software"), to deal in the Software without restriction, including
9237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner * without limitation the rights to use, copy, modify, merge, publish,
10befa499d45ffcc32bd9902518aec18589464e47cChris Lattner * distribute, sub license, and/or sell copies of the Software, and to
11befa499d45ffcc32bd9902518aec18589464e47cChris Lattner * permit persons to whom the Software is furnished to do so, subject to
12befa499d45ffcc32bd9902518aec18589464e47cChris Lattner * the following conditions:
13237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner *
14237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner * The above copyright notice and this permission notice (including the
15237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner * next paragraph) shall be included in all copies or substantial portions
1686453c52ba02e743d29c08456e51006500041456Chris Lattner * of the Software.
17237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner *
1847b14a4a6a455c7be169cfd312fcbe796f0ad426Misha Brukman * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
191f67ce4aa3f65619f54c8a3072539da5b0022841Dale Johannesen * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21e4aeec003f82a5263ffb168e175e6fca8b6f681dDan Gohman * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
236f7426ec2e46bb19cc9f9e75f1c355b35cf12d7dTanya Lattner * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
254ff4141a9ee9ce705f2a709f3372acaf58d86ea3Chris Lattner *
264ff4141a9ee9ce705f2a709f3372acaf58d86ea3Chris Lattner **************************************************************************/
27551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer
28551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer /*
29ce63ffb52f249b62cdf2d250c128007b13f27e71Daniel Dunbar  * Authors:
3012f0babca4459c253675700e1d707652d5b6ba17Chris Lattner  *   Brian Paul
31551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer  */
32befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
33a51bcb50b0c74adc741361824ef81dbefb715c53Chris Lattner#include "main/imports.h"
34d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke#include "main/image.h"
3586453c52ba02e743d29c08456e51006500041456Chris Lattner#include "main/bufferobj.h"
36dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner#include "main/macros.h"
3786453c52ba02e743d29c08456e51006500041456Chris Lattner#include "main/texformat.h"
38199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner#include "main/texstore.h"
3986453c52ba02e743d29c08456e51006500041456Chris Lattner#include "shader/program.h"
40844731a7f1909f55935e3514c9e713a62d67662eDan Gohman#include "shader/prog_print.h"
41f9c3b228e5579e0d2a9cd05a2191fe17b4c58b23Jakob Stoklund Olesen
42f9c3b228e5579e0d2a9cd05a2191fe17b4c58b23Jakob Stoklund Olesen#include "st_debug.h"
43237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner#include "st_context.h"
44f0907fe59093753fe5a9e8fe5adc399dbdc94627Jakob Stoklund Olesen#include "st_atom.h"
45f0907fe59093753fe5a9e8fe5adc399dbdc94627Jakob Stoklund Olesen#include "st_atom_constbuf.h"
46f0907fe59093753fe5a9e8fe5adc399dbdc94627Jakob Stoklund Olesen#include "st_program.h"
47570a4a5d9ca31f276a67502d1e0533d59d331feaJakob Stoklund Olesen#include "st_cb_drawpixels.h"
48570a4a5d9ca31f276a67502d1e0533d59d331feaJakob Stoklund Olesen#include "st_cb_readpixels.h"
49570a4a5d9ca31f276a67502d1e0533d59d331feaJakob Stoklund Olesen#include "st_cb_fbo.h"
50570a4a5d9ca31f276a67502d1e0533d59d331feaJakob Stoklund Olesen#include "st_format.h"
51ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman#include "st_texture.h"
52ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman
53237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner#include "pipe/p_context.h"
54ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman#include "pipe/p_defines.h"
55ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman#include "util/u_inlines.h"
56120d053e3ba810b44047fbcb719824bed5673ca9Chris Lattner#include "tgsi/tgsi_ureg.h"
57ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner#include "util/u_tile.h"
58ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner#include "util/u_draw_quad.h"
59ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner#include "util/u_format.h"
60ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner#include "util/u_math.h"
61ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner#include "shader/prog_instruction.h"
62ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner#include "cso_cache/cso_context.h"
63ff2dad312883e5da91fb9f4e3619b7d095867f3bChris Lattner
64199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner
65199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner/**
66199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner * Check if the given program is:
67199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner * 0: MOVE result.color, fragment.color;
68199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner * 1: END;
69199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner */
70199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattnerstatic GLboolean
71199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattneris_passthrough_program(const struct gl_fragment_program *prog)
72cc0a0299d96676e0a51e9b8f5bf617d8025f09a7Chris Lattner{
73cc0a0299d96676e0a51e9b8f5bf617d8025f09a7Chris Lattner   if (prog->Base.NumInstructions == 2) {
74cc0a0299d96676e0a51e9b8f5bf617d8025f09a7Chris Lattner      const struct prog_instruction *inst = prog->Base.Instructions;
75cc0a0299d96676e0a51e9b8f5bf617d8025f09a7Chris Lattner      if (inst[0].Opcode == OPCODE_MOV &&
76199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner          inst[1].Opcode == OPCODE_END &&
77199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner          inst[0].DstReg.File == PROGRAM_OUTPUT &&
78199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner          inst[0].DstReg.Index == FRAG_RESULT_COLOR &&
79befa499d45ffcc32bd9902518aec18589464e47cChris Lattner          inst[0].DstReg.WriteMask == WRITEMASK_XYZW &&
8066c75aaa028683c389c55b377ee2411b61081677Bill Wendling          inst[0].SrcReg[0].File == PROGRAM_INPUT &&
8166c75aaa028683c389c55b377ee2411b61081677Bill Wendling          inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 &&
82199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner          inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) {
83199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner         return GL_TRUE;
84199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      }
85199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   }
8612f0babca4459c253675700e1d707652d5b6ba17Chris Lattner   return GL_FALSE;
87fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman}
888c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling
898c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling
908c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling
918c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling/**
928c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling * Make fragment shader for glDraw/CopyPixels.  This shader is made
938c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling * by combining the pixel transfer shader with the user-defined shader.
948c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling * \return pointer to Gallium driver fragment shader
958c1604e7d617622cb391f1c679ddf70ea03baedcBill Wendling */
96199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattnerstatic void *
97199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattnercombined_drawpix_fragment_program(GLcontext *ctx)
98199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner{
99199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   struct st_context *st = st_context(ctx);
100199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   struct st_fragment_program *stfp;
101199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner
102199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn
103199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner       && st->fp->serialNo == st->pixel_xfer.user_prog_sn) {
104199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      /* the pixel tranfer program has not changed and the user-defined
105199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner       * program has not changed, so re-use the combined program.
106199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner       */
107199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      stfp = st->pixel_xfer.combined_prog;
108199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   }
109199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   else {
110199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      /* Concatenate the pixel transfer program with the current user-
111199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner       * defined program.
112199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner       */
113199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      if (is_passthrough_program(&st->fp->Base)) {
114199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner         stfp = (struct st_fragment_program *)
115199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner            _mesa_clone_fragment_program(ctx, &st->pixel_xfer.program->Base);
116199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      }
117199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      else {
118199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner#if 0
119199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner         printf("Base program:\n");
120199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner         _mesa_print_program(&st->fp->Base.Base);
121199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner         printf("DrawPix program:\n");
122199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner         _mesa_print_program(&st->pixel_xfer.program->Base.Base);
123199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner#endif
124199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner         stfp = (struct st_fragment_program *)
125199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner            _mesa_combine_programs(ctx,
126199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner                                   &st->pixel_xfer.program->Base.Base,
127199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner                                   &st->fp->Base.Base);
128199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      }
129199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner
130199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner#if 0
131199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      {
132199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner         struct gl_program *p = &stfp->Base.Base;
133199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner         printf("Combined DrawPixels program:\n");
134199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner         _mesa_print_program(p);
135199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner         printf("InputsRead: 0x%x\n", p->InputsRead);
136199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner         printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
137199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner         _mesa_print_parameter_list(p->Parameters);
138199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      }
139199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner#endif
140199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner
141199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      /* translate to TGSI tokens */
142199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      st_translate_fragment_program(st, stfp);
143199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner
144199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      /* save new program, update serial numbers */
145199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
146199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      st->pixel_xfer.user_prog_sn = st->fp->serialNo;
147199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      st->pixel_xfer.combined_prog_sn = stfp->serialNo;
148199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      /* can't reference new program directly, already have a reference on it */
149199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
150199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      st->pixel_xfer.combined_prog = stfp;
151199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   }
152199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner
153199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   /* Ideally we'd have updated the pipe constants during the normal
154199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner    * st/atom mechanism.  But we can't since this is specific to glDrawPixels.
155199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner    */
156199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
157c0aa67950ae0f6e9611240d8f0e3ac49dc8195c0David Greene
158199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   return stfp->driver_shader;
159199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner}
160199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner
161199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner
162199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner/**
163199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner * Create fragment shader that does a TEX() instruction to get a Z
164199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner * value, then writes to FRAG_RESULT_DEPTH.
165fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman * Pass fragment color through as-is.
166199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner * \return pointer to the Gallium driver fragment shader
167199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner */
168199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattnerstatic void *
1691f67ce4aa3f65619f54c8a3072539da5b0022841Dale Johannesenmake_fragment_shader_z(struct st_context *st)
170199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner{
171199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   GLcontext *ctx = st->ctx;
172199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   struct gl_program *p;
173199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   GLuint ic = 0;
174199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner
175199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   if (st->drawpix.z_shader) {
176199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      return st->drawpix.z_shader->driver_shader;
177befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   }
178199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner
179befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   /*
180237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner    * Create shader now
181f8526cb711ec96cd2d5aff30da57f65ae8e5b7b8Jakob Stoklund Olesen    */
182570a4a5d9ca31f276a67502d1e0533d59d331feaJakob Stoklund Olesen   p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
183f0907fe59093753fe5a9e8fe5adc399dbdc94627Jakob Stoklund Olesen   if (!p)
184570a4a5d9ca31f276a67502d1e0533d59d331feaJakob Stoklund Olesen      return NULL;
185570a4a5d9ca31f276a67502d1e0533d59d331feaJakob Stoklund Olesen
186570a4a5d9ca31f276a67502d1e0533d59d331feaJakob Stoklund Olesen   p->NumInstructions = 3;
187f8526cb711ec96cd2d5aff30da57f65ae8e5b7b8Jakob Stoklund Olesen
188f8526cb711ec96cd2d5aff30da57f65ae8e5b7b8Jakob Stoklund Olesen   p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
189f8526cb711ec96cd2d5aff30da57f65ae8e5b7b8Jakob Stoklund Olesen   if (!p->Instructions) {
190f0907fe59093753fe5a9e8fe5adc399dbdc94627Jakob Stoklund Olesen      ctx->Driver.DeleteProgram(ctx, p);
191f0907fe59093753fe5a9e8fe5adc399dbdc94627Jakob Stoklund Olesen      return NULL;
192f0907fe59093753fe5a9e8fe5adc399dbdc94627Jakob Stoklund Olesen   }
193f0907fe59093753fe5a9e8fe5adc399dbdc94627Jakob Stoklund Olesen   _mesa_init_instructions(p->Instructions, p->NumInstructions);
194f0907fe59093753fe5a9e8fe5adc399dbdc94627Jakob Stoklund Olesen
195f0907fe59093753fe5a9e8fe5adc399dbdc94627Jakob Stoklund Olesen   /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */
196f0907fe59093753fe5a9e8fe5adc399dbdc94627Jakob Stoklund Olesen   p->Instructions[ic].Opcode = OPCODE_TEX;
197570a4a5d9ca31f276a67502d1e0533d59d331feaJakob Stoklund Olesen   p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
198f0907fe59093753fe5a9e8fe5adc399dbdc94627Jakob Stoklund Olesen   p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPTH;
199f8526cb711ec96cd2d5aff30da57f65ae8e5b7b8Jakob Stoklund Olesen   p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z;
200f8526cb711ec96cd2d5aff30da57f65ae8e5b7b8Jakob Stoklund Olesen   p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
2011a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar   p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
2021a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar   p->Instructions[ic].TexSrcUnit = 0;
2031a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar   p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
204c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar   ic++;
2051a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar
206c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar   /* MOV result.color, fragment.color */
207c0aa67950ae0f6e9611240d8f0e3ac49dc8195c0David Greene   p->Instructions[ic].Opcode = OPCODE_MOV;
20884a832f9272ed7f1a47c3e019c770b62e373cc6cBill Wendling   p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
209c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar   p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLOR;
210c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar   p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
211c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar   p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0;
212c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar   ic++;
213c0aa67950ae0f6e9611240d8f0e3ac49dc8195c0David Greene
21484a832f9272ed7f1a47c3e019c770b62e373cc6cBill Wendling   /* END; */
215c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar   p->Instructions[ic++].Opcode = OPCODE_END;
216c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar
217c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar   assert(ic == p->NumInstructions);
218c5e1ec47c719806fcc882470595960512edc7441Daniel Dunbar
219e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen   p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
220570a4a5d9ca31f276a67502d1e0533d59d331feaJakob Stoklund Olesen   p->OutputsWritten = (1 << FRAG_RESULT_COLOR) | (1 << FRAG_RESULT_DEPTH);
221135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner   p->SamplersUsed = 0x1;  /* sampler 0 (bit 0) is used */
2222ddbf8208e0ee50cb1aeb24d509b52549a85c211Jakob Stoklund Olesen
2232ddbf8208e0ee50cb1aeb24d509b52549a85c211Jakob Stoklund Olesen   st->drawpix.z_shader = (struct st_fragment_program *) p;
224c0aa67950ae0f6e9611240d8f0e3ac49dc8195c0David Greene   st_translate_fragment_program(st, st->drawpix.z_shader);
2252ddbf8208e0ee50cb1aeb24d509b52549a85c211Jakob Stoklund Olesen
22684a832f9272ed7f1a47c3e019c770b62e373cc6cBill Wendling   return st->drawpix.z_shader->driver_shader;
2271a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar}
2281a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar
229135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
230e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen
231e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen/**
232e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen * Create a simple vertex shader that just passes through the
233e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen * vertex position and texcoord (and optionally, color).
234e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen */
235e91b9a3b59688023e20cee8441179300b87c844eDale Johannesenstatic void *
236e91b9a3b59688023e20cee8441179300b87c844eDale Johannesenmake_passthrough_vertex_shader(struct st_context *st,
237e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen                               GLboolean passColor)
238e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen{
239e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen   if (!st->drawpix.vert_shaders[passColor]) {
240e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen      struct ureg_program *ureg =
241e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen         ureg_create( TGSI_PROCESSOR_VERTEX );
242e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen
243e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen      if (ureg == NULL)
244e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen         return NULL;
245e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen
246e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen      /* MOV result.pos, vertex.pos; */
247e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen      ureg_MOV(ureg,
248e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen               ureg_DECL_output( ureg, TGSI_SEMANTIC_POSITION, 0 ),
249e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen               ureg_DECL_vs_input( ureg, 0 ));
250e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen
251e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen      /* MOV result.texcoord0, vertex.attr[1]; */
252e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen      ureg_MOV(ureg,
253e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen               ureg_DECL_output( ureg, TGSI_SEMANTIC_GENERIC, 0 ),
254e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen               ureg_DECL_vs_input( ureg, 1 ));
255e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen
256e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen      if (passColor) {
257e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen         /* MOV result.color0, vertex.attr[2]; */
258570a4a5d9ca31f276a67502d1e0533d59d331feaJakob Stoklund Olesen         ureg_MOV(ureg,
259e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen                  ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ),
260e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen                  ureg_DECL_vs_input( ureg, 2 ));
261e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen      }
262e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen
263e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen      ureg_END( ureg );
264bdb984bc2757114bc706026603ed40d7f508c4c1Dale Johannesen
265e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen      st->drawpix.vert_shaders[passColor] =
266e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen         ureg_create_shader_and_destroy( ureg, st->pipe );
267bdb984bc2757114bc706026603ed40d7f508c4c1Dale Johannesen   }
268bdb984bc2757114bc706026603ed40d7f508c4c1Dale Johannesen
269e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen   return st->drawpix.vert_shaders[passColor];
270e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen}
271e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen
272e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen
273e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen/**
274e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen * Return a texture internalFormat for drawing/copying an image
275e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen * of the given type.
276e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen */
277e91b9a3b59688023e20cee8441179300b87c844eDale Johannesenstatic GLenum
278bdb984bc2757114bc706026603ed40d7f508c4c1Dale Johannesenbase_format(GLenum format)
279e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen{
280e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen   switch (format) {
281e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen   case GL_DEPTH_COMPONENT:
282c0aa67950ae0f6e9611240d8f0e3ac49dc8195c0David Greene      return GL_DEPTH_COMPONENT;
283e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen   case GL_DEPTH_STENCIL:
284e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen      return GL_DEPTH_STENCIL;
285e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen   case GL_STENCIL_INDEX:
286e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen      return GL_STENCIL_INDEX;
287e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen   default:
288e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen      return GL_RGBA;
289c0aa67950ae0f6e9611240d8f0e3ac49dc8195c0David Greene   }
2902ddbf8208e0ee50cb1aeb24d509b52549a85c211Jakob Stoklund Olesen}
291e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen
292135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
2931a99dbfe3b70c83d3f3e4648b5868c04697cd77cDaniel Dunbar/**
294237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner * Create a temporary texture to hold an image of the given size.
2955095e3d1d1caef8d573534d369e37277c623064cChris Lattner * If width, height are not POT and the driver only handles POT textures,
296237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner * allocate the next larger size of texture that is POT.
29702a436c48ecff9e34d50ce0a2f861e5acdd9bf3fDan Gohman */
298237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattnerstatic struct pipe_resource *
29916581bf931c0ccf2f8993397acfa4e1d509a68dcDale Johannesenalloc_texture(struct st_context *st, GLsizei width, GLsizei height,
300c0aa67950ae0f6e9611240d8f0e3ac49dc8195c0David Greene              enum pipe_format texFormat)
301237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner{
302befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   struct pipe_context *pipe = st->pipe;
303befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   struct pipe_screen *screen = pipe->screen;
304c0aa67950ae0f6e9611240d8f0e3ac49dc8195c0David Greene   struct pipe_resource *pt;
305237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner   int ptw, pth;
306237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner
307befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   ptw = width;
308befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   pth = height;
309befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
310199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   /* Need to use POT texture? */
311befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) {
312135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      int l2pt, maxSize;
313135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
314135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      l2pt = util_logbase2(width);
315135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      if (1 << l2pt != width) {
316135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner         ptw = 1 << (l2pt + 1);
317135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      }
318135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
319e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen      l2pt = util_logbase2(height);
320d43d5e832f756c9d2c0c8ff4d2f51807a27cab8dChris Lattner      if (1 << l2pt != height) {
321d43d5e832f756c9d2c0c8ff4d2f51807a27cab8dChris Lattner         pth = 1 << (l2pt + 1);
322135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      }
323135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
324d43d5e832f756c9d2c0c8ff4d2f51807a27cab8dChris Lattner      /* Check against maximum texture size */
325d43d5e832f756c9d2c0c8ff4d2f51807a27cab8dChris Lattner      maxSize = 1 << (pipe->screen->get_param(pipe->screen,
326d43d5e832f756c9d2c0c8ff4d2f51807a27cab8dChris Lattner                               PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
327d43d5e832f756c9d2c0c8ff4d2f51807a27cab8dChris Lattner      assert(ptw <= maxSize);
328d43d5e832f756c9d2c0c8ff4d2f51807a27cab8dChris Lattner      assert(pth <= maxSize);
329d43d5e832f756c9d2c0c8ff4d2f51807a27cab8dChris Lattner   }
330d43d5e832f756c9d2c0c8ff4d2f51807a27cab8dChris Lattner
331135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner   pt = st_texture_create(st, PIPE_TEXTURE_2D, texFormat, 0,
332135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner                          ptw, pth, 1, PIPE_BIND_SAMPLER_VIEW);
333237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner
334c0aa67950ae0f6e9611240d8f0e3ac49dc8195c0David Greene   return pt;
335fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman}
336befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
337befa499d45ffcc32bd9902518aec18589464e47cChris Lattner
338befa499d45ffcc32bd9902518aec18589464e47cChris Lattner/**
339befa499d45ffcc32bd9902518aec18589464e47cChris Lattner * Make texture containing an image for glDrawPixels image.
340befa499d45ffcc32bd9902518aec18589464e47cChris Lattner * If 'pixels' is NULL, leave the texture image data undefined.
341befa499d45ffcc32bd9902518aec18589464e47cChris Lattner */
342befa499d45ffcc32bd9902518aec18589464e47cChris Lattnerstatic struct pipe_resource *
343fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukmanmake_texture(struct st_context *st,
344199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner	     GLsizei width, GLsizei height, GLenum format, GLenum type,
345199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner	     const struct gl_pixelstore_attrib *unpack,
346199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner	     const GLvoid *pixels)
347befa499d45ffcc32bd9902518aec18589464e47cChris Lattner{
348befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   GLcontext *ctx = st->ctx;
349befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   struct pipe_context *pipe = st->pipe;
350befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   gl_format mformat;
351befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   struct pipe_resource *pt;
352befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   enum pipe_format pipeFormat;
353befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   GLuint cpp;
354befa499d45ffcc32bd9902518aec18589464e47cChris Lattner   GLenum baseFormat;
355135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
356199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   baseFormat = base_format(format);
357199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner
358dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner   mformat = st_ChooseTextureFormat(ctx, baseFormat, format, type);
359199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner   assert(mformat);
360dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner
361dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner   pipeFormat = st_mesa_format_to_pipe_format(mformat);
362dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner   assert(pipeFormat);
363dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner   cpp = util_format_get_blocksize(pipeFormat);
364dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner
3654ff4141a9ee9ce705f2a709f3372acaf58d86ea3Chris Lattner   pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
366c0aa67950ae0f6e9611240d8f0e3ac49dc8195c0David Greene   if (!pixels)
367dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner      return NULL;
368dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner
369dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner   /* alloc temporary texture */
370dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner   pt = alloc_texture(st, width, height, pipeFormat);
371dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner   if (!pt) {
372f7477470d37ee2ab9075eaee4745fa084d424ab8Jakob Stoklund Olesen      _mesa_unmap_pbo_source(ctx, unpack);
373f7477470d37ee2ab9075eaee4745fa084d424ab8Jakob Stoklund Olesen      return NULL;
374dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner   }
375dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner
376dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner   {
377135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      struct pipe_transfer *transfer;
378dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner      static const GLuint dstImageOffsets = 0;
379dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner      GLboolean success;
380dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner      GLubyte *dest;
381dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner      const GLbitfield imageTransferStateSave = ctx->_ImageTransferState;
382e91b9a3b59688023e20cee8441179300b87c844eDale Johannesen
383dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner      /* we'll do pixel transfer in a fragment shader */
384dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner      ctx->_ImageTransferState = 0x0;
385dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner
386dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner      transfer = pipe_get_transfer(st->pipe, pt, 0, 0, 0,
387f7477470d37ee2ab9075eaee4745fa084d424ab8Jakob Stoklund Olesen					      PIPE_TRANSFER_WRITE, 0, 0,
388f7477470d37ee2ab9075eaee4745fa084d424ab8Jakob Stoklund Olesen					      width, height);
389f7477470d37ee2ab9075eaee4745fa084d424ab8Jakob Stoklund Olesen
390dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner      /* map texture transfer */
391135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      dest = pipe_transfer_map(pipe, transfer);
392dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner
393dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner
394dbab4dc942e0c3286415908762de71a9447f9dfaChris Lattner      /* Put image into texture transfer.
395d43d5e832f756c9d2c0c8ff4d2f51807a27cab8dChris Lattner       * Note that the image is actually going to be upside down in
396b374b90e81d0ce6b5d02041ba4f7b15a945b38d8Chris Lattner       * the texture.  We deal with that with texcoords.
397d43d5e832f756c9d2c0c8ff4d2f51807a27cab8dChris Lattner       */
398b374b90e81d0ce6b5d02041ba4f7b15a945b38d8Chris Lattner      success = _mesa_texstore(ctx, 2,           /* dims */
399b374b90e81d0ce6b5d02041ba4f7b15a945b38d8Chris Lattner                               baseFormat,       /* baseInternalFormat */
400b374b90e81d0ce6b5d02041ba4f7b15a945b38d8Chris Lattner                               mformat,          /* gl_format */
401b374b90e81d0ce6b5d02041ba4f7b15a945b38d8Chris Lattner                               dest,             /* dest */
402c0aa67950ae0f6e9611240d8f0e3ac49dc8195c0David Greene                               0, 0, 0,          /* dstX/Y/Zoffset */
403199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner                               transfer->stride, /* dstRowStride, bytes */
404199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner                               &dstImageOffsets, /* dstImageOffsets */
405199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner                               width, height, 1, /* size */
406199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner                               format, type,     /* src format/type */
407199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner                               pixels,           /* data source */
408199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner                               unpack);
409199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner
410199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      /* unmap */
411199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      pipe_transfer_unmap(pipe, transfer);
412199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      pipe->transfer_destroy(pipe, transfer);
413199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner
414199ba42cbf56b2fc9c708edb4f08f97dd99ddd49Chris Lattner      assert(success);
415135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
416135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      /* restore */
417135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      ctx->_ImageTransferState = imageTransferStateSave;
418135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner   }
419135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
420135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner   _mesa_unmap_pbo_source(ctx, unpack);
421135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
422135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner   return pt;
423135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner}
424135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
425237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner
426135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner/**
427135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner * Draw quad with texcoords and optional color.
428135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner * Coords are gallium window coords with y=0=top.
429135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner * \param color  may be null
430135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner * \param invertTex  if true, flip texcoords vertically
431befa499d45ffcc32bd9902518aec18589464e47cChris Lattner */
432237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattnerstatic void
433775cbdd51a3b33dd5eb343689f65ab5cc8ac7118Chris Lattnerdraw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
434237ef567f6764f24a47c63121cc0a599ddc8f56dChris Lattner          GLfloat x1, GLfloat y1, const GLfloat *color,
435d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke          GLboolean invertTex, GLfloat maxXcoord, GLfloat maxYcoord)
43668d57e7ae80044401efd889270a12c71b3efb9abChris Lattner{
43768d57e7ae80044401efd889270a12c71b3efb9abChris Lattner   struct st_context *st = st_context(ctx);
43868d57e7ae80044401efd889270a12c71b3efb9abChris Lattner   struct pipe_context *pipe = st->pipe;
439b7c6bf1e073088635951435acedff793add1cefdDevang Patel   GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */
440b7c6bf1e073088635951435acedff793add1cefdDevang Patel
441b7c6bf1e073088635951435acedff793add1cefdDevang Patel   /* setup vertex data */
442135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner   {
443135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
444b7c6bf1e073088635951435acedff793add1cefdDevang Patel      const GLfloat fb_width = (GLfloat) fb->Width;
445135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      const GLfloat fb_height = (GLfloat) fb->Height;
446135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f;
4473e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner      const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f;
4483e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner      const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f;
4493e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner      const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f;
4503e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner      const GLfloat sLeft = 0.0f, sRight = maxXcoord;
4513e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner      const GLfloat tTop = invertTex ? maxYcoord : 0.0f;
452b374b90e81d0ce6b5d02041ba4f7b15a945b38d8Chris Lattner      const GLfloat tBot = invertTex ? 0.0f : maxYcoord;
453135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      GLuint i;
454135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
455135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      /* upper-left */
456135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      verts[0][0][0] = clip_x0;    /* v[0].attr[0].x */
457135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      verts[0][0][1] = clip_y0;    /* v[0].attr[0].y */
458135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
459135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      /* upper-right */
460135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      verts[1][0][0] = clip_x1;
461135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      verts[1][0][1] = clip_y0;
462135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
463b374b90e81d0ce6b5d02041ba4f7b15a945b38d8Chris Lattner      /* lower-right */
464b374b90e81d0ce6b5d02041ba4f7b15a945b38d8Chris Lattner      verts[2][0][0] = clip_x1;
465135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      verts[2][0][1] = clip_y1;
466135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
467135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      /* lower-left */
468135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      verts[3][0][0] = clip_x0;
469135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      verts[3][0][1] = clip_y1;
470135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner
471135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      verts[0][1][0] = sLeft; /* v[0].attr[1].S */
472135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      verts[0][1][1] = tTop;  /* v[0].attr[1].T */
473135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      verts[1][1][0] = sRight;
474135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      verts[1][1][1] = tTop;
475135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      verts[2][1][0] = sRight;
476fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman      verts[2][1][1] = tBot;
477135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      verts[3][1][0] = sLeft;
478135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner      verts[3][1][1] = tBot;
47968d57e7ae80044401efd889270a12c71b3efb9abChris Lattner
4803e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner      /* same for all verts: */
4813e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner      if (color) {
4823e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner         for (i = 0; i < 4; i++) {
4833e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner            verts[i][0][2] = z;         /* v[i].attr[0].z */
484135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner            verts[i][0][3] = 1.0f;      /* v[i].attr[0].w */
485135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner            verts[i][2][0] = color[0];  /* v[i].attr[2].r */
486135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner            verts[i][2][1] = color[1];  /* v[i].attr[2].g */
487135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner            verts[i][2][2] = color[2];  /* v[i].attr[2].b */
4883e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner            verts[i][2][3] = color[3];  /* v[i].attr[2].a */
489135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner            verts[i][1][2] = 0.0f;      /* v[i].attr[1].R */
490135755dae4c3fa8003b76150689d5064aa4612eeChris Lattner            verts[i][1][3] = 1.0f;      /* v[i].attr[1].Q */
4911f67ce4aa3f65619f54c8a3072539da5b0022841Dale Johannesen         }
4923e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner      }
4933e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner      else {
4943e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner         for (i = 0; i < 4; i++) {
4953e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner            verts[i][0][2] = z;    /*Z*/
4963e1358a9fa1ebd3f51c94eb69da55d693895fe7cChris Lattner            verts[i][0][3] = 1.0f; /*W*/
49768d57e7ae80044401efd889270a12c71b3efb9abChris Lattner            verts[i][1][2] = 0.0f; /*R*/
49868d57e7ae80044401efd889270a12c71b3efb9abChris Lattner            verts[i][1][3] = 1.0f; /*Q*/
499         }
500      }
501   }
502
503   {
504      struct pipe_resource *buf;
505
506      /* allocate/load buffer object with vertex data */
507      buf = pipe_buffer_create(pipe->screen,
508			       PIPE_BIND_VERTEX_BUFFER,
509                               sizeof(verts));
510      pipe_buffer_write(st->pipe, buf, 0, sizeof(verts), verts);
511
512      util_draw_vertex_buffer(pipe, buf, 0,
513                              PIPE_PRIM_QUADS,
514                              4,  /* verts */
515                              3); /* attribs/vert */
516      pipe_resource_reference(&buf, NULL);
517   }
518}
519
520
521
522static void
523draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
524                   GLsizei width, GLsizei height,
525                   GLfloat zoomX, GLfloat zoomY,
526                   struct pipe_sampler_view *sv,
527                   void *driver_vp,
528                   void *driver_fp,
529                   const GLfloat *color,
530                   GLboolean invertTex)
531{
532   struct st_context *st = st_context(ctx);
533   struct pipe_context *pipe = st->pipe;
534   struct cso_context *cso = st->cso_context;
535   GLfloat x0, y0, x1, y1;
536   GLsizei maxSize;
537
538   /* limit checks */
539   /* XXX if DrawPixels image is larger than max texture size, break
540    * it up into chunks.
541    */
542   maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
543   assert(width <= maxSize);
544   assert(height <= maxSize);
545
546   cso_save_rasterizer(cso);
547   cso_save_viewport(cso);
548   cso_save_samplers(cso);
549   cso_save_fragment_sampler_views(cso);
550   cso_save_fragment_shader(cso);
551   cso_save_vertex_shader(cso);
552   cso_save_vertex_elements(cso);
553
554   /* rasterizer state: just scissor */
555   {
556      struct pipe_rasterizer_state rasterizer;
557      memset(&rasterizer, 0, sizeof(rasterizer));
558      rasterizer.gl_rasterization_rules = 1;
559      rasterizer.scissor = ctx->Scissor.Enabled;
560      cso_set_rasterizer(cso, &rasterizer);
561   }
562
563   /* fragment shader state: TEX lookup program */
564   cso_set_fragment_shader_handle(cso, driver_fp);
565
566   /* vertex shader state: position + texcoord pass-through */
567   cso_set_vertex_shader_handle(cso, driver_vp);
568
569
570   /* texture sampling state: */
571   {
572      struct pipe_sampler_state sampler;
573      memset(&sampler, 0, sizeof(sampler));
574      sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
575      sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
576      sampler.wrap_r = PIPE_TEX_WRAP_CLAMP;
577      sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
578      sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
579      sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
580      sampler.normalized_coords = 1;
581
582      cso_single_sampler(cso, 0, &sampler);
583      if (st->pixel_xfer.pixelmap_enabled) {
584         cso_single_sampler(cso, 1, &sampler);
585      }
586      cso_single_sampler_done(cso);
587   }
588
589   /* viewport state: viewport matching window dims */
590   {
591      const float w = (float) ctx->DrawBuffer->Width;
592      const float h = (float) ctx->DrawBuffer->Height;
593      struct pipe_viewport_state vp;
594      vp.scale[0] =  0.5f * w;
595      vp.scale[1] = -0.5f * h;
596      vp.scale[2] = 0.5f;
597      vp.scale[3] = 1.0f;
598      vp.translate[0] = 0.5f * w;
599      vp.translate[1] = 0.5f * h;
600      vp.translate[2] = 0.5f;
601      vp.translate[3] = 0.0f;
602      cso_set_viewport(cso, &vp);
603   }
604
605   cso_set_vertex_elements(cso, 3, st->velems_util_draw);
606
607   /* texture state: */
608   if (st->pixel_xfer.pixelmap_enabled) {
609      struct pipe_sampler_view *sampler_views[2];
610      sampler_views[0] = sv;
611      sampler_views[1] = st->pixel_xfer.pixelmap_sampler_view;
612      cso_set_fragment_sampler_views(cso, 2, sampler_views);
613   }
614   else {
615      cso_set_fragment_sampler_views(cso, 1, &sv);
616   }
617
618   /* Compute Gallium window coords (y=0=top) with pixel zoom.
619    * Recall that these coords are transformed by the current
620    * vertex shader and viewport transformation.
621    */
622   if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) {
623      y = ctx->DrawBuffer->Height - (int) (y + height * ctx->Pixel.ZoomY);
624      invertTex = !invertTex;
625   }
626
627   x0 = (GLfloat) x;
628   x1 = x + width * ctx->Pixel.ZoomX;
629   y0 = (GLfloat) y;
630   y1 = y + height * ctx->Pixel.ZoomY;
631
632   /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
633   z = z * 2.0 - 1.0;
634
635   draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex,
636             (GLfloat) width / sv->texture->width0,
637             (GLfloat) height / sv->texture->height0);
638
639   /* restore state */
640   cso_restore_rasterizer(cso);
641   cso_restore_viewport(cso);
642   cso_restore_samplers(cso);
643   cso_restore_fragment_sampler_views(cso);
644   cso_restore_fragment_shader(cso);
645   cso_restore_vertex_shader(cso);
646   cso_restore_vertex_elements(cso);
647}
648
649
650static void
651draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
652                    GLsizei width, GLsizei height, GLenum format, GLenum type,
653                    const struct gl_pixelstore_attrib *unpack,
654                    const GLvoid *pixels)
655{
656   struct st_context *st = st_context(ctx);
657   struct pipe_context *pipe = st->pipe;
658   struct st_renderbuffer *strb;
659   enum pipe_transfer_usage usage;
660   struct pipe_transfer *pt;
661   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
662   GLint skipPixels;
663   ubyte *stmap;
664   struct gl_pixelstore_attrib clippedUnpack = *unpack;
665
666   if (!zoom) {
667      if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height,
668                                 &clippedUnpack)) {
669         /* totally clipped */
670         return;
671      }
672   }
673
674   strb = st_renderbuffer(ctx->DrawBuffer->
675                          Attachment[BUFFER_STENCIL].Renderbuffer);
676
677   if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
678      y = ctx->DrawBuffer->Height - y - height;
679   }
680
681   if(format != GL_DEPTH_STENCIL &&
682      util_format_get_component_bits(strb->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0)
683      usage = PIPE_TRANSFER_READ_WRITE;
684   else
685      usage = PIPE_TRANSFER_WRITE;
686
687   pt = pipe_get_transfer(st_context(ctx)->pipe, strb->texture, 0, 0, 0,
688				       usage, x, y,
689				       width, height);
690
691   stmap = pipe_transfer_map(pipe, pt);
692
693   pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels);
694   assert(pixels);
695
696   /* if width > MAX_WIDTH, have to process image in chunks */
697   skipPixels = 0;
698   while (skipPixels < width) {
699      const GLint spanX = skipPixels;
700      const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
701      GLint row;
702      for (row = 0; row < height; row++) {
703         GLubyte sValues[MAX_WIDTH];
704         GLuint zValues[MAX_WIDTH];
705         GLenum destType = GL_UNSIGNED_BYTE;
706         const GLvoid *source = _mesa_image_address2d(&clippedUnpack, pixels,
707                                                      width, height,
708                                                      format, type,
709                                                      row, skipPixels);
710         _mesa_unpack_stencil_span(ctx, spanWidth, destType, sValues,
711                                   type, source, &clippedUnpack,
712                                   ctx->_ImageTransferState);
713
714         if (format == GL_DEPTH_STENCIL) {
715            _mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues,
716                                    (1 << 24) - 1, type, source,
717                                    &clippedUnpack);
718         }
719
720         if (zoom) {
721            _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with "
722                          "zoom not complete");
723         }
724
725         {
726            GLint spanY;
727
728            if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
729               spanY = height - row - 1;
730            }
731            else {
732               spanY = row;
733            }
734
735            /* now pack the stencil (and Z) values in the dest format */
736            switch (pt->resource->format) {
737            case PIPE_FORMAT_S8_USCALED:
738               {
739                  ubyte *dest = stmap + spanY * pt->stride + spanX;
740                  assert(usage == PIPE_TRANSFER_WRITE);
741                  memcpy(dest, sValues, spanWidth);
742               }
743               break;
744            case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
745               if (format == GL_DEPTH_STENCIL) {
746                  uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
747                  GLint k;
748                  assert(usage == PIPE_TRANSFER_WRITE);
749                  for (k = 0; k < spanWidth; k++) {
750                     dest[k] = zValues[k] | (sValues[k] << 24);
751                  }
752               }
753               else {
754                  uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
755                  GLint k;
756                  assert(usage == PIPE_TRANSFER_READ_WRITE);
757                  for (k = 0; k < spanWidth; k++) {
758                     dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24);
759                  }
760               }
761               break;
762            case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
763               if (format == GL_DEPTH_STENCIL) {
764                  uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
765                  GLint k;
766                  assert(usage == PIPE_TRANSFER_WRITE);
767                  for (k = 0; k < spanWidth; k++) {
768                     dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff);
769                  }
770               }
771               else {
772                  uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
773                  GLint k;
774                  assert(usage == PIPE_TRANSFER_READ_WRITE);
775                  for (k = 0; k < spanWidth; k++) {
776                     dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff);
777                  }
778               }
779               break;
780            default:
781               assert(0);
782            }
783         }
784      }
785      skipPixels += spanWidth;
786   }
787
788   _mesa_unmap_pbo_source(ctx, &clippedUnpack);
789
790   /* unmap the stencil buffer */
791   pipe_transfer_unmap(pipe, pt);
792   pipe->transfer_destroy(pipe, pt);
793}
794
795
796/**
797 * Called via ctx->Driver.DrawPixels()
798 */
799static void
800st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
801              GLenum format, GLenum type,
802              const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
803{
804   void *driver_vp, *driver_fp;
805   struct st_context *st = st_context(ctx);
806   const GLfloat *color;
807
808   if (format == GL_STENCIL_INDEX ||
809       format == GL_DEPTH_STENCIL) {
810      draw_stencil_pixels(ctx, x, y, width, height, format, type,
811                          unpack, pixels);
812      return;
813   }
814
815   /* Mesa state should be up to date by now */
816   assert(ctx->NewState == 0x0);
817
818   st_validate_state(st);
819
820   if (format == GL_DEPTH_COMPONENT) {
821      driver_fp = make_fragment_shader_z(st);
822      driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
823      color = ctx->Current.RasterColor;
824   }
825   else {
826      driver_fp = combined_drawpix_fragment_program(ctx);
827      driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
828      color = NULL;
829   }
830
831   /* draw with textured quad */
832   {
833      struct pipe_resource *pt
834         = make_texture(st, width, height, format, type, unpack, pixels);
835      if (pt) {
836         struct pipe_sampler_view *sv = st_create_texture_sampler_view(st->pipe, pt);
837
838         if (sv) {
839            draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
840                               width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
841                               sv,
842                               driver_vp,
843                               driver_fp,
844                               color, GL_FALSE);
845            pipe_sampler_view_reference(&sv, NULL);
846         }
847         pipe_resource_reference(&pt, NULL);
848      }
849   }
850}
851
852
853
854static void
855copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
856                    GLsizei width, GLsizei height,
857                    GLint dstx, GLint dsty)
858{
859   struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer);
860   struct pipe_context *pipe = st_context(ctx)->pipe;
861   enum pipe_transfer_usage usage;
862   struct pipe_transfer *ptDraw;
863   ubyte *drawMap;
864   ubyte *buffer;
865   int i;
866
867   buffer = malloc(width * height * sizeof(ubyte));
868   if (!buffer) {
869      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
870      return;
871   }
872
873   /* this will do stencil pixel transfer ops */
874   st_read_stencil_pixels(ctx, srcx, srcy, width, height,
875                          GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
876                          &ctx->DefaultPacking, buffer);
877
878   if(util_format_get_component_bits(rbDraw->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0)
879      usage = PIPE_TRANSFER_READ_WRITE;
880   else
881      usage = PIPE_TRANSFER_WRITE;
882
883   if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
884      dsty = rbDraw->Base.Height - dsty - height;
885   }
886
887   ptDraw = pipe_get_transfer(st_context(ctx)->pipe,
888					   rbDraw->texture, 0, 0, 0,
889					   usage, dstx, dsty,
890					   width, height);
891
892   assert(util_format_get_blockwidth(ptDraw->resource->format) == 1);
893   assert(util_format_get_blockheight(ptDraw->resource->format) == 1);
894
895   /* map the stencil buffer */
896   drawMap = pipe_transfer_map(pipe, ptDraw);
897
898   /* draw */
899   /* XXX PixelZoom not handled yet */
900   for (i = 0; i < height; i++) {
901      ubyte *dst;
902      const ubyte *src;
903      int y;
904
905      y = i;
906
907      if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
908         y = height - y - 1;
909      }
910
911      dst = drawMap + y * ptDraw->stride;
912      src = buffer + i * width;
913
914      switch (ptDraw->resource->format) {
915      case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
916         {
917            uint *dst4 = (uint *) dst;
918            int j;
919            assert(usage == PIPE_TRANSFER_READ_WRITE);
920            for (j = 0; j < width; j++) {
921               *dst4 = (*dst4 & 0xffffff) | (src[j] << 24);
922               dst4++;
923            }
924         }
925         break;
926      case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
927         {
928            uint *dst4 = (uint *) dst;
929            int j;
930            assert(usage == PIPE_TRANSFER_READ_WRITE);
931            for (j = 0; j < width; j++) {
932               *dst4 = (*dst4 & 0xffffff00) | (src[j] & 0xff);
933               dst4++;
934            }
935         }
936         break;
937      case PIPE_FORMAT_S8_USCALED:
938         assert(usage == PIPE_TRANSFER_WRITE);
939         memcpy(dst, src, width);
940         break;
941      default:
942         assert(0);
943      }
944   }
945
946   free(buffer);
947
948   /* unmap the stencil buffer */
949   pipe_transfer_unmap(pipe, ptDraw);
950   pipe->transfer_destroy(pipe, ptDraw);
951}
952
953
954static void
955st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
956              GLsizei width, GLsizei height,
957              GLint dstx, GLint dsty, GLenum type)
958{
959   struct st_context *st = st_context(ctx);
960   struct pipe_context *pipe = st->pipe;
961   struct pipe_screen *screen = pipe->screen;
962   struct st_renderbuffer *rbRead;
963   void *driver_vp, *driver_fp;
964   struct pipe_resource *pt;
965   struct pipe_sampler_view *sv;
966   GLfloat *color;
967   enum pipe_format srcFormat, texFormat;
968   GLboolean invertTex = GL_FALSE;
969   GLint readX, readY, readW, readH;
970   struct gl_pixelstore_attrib pack = ctx->DefaultPacking;
971
972   st_validate_state(st);
973
974   if (type == GL_STENCIL) {
975      /* can't use texturing to do stencil */
976      copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
977      return;
978   }
979
980   if (type == GL_COLOR) {
981      rbRead = st_get_color_read_renderbuffer(ctx);
982      color = NULL;
983      driver_fp = combined_drawpix_fragment_program(ctx);
984      driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
985   }
986   else {
987      assert(type == GL_DEPTH);
988      rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
989      color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
990      driver_fp = make_fragment_shader_z(st);
991      driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
992   }
993
994   srcFormat = rbRead->texture->format;
995
996   if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE_2D,
997                                   PIPE_BIND_SAMPLER_VIEW, 0)) {
998      texFormat = srcFormat;
999   }
1000   else {
1001      /* srcFormat can't be used as a texture format */
1002      if (type == GL_DEPTH) {
1003         texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT,
1004                                      PIPE_TEXTURE_2D,
1005                                      PIPE_BIND_DEPTH_STENCIL);
1006         assert(texFormat != PIPE_FORMAT_NONE);
1007      }
1008      else {
1009         /* default color format */
1010         texFormat = st_choose_format(screen, GL_RGBA, PIPE_TEXTURE_2D,
1011                                      PIPE_BIND_SAMPLER_VIEW);
1012         assert(texFormat != PIPE_FORMAT_NONE);
1013      }
1014   }
1015
1016   /* Invert src region if needed */
1017   if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
1018      srcy = ctx->ReadBuffer->Height - srcy - height;
1019      invertTex = !invertTex;
1020   }
1021
1022   /* Clip the read region against the src buffer bounds.
1023    * We'll still allocate a temporary buffer/texture for the original
1024    * src region size but we'll only read the region which is on-screen.
1025    * This may mean that we draw garbage pixels into the dest region, but
1026    * that's expected.
1027    */
1028   readX = srcx;
1029   readY = srcy;
1030   readW = width;
1031   readH = height;
1032   _mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack);
1033   readW = MAX2(0, readW);
1034   readH = MAX2(0, readH);
1035
1036   /* alloc temporary texture */
1037   pt = alloc_texture(st, width, height, texFormat);
1038   if (!pt)
1039      return;
1040
1041   sv = st_create_texture_sampler_view(st->pipe, pt);
1042   if (!sv) {
1043      pipe_resource_reference(&pt, NULL);
1044      return;
1045   }
1046
1047   /* Make temporary texture which is a copy of the src region.
1048    */
1049   if (srcFormat == texFormat) {
1050      /* copy source framebuffer surface into mipmap/texture */
1051      struct pipe_surface *psRead = screen->get_tex_surface(screen,
1052                                       rbRead->texture, 0, 0, 0,
1053                                       PIPE_BIND_BLIT_SOURCE);
1054      struct pipe_surface *psTex = screen->get_tex_surface(screen, pt, 0, 0, 0,
1055                                       PIPE_BIND_RENDER_TARGET |
1056                                       PIPE_BIND_BLIT_DESTINATION);
1057      pipe->surface_copy(pipe,
1058                         psTex,                               /* dest surf */
1059                         pack.SkipPixels, pack.SkipRows,      /* dest pos */
1060                         psRead,                              /* src surf */
1061                         readX, readY, readW, readH);         /* src region */
1062
1063      if (0) {
1064         /* debug */
1065         debug_dump_surface(pipe, "copypixsrcsurf", psRead);
1066         debug_dump_surface(pipe, "copypixtemptex", psTex);
1067      }
1068
1069      pipe_surface_reference(&psRead, NULL);
1070      pipe_surface_reference(&psTex, NULL);
1071   }
1072   else {
1073      /* CPU-based fallback/conversion */
1074      struct pipe_transfer *ptRead =
1075         pipe_get_transfer(st->pipe, rbRead->texture, 0, 0, 0,
1076                                        PIPE_TRANSFER_READ,
1077                                        readX, readY, readW, readH);
1078      struct pipe_transfer *ptTex;
1079      enum pipe_transfer_usage transfer_usage;
1080
1081      if (ST_DEBUG & DEBUG_FALLBACK)
1082         debug_printf("%s: fallback processing\n", __FUNCTION__);
1083
1084      if (type == GL_DEPTH && util_format_is_depth_and_stencil(pt->format))
1085         transfer_usage = PIPE_TRANSFER_READ_WRITE;
1086      else
1087         transfer_usage = PIPE_TRANSFER_WRITE;
1088
1089      ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, 0, transfer_usage,
1090                                             0, 0, width, height);
1091
1092      /* copy image from ptRead surface to ptTex surface */
1093      if (type == GL_COLOR) {
1094         /* alternate path using get/put_tile() */
1095         GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
1096         pipe_get_tile_rgba(pipe, ptRead, readX, readY, readW, readH, buf);
1097         pipe_put_tile_rgba(pipe, ptTex, pack.SkipPixels, pack.SkipRows,
1098                            readW, readH, buf);
1099         free(buf);
1100      }
1101      else {
1102         /* GL_DEPTH */
1103         GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint));
1104         pipe_get_tile_z(pipe, ptRead, readX, readY, readW, readH, buf);
1105         pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows,
1106                         readW, readH, buf);
1107         free(buf);
1108      }
1109
1110      pipe->transfer_destroy(pipe, ptRead);
1111      pipe->transfer_destroy(pipe, ptTex);
1112   }
1113
1114   /* OK, the texture 'pt' contains the src image/pixels.  Now draw a
1115    * textured quad with that texture.
1116    */
1117   draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
1118                      width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
1119                      sv,
1120                      driver_vp,
1121                      driver_fp,
1122                      color, invertTex);
1123
1124   pipe_resource_reference(&pt, NULL);
1125   pipe_sampler_view_reference(&sv, NULL);
1126}
1127
1128
1129
1130void st_init_drawpixels_functions(struct dd_function_table *functions)
1131{
1132   functions->DrawPixels = st_DrawPixels;
1133   functions->CopyPixels = st_CopyPixels;
1134}
1135
1136
1137void
1138st_destroy_drawpix(struct st_context *st)
1139{
1140   st_reference_fragprog(st, &st->drawpix.z_shader, NULL);
1141   st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
1142   if (st->drawpix.vert_shaders[0])
1143      ureg_free_tokens(st->drawpix.vert_shaders[0]);
1144   if (st->drawpix.vert_shaders[1])
1145      ureg_free_tokens(st->drawpix.vert_shaders[1]);
1146}
1147