u_simple_shaders.c revision bdaf0a085ba7b8af4cf858b31f701caf571b7c4f
1/**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 * Copyright 2009 Marek Olšák <maraeo@gmail.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29/**
30 * @file
31 * Simple vertex/fragment shader generators.
32 *
33 * @author Brian Paul
34           Marek Olšák
35 */
36
37
38#include "pipe/p_context.h"
39#include "pipe/p_shader_tokens.h"
40#include "pipe/p_state.h"
41#include "util/u_simple_shaders.h"
42#include "util/u_debug.h"
43#include "tgsi/tgsi_ureg.h"
44
45
46
47/**
48 * Make simple vertex pass-through shader.
49 * \param num_attribs  number of attributes to pass through
50 * \param semantic_names  array of semantic names for each attribute
51 * \param semantic_indexes  array of semantic indexes for each attribute
52 */
53void *
54util_make_vertex_passthrough_shader(struct pipe_context *pipe,
55                                    uint num_attribs,
56                                    const uint *semantic_names,
57                                    const uint *semantic_indexes)
58{
59   return util_make_vertex_passthrough_shader_with_so(pipe, num_attribs,
60                                                      semantic_names,
61                                                      semantic_indexes, NULL);
62}
63
64void *
65util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe,
66                                    uint num_attribs,
67                                    const uint *semantic_names,
68                                    const uint *semantic_indexes,
69				    const struct pipe_stream_output_info *so)
70{
71   struct ureg_program *ureg;
72   uint i;
73
74   ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
75   if (ureg == NULL)
76      return NULL;
77
78   for (i = 0; i < num_attribs; i++) {
79      struct ureg_src src;
80      struct ureg_dst dst;
81
82      src = ureg_DECL_vs_input( ureg, i );
83
84      dst = ureg_DECL_output( ureg,
85                              semantic_names[i],
86                              semantic_indexes[i]);
87
88      ureg_MOV( ureg, dst, src );
89   }
90
91   ureg_END( ureg );
92
93   return ureg_create_shader_with_so_and_destroy( ureg, pipe, so );
94}
95
96
97/**
98 * Make simple fragment texture shader:
99 *  IMM {0,0,0,1}                         // (if writemask != 0xf)
100 *  MOV OUT[0], IMM[0]                    // (if writemask != 0xf)
101 *  TEX OUT[0].writemask, IN[0], SAMP[0], 2D;
102 *  END;
103 *
104 * \param tex_target  one of PIPE_TEXTURE_x
105 * \parma interp_mode  either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE
106 * \param writemask  mask of TGSI_WRITEMASK_x
107 */
108void *
109util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
110                                        unsigned tex_target,
111                                        unsigned interp_mode,
112                                        unsigned writemask )
113{
114   struct ureg_program *ureg;
115   struct ureg_src sampler;
116   struct ureg_src tex;
117   struct ureg_dst out;
118
119   assert(interp_mode == TGSI_INTERPOLATE_LINEAR ||
120          interp_mode == TGSI_INTERPOLATE_PERSPECTIVE);
121
122   ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
123   if (ureg == NULL)
124      return NULL;
125
126   sampler = ureg_DECL_sampler( ureg, 0 );
127
128   tex = ureg_DECL_fs_input( ureg,
129                             TGSI_SEMANTIC_GENERIC, 0,
130                             interp_mode );
131
132   out = ureg_DECL_output( ureg,
133                           TGSI_SEMANTIC_COLOR,
134                           0 );
135
136   if (writemask != TGSI_WRITEMASK_XYZW) {
137      struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
138
139      ureg_MOV( ureg, out, imm );
140   }
141
142   ureg_TEX( ureg,
143             ureg_writemask(out, writemask),
144             tex_target, tex, sampler );
145   ureg_END( ureg );
146
147   return ureg_create_shader_and_destroy( ureg, pipe );
148}
149
150
151/**
152 * Make a simple fragment shader that sets the output color to a color
153 * taken from a texture.
154 * \param tex_target  one of PIPE_TEXTURE_x
155 */
156void *
157util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target,
158                              unsigned interp_mode)
159{
160   return util_make_fragment_tex_shader_writemask( pipe,
161                                                   tex_target,
162                                                   interp_mode,
163                                                   TGSI_WRITEMASK_XYZW );
164}
165
166
167/**
168 * Make a simple fragment texture shader which reads an X component from
169 * a texture and writes it as depth.
170 */
171void *
172util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
173                                         unsigned tex_target,
174                                         unsigned interp_mode)
175{
176   struct ureg_program *ureg;
177   struct ureg_src sampler;
178   struct ureg_src tex;
179   struct ureg_dst out, depth;
180   struct ureg_src imm;
181
182   ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
183   if (ureg == NULL)
184      return NULL;
185
186   sampler = ureg_DECL_sampler( ureg, 0 );
187
188   tex = ureg_DECL_fs_input( ureg,
189                             TGSI_SEMANTIC_GENERIC, 0,
190                             interp_mode );
191
192   out = ureg_DECL_output( ureg,
193                           TGSI_SEMANTIC_COLOR,
194                           0 );
195
196   depth = ureg_DECL_output( ureg,
197                             TGSI_SEMANTIC_POSITION,
198                             0 );
199
200   imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
201
202   ureg_MOV( ureg, out, imm );
203
204   ureg_TEX( ureg,
205             ureg_writemask(depth, TGSI_WRITEMASK_Z),
206             tex_target, tex, sampler );
207   ureg_END( ureg );
208
209   return ureg_create_shader_and_destroy( ureg, pipe );
210}
211
212
213/**
214 * Make a simple fragment texture shader which reads the texture unit 0 and 1
215 * and writes it as depth and stencil, respectively.
216 */
217void *
218util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe,
219                                                unsigned tex_target,
220                                                unsigned interp_mode)
221{
222   struct ureg_program *ureg;
223   struct ureg_src depth_sampler, stencil_sampler;
224   struct ureg_src tex;
225   struct ureg_dst out, depth, stencil;
226   struct ureg_src imm;
227
228   ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
229   if (ureg == NULL)
230      return NULL;
231
232   depth_sampler = ureg_DECL_sampler( ureg, 0 );
233   stencil_sampler = ureg_DECL_sampler( ureg, 1 );
234
235   tex = ureg_DECL_fs_input( ureg,
236                             TGSI_SEMANTIC_GENERIC, 0,
237                             interp_mode );
238
239   out = ureg_DECL_output( ureg,
240                           TGSI_SEMANTIC_COLOR,
241                           0 );
242
243   depth = ureg_DECL_output( ureg,
244                             TGSI_SEMANTIC_POSITION,
245                             0 );
246
247   stencil = ureg_DECL_output( ureg,
248                             TGSI_SEMANTIC_STENCIL,
249                             0 );
250
251   imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
252
253   ureg_MOV( ureg, out, imm );
254
255   ureg_TEX( ureg,
256             ureg_writemask(depth, TGSI_WRITEMASK_Z),
257             tex_target, tex, depth_sampler );
258   ureg_TEX( ureg,
259             ureg_writemask(stencil, TGSI_WRITEMASK_Y),
260             tex_target, tex, stencil_sampler );
261   ureg_END( ureg );
262
263   return ureg_create_shader_and_destroy( ureg, pipe );
264}
265
266
267/**
268 * Make a simple fragment texture shader which reads a texture and writes it
269 * as stencil.
270 */
271void *
272util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe,
273                                           unsigned tex_target,
274                                           unsigned interp_mode)
275{
276   struct ureg_program *ureg;
277   struct ureg_src stencil_sampler;
278   struct ureg_src tex;
279   struct ureg_dst out, stencil;
280   struct ureg_src imm;
281
282   ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
283   if (ureg == NULL)
284      return NULL;
285
286   stencil_sampler = ureg_DECL_sampler( ureg, 0 );
287
288   tex = ureg_DECL_fs_input( ureg,
289                             TGSI_SEMANTIC_GENERIC, 0,
290                             interp_mode );
291
292   out = ureg_DECL_output( ureg,
293                           TGSI_SEMANTIC_COLOR,
294                           0 );
295
296   stencil = ureg_DECL_output( ureg,
297                             TGSI_SEMANTIC_STENCIL,
298                             0 );
299
300   imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
301
302   ureg_MOV( ureg, out, imm );
303
304   ureg_TEX( ureg,
305             ureg_writemask(stencil, TGSI_WRITEMASK_Y),
306             tex_target, tex, stencil_sampler );
307   ureg_END( ureg );
308
309   return ureg_create_shader_and_destroy( ureg, pipe );
310}
311
312
313/**
314 * Make simple fragment color pass-through shader.
315 */
316void *
317util_make_fragment_passthrough_shader(struct pipe_context *pipe)
318{
319   return util_make_fragment_cloneinput_shader(pipe, 1, TGSI_SEMANTIC_COLOR,
320                                               TGSI_INTERPOLATE_PERSPECTIVE);
321}
322
323
324/**
325 * Make a fragment shader that copies the input color to N output colors.
326 */
327void *
328util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs,
329                                     int input_semantic,
330                                     int input_interpolate)
331{
332   struct ureg_program *ureg;
333   struct ureg_src src;
334   struct ureg_dst dst[PIPE_MAX_COLOR_BUFS];
335   int i;
336
337   assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
338
339   ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
340   if (ureg == NULL)
341      return NULL;
342
343   src = ureg_DECL_fs_input( ureg, input_semantic, 0,
344                             input_interpolate );
345
346   for (i = 0; i < num_cbufs; i++)
347      dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i );
348
349   for (i = 0; i < num_cbufs; i++)
350      ureg_MOV( ureg, dst[i], src );
351
352   ureg_END( ureg );
353
354   return ureg_create_shader_and_destroy( ureg, pipe );
355}
356