OSDN Git Service

mesa: move call to init_c_cliptest() from enable.c to tnl module.
[android-x86/external-mesa.git] / src / mesa / tnl / t_vb_vertex.c
1 /*
2  * Mesa 3-D graphics library
3  * Version:  6.5
4  *
5  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Keith Whitwell <keith@tungstengraphics.com>
26  */
27
28
29 #include "main/glheader.h"
30 #include "main/colormac.h"
31 #include "main/context.h"
32 #include "main/macros.h"
33 #include "main/imports.h"
34 #include "main/mtypes.h"
35
36 #include "math/m_xform.h"
37
38 #include "t_context.h"
39 #include "t_pipeline.h"
40
41
42
43 struct vertex_stage_data {
44    GLvector4f eye;
45    GLvector4f clip;
46    GLvector4f proj;
47    GLubyte *clipmask;
48    GLubyte ormask;
49    GLubyte andmask;
50 };
51
52 #define VERTEX_STAGE_DATA(stage) ((struct vertex_stage_data *)stage->privatePtr)
53
54
55
56
57 /* This function implements cliptesting for user-defined clip planes.
58  * The clipping of primitives to these planes is implemented in
59  * t_render_clip.h.
60  */
61 #define USER_CLIPTEST(NAME, SZ)                                 \
62 static void NAME( GLcontext *ctx,                               \
63                   GLvector4f *clip,                             \
64                   GLubyte *clipmask,                            \
65                   GLubyte *clipormask,                          \
66                   GLubyte *clipandmask )                        \
67 {                                                               \
68    GLuint p;                                                    \
69                                                                 \
70    for (p = 0; p < ctx->Const.MaxClipPlanes; p++)               \
71       if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {        \
72          GLuint nr, i;                                          \
73          const GLfloat a = ctx->Transform._ClipUserPlane[p][0]; \
74          const GLfloat b = ctx->Transform._ClipUserPlane[p][1]; \
75          const GLfloat c = ctx->Transform._ClipUserPlane[p][2]; \
76          const GLfloat d = ctx->Transform._ClipUserPlane[p][3]; \
77          GLfloat *coord = (GLfloat *)clip->data;                \
78          GLuint stride = clip->stride;                          \
79          GLuint count = clip->count;                            \
80                                                                 \
81          for (nr = 0, i = 0 ; i < count ; i++) {                \
82             GLfloat dp = coord[0] * a + coord[1] * b;           \
83             if (SZ > 2) dp += coord[2] * c;                     \
84             if (SZ > 3) dp += coord[3] * d; else dp += d;       \
85                                                                 \
86             if (dp < 0) {                                       \
87                nr++;                                            \
88                clipmask[i] |= CLIP_USER_BIT;                    \
89             }                                                   \
90                                                                 \
91             STRIDE_F(coord, stride);                            \
92          }                                                      \
93                                                                 \
94          if (nr > 0) {                                          \
95             *clipormask |= CLIP_USER_BIT;                       \
96             if (nr == count) {                                  \
97                *clipandmask |= CLIP_USER_BIT;                   \
98                return;                                          \
99             }                                                   \
100          }                                                      \
101       }                                                         \
102 }
103
104
105 USER_CLIPTEST(userclip2, 2)
106 USER_CLIPTEST(userclip3, 3)
107 USER_CLIPTEST(userclip4, 4)
108
109 static void (*(usercliptab[5]))( GLcontext *,
110                                  GLvector4f *, GLubyte *,
111                                  GLubyte *, GLubyte * ) =
112 {
113    NULL,
114    NULL,
115    userclip2,
116    userclip3,
117    userclip4
118 };
119
120
121 void
122 tnl_clip_prepare(GLcontext *ctx)
123 {
124    /* Neither the x86 nor sparc asm cliptest functions have been updated
125     * for ARB_depth_clamp, so force the C paths.
126     */
127    if (ctx->Transform.DepthClamp) {
128       static GLboolean c_funcs_installed = GL_FALSE;
129       if (!c_funcs_installed) {
130          init_c_cliptest();
131          c_funcs_installed = GL_TRUE;
132       }
133    }
134 }
135
136
137
138 static GLboolean run_vertex_stage( GLcontext *ctx,
139                                    struct tnl_pipeline_stage *stage )
140 {
141    struct vertex_stage_data *store = (struct vertex_stage_data *)stage->privatePtr;
142    TNLcontext *tnl = TNL_CONTEXT(ctx);
143    struct vertex_buffer *VB = &tnl->vb;
144
145    if (ctx->VertexProgram._Current) 
146       return GL_TRUE;
147
148    tnl_clip_prepare(ctx);
149
150    if (ctx->_NeedEyeCoords) {
151       /* Separate modelview transformation:
152        * Use combined ModelProject to avoid some depth artifacts
153        */
154       if (ctx->ModelviewMatrixStack.Top->type == MATRIX_IDENTITY)
155          VB->EyePtr = VB->ObjPtr;
156       else
157          VB->EyePtr = TransformRaw( &store->eye,
158                                     ctx->ModelviewMatrixStack.Top,
159                                     VB->ObjPtr);
160    }
161
162    VB->ClipPtr = TransformRaw( &store->clip,
163                                &ctx->_ModelProjectMatrix,
164                                VB->ObjPtr );
165
166    /* Drivers expect this to be clean to element 4...
167     */
168    switch (VB->ClipPtr->size) {
169    case 1:                      
170       /* impossible */
171    case 2:
172       _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 );
173       /* fall-through */
174    case 3:
175       _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 );
176       /* fall-through */
177    case 4:
178       break;
179    }
180
181
182    /* Cliptest and perspective divide.  Clip functions must clear
183     * the clipmask.
184     */
185    store->ormask = 0;
186    store->andmask = CLIP_FRUSTUM_BITS;
187
188    if (tnl->NeedNdcCoords) {
189       VB->NdcPtr =
190          _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
191                                             &store->proj,
192                                             store->clipmask,
193                                             &store->ormask,
194                                             &store->andmask,
195                                             !ctx->Transform.DepthClamp );
196    }
197    else {
198       VB->NdcPtr = NULL;
199       _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,
200                                             NULL,
201                                             store->clipmask,
202                                             &store->ormask,
203                                             &store->andmask,
204                                             !ctx->Transform.DepthClamp );
205    }
206
207    if (store->andmask)
208       return GL_FALSE;
209
210
211    /* Test userclip planes.  This contributes to VB->ClipMask, so
212     * is essentially required to be in this stage.
213     */
214    if (ctx->Transform.ClipPlanesEnabled) {
215       usercliptab[VB->ClipPtr->size]( ctx,
216                                       VB->ClipPtr,
217                                       store->clipmask,
218                                       &store->ormask,
219                                       &store->andmask );
220
221       if (store->andmask)
222          return GL_FALSE;
223    }
224
225    VB->ClipAndMask = store->andmask;
226    VB->ClipOrMask = store->ormask;
227    VB->ClipMask = store->clipmask;
228
229    return GL_TRUE;
230 }
231
232
233 static GLboolean init_vertex_stage( GLcontext *ctx,
234                                     struct tnl_pipeline_stage *stage )
235 {
236    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
237    struct vertex_stage_data *store;
238    GLuint size = VB->Size;
239
240    stage->privatePtr = CALLOC(sizeof(*store));
241    store = VERTEX_STAGE_DATA(stage);
242    if (!store)
243       return GL_FALSE;
244
245    _mesa_vector4f_alloc( &store->eye, 0, size, 32 );
246    _mesa_vector4f_alloc( &store->clip, 0, size, 32 );
247    _mesa_vector4f_alloc( &store->proj, 0, size, 32 );
248
249    store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
250
251    if (!store->clipmask ||
252        !store->eye.data ||
253        !store->clip.data ||
254        !store->proj.data)
255       return GL_FALSE;
256
257    return GL_TRUE;
258 }
259
260 static void dtr( struct tnl_pipeline_stage *stage )
261 {
262    struct vertex_stage_data *store = VERTEX_STAGE_DATA(stage);
263
264    if (store) {
265       _mesa_vector4f_free( &store->eye );
266       _mesa_vector4f_free( &store->clip );
267       _mesa_vector4f_free( &store->proj );
268       ALIGN_FREE( store->clipmask );
269       FREE(store);
270       stage->privatePtr = NULL;
271       stage->run = init_vertex_stage;
272    }
273 }
274
275
276 const struct tnl_pipeline_stage _tnl_vertex_transform_stage =
277 {
278    "modelview/project/cliptest/divide",
279    NULL,                        /* private data */
280    init_vertex_stage,
281    dtr,                         /* destructor */
282    NULL,
283    run_vertex_stage             /* run -- initially set to init */
284 };