1 /**************************************************************************
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 **************************************************************************/
30 #include "tgsi/tgsi_ureg.h"
32 typedef void (* ureg_func
)( struct ureg_program
*ureg
,
35 struct ureg_src
*sampler
,
36 struct ureg_dst
*temp
,
37 struct ureg_src
*constant
);
40 solid_fill( struct ureg_program
*ureg
,
43 struct ureg_src
*sampler
,
44 struct ureg_dst
*temp
,
45 struct ureg_src
*constant
)
47 ureg_MOV(ureg
, *out
, constant
[2]);
51 * Perform frag-coord-to-paint-coord transform. The transformation is in
54 #define PAINT_TRANSFORM \
55 ureg_MOV(ureg, ureg_writemask(temp[0], TGSI_WRITEMASK_XY), in[0]); \
57 ureg_writemask(temp[0], TGSI_WRITEMASK_Z), \
58 ureg_scalar(constant[3], TGSI_SWIZZLE_Y)); \
59 ureg_DP3(ureg, temp[1], constant[4], ureg_src(temp[0])); \
60 ureg_DP3(ureg, temp[2], constant[5], ureg_src(temp[0])); \
61 ureg_DP3(ureg, temp[3], constant[6], ureg_src(temp[0])); \
62 ureg_RCP(ureg, temp[3], ureg_src(temp[3])); \
63 ureg_MUL(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[3])); \
64 ureg_MUL(ureg, temp[2], ureg_src(temp[2]), ureg_src(temp[3])); \
66 ureg_writemask(temp[4], TGSI_WRITEMASK_X), \
69 ureg_writemask(temp[4], TGSI_WRITEMASK_Y), \
73 linear_grad( struct ureg_program
*ureg
,
76 struct ureg_src
*sampler
,
77 struct ureg_dst
*temp
,
78 struct ureg_src
*constant
)
82 /* grad = DP2((x, y), CONST[2].xy) * CONST[2].z */
83 ureg_MUL(ureg
, temp
[0],
84 ureg_scalar(constant
[2], TGSI_SWIZZLE_Y
),
85 ureg_scalar(ureg_src(temp
[4]), TGSI_SWIZZLE_Y
));
86 ureg_MAD(ureg
, temp
[1],
87 ureg_scalar(constant
[2], TGSI_SWIZZLE_X
),
88 ureg_scalar(ureg_src(temp
[4]), TGSI_SWIZZLE_X
),
90 ureg_MUL(ureg
, temp
[2], ureg_src(temp
[1]),
91 ureg_scalar(constant
[2], TGSI_SWIZZLE_Z
));
93 ureg_TEX(ureg
, *out
, TGSI_TEXTURE_1D
, ureg_src(temp
[2]), sampler
[0]);
97 radial_grad( struct ureg_program
*ureg
,
100 struct ureg_src
*sampler
,
101 struct ureg_dst
*temp
,
102 struct ureg_src
*constant
)
107 * Calculate (sqrt(B^2 + AC) - B) / A, where
110 * B is DP2((x, y), CONST[2].xy), and
111 * C is DP2((x, y), (x, y)).
115 ureg_DP2(ureg
, temp
[0], ureg_src(temp
[4]), constant
[2]);
116 ureg_DP2(ureg
, temp
[1], ureg_src(temp
[4]), ureg_src(temp
[4]));
118 /* the square root */
119 ureg_MUL(ureg
, temp
[2], ureg_src(temp
[0]), ureg_src(temp
[0]));
120 ureg_MAD(ureg
, temp
[3], ureg_src(temp
[1]),
121 ureg_scalar(constant
[2], TGSI_SWIZZLE_Z
), ureg_src(temp
[2]));
122 ureg_RSQ(ureg
, temp
[3], ureg_src(temp
[3]));
123 ureg_RCP(ureg
, temp
[3], ureg_src(temp
[3]));
125 ureg_SUB(ureg
, temp
[3], ureg_src(temp
[3]), ureg_src(temp
[0]));
126 ureg_RCP(ureg
, temp
[0], ureg_scalar(constant
[2], TGSI_SWIZZLE_Z
));
127 ureg_MUL(ureg
, temp
[0], ureg_src(temp
[0]), ureg_src(temp
[3]));
129 ureg_TEX(ureg
, *out
, TGSI_TEXTURE_1D
, ureg_src(temp
[0]), sampler
[0]);
134 pattern( struct ureg_program
*ureg
,
135 struct ureg_dst
*out
,
137 struct ureg_src
*sampler
,
138 struct ureg_dst
*temp
,
139 struct ureg_src
*constant
)
143 /* (s, t) = (x / tex_width, y / tex_height) */
144 ureg_RCP(ureg
, temp
[0],
145 ureg_swizzle(constant
[3],
150 ureg_MOV(ureg
, temp
[1], ureg_src(temp
[4]));
152 ureg_writemask(temp
[1], TGSI_WRITEMASK_X
),
156 ureg_writemask(temp
[1], TGSI_WRITEMASK_Y
),
160 ureg_TEX(ureg
, *out
, TGSI_TEXTURE_2D
, ureg_src(temp
[1]), sampler
[0]);
164 paint_degenerate( struct ureg_program
*ureg
,
165 struct ureg_dst
*out
,
167 struct ureg_src
*sampler
,
168 struct ureg_dst
*temp
,
169 struct ureg_src
*constant
)
171 /* CONST[3].y is 1.0f */
172 ureg_MOV(ureg
, temp
[1], ureg_scalar(constant
[3], TGSI_SWIZZLE_Y
));
173 ureg_TEX(ureg
, *out
, TGSI_TEXTURE_1D
, ureg_src(temp
[1]), sampler
[0]);
177 image_normal( struct ureg_program
*ureg
,
178 struct ureg_dst
*out
,
180 struct ureg_src
*sampler
,
181 struct ureg_dst
*temp
,
182 struct ureg_src
*constant
)
184 /* store and pass image color in TEMP[1] */
185 ureg_TEX(ureg
, temp
[1], TGSI_TEXTURE_2D
, in
[1], sampler
[3]);
186 ureg_MOV(ureg
, *out
, ureg_src(temp
[1]));
191 image_multiply( struct ureg_program
*ureg
,
192 struct ureg_dst
*out
,
194 struct ureg_src
*sampler
,
195 struct ureg_dst
*temp
,
196 struct ureg_src
*constant
)
198 /* store and pass image color in TEMP[1] */
199 ureg_TEX(ureg
, temp
[1], TGSI_TEXTURE_2D
, in
[1], sampler
[3]);
200 ureg_MUL(ureg
, *out
, ureg_src(temp
[0]), ureg_src(temp
[1]));
205 image_stencil( struct ureg_program
*ureg
,
206 struct ureg_dst
*out
,
208 struct ureg_src
*sampler
,
209 struct ureg_dst
*temp
,
210 struct ureg_src
*constant
)
212 /* store and pass image color in TEMP[1] */
213 ureg_TEX(ureg
, temp
[1], TGSI_TEXTURE_2D
, in
[1], sampler
[3]);
214 ureg_MOV(ureg
, *out
, ureg_src(temp
[0]));
218 color_transform( struct ureg_program
*ureg
,
219 struct ureg_dst
*out
,
221 struct ureg_src
*sampler
,
222 struct ureg_dst
*temp
,
223 struct ureg_src
*constant
)
225 /* note that TEMP[1] may already be used for image color */
227 ureg_MAD(ureg
, temp
[2], ureg_src(temp
[0]), constant
[0], constant
[1]);
228 /* clamp to [0.0f, 1.0f] */
229 ureg_CLAMP(ureg
, temp
[2],
231 ureg_scalar(constant
[3], TGSI_SWIZZLE_X
),
232 ureg_scalar(constant
[3], TGSI_SWIZZLE_Y
));
233 ureg_MOV(ureg
, *out
, ureg_src(temp
[2]));
237 alpha_normal( struct ureg_program
*ureg
,
238 struct ureg_dst
*out
,
240 struct ureg_src
*sampler
,
241 struct ureg_dst
*temp
,
242 struct ureg_src
*constant
)
244 /* save per-channel alpha in TEMP[1] */
245 ureg_MOV(ureg
, temp
[1], ureg_scalar(ureg_src(temp
[0]), TGSI_SWIZZLE_W
));
247 ureg_MOV(ureg
, *out
, ureg_src(temp
[0]));
251 alpha_per_channel( struct ureg_program
*ureg
,
252 struct ureg_dst
*out
,
254 struct ureg_src
*sampler
,
255 struct ureg_dst
*temp
,
256 struct ureg_src
*constant
)
258 /* save per-channel alpha in TEMP[1] */
260 ureg_writemask(temp
[1], TGSI_WRITEMASK_W
),
264 ureg_writemask(temp
[1], TGSI_WRITEMASK_XYZ
),
266 ureg_scalar(ureg_src(temp
[1]), TGSI_SWIZZLE_W
));
270 ureg_writemask(temp
[0], TGSI_WRITEMASK_W
),
272 ureg_MOV(ureg
, *out
, ureg_src(temp
[0]));
276 * Premultiply src and dst.
279 blend_premultiply( struct ureg_program
*ureg
,
281 struct ureg_src src_channel_alpha
,
284 /* premultiply src */
286 ureg_writemask(ureg_dst(src
), TGSI_WRITEMASK_XYZ
),
289 /* premultiply dst */
291 ureg_writemask(ureg_dst(dst
), TGSI_WRITEMASK_XYZ
),
293 ureg_scalar(dst
, TGSI_SWIZZLE_W
));
300 blend_unpremultiply( struct ureg_program
*ureg
,
303 struct ureg_dst temp
[1])
305 /* replace 0.0f by 1.0f before calculating reciprocal */
308 ureg_negate(ureg_scalar(src
, TGSI_SWIZZLE_W
)),
309 ureg_scalar(src
, TGSI_SWIZZLE_W
),
311 ureg_RCP(ureg
, temp
[0], ureg_src(temp
[0]));
314 ureg_writemask(ureg_dst(src
), TGSI_WRITEMASK_XYZ
),
320 * Emit instructions for the specified blend mode. Colors will be
321 * unpremultiplied. Two temporary registers are required.
323 * The output is written back to src.
326 blend_generic(struct ureg_program
*ureg
,
329 struct ureg_src src_channel_alpha
,
332 struct ureg_dst temp
[2])
336 blend_premultiply(ureg
, src
, src_channel_alpha
, dst
);
343 ureg_MOV(ureg
, out
, src
);
345 case VG_BLEND_SRC_OVER
:
346 /* RGBA_out = RGBA_src + (1 - A_src) * RGBA_dst */
347 ureg_SUB(ureg
, temp
[0], one
, src_channel_alpha
);
348 ureg_MAD(ureg
, out
, ureg_src(temp
[0]), dst
, src
);
350 case VG_BLEND_DST_OVER
:
351 /* RGBA_out = RGBA_dst + (1 - A_dst) * RGBA_src */
352 ureg_SUB(ureg
, temp
[0], one
, ureg_scalar(dst
, TGSI_SWIZZLE_W
));
353 ureg_MAD(ureg
, out
, ureg_src(temp
[0]), src
, dst
);
355 case VG_BLEND_SRC_IN
:
356 ureg_MUL(ureg
, out
, src
, ureg_scalar(dst
, TGSI_SWIZZLE_W
));
358 case VG_BLEND_DST_IN
:
359 ureg_MUL(ureg
, out
, dst
, src_channel_alpha
);
361 case VG_BLEND_MULTIPLY
:
363 * RGB_out = (1 - A_dst) * RGB_src + (1 - A_src) * RGB_dst +
366 ureg_MAD(ureg
, temp
[0],
367 ureg_scalar(dst
, TGSI_SWIZZLE_W
), ureg_negate(src
), src
);
368 ureg_MAD(ureg
, temp
[1],
369 src_channel_alpha
, ureg_negate(dst
), dst
);
370 ureg_MAD(ureg
, temp
[1], src
, dst
, ureg_src(temp
[1]));
371 ureg_ADD(ureg
, out
, ureg_src(temp
[0]), ureg_src(temp
[1]));
372 /* alpha is src over */
373 ureg_ADD(ureg
, ureg_writemask(out
, TGSI_WRITEMASK_W
),
374 src
, ureg_src(temp
[1]));
376 case VG_BLEND_SCREEN
:
377 /* RGBA_out = RGBA_src + (1 - RGBA_src) * RGBA_dst */
378 ureg_SUB(ureg
, temp
[0], one
, src
);
379 ureg_MAD(ureg
, out
, ureg_src(temp
[0]), dst
, src
);
381 case VG_BLEND_DARKEN
:
382 case VG_BLEND_LIGHTEN
:
384 ureg_SUB(ureg
, temp
[0], one
, src_channel_alpha
);
385 ureg_MAD(ureg
, temp
[0], ureg_src(temp
[0]), dst
, src
);
387 ureg_SUB(ureg
, temp
[1], one
, ureg_scalar(dst
, TGSI_SWIZZLE_W
));
388 ureg_MAD(ureg
, temp
[1], ureg_src(temp
[1]), src
, dst
);
389 /* take min/max for colors */
390 if (mode
== VG_BLEND_DARKEN
) {
391 ureg_MIN(ureg
, ureg_writemask(out
, TGSI_WRITEMASK_XYZ
),
392 ureg_src(temp
[0]), ureg_src(temp
[1]));
395 ureg_MAX(ureg
, ureg_writemask(out
, TGSI_WRITEMASK_XYZ
),
396 ureg_src(temp
[0]), ureg_src(temp
[1]));
399 case VG_BLEND_ADDITIVE
:
400 /* RGBA_out = RGBA_src + RGBA_dst */
401 ureg_ADD(ureg
, temp
[0], src
, dst
);
402 ureg_MIN(ureg
, out
, ureg_src(temp
[0]), one
);
409 blend_unpremultiply(ureg
, src
, one
, temp
);
413 blend_multiply( struct ureg_program
*ureg
,
414 struct ureg_dst
*out
,
416 struct ureg_src
*sampler
,
417 struct ureg_dst
*temp
,
418 struct ureg_src
*constant
)
420 ureg_TEX(ureg
, temp
[2], TGSI_TEXTURE_2D
, in
[0], sampler
[2]);
422 blend_generic(ureg
, VG_BLEND_MULTIPLY
,
426 ureg_scalar(constant
[3], TGSI_SWIZZLE_Y
),
429 ureg_MOV(ureg
, *out
, ureg_src(temp
[0]));
433 blend_screen( struct ureg_program
*ureg
,
434 struct ureg_dst
*out
,
436 struct ureg_src
*sampler
,
437 struct ureg_dst
*temp
,
438 struct ureg_src
*constant
)
440 ureg_TEX(ureg
, temp
[2], TGSI_TEXTURE_2D
, in
[0], sampler
[2]);
442 blend_generic(ureg
, VG_BLEND_SCREEN
,
446 ureg_scalar(constant
[3], TGSI_SWIZZLE_Y
),
449 ureg_MOV(ureg
, *out
, ureg_src(temp
[0]));
453 blend_darken( struct ureg_program
*ureg
,
454 struct ureg_dst
*out
,
456 struct ureg_src
*sampler
,
457 struct ureg_dst
*temp
,
458 struct ureg_src
*constant
)
460 ureg_TEX(ureg
, temp
[2], TGSI_TEXTURE_2D
, in
[0], sampler
[2]);
462 blend_generic(ureg
, VG_BLEND_DARKEN
,
466 ureg_scalar(constant
[3], TGSI_SWIZZLE_Y
),
469 ureg_MOV(ureg
, *out
, ureg_src(temp
[0]));
473 blend_lighten( struct ureg_program
*ureg
,
474 struct ureg_dst
*out
,
476 struct ureg_src
*sampler
,
477 struct ureg_dst
*temp
,
478 struct ureg_src
*constant
)
480 ureg_TEX(ureg
, temp
[2], TGSI_TEXTURE_2D
, in
[0], sampler
[2]);
482 blend_generic(ureg
, VG_BLEND_LIGHTEN
,
486 ureg_scalar(constant
[3], TGSI_SWIZZLE_Y
),
489 ureg_MOV(ureg
, *out
, ureg_src(temp
[0]));
493 mask( struct ureg_program
*ureg
,
494 struct ureg_dst
*out
,
496 struct ureg_src
*sampler
,
497 struct ureg_dst
*temp
,
498 struct ureg_src
*constant
)
500 ureg_TEX(ureg
, temp
[1], TGSI_TEXTURE_2D
, in
[0], sampler
[1]);
501 ureg_MUL(ureg
, ureg_writemask(temp
[0], TGSI_WRITEMASK_W
),
502 ureg_scalar(ureg_src(temp
[0]), TGSI_SWIZZLE_W
),
503 ureg_scalar(ureg_src(temp
[1]), TGSI_SWIZZLE_W
));
504 ureg_MOV(ureg
, *out
, ureg_src(temp
[0]));
508 premultiply( struct ureg_program
*ureg
,
509 struct ureg_dst
*out
,
511 struct ureg_src
*sampler
,
512 struct ureg_dst
*temp
,
513 struct ureg_src
*constant
)
516 ureg_writemask(temp
[0], TGSI_WRITEMASK_XYZ
),
518 ureg_scalar(ureg_src(temp
[0]), TGSI_SWIZZLE_W
));
522 unpremultiply( struct ureg_program
*ureg
,
523 struct ureg_dst
*out
,
525 struct ureg_src
*sampler
,
526 struct ureg_dst
*temp
,
527 struct ureg_src
*constant
)
529 ureg_TEX(ureg
, temp
[0], TGSI_TEXTURE_2D
, in
[0], sampler
[1]);
534 color_bw( struct ureg_program
*ureg
,
535 struct ureg_dst
*out
,
537 struct ureg_src
*sampler
,
538 struct ureg_dst
*temp
,
539 struct ureg_src
*constant
)
541 ureg_ADD(ureg
, temp
[1],
542 ureg_scalar(constant
[3], TGSI_SWIZZLE_Y
),
543 ureg_scalar(constant
[3], TGSI_SWIZZLE_Y
));
544 ureg_RCP(ureg
, temp
[2], ureg_src(temp
[1]));
545 ureg_ADD(ureg
, temp
[1],
546 ureg_scalar(constant
[3], TGSI_SWIZZLE_Y
),
548 ureg_ADD(ureg
, ureg_writemask(temp
[2], TGSI_WRITEMASK_X
),
549 ureg_scalar(ureg_src(temp
[0]), TGSI_SWIZZLE_X
),
550 ureg_scalar(ureg_src(temp
[0]), TGSI_SWIZZLE_Y
));
551 ureg_ADD(ureg
, ureg_writemask(temp
[2], TGSI_WRITEMASK_X
),
552 ureg_scalar(ureg_src(temp
[0]), TGSI_SWIZZLE_Z
),
553 ureg_scalar(ureg_src(temp
[0]), TGSI_SWIZZLE_X
));
555 ureg_writemask(temp
[0], TGSI_WRITEMASK_XYZ
),
556 ureg_scalar(ureg_src(temp
[2]), TGSI_SWIZZLE_X
),
559 ureg_writemask(temp
[0], TGSI_WRITEMASK_W
),
560 ureg_scalar(ureg_src(temp
[0]), TGSI_SWIZZLE_W
),
561 ureg_scalar(ureg_src(temp
[2]), TGSI_SWIZZLE_Y
));
562 ureg_MOV(ureg
, *out
, ureg_src(temp
[0]));
566 struct shader_asm_info
{
570 VGboolean needs_position
;
584 static const struct shader_asm_info shaders_paint_asm
[] = {
585 {VEGA_SOLID_FILL_SHADER
, solid_fill
,
586 VG_FALSE
, 2, 1, 0, 0, 0, 0},
587 {VEGA_LINEAR_GRADIENT_SHADER
, linear_grad
,
588 VG_TRUE
, 2, 5, 0, 1, 0, 5},
589 {VEGA_RADIAL_GRADIENT_SHADER
, radial_grad
,
590 VG_TRUE
, 2, 5, 0, 1, 0, 5},
591 {VEGA_PATTERN_SHADER
, pattern
,
592 VG_TRUE
, 3, 4, 0, 1, 0, 5},
593 {VEGA_PAINT_DEGENERATE_SHADER
, paint_degenerate
,
594 VG_FALSE
, 3, 1, 0, 1, 0, 2}
597 /* image draw modes */
598 static const struct shader_asm_info shaders_image_asm
[] = {
599 {VEGA_IMAGE_NORMAL_SHADER
, image_normal
,
600 VG_TRUE
, 0, 0, 3, 1, 0, 2},
601 {VEGA_IMAGE_MULTIPLY_SHADER
, image_multiply
,
602 VG_TRUE
, 0, 0, 3, 1, 0, 2},
603 {VEGA_IMAGE_STENCIL_SHADER
, image_stencil
,
604 VG_TRUE
, 0, 0, 3, 1, 0, 2}
607 static const struct shader_asm_info shaders_color_transform_asm
[] = {
608 {VEGA_COLOR_TRANSFORM_SHADER
, color_transform
,
609 VG_FALSE
, 0, 4, 0, 0, 0, 3}
612 static const struct shader_asm_info shaders_alpha_asm
[] = {
613 {VEGA_ALPHA_NORMAL_SHADER
, alpha_normal
,
614 VG_FALSE
, 0, 0, 0, 0, 0, 2},
615 {VEGA_ALPHA_PER_CHANNEL_SHADER
, alpha_per_channel
,
616 VG_FALSE
, 0, 0, 0, 0, 0, 2}
619 /* extra blend modes */
620 static const struct shader_asm_info shaders_blend_asm
[] = {
621 {VEGA_BLEND_MULTIPLY_SHADER
, blend_multiply
,
622 VG_TRUE
, 3, 1, 2, 1, 0, 5},
623 {VEGA_BLEND_SCREEN_SHADER
, blend_screen
,
624 VG_TRUE
, 3, 1, 2, 1, 0, 5},
625 {VEGA_BLEND_DARKEN_SHADER
, blend_darken
,
626 VG_TRUE
, 3, 1, 2, 1, 0, 5},
627 {VEGA_BLEND_LIGHTEN_SHADER
, blend_lighten
,
628 VG_TRUE
, 3, 1, 2, 1, 0, 5},
631 static const struct shader_asm_info shaders_mask_asm
[] = {
632 {VEGA_MASK_SHADER
, mask
,
633 VG_TRUE
, 0, 0, 1, 1, 0, 2}
637 static const struct shader_asm_info shaders_premultiply_asm
[] = {
638 {VEGA_PREMULTIPLY_SHADER
, premultiply
,
639 VG_FALSE
, 0, 0, 0, 0, 0, 1},
640 {VEGA_UNPREMULTIPLY_SHADER
, unpremultiply
,
641 VG_FALSE
, 0, 0, 0, 0, 0, 1},
644 /* color transform to black and white */
645 static const struct shader_asm_info shaders_bw_asm
[] = {
646 {VEGA_BW_SHADER
, color_bw
,
647 VG_FALSE
, 3, 1, 0, 0, 0, 3},