1 /************************************************************************** 2 * 3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 #include "util/u_memory.h" 29 #include "util/u_math.h" 30 #include "pipe/p_context.h" 31 #include "draw/draw_context.h" 32 #include "draw/draw_private.h" 33 #include "draw/draw_pt.h" 34 #include "draw/draw_vs.h" 35 36 #define DO_CLIP_XY 0x1 37 #define DO_CLIP_FULL_Z 0x2 38 #define DO_CLIP_HALF_Z 0x4 39 #define DO_CLIP_USER 0x8 40 #define DO_VIEWPORT 0x10 41 #define DO_EDGEFLAG 0x20 42 #define DO_CLIP_XY_GUARD_BAND 0x40 43 44 45 struct pt_post_vs { 46 struct draw_context *draw; 47 48 unsigned flags; 49 50 boolean (*run)( struct pt_post_vs *pvs, 51 struct draw_vertex_info *info ); 52 }; 53 54 static INLINE void 55 initialize_vertex_header(struct vertex_header *header) 56 { 57 header->clipmask = 0; 58 header->edgeflag = 1; 59 header->have_clipdist = 0; 60 header->vertex_id = UNDEFINED_VERTEX_ID; 61 } 62 63 static INLINE float 64 dot4(const float *a, const float *b) 65 { 66 return (a[0]*b[0] + 67 a[1]*b[1] + 68 a[2]*b[2] + 69 a[3]*b[3]); 70 } 71 72 #define FLAGS (0) 73 #define TAG(x) x##_none 74 #include "draw_cliptest_tmp.h" 75 76 #define FLAGS (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_VIEWPORT) 77 #define TAG(x) x##_xy_fullz_viewport 78 #include "draw_cliptest_tmp.h" 79 80 #define FLAGS (DO_CLIP_XY | DO_CLIP_HALF_Z | DO_VIEWPORT) 81 #define TAG(x) x##_xy_halfz_viewport 82 #include "draw_cliptest_tmp.h" 83 84 #define FLAGS (DO_CLIP_XY_GUARD_BAND | DO_CLIP_HALF_Z | DO_VIEWPORT) 85 #define TAG(x) x##_xy_gb_halfz_viewport 86 #include "draw_cliptest_tmp.h" 87 88 #define FLAGS (DO_CLIP_FULL_Z | DO_VIEWPORT) 89 #define TAG(x) x##_fullz_viewport 90 #include "draw_cliptest_tmp.h" 91 92 #define FLAGS (DO_CLIP_HALF_Z | DO_VIEWPORT) 93 #define TAG(x) x##_halfz_viewport 94 #include "draw_cliptest_tmp.h" 95 96 #define FLAGS (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER | DO_VIEWPORT) 97 #define TAG(x) x##_xy_fullz_user_viewport 98 #include "draw_cliptest_tmp.h" 99 100 #define FLAGS (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER | DO_VIEWPORT | DO_EDGEFLAG) 101 #define TAG(x) x##_xy_fullz_user_viewport_edgeflag 102 #include "draw_cliptest_tmp.h" 103 104 105 106 /* Don't want to create 64 versions of this function, so catch the 107 * less common ones here. This is looking like something which should 108 * be code-generated, perhaps appended to the end of the vertex 109 * shader. 110 */ 111 #define FLAGS (pvs->flags) 112 #define TAG(x) x##_generic 113 #include "draw_cliptest_tmp.h" 114 115 116 117 boolean draw_pt_post_vs_run( struct pt_post_vs *pvs, 118 struct draw_vertex_info *info ) 119 { 120 return pvs->run( pvs, info ); 121 } 122 123 124 void draw_pt_post_vs_prepare( struct pt_post_vs *pvs, 125 boolean clip_xy, 126 boolean clip_z, 127 boolean clip_user, 128 boolean guard_band, 129 boolean bypass_viewport, 130 boolean opengl, 131 boolean need_edgeflags ) 132 { 133 pvs->flags = 0; 134 135 /* This combination not currently tested/in use: 136 */ 137 if (opengl) 138 guard_band = FALSE; 139 140 if (clip_xy && !guard_band) { 141 pvs->flags |= DO_CLIP_XY; 142 ASSIGN_4V( pvs->draw->plane[0], -1, 0, 0, 1 ); 143 ASSIGN_4V( pvs->draw->plane[1], 1, 0, 0, 1 ); 144 ASSIGN_4V( pvs->draw->plane[2], 0, -1, 0, 1 ); 145 ASSIGN_4V( pvs->draw->plane[3], 0, 1, 0, 1 ); 146 } 147 else if (clip_xy && guard_band) { 148 pvs->flags |= DO_CLIP_XY_GUARD_BAND; 149 ASSIGN_4V( pvs->draw->plane[0], -0.5, 0, 0, 1 ); 150 ASSIGN_4V( pvs->draw->plane[1], 0.5, 0, 0, 1 ); 151 ASSIGN_4V( pvs->draw->plane[2], 0, -0.5, 0, 1 ); 152 ASSIGN_4V( pvs->draw->plane[3], 0, 0.5, 0, 1 ); 153 } 154 155 if (clip_z && opengl) { 156 pvs->flags |= DO_CLIP_FULL_Z; 157 ASSIGN_4V( pvs->draw->plane[4], 0, 0, 1, 1 ); 158 } 159 160 if (clip_z && !opengl) { 161 pvs->flags |= DO_CLIP_HALF_Z; 162 ASSIGN_4V( pvs->draw->plane[4], 0, 0, 1, 0 ); 163 } 164 165 if (clip_user) 166 pvs->flags |= DO_CLIP_USER; 167 168 if (!bypass_viewport) 169 pvs->flags |= DO_VIEWPORT; 170 171 if (need_edgeflags) 172 pvs->flags |= DO_EDGEFLAG; 173 174 /* Now select the relevant function: 175 */ 176 switch (pvs->flags) { 177 case 0: 178 pvs->run = do_cliptest_none; 179 break; 180 181 case DO_CLIP_XY | DO_CLIP_FULL_Z | DO_VIEWPORT: 182 pvs->run = do_cliptest_xy_fullz_viewport; 183 break; 184 185 case DO_CLIP_XY | DO_CLIP_HALF_Z | DO_VIEWPORT: 186 pvs->run = do_cliptest_xy_halfz_viewport; 187 break; 188 189 case DO_CLIP_XY_GUARD_BAND | DO_CLIP_HALF_Z | DO_VIEWPORT: 190 pvs->run = do_cliptest_xy_gb_halfz_viewport; 191 break; 192 193 case DO_CLIP_FULL_Z | DO_VIEWPORT: 194 pvs->run = do_cliptest_fullz_viewport; 195 break; 196 197 case DO_CLIP_HALF_Z | DO_VIEWPORT: 198 pvs->run = do_cliptest_halfz_viewport; 199 break; 200 201 case DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER | DO_VIEWPORT: 202 pvs->run = do_cliptest_xy_fullz_user_viewport; 203 break; 204 205 case (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER | 206 DO_VIEWPORT | DO_EDGEFLAG): 207 pvs->run = do_cliptest_xy_fullz_user_viewport_edgeflag; 208 break; 209 210 default: 211 pvs->run = do_cliptest_generic; 212 break; 213 } 214 } 215 216 217 struct pt_post_vs *draw_pt_post_vs_create( struct draw_context *draw ) 218 { 219 struct pt_post_vs *pvs = CALLOC_STRUCT( pt_post_vs ); 220 if (!pvs) 221 return NULL; 222 223 pvs->draw = draw; 224 225 return pvs; 226 } 227 228 void draw_pt_post_vs_destroy( struct pt_post_vs *pvs ) 229 { 230 FREE(pvs); 231 } 232