1 /**************************************************************************
3 * Copyright 2008 VMware, Inc.
5 * Copyright 2009 Marek Olšák <maraeo@gmail.com>
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:
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
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 VMWARE 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.
27 **************************************************************************/
31 * Simple vertex/fragment shader generators.
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 "util/u_memory.h"
44 #include "tgsi/tgsi_dump.h"
45 #include "tgsi/tgsi_strings.h"
46 #include "tgsi/tgsi_ureg.h"
47 #include "tgsi/tgsi_text.h"
48 #include <stdio.h> /* include last */
53 * Make simple vertex pass-through shader.
54 * \param num_attribs number of attributes to pass through
55 * \param semantic_names array of semantic names for each attribute
56 * \param semantic_indexes array of semantic indexes for each attribute
59 util_make_vertex_passthrough_shader(struct pipe_context
*pipe
,
61 const uint
*semantic_names
,
62 const uint
*semantic_indexes
,
65 return util_make_vertex_passthrough_shader_with_so(pipe
, num_attribs
,
72 util_make_vertex_passthrough_shader_with_so(struct pipe_context
*pipe
,
74 const uint
*semantic_names
,
75 const uint
*semantic_indexes
,
77 const struct pipe_stream_output_info
*so
)
79 struct ureg_program
*ureg
;
82 ureg
= ureg_create( TGSI_PROCESSOR_VERTEX
);
87 ureg_property(ureg
, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION
, TRUE
);
89 for (i
= 0; i
< num_attribs
; i
++) {
93 src
= ureg_DECL_vs_input( ureg
, i
);
95 dst
= ureg_DECL_output( ureg
,
99 ureg_MOV( ureg
, dst
, src
);
104 return ureg_create_shader_with_so_and_destroy( ureg
, pipe
, so
);
108 void *util_make_layered_clear_vertex_shader(struct pipe_context
*pipe
)
110 static const char text
[] =
114 "DCL SV[0], INSTANCEID\n"
115 "DCL OUT[0], POSITION\n"
116 "DCL OUT[1], GENERIC[0]\n"
117 "DCL OUT[2], LAYER\n"
119 "MOV OUT[0], IN[0]\n"
120 "MOV OUT[1], IN[1]\n"
121 "MOV OUT[2], SV[0]\n"
123 struct tgsi_token tokens
[1000];
124 struct pipe_shader_state state
= {tokens
};
126 if (!tgsi_text_translate(text
, tokens
, Elements(tokens
))) {
130 return pipe
->create_vs_state(pipe
, &state
);
134 * Takes position and color, and outputs position, color, and instance id.
136 void *util_make_layered_clear_helper_vertex_shader(struct pipe_context
*pipe
)
138 static const char text
[] =
142 "DCL SV[0], INSTANCEID\n"
143 "DCL OUT[0], POSITION\n"
144 "DCL OUT[1], GENERIC[0]\n"
145 "DCL OUT[2], GENERIC[1]\n"
147 "MOV OUT[0], IN[0]\n"
148 "MOV OUT[1], IN[1]\n"
149 "MOV OUT[2].x, SV[0].xxxx\n"
151 struct tgsi_token tokens
[1000];
152 struct pipe_shader_state state
= {tokens
};
154 if (!tgsi_text_translate(text
, tokens
, Elements(tokens
))) {
158 return pipe
->create_vs_state(pipe
, &state
);
162 * Takes position, color, and target layer, and emits vertices on that target
163 * layer, with the specified color.
165 void *util_make_layered_clear_geometry_shader(struct pipe_context
*pipe
)
167 static const char text
[] =
169 "PROPERTY GS_INPUT_PRIMITIVE TRIANGLES\n"
170 "PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP\n"
171 "PROPERTY GS_MAX_OUTPUT_VERTICES 3\n"
172 "PROPERTY GS_INVOCATIONS 1\n"
173 "DCL IN[][0], POSITION\n" /* position */
174 "DCL IN[][1], GENERIC[0]\n" /* color */
175 "DCL IN[][2], GENERIC[1]\n" /* vs invocation */
176 "DCL OUT[0], POSITION\n"
177 "DCL OUT[1], GENERIC[0]\n"
178 "DCL OUT[2], LAYER\n"
179 "IMM[0] INT32 {0, 0, 0, 0}\n"
181 "MOV OUT[0], IN[0][0]\n"
182 "MOV OUT[1], IN[0][1]\n"
183 "MOV OUT[2].x, IN[0][2].xxxx\n"
185 "MOV OUT[0], IN[1][0]\n"
186 "MOV OUT[1], IN[1][1]\n"
187 "MOV OUT[2].x, IN[1][2].xxxx\n"
189 "MOV OUT[0], IN[2][0]\n"
190 "MOV OUT[1], IN[2][1]\n"
191 "MOV OUT[2].x, IN[2][2].xxxx\n"
194 struct tgsi_token tokens
[1000];
195 struct pipe_shader_state state
= {tokens
};
197 if (!tgsi_text_translate(text
, tokens
, Elements(tokens
))) {
201 return pipe
->create_gs_state(pipe
, &state
);
205 * Make simple fragment texture shader:
206 * IMM {0,0,0,1} // (if writemask != 0xf)
207 * MOV OUT[0], IMM[0] // (if writemask != 0xf)
208 * TEX OUT[0].writemask, IN[0], SAMP[0], 2D;
211 * \param tex_target one of PIPE_TEXTURE_x
212 * \parma interp_mode either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE
213 * \param writemask mask of TGSI_WRITEMASK_x
216 util_make_fragment_tex_shader_writemask(struct pipe_context
*pipe
,
218 unsigned interp_mode
,
220 enum tgsi_return_type stype
)
222 struct ureg_program
*ureg
;
223 struct ureg_src sampler
;
227 assert(interp_mode
== TGSI_INTERPOLATE_LINEAR
||
228 interp_mode
== TGSI_INTERPOLATE_PERSPECTIVE
);
230 ureg
= ureg_create( TGSI_PROCESSOR_FRAGMENT
);
234 sampler
= ureg_DECL_sampler( ureg
, 0 );
236 ureg_DECL_sampler_view(ureg
, 0, tex_target
, stype
, stype
, stype
, stype
);
238 tex
= ureg_DECL_fs_input( ureg
,
239 TGSI_SEMANTIC_GENERIC
, 0,
242 out
= ureg_DECL_output( ureg
,
246 if (writemask
!= TGSI_WRITEMASK_XYZW
) {
247 struct ureg_src imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
249 ureg_MOV( ureg
, out
, imm
);
252 if (tex_target
== TGSI_TEXTURE_BUFFER
)
254 ureg_writemask(out
, writemask
),
255 tex_target
, tex
, sampler
);
258 ureg_writemask(out
, writemask
),
259 tex_target
, tex
, sampler
);
263 return ureg_create_shader_and_destroy( ureg
, pipe
);
268 * Make a simple fragment shader that sets the output color to a color
269 * taken from a texture.
270 * \param tex_target one of PIPE_TEXTURE_x
273 util_make_fragment_tex_shader(struct pipe_context
*pipe
, unsigned tex_target
,
274 unsigned interp_mode
,
275 enum tgsi_return_type stype
)
277 return util_make_fragment_tex_shader_writemask( pipe
,
286 * Make a simple fragment texture shader which reads an X component from
287 * a texture and writes it as depth.
290 util_make_fragment_tex_shader_writedepth(struct pipe_context
*pipe
,
292 unsigned interp_mode
)
294 struct ureg_program
*ureg
;
295 struct ureg_src sampler
;
297 struct ureg_dst out
, depth
;
300 ureg
= ureg_create( TGSI_PROCESSOR_FRAGMENT
);
304 sampler
= ureg_DECL_sampler( ureg
, 0 );
306 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
307 TGSI_RETURN_TYPE_FLOAT
,
308 TGSI_RETURN_TYPE_FLOAT
,
309 TGSI_RETURN_TYPE_FLOAT
,
310 TGSI_RETURN_TYPE_FLOAT
);
312 tex
= ureg_DECL_fs_input( ureg
,
313 TGSI_SEMANTIC_GENERIC
, 0,
316 out
= ureg_DECL_output( ureg
,
320 depth
= ureg_DECL_output( ureg
,
321 TGSI_SEMANTIC_POSITION
,
324 imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
326 ureg_MOV( ureg
, out
, imm
);
329 ureg_writemask(depth
, TGSI_WRITEMASK_Z
),
330 tex_target
, tex
, sampler
);
333 return ureg_create_shader_and_destroy( ureg
, pipe
);
338 * Make a simple fragment texture shader which reads the texture unit 0 and 1
339 * and writes it as depth and stencil, respectively.
342 util_make_fragment_tex_shader_writedepthstencil(struct pipe_context
*pipe
,
344 unsigned interp_mode
)
346 struct ureg_program
*ureg
;
347 struct ureg_src depth_sampler
, stencil_sampler
;
349 struct ureg_dst out
, depth
, stencil
;
352 ureg
= ureg_create( TGSI_PROCESSOR_FRAGMENT
);
356 depth_sampler
= ureg_DECL_sampler( ureg
, 0 );
357 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
358 TGSI_RETURN_TYPE_FLOAT
,
359 TGSI_RETURN_TYPE_FLOAT
,
360 TGSI_RETURN_TYPE_FLOAT
,
361 TGSI_RETURN_TYPE_FLOAT
);
362 stencil_sampler
= ureg_DECL_sampler( ureg
, 1 );
363 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
364 TGSI_RETURN_TYPE_UINT
,
365 TGSI_RETURN_TYPE_UINT
,
366 TGSI_RETURN_TYPE_UINT
,
367 TGSI_RETURN_TYPE_UINT
);
369 tex
= ureg_DECL_fs_input( ureg
,
370 TGSI_SEMANTIC_GENERIC
, 0,
373 out
= ureg_DECL_output( ureg
,
377 depth
= ureg_DECL_output( ureg
,
378 TGSI_SEMANTIC_POSITION
,
381 stencil
= ureg_DECL_output( ureg
,
382 TGSI_SEMANTIC_STENCIL
,
385 imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
387 ureg_MOV( ureg
, out
, imm
);
390 ureg_writemask(depth
, TGSI_WRITEMASK_Z
),
391 tex_target
, tex
, depth_sampler
);
393 ureg_writemask(stencil
, TGSI_WRITEMASK_Y
),
394 tex_target
, tex
, stencil_sampler
);
397 return ureg_create_shader_and_destroy( ureg
, pipe
);
402 * Make a simple fragment texture shader which reads a texture and writes it
406 util_make_fragment_tex_shader_writestencil(struct pipe_context
*pipe
,
408 unsigned interp_mode
)
410 struct ureg_program
*ureg
;
411 struct ureg_src stencil_sampler
;
413 struct ureg_dst out
, stencil
;
416 ureg
= ureg_create( TGSI_PROCESSOR_FRAGMENT
);
420 stencil_sampler
= ureg_DECL_sampler( ureg
, 0 );
422 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
423 TGSI_RETURN_TYPE_UINT
,
424 TGSI_RETURN_TYPE_UINT
,
425 TGSI_RETURN_TYPE_UINT
,
426 TGSI_RETURN_TYPE_UINT
);
428 tex
= ureg_DECL_fs_input( ureg
,
429 TGSI_SEMANTIC_GENERIC
, 0,
432 out
= ureg_DECL_output( ureg
,
436 stencil
= ureg_DECL_output( ureg
,
437 TGSI_SEMANTIC_STENCIL
,
440 imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
442 ureg_MOV( ureg
, out
, imm
);
445 ureg_writemask(stencil
, TGSI_WRITEMASK_Y
),
446 tex_target
, tex
, stencil_sampler
);
449 return ureg_create_shader_and_destroy( ureg
, pipe
);
454 * Make simple fragment color pass-through shader that replicates OUT[0]
455 * to all bound colorbuffers.
458 util_make_fragment_passthrough_shader(struct pipe_context
*pipe
,
460 int input_interpolate
,
461 boolean write_all_cbufs
)
463 static const char shader_templ
[] =
466 "DCL IN[0], %s[0], %s\n"
467 "DCL OUT[0], COLOR[0]\n"
469 "MOV OUT[0], IN[0]\n"
472 char text
[sizeof(shader_templ
)+100];
473 struct tgsi_token tokens
[1000];
474 struct pipe_shader_state state
= {tokens
};
476 sprintf(text
, shader_templ
,
477 write_all_cbufs
? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "",
478 tgsi_semantic_names
[input_semantic
],
479 tgsi_interpolate_names
[input_interpolate
]);
481 if (!tgsi_text_translate(text
, tokens
, Elements(tokens
))) {
486 tgsi_dump(state
.tokens
, 0);
489 return pipe
->create_fs_state(pipe
, &state
);
494 util_make_empty_fragment_shader(struct pipe_context
*pipe
)
496 struct ureg_program
*ureg
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
501 return ureg_create_shader_and_destroy(ureg
, pipe
);
506 * Make a fragment shader that copies the input color to N output colors.
509 util_make_fragment_cloneinput_shader(struct pipe_context
*pipe
, int num_cbufs
,
511 int input_interpolate
)
513 struct ureg_program
*ureg
;
515 struct ureg_dst dst
[PIPE_MAX_COLOR_BUFS
];
518 assert(num_cbufs
<= PIPE_MAX_COLOR_BUFS
);
520 ureg
= ureg_create( TGSI_PROCESSOR_FRAGMENT
);
524 src
= ureg_DECL_fs_input( ureg
, input_semantic
, 0,
527 for (i
= 0; i
< num_cbufs
; i
++)
528 dst
[i
] = ureg_DECL_output( ureg
, TGSI_SEMANTIC_COLOR
, i
);
530 for (i
= 0; i
< num_cbufs
; i
++)
531 ureg_MOV( ureg
, dst
[i
], src
);
535 return ureg_create_shader_and_destroy( ureg
, pipe
);
540 util_make_fs_blit_msaa_gen(struct pipe_context
*pipe
,
542 const char *samp_type
,
543 const char *output_semantic
,
544 const char *output_mask
)
546 static const char shader_templ
[] =
548 "DCL IN[0], GENERIC[0], LINEAR\n"
550 "DCL SVIEW[0], %s, %s\n"
554 "F2U TEMP[0], IN[0]\n"
555 "TXF OUT[0]%s, TEMP[0], SAMP[0], %s\n"
558 const char *type
= tgsi_texture_names
[tgsi_tex
];
559 char text
[sizeof(shader_templ
)+100];
560 struct tgsi_token tokens
[1000];
561 struct pipe_shader_state state
= {tokens
};
563 assert(tgsi_tex
== TGSI_TEXTURE_2D_MSAA
||
564 tgsi_tex
== TGSI_TEXTURE_2D_ARRAY_MSAA
);
566 sprintf(text
, shader_templ
, type
, samp_type
,
567 output_semantic
, output_mask
, type
);
569 if (!tgsi_text_translate(text
, tokens
, Elements(tokens
))) {
575 tgsi_dump(state
.tokens
, 0);
578 return pipe
->create_fs_state(pipe
, &state
);
583 * Make a fragment shader that sets the output color to a color
584 * fetched from a multisample texture.
585 * \param tex_target one of PIPE_TEXTURE_x
588 util_make_fs_blit_msaa_color(struct pipe_context
*pipe
,
590 enum tgsi_return_type stype
)
592 const char *samp_type
;
594 if (stype
== TGSI_RETURN_TYPE_UINT
)
596 else if (stype
== TGSI_RETURN_TYPE_SINT
)
601 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
, samp_type
,
607 * Make a fragment shader that sets the output depth to a depth value
608 * fetched from a multisample texture.
609 * \param tex_target one of PIPE_TEXTURE_x
612 util_make_fs_blit_msaa_depth(struct pipe_context
*pipe
,
615 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
, "FLOAT",
621 * Make a fragment shader that sets the output stencil to a stencil value
622 * fetched from a multisample texture.
623 * \param tex_target one of PIPE_TEXTURE_x
626 util_make_fs_blit_msaa_stencil(struct pipe_context
*pipe
,
629 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
, "UINT",
635 * Make a fragment shader that sets the output depth and stencil to depth
636 * and stencil values fetched from two multisample textures / samplers.
637 * The sizes of both textures should match (it should be one depth-stencil
639 * \param tex_target one of PIPE_TEXTURE_x
642 util_make_fs_blit_msaa_depthstencil(struct pipe_context
*pipe
,
645 static const char shader_templ
[] =
647 "DCL IN[0], GENERIC[0], LINEAR\n"
649 "DCL OUT[0], POSITION\n"
650 "DCL OUT[1], STENCIL\n"
653 "F2U TEMP[0], IN[0]\n"
654 "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
655 "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
658 const char *type
= tgsi_texture_names
[tgsi_tex
];
659 char text
[sizeof(shader_templ
)+100];
660 struct tgsi_token tokens
[1000];
661 struct pipe_shader_state state
= {tokens
};
663 assert(tgsi_tex
== TGSI_TEXTURE_2D_MSAA
||
664 tgsi_tex
== TGSI_TEXTURE_2D_ARRAY_MSAA
);
666 sprintf(text
, shader_templ
, type
, type
);
668 if (!tgsi_text_translate(text
, tokens
, Elements(tokens
))) {
673 tgsi_dump(state
.tokens
, 0);
676 return pipe
->create_fs_state(pipe
, &state
);
681 util_make_fs_msaa_resolve(struct pipe_context
*pipe
,
682 unsigned tgsi_tex
, unsigned nr_samples
,
683 enum tgsi_return_type stype
)
685 struct ureg_program
*ureg
;
686 struct ureg_src sampler
, coord
;
687 struct ureg_dst out
, tmp_sum
, tmp_coord
, tmp
;
690 ureg
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
695 sampler
= ureg_DECL_sampler(ureg
, 0);
696 ureg_DECL_sampler_view(ureg
, 0, tgsi_tex
, stype
, stype
, stype
, stype
);
697 coord
= ureg_DECL_fs_input(ureg
, TGSI_SEMANTIC_GENERIC
, 0,
698 TGSI_INTERPOLATE_LINEAR
);
699 out
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0);
700 tmp_sum
= ureg_DECL_temporary(ureg
);
701 tmp_coord
= ureg_DECL_temporary(ureg
);
702 tmp
= ureg_DECL_temporary(ureg
);
705 ureg_MOV(ureg
, tmp_sum
, ureg_imm1f(ureg
, 0));
706 ureg_F2U(ureg
, tmp_coord
, coord
);
708 for (i
= 0; i
< nr_samples
; i
++) {
709 /* Read one sample. */
710 ureg_MOV(ureg
, ureg_writemask(tmp_coord
, TGSI_WRITEMASK_W
),
711 ureg_imm1u(ureg
, i
));
712 ureg_TXF(ureg
, tmp
, tgsi_tex
, ureg_src(tmp_coord
), sampler
);
714 if (stype
== TGSI_RETURN_TYPE_UINT
)
715 ureg_U2F(ureg
, tmp
, ureg_src(tmp
));
716 else if (stype
== TGSI_RETURN_TYPE_SINT
)
717 ureg_I2F(ureg
, tmp
, ureg_src(tmp
));
719 /* Add it to the sum.*/
720 ureg_ADD(ureg
, tmp_sum
, ureg_src(tmp_sum
), ureg_src(tmp
));
723 /* Calculate the average and return. */
724 ureg_MUL(ureg
, tmp_sum
, ureg_src(tmp_sum
),
725 ureg_imm1f(ureg
, 1.0 / nr_samples
));
727 if (stype
== TGSI_RETURN_TYPE_UINT
)
728 ureg_F2U(ureg
, out
, ureg_src(tmp_sum
));
729 else if (stype
== TGSI_RETURN_TYPE_SINT
)
730 ureg_F2I(ureg
, out
, ureg_src(tmp_sum
));
732 ureg_MOV(ureg
, out
, ureg_src(tmp_sum
));
736 return ureg_create_shader_and_destroy(ureg
, pipe
);
741 util_make_fs_msaa_resolve_bilinear(struct pipe_context
*pipe
,
742 unsigned tgsi_tex
, unsigned nr_samples
,
743 enum tgsi_return_type stype
)
745 struct ureg_program
*ureg
;
746 struct ureg_src sampler
, coord
;
747 struct ureg_dst out
, tmp
, top
, bottom
;
748 struct ureg_dst tmp_coord
[4], tmp_sum
[4];
751 ureg
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
756 sampler
= ureg_DECL_sampler(ureg
, 0);
757 ureg_DECL_sampler_view(ureg
, 0, tgsi_tex
, stype
, stype
, stype
, stype
);
758 coord
= ureg_DECL_fs_input(ureg
, TGSI_SEMANTIC_GENERIC
, 0,
759 TGSI_INTERPOLATE_LINEAR
);
760 out
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0);
761 for (c
= 0; c
< 4; c
++)
762 tmp_sum
[c
] = ureg_DECL_temporary(ureg
);
763 for (c
= 0; c
< 4; c
++)
764 tmp_coord
[c
] = ureg_DECL_temporary(ureg
);
765 tmp
= ureg_DECL_temporary(ureg
);
766 top
= ureg_DECL_temporary(ureg
);
767 bottom
= ureg_DECL_temporary(ureg
);
770 for (c
= 0; c
< 4; c
++)
771 ureg_MOV(ureg
, tmp_sum
[c
], ureg_imm1f(ureg
, 0));
773 /* Get 4 texture coordinates for the bilinear filter. */
774 ureg_F2U(ureg
, tmp_coord
[0], coord
); /* top-left */
775 ureg_UADD(ureg
, tmp_coord
[1], ureg_src(tmp_coord
[0]),
776 ureg_imm4u(ureg
, 1, 0, 0, 0)); /* top-right */
777 ureg_UADD(ureg
, tmp_coord
[2], ureg_src(tmp_coord
[0]),
778 ureg_imm4u(ureg
, 0, 1, 0, 0)); /* bottom-left */
779 ureg_UADD(ureg
, tmp_coord
[3], ureg_src(tmp_coord
[0]),
780 ureg_imm4u(ureg
, 1, 1, 0, 0)); /* bottom-right */
782 for (i
= 0; i
< nr_samples
; i
++) {
783 for (c
= 0; c
< 4; c
++) {
784 /* Read one sample. */
785 ureg_MOV(ureg
, ureg_writemask(tmp_coord
[c
], TGSI_WRITEMASK_W
),
786 ureg_imm1u(ureg
, i
));
787 ureg_TXF(ureg
, tmp
, tgsi_tex
, ureg_src(tmp_coord
[c
]), sampler
);
789 if (stype
== TGSI_RETURN_TYPE_UINT
)
790 ureg_U2F(ureg
, tmp
, ureg_src(tmp
));
791 else if (stype
== TGSI_RETURN_TYPE_SINT
)
792 ureg_I2F(ureg
, tmp
, ureg_src(tmp
));
794 /* Add it to the sum.*/
795 ureg_ADD(ureg
, tmp_sum
[c
], ureg_src(tmp_sum
[c
]), ureg_src(tmp
));
799 /* Calculate the average. */
800 for (c
= 0; c
< 4; c
++)
801 ureg_MUL(ureg
, tmp_sum
[c
], ureg_src(tmp_sum
[c
]),
802 ureg_imm1f(ureg
, 1.0 / nr_samples
));
804 /* Take the 4 average values and apply a standard bilinear filter. */
805 ureg_FRC(ureg
, tmp
, coord
);
808 ureg_scalar(ureg_src(tmp
), 0),
809 ureg_src(tmp_sum
[1]),
810 ureg_src(tmp_sum
[0]));
812 ureg_LRP(ureg
, bottom
,
813 ureg_scalar(ureg_src(tmp
), 0),
814 ureg_src(tmp_sum
[3]),
815 ureg_src(tmp_sum
[2]));
818 ureg_scalar(ureg_src(tmp
), 1),
822 /* Convert to the texture format and return. */
823 if (stype
== TGSI_RETURN_TYPE_UINT
)
824 ureg_F2U(ureg
, out
, ureg_src(tmp
));
825 else if (stype
== TGSI_RETURN_TYPE_SINT
)
826 ureg_F2I(ureg
, out
, ureg_src(tmp
));
828 ureg_MOV(ureg
, out
, ureg_src(tmp
));
832 return ureg_create_shader_and_destroy(ureg
, pipe
);