summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/cell/spu/spu_ztest.h
blob: ce8ad0033932353900eb0fd10c17b844c9be92df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**************************************************************************
 * 
 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * 
 **************************************************************************/


/**
 * Zbuffer/depth test code.
 */


#ifndef SPU_ZTEST_H
#define SPU_ZTEST_H


#ifdef __SPU__
#include <spu_intrinsics.h>
#endif



/**
 * Perform Z testing for a 16-bit/value Z buffer.
 *
 * \param zvals  vector of four fragment zvalues as floats
 * \param zbuf   ptr to vector of ushort[8] zbuffer values.  Note that this
 *               contains the Z values for 2 quads, 8 pixels.
 * \param x      x coordinate of quad (only lsbit is significant)
 * \param inMask indicates which fragments in the quad are alive
 * \return new mask indicating which fragments are alive after ztest
 */
static INLINE vector unsigned int
spu_z16_test_less(vector float zvals, vector unsigned short *zbuf,
                  uint x, vector unsigned int inMask)
{
#define ZERO 0x80
   vector unsigned int zvals_ui4, zbuf_ui4, mask;

   /* convert floats to uints in [0, 65535] */
   zvals_ui4 = spu_convtu(zvals, 32); /* convert to [0, 2^32] */
   zvals_ui4 = spu_rlmask(zvals_ui4, -16);  /* right shift 16 */

   /* XXX this conditional could be removed with a bit of work */
   if (x & 1) {
      /* convert zbuffer values from ushorts to uints */
      /* gather lower four ushorts */
      zbuf_ui4 = spu_shuffle((vector unsigned int) *zbuf,
                             (vector unsigned int) *zbuf,
                             ((vector unsigned char) {
                                ZERO, ZERO,  8,  9, ZERO, ZERO, 10, 11,
                                ZERO, ZERO, 12, 13, ZERO, ZERO, 14, 15}));
      /* mask = (zbuf_ui4 < zvals_ui4) ? ~0 : 0 */
      mask = spu_cmpgt(zbuf_ui4, zvals_ui4);
      /* mask &= inMask */
      mask = spu_and(mask, inMask);
      /* zbuf = mask ? zval : zbuf */
      zbuf_ui4 = spu_sel(zbuf_ui4, zvals_ui4, mask);
      /* convert zbuffer values from uints back to ushorts, preserve lower 4 */
      *zbuf = (vector unsigned short)
         spu_shuffle(zbuf_ui4, (vector unsigned int) *zbuf,
                     ((vector unsigned char) {
                        16, 17, 18, 19, 20, 21, 22, 23,
                        2, 3, 6, 7, 10, 11, 14, 15}));
   }
   else {
      /* convert zbuffer values from ushorts to uints */
      /* gather upper four ushorts */
      zbuf_ui4 = spu_shuffle((vector unsigned int) *zbuf,
                             (vector unsigned int) *zbuf,
                             ((vector unsigned char) {
                                ZERO, ZERO, 0, 1, ZERO, ZERO, 2, 3,
                                ZERO, ZERO, 4, 5, ZERO, ZERO, 6, 7}));
      /* mask = (zbuf_ui4 < zvals_ui4) ? ~0 : 0 */
      mask = spu_cmpgt(zbuf_ui4, zvals_ui4);
      /* mask &= inMask */
      mask = spu_and(mask, inMask);
      /* zbuf = mask ? zval : zbuf */
      zbuf_ui4 = spu_sel(zbuf_ui4, zvals_ui4, mask);
      /* convert zbuffer values from uints back to ushorts, preserve upper 4 */
      *zbuf = (vector unsigned short)
         spu_shuffle(zbuf_ui4, (vector unsigned int) *zbuf,
                     ((vector unsigned char) {
                        2, 3, 6, 7, 10, 11, 14, 15,
                        24, 25, 26, 27, 28, 29, 30, 31}));
   }
   return mask;
#undef ZERO
}


/**
 * As above, but Zbuffer values as 32-bit uints
 */
static INLINE vector unsigned int
spu_z32_test_less(vector float zvals, vector unsigned int *zbuf_ptr,
                  vector unsigned int inMask)
{
   vector unsigned int zvals_ui4, mask, zbuf = *zbuf_ptr;

   /* convert floats to uints in [0, 0xffffffff] */
   zvals_ui4 = spu_convtu(zvals, 32);
   /* mask = (zbuf < zvals_ui4) ? ~0 : 0 */
   mask = spu_cmpgt(zbuf, zvals_ui4);
   /* mask &= inMask */
   mask = spu_and(mask, inMask);
   /* zbuf = mask ? zval : zbuf */
   *zbuf_ptr = spu_sel(zbuf, zvals_ui4, mask);

   return mask;
}


#endif /* SPU_ZTEST_H */