don't use __FUNCTION__ - not portable
[mesa.git] / src / mesa / tnl / t_vtx_x86.c
1 /**************************************************************************
2
3 Copyright 2004 Tungsten Graphics Inc., Cedar Park, Texas.
4
5 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 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
16 Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Keith Whitwell <keith@tungstengraphics.com>
31 * Daniel Borca <dborca@yahoo.com>
32 */
33
34
35 #include "glheader.h"
36 #include "context.h"
37 #include "macros.h"
38 #include "vtxfmt.h"
39 #include "dlist.h"
40 #include "state.h"
41 #include "light.h"
42 #include "api_arrayelt.h"
43 #include "api_noop.h"
44 #include "t_vtx_api.h"
45 #include "simple_list.h"
46
47
48 #if defined(USE_X86_ASM) && !defined(HAVE_NONSTANDARD_GLAPIENTRY)
49
50 #define EXTERN( FUNC ) \
51 extern const char *FUNC; \
52 extern const char *FUNC##_end
53
54 EXTERN( _tnl_x86_Attribute1fv );
55 EXTERN( _tnl_x86_Attribute2fv );
56 EXTERN( _tnl_x86_Attribute3fv );
57 EXTERN( _tnl_x86_Attribute4fv );
58 EXTERN( _tnl_x86_Vertex1fv );
59 EXTERN( _tnl_x86_Vertex2fv );
60 EXTERN( _tnl_x86_Vertex3fv );
61 EXTERN( _tnl_x86_Vertex4fv );
62
63 EXTERN( _tnl_x86_dispatch_attrf1 );
64 EXTERN( _tnl_x86_dispatch_attrf2 );
65 EXTERN( _tnl_x86_dispatch_attrf3 );
66 EXTERN( _tnl_x86_dispatch_attrf4 );
67 EXTERN( _tnl_x86_dispatch_attrfv );
68 EXTERN( _tnl_x86_dispatch_multitexcoordf1 );
69 EXTERN( _tnl_x86_dispatch_multitexcoordf2 );
70 EXTERN( _tnl_x86_dispatch_multitexcoordf3 );
71 EXTERN( _tnl_x86_dispatch_multitexcoordf4 );
72 EXTERN( _tnl_x86_dispatch_multitexcoordfv );
73 EXTERN( _tnl_x86_dispatch_vertexattribf1 );
74 EXTERN( _tnl_x86_dispatch_vertexattribf2 );
75 EXTERN( _tnl_x86_dispatch_vertexattribf3 );
76 EXTERN( _tnl_x86_dispatch_vertexattribf4 );
77 EXTERN( _tnl_x86_dispatch_vertexattribfv );
78
79 EXTERN( _tnl_x86_choose_fv );
80
81
82 #define DONT_KNOW_OFFSETS 1
83
84
85 #define DFN( FUNC, CACHE, KEY ) \
86 struct _tnl_dynfn *dfn = MALLOC_STRUCT( _tnl_dynfn );\
87 char *start = (char *)&FUNC; \
88 char *end = (char *)&FUNC##_end; \
89 int offset = 0; \
90 insert_at_head( &CACHE, dfn ); \
91 dfn->key = KEY; \
92 dfn->code = ALIGN_MALLOC( end - start, 16 ); \
93 memcpy (dfn->code, start, end - start)
94
95
96
97 #define FIXUP( CODE, KNOWN_OFFSET, CHECKVAL, NEWVAL ) \
98 do { \
99 GLint subst = 0x10101010 + CHECKVAL; \
100 \
101 if (DONT_KNOW_OFFSETS) { \
102 while (*(int *)(CODE+offset) != subst) offset++; \
103 *(int *)(CODE+offset) = (int)(NEWVAL); \
104 if (0) fprintf(stderr, "%s/%d: offset %d, new value: 0x%x\n", __FILE__, __LINE__, offset, (int)(NEWVAL)); \
105 offset += 4; \
106 } \
107 else { \
108 int *icode = (int *)(CODE+KNOWN_OFFSET); \
109 assert (*icode == subst); \
110 *icode = (int)NEWVAL; \
111 } \
112 } while (0)
113
114
115
116 #define FIXUPREL( CODE, KNOWN_OFFSET, CHECKVAL, NEWVAL )\
117 do { \
118 GLint subst = 0x10101010 + CHECKVAL; \
119 \
120 if (DONT_KNOW_OFFSETS) { \
121 while (*(int *)(CODE+offset) != subst) offset++; \
122 *(int *)(CODE+offset) = (int)(NEWVAL) - ((int)(CODE)+offset) - 4; \
123 if (0) fprintf(stderr, "%s/%d: offset %d, new value: 0x%x\n", __FILE__, __LINE__, offset, (int)(NEWVAL) - ((int)(CODE)+offset) - 4); \
124 offset += 4; \
125 } \
126 else { \
127 int *icode = (int *)(CODE+KNOWN_OFFSET); \
128 assert (*icode == subst); \
129 *icode = (int)(NEWVAL) - (int)(icode) - 4; \
130 } \
131 } while (0)
132
133
134
135
136 /* Build specialized versions of the immediate calls on the fly for
137 * the current state. Generic x86 versions.
138 */
139
140 static struct _tnl_dynfn *makeX86Vertex1fv( GLcontext *ctx, int vertex_size )
141 {
142 TNLcontext *tnl = TNL_CONTEXT(ctx);
143 DFN ( _tnl_x86_Vertex1fv, tnl->vtx.cache.Vertex[1-1], vertex_size );
144
145 FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
146 FIXUP(dfn->code, 0, 1, vertex_size - 1);
147 FIXUP(dfn->code, 0, 2, (int)&tnl->vtx.vertex[1]);
148 FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
149 FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
150 FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
151 FIXUP(dfn->code, 0, 4, (int)ctx);
152 FIXUPREL(dfn->code, 0, 5, (int)&_tnl_wrap_filled_vertex);
153
154 return dfn;
155 }
156
157 static struct _tnl_dynfn *makeX86Vertex2fv( GLcontext *ctx, int vertex_size )
158 {
159 TNLcontext *tnl = TNL_CONTEXT(ctx);
160 DFN ( _tnl_x86_Vertex2fv, tnl->vtx.cache.Vertex[2-1], vertex_size );
161
162 FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
163 FIXUP(dfn->code, 0, 1, vertex_size - 2);
164 FIXUP(dfn->code, 0, 2, (int)&tnl->vtx.vertex[2]);
165 FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
166 FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
167 FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
168 FIXUP(dfn->code, 0, 4, (int)ctx);
169 FIXUPREL(dfn->code, 0, 5, (int)&_tnl_wrap_filled_vertex);
170
171 return dfn;
172 }
173
174 static struct _tnl_dynfn *makeX86Vertex3fv( GLcontext *ctx, int vertex_size )
175 {
176 TNLcontext *tnl = TNL_CONTEXT(ctx);
177 DFN ( _tnl_x86_Vertex3fv, tnl->vtx.cache.Vertex[3-1], vertex_size );
178
179 switch (vertex_size) {
180 default: {
181 FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
182 FIXUP(dfn->code, 0, 1, vertex_size - 3);
183 FIXUP(dfn->code, 0, 2, (int)&tnl->vtx.vertex[3]);
184 FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
185 FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
186 FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
187 FIXUP(dfn->code, 0, 4, (int)ctx);
188 FIXUPREL(dfn->code, 0, 5, (int)&_tnl_wrap_filled_vertex);
189 return dfn;
190 }
191 }
192 }
193
194 static struct _tnl_dynfn *makeX86Vertex4fv( GLcontext *ctx, int vertex_size )
195 {
196 TNLcontext *tnl = TNL_CONTEXT(ctx);
197 DFN ( _tnl_x86_Vertex4fv, tnl->vtx.cache.Vertex[4-1], vertex_size );
198
199 FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
200 FIXUP(dfn->code, 0, 1, vertex_size - 4);
201 FIXUP(dfn->code, 0, 2, (int)&tnl->vtx.vertex[4]);
202 FIXUP(dfn->code, 0, 0, (int)&tnl->vtx.vbptr);
203 FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
204 FIXUP(dfn->code, 0, 3, (int)&tnl->vtx.counter);
205 FIXUP(dfn->code, 0, 4, (int)ctx);
206 FIXUPREL(dfn->code, 0, 5, (int)&_tnl_wrap_filled_vertex);
207
208 return dfn;
209 }
210
211
212 static struct _tnl_dynfn *makeX86Attribute1fv( GLcontext *ctx, int dest )
213 {
214 TNLcontext *tnl = TNL_CONTEXT(ctx);
215 DFN ( _tnl_x86_Attribute1fv, tnl->vtx.cache.Attribute[1-1], dest );
216
217 FIXUP(dfn->code, 0, 0, dest);
218
219 return dfn;
220 }
221
222 static struct _tnl_dynfn *makeX86Attribute2fv( GLcontext *ctx, int dest )
223 {
224 TNLcontext *tnl = TNL_CONTEXT(ctx);
225 DFN ( _tnl_x86_Attribute2fv, tnl->vtx.cache.Attribute[2-1], dest );
226
227 FIXUP(dfn->code, 0, 0, dest);
228 FIXUP(dfn->code, 0, 1, 4+dest);
229
230 return dfn;
231 }
232
233 static struct _tnl_dynfn *makeX86Attribute3fv( GLcontext *ctx, int dest )
234 {
235 TNLcontext *tnl = TNL_CONTEXT(ctx);
236 DFN ( _tnl_x86_Attribute3fv, tnl->vtx.cache.Attribute[3-1], dest );
237
238 FIXUP(dfn->code, 0, 0, dest);
239 FIXUP(dfn->code, 0, 1, 4+dest);
240 FIXUP(dfn->code, 0, 2, 8+dest);
241
242 return dfn;
243 }
244
245 static struct _tnl_dynfn *makeX86Attribute4fv( GLcontext *ctx, int dest )
246 {
247 TNLcontext *tnl = TNL_CONTEXT(ctx);
248 DFN ( _tnl_x86_Attribute4fv, tnl->vtx.cache.Attribute[4-1], dest );
249
250 FIXUP(dfn->code, 0, 0, dest);
251 FIXUP(dfn->code, 0, 1, 4+dest);
252 FIXUP(dfn->code, 0, 2, 8+dest);
253 FIXUP(dfn->code, 0, 3, 12+dest);
254
255 return dfn;
256 }
257
258
259 void _tnl_InitX86Codegen( struct _tnl_dynfn_generators *gen )
260 {
261 gen->Vertex[0] = makeX86Vertex1fv;
262 gen->Vertex[1] = makeX86Vertex2fv;
263 gen->Vertex[2] = makeX86Vertex3fv;
264 gen->Vertex[3] = makeX86Vertex4fv;
265 gen->Attribute[0] = makeX86Attribute1fv;
266 gen->Attribute[1] = makeX86Attribute2fv;
267 gen->Attribute[2] = makeX86Attribute3fv;
268 gen->Attribute[3] = makeX86Attribute4fv;
269 }
270
271
272 #define MKDISP(FUNC, SIZE, ATTR, WARP) \
273 do { \
274 char *code; \
275 char *start = (char *)&WARP; \
276 char *end = (char *)&WARP##_end; \
277 int offset = 0; \
278 code = ALIGN_MALLOC( end - start, 16 ); \
279 memcpy (code, start, end - start); \
280 FIXUP(code, 0, 0, (int)&(TNL_CONTEXT(ctx)->vtx.tabfv[ATTR][SIZE-1]));\
281 *(void **)&vfmt->FUNC = code; \
282 } while (0)
283
284
285 /* Install the codegen'ed versions of the 2nd level dispatch
286 * functions. We should keep a list and free them in the end...
287 */
288 void _tnl_x86_exec_vtxfmt_init( GLcontext *ctx )
289 {
290 GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->exec_vtxfmt);
291
292 MKDISP(Color3f, 3, _TNL_ATTRIB_COLOR0, _tnl_x86_dispatch_attrf3);
293 MKDISP(Color3fv, 3, _TNL_ATTRIB_COLOR0, _tnl_x86_dispatch_attrfv);
294 MKDISP(Color4f, 4, _TNL_ATTRIB_COLOR0, _tnl_x86_dispatch_attrf4);
295 MKDISP(Color4fv, 4, _TNL_ATTRIB_COLOR0, _tnl_x86_dispatch_attrfv);
296 MKDISP(FogCoordfEXT, 1, _TNL_ATTRIB_FOG, _tnl_x86_dispatch_attrf1);
297 MKDISP(FogCoordfvEXT, 1, _TNL_ATTRIB_FOG, _tnl_x86_dispatch_attrfv);
298 MKDISP(Normal3f, 3, _TNL_ATTRIB_NORMAL, _tnl_x86_dispatch_attrf3);
299 MKDISP(Normal3fv, 3, _TNL_ATTRIB_NORMAL, _tnl_x86_dispatch_attrfv);
300 MKDISP(SecondaryColor3fEXT, 3, _TNL_ATTRIB_COLOR1, _tnl_x86_dispatch_attrf3);
301 MKDISP(SecondaryColor3fvEXT,3, _TNL_ATTRIB_COLOR1, _tnl_x86_dispatch_attrfv);
302 MKDISP(TexCoord1f, 1, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_attrf1);
303 MKDISP(TexCoord1fv, 1, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_attrfv);
304 MKDISP(TexCoord2f, 2, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_attrf2);
305 MKDISP(TexCoord2fv, 2, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_attrfv);
306 MKDISP(TexCoord3f, 3, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_attrf3);
307 MKDISP(TexCoord3fv, 3, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_attrfv);
308 MKDISP(TexCoord4f, 4, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_attrf4);
309 MKDISP(TexCoord4fv, 4, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_attrfv);
310 MKDISP(Vertex2f, 2, _TNL_ATTRIB_POS, _tnl_x86_dispatch_attrf2);
311 MKDISP(Vertex2fv, 2, _TNL_ATTRIB_POS, _tnl_x86_dispatch_attrfv);
312 MKDISP(Vertex3f, 3, _TNL_ATTRIB_POS, _tnl_x86_dispatch_attrf3);
313 MKDISP(Vertex3fv, 3, _TNL_ATTRIB_POS, _tnl_x86_dispatch_attrfv);
314 MKDISP(Vertex4f, 4, _TNL_ATTRIB_POS, _tnl_x86_dispatch_attrf4);
315 MKDISP(Vertex4fv, 4, _TNL_ATTRIB_POS, _tnl_x86_dispatch_attrfv);
316
317 MKDISP(MultiTexCoord1fARB, 1, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_multitexcoordf1);
318 MKDISP(MultiTexCoord1fvARB, 1, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_multitexcoordfv);
319 MKDISP(MultiTexCoord2fARB, 2, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_multitexcoordf2);
320 MKDISP(MultiTexCoord2fvARB, 2, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_multitexcoordfv);
321 MKDISP(MultiTexCoord3fARB, 3, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_multitexcoordf3);
322 MKDISP(MultiTexCoord3fvARB, 3, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_multitexcoordfv);
323 MKDISP(MultiTexCoord4fARB, 4, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_multitexcoordf4);
324 MKDISP(MultiTexCoord4fvARB, 4, _TNL_ATTRIB_TEX0, _tnl_x86_dispatch_multitexcoordfv);
325
326 MKDISP(VertexAttrib1fNV, 1, 0, _tnl_x86_dispatch_vertexattribf1);
327 MKDISP(VertexAttrib1fvNV, 1, 0, _tnl_x86_dispatch_vertexattribfv);
328 MKDISP(VertexAttrib2fNV, 2, 0, _tnl_x86_dispatch_vertexattribf2);
329 MKDISP(VertexAttrib2fvNV, 2, 0, _tnl_x86_dispatch_vertexattribfv);
330 MKDISP(VertexAttrib3fNV, 3, 0, _tnl_x86_dispatch_vertexattribf3);
331 MKDISP(VertexAttrib3fvNV, 3, 0, _tnl_x86_dispatch_vertexattribfv);
332 MKDISP(VertexAttrib4fNV, 4, 0, _tnl_x86_dispatch_vertexattribf4);
333 MKDISP(VertexAttrib4fvNV, 4, 0, _tnl_x86_dispatch_vertexattribfv);
334 }
335
336
337 /* Install the codegen'ed choosers.
338 * We should keep a list and free them in the end...
339 */
340 void _tnl_x86choosers( tnl_attrfv_func (*choose)[4],
341 tnl_attrfv_func (*do_choose)( GLuint attr,
342 GLuint sz ))
343 {
344 int attr, size;
345
346 for (attr = 0; attr < _TNL_MAX_ATTR_CODEGEN; attr++) {
347 for (size = 0; size < 4; size++) {
348 char *code;
349 char *start = (char *)&_tnl_x86_choose_fv;
350 char *end = (char *)&_tnl_x86_choose_fv_end;
351 int offset = 0;
352 code = ALIGN_MALLOC( end - start, 16 );
353 memcpy (code, start, end - start);
354 FIXUP(code, 0, 0, attr);
355 FIXUP(code, 0, 1, size + 1);
356 FIXUPREL(code, 0, 2, do_choose);
357 choose[attr][size] = (tnl_attrfv_func)code;
358 }
359 }
360 }
361
362 #else
363
364 void _tnl_InitX86Codegen( struct _tnl_dynfn_generators *gen )
365 {
366 (void) gen;
367 }
368
369
370 void _tnl_x86_exec_vtxfmt_init( GLcontext *ctx )
371 {
372 (void) ctx;
373 }
374
375
376 void _tnl_x86choosers( tnl_attrfv_func (*choose)[4],
377 tnl_attrfv_func (*do_choose)( GLuint attr,
378 GLuint sz ))
379 {
380 (void) choose;
381 (void) do_choose;
382 }
383
384 #endif