1 /**************************************************************************
3 Copyright 2004 Tungsten Graphics Inc., Cedar Park, Texas.
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:
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
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.
26 **************************************************************************/
30 * Keith Whitwell <keith@tungstengraphics.com>
31 * Daniel Borca <dborca@yahoo.com>
42 #include "api_arrayelt.h"
44 #include "t_vtx_api.h"
45 #include "simple_list.h"
48 #if defined(USE_X86_ASM) && !defined(HAVE_NONSTANDARD_GLAPIENTRY)
50 #define EXTERN( FUNC ) \
51 extern const char FUNC[]; \
52 extern const char FUNC##_end[]
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
);
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
);
79 EXTERN( _tnl_x86_choose_fv
);
82 #define DONT_KNOW_OFFSETS 1
85 #define DFN( FUNC, CACHE, KEY ) \
86 struct _tnl_dynfn *dfn = MALLOC_STRUCT( _tnl_dynfn );\
87 const char *start = FUNC; \
88 const char *end = FUNC##_end; \
90 insert_at_head( &CACHE, dfn ); \
92 dfn->code = ALIGN_MALLOC( end - start, 16 ); \
93 memcpy (dfn->code, start, end - start)
97 #define FIXUP( CODE, KNOWN_OFFSET, CHECKVAL, NEWVAL ) \
99 GLint subst = 0x10101010 + CHECKVAL; \
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)); \
108 int *icode = (int *)(CODE+KNOWN_OFFSET); \
109 assert (*icode == subst); \
110 *icode = (int)NEWVAL; \
116 #define FIXUPREL( CODE, KNOWN_OFFSET, CHECKVAL, NEWVAL )\
118 GLint subst = 0x10101010 + CHECKVAL; \
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); \
127 int *icode = (int *)(CODE+KNOWN_OFFSET); \
128 assert (*icode == subst); \
129 *icode = (int)(NEWVAL) - (int)(icode) - 4; \
136 /* Build specialized versions of the immediate calls on the fly for
137 * the current state. Generic x86 versions.
140 static struct _tnl_dynfn
*makeX86Vertex1fv( GLcontext
*ctx
, int vertex_size
)
142 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
143 DFN ( _tnl_x86_Vertex1fv
, tnl
->vtx
.cache
.Vertex
[1-1], vertex_size
);
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
);
157 static struct _tnl_dynfn
*makeX86Vertex2fv( GLcontext
*ctx
, int vertex_size
)
159 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
160 DFN ( _tnl_x86_Vertex2fv
, tnl
->vtx
.cache
.Vertex
[2-1], vertex_size
);
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
);
174 static struct _tnl_dynfn
*makeX86Vertex3fv( GLcontext
*ctx
, int vertex_size
)
176 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
178 switch (vertex_size
) {
180 DFN ( _tnl_x86_Vertex3fv
, tnl
->vtx
.cache
.Vertex
[3-1], vertex_size
);
182 FIXUP(dfn
->code
, 0, 0, (int)&tnl
->vtx
.vbptr
);
183 FIXUP(dfn
->code
, 0, 1, vertex_size
- 3);
184 FIXUP(dfn
->code
, 0, 2, (int)&tnl
->vtx
.vertex
[3]);
185 FIXUP(dfn
->code
, 0, 0, (int)&tnl
->vtx
.vbptr
);
186 FIXUP(dfn
->code
, 0, 3, (int)&tnl
->vtx
.counter
);
187 FIXUP(dfn
->code
, 0, 3, (int)&tnl
->vtx
.counter
);
188 FIXUP(dfn
->code
, 0, 4, (int)ctx
);
189 FIXUPREL(dfn
->code
, 0, 5, (int)&_tnl_wrap_filled_vertex
);
195 static struct _tnl_dynfn
*makeX86Vertex4fv( GLcontext
*ctx
, int vertex_size
)
197 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
198 DFN ( _tnl_x86_Vertex4fv
, tnl
->vtx
.cache
.Vertex
[4-1], vertex_size
);
200 FIXUP(dfn
->code
, 0, 0, (int)&tnl
->vtx
.vbptr
);
201 FIXUP(dfn
->code
, 0, 1, vertex_size
- 4);
202 FIXUP(dfn
->code
, 0, 2, (int)&tnl
->vtx
.vertex
[4]);
203 FIXUP(dfn
->code
, 0, 0, (int)&tnl
->vtx
.vbptr
);
204 FIXUP(dfn
->code
, 0, 3, (int)&tnl
->vtx
.counter
);
205 FIXUP(dfn
->code
, 0, 3, (int)&tnl
->vtx
.counter
);
206 FIXUP(dfn
->code
, 0, 4, (int)ctx
);
207 FIXUPREL(dfn
->code
, 0, 5, (int)&_tnl_wrap_filled_vertex
);
213 static struct _tnl_dynfn
*makeX86Attribute1fv( GLcontext
*ctx
, int dest
)
215 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
216 DFN ( _tnl_x86_Attribute1fv
, tnl
->vtx
.cache
.Attribute
[1-1], dest
);
218 FIXUP(dfn
->code
, 0, 0, dest
);
223 static struct _tnl_dynfn
*makeX86Attribute2fv( GLcontext
*ctx
, int dest
)
225 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
226 DFN ( _tnl_x86_Attribute2fv
, tnl
->vtx
.cache
.Attribute
[2-1], dest
);
228 FIXUP(dfn
->code
, 0, 0, dest
);
229 FIXUP(dfn
->code
, 0, 1, 4+dest
);
234 static struct _tnl_dynfn
*makeX86Attribute3fv( GLcontext
*ctx
, int dest
)
236 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
237 DFN ( _tnl_x86_Attribute3fv
, tnl
->vtx
.cache
.Attribute
[3-1], dest
);
239 FIXUP(dfn
->code
, 0, 0, dest
);
240 FIXUP(dfn
->code
, 0, 1, 4+dest
);
241 FIXUP(dfn
->code
, 0, 2, 8+dest
);
246 static struct _tnl_dynfn
*makeX86Attribute4fv( GLcontext
*ctx
, int dest
)
248 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
249 DFN ( _tnl_x86_Attribute4fv
, tnl
->vtx
.cache
.Attribute
[4-1], dest
);
251 FIXUP(dfn
->code
, 0, 0, dest
);
252 FIXUP(dfn
->code
, 0, 1, 4+dest
);
253 FIXUP(dfn
->code
, 0, 2, 8+dest
);
254 FIXUP(dfn
->code
, 0, 3, 12+dest
);
260 void _tnl_InitX86Codegen( struct _tnl_dynfn_generators
*gen
)
262 gen
->Vertex
[0] = makeX86Vertex1fv
;
263 gen
->Vertex
[1] = makeX86Vertex2fv
;
264 gen
->Vertex
[2] = makeX86Vertex3fv
;
265 gen
->Vertex
[3] = makeX86Vertex4fv
;
266 gen
->Attribute
[0] = makeX86Attribute1fv
;
267 gen
->Attribute
[1] = makeX86Attribute2fv
;
268 gen
->Attribute
[2] = makeX86Attribute3fv
;
269 gen
->Attribute
[3] = makeX86Attribute4fv
;
273 #define MKDISP(FUNC, SIZE, ATTR, WARP) \
276 const char *start = WARP; \
277 const char *end = WARP##_end; \
279 code = ALIGN_MALLOC( end - start, 16 ); \
280 memcpy (code, start, end - start); \
281 FIXUP(code, 0, 0, (int)&(TNL_CONTEXT(ctx)->vtx.tabfv[ATTR][SIZE-1]));\
282 *(void **)&vfmt->FUNC = code; \
286 /* Install the codegen'ed versions of the 2nd level dispatch
287 * functions. We should keep a list and free them in the end...
289 void _tnl_x86_exec_vtxfmt_init( GLcontext
*ctx
)
291 GLvertexformat
*vfmt
= &(TNL_CONTEXT(ctx
)->exec_vtxfmt
);
293 MKDISP(Color3f
, 3, _TNL_ATTRIB_COLOR0
, _tnl_x86_dispatch_attrf3
);
294 MKDISP(Color3fv
, 3, _TNL_ATTRIB_COLOR0
, _tnl_x86_dispatch_attrfv
);
295 MKDISP(Color4f
, 4, _TNL_ATTRIB_COLOR0
, _tnl_x86_dispatch_attrf4
);
296 MKDISP(Color4fv
, 4, _TNL_ATTRIB_COLOR0
, _tnl_x86_dispatch_attrfv
);
297 MKDISP(FogCoordfEXT
, 1, _TNL_ATTRIB_FOG
, _tnl_x86_dispatch_attrf1
);
298 MKDISP(FogCoordfvEXT
, 1, _TNL_ATTRIB_FOG
, _tnl_x86_dispatch_attrfv
);
299 MKDISP(Normal3f
, 3, _TNL_ATTRIB_NORMAL
, _tnl_x86_dispatch_attrf3
);
300 MKDISP(Normal3fv
, 3, _TNL_ATTRIB_NORMAL
, _tnl_x86_dispatch_attrfv
);
301 MKDISP(SecondaryColor3fEXT
, 3, _TNL_ATTRIB_COLOR1
, _tnl_x86_dispatch_attrf3
);
302 MKDISP(SecondaryColor3fvEXT
,3, _TNL_ATTRIB_COLOR1
, _tnl_x86_dispatch_attrfv
);
303 MKDISP(TexCoord1f
, 1, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_attrf1
);
304 MKDISP(TexCoord1fv
, 1, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_attrfv
);
305 MKDISP(TexCoord2f
, 2, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_attrf2
);
306 MKDISP(TexCoord2fv
, 2, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_attrfv
);
307 MKDISP(TexCoord3f
, 3, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_attrf3
);
308 MKDISP(TexCoord3fv
, 3, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_attrfv
);
309 MKDISP(TexCoord4f
, 4, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_attrf4
);
310 MKDISP(TexCoord4fv
, 4, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_attrfv
);
311 MKDISP(Vertex2f
, 2, _TNL_ATTRIB_POS
, _tnl_x86_dispatch_attrf2
);
312 MKDISP(Vertex2fv
, 2, _TNL_ATTRIB_POS
, _tnl_x86_dispatch_attrfv
);
313 MKDISP(Vertex3f
, 3, _TNL_ATTRIB_POS
, _tnl_x86_dispatch_attrf3
);
314 MKDISP(Vertex3fv
, 3, _TNL_ATTRIB_POS
, _tnl_x86_dispatch_attrfv
);
315 MKDISP(Vertex4f
, 4, _TNL_ATTRIB_POS
, _tnl_x86_dispatch_attrf4
);
316 MKDISP(Vertex4fv
, 4, _TNL_ATTRIB_POS
, _tnl_x86_dispatch_attrfv
);
318 MKDISP(MultiTexCoord1fARB
, 1, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_multitexcoordf1
);
319 MKDISP(MultiTexCoord1fvARB
, 1, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_multitexcoordfv
);
320 MKDISP(MultiTexCoord2fARB
, 2, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_multitexcoordf2
);
321 MKDISP(MultiTexCoord2fvARB
, 2, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_multitexcoordfv
);
322 MKDISP(MultiTexCoord3fARB
, 3, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_multitexcoordf3
);
323 MKDISP(MultiTexCoord3fvARB
, 3, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_multitexcoordfv
);
324 MKDISP(MultiTexCoord4fARB
, 4, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_multitexcoordf4
);
325 MKDISP(MultiTexCoord4fvARB
, 4, _TNL_ATTRIB_TEX0
, _tnl_x86_dispatch_multitexcoordfv
);
327 MKDISP(VertexAttrib1fNV
, 1, 0, _tnl_x86_dispatch_vertexattribf1
);
328 MKDISP(VertexAttrib1fvNV
, 1, 0, _tnl_x86_dispatch_vertexattribfv
);
329 MKDISP(VertexAttrib2fNV
, 2, 0, _tnl_x86_dispatch_vertexattribf2
);
330 MKDISP(VertexAttrib2fvNV
, 2, 0, _tnl_x86_dispatch_vertexattribfv
);
331 MKDISP(VertexAttrib3fNV
, 3, 0, _tnl_x86_dispatch_vertexattribf3
);
332 MKDISP(VertexAttrib3fvNV
, 3, 0, _tnl_x86_dispatch_vertexattribfv
);
333 MKDISP(VertexAttrib4fNV
, 4, 0, _tnl_x86_dispatch_vertexattribf4
);
334 MKDISP(VertexAttrib4fvNV
, 4, 0, _tnl_x86_dispatch_vertexattribfv
);
338 /* Install the codegen'ed choosers.
339 * We should keep a list and free them in the end...
341 void _tnl_x86choosers( tnl_attrfv_func (*choose
)[4],
342 tnl_attrfv_func (*do_choose
)( GLuint attr
,
347 for (attr
= 0; attr
< _TNL_MAX_ATTR_CODEGEN
; attr
++) {
348 for (size
= 0; size
< 4; size
++) {
350 const char *start
= _tnl_x86_choose_fv
;
351 const char *end
= _tnl_x86_choose_fv_end
;
353 code
= ALIGN_MALLOC( end
- start
, 16 );
354 memcpy (code
, start
, end
- start
);
355 FIXUP(code
, 0, 0, attr
);
356 FIXUP(code
, 0, 1, size
+ 1);
357 FIXUPREL(code
, 0, 2, do_choose
);
358 choose
[attr
][size
] = (tnl_attrfv_func
)code
;
365 void _tnl_InitX86Codegen( struct _tnl_dynfn_generators
*gen
)
371 void _tnl_x86_exec_vtxfmt_init( GLcontext
*ctx
)
377 void _tnl_x86choosers( tnl_attrfv_func (*choose
)[4],
378 tnl_attrfv_func (*do_choose
)( GLuint attr
,