new X86 CPU detection code (Petr Sebor)
[mesa.git] / src / mesa / main / imports.c
1 /* $Id: imports.c,v 1.30 2003/01/19 15:27:38 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 5.1
6 *
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 /*
29 * Imports are services which the device driver or window system or
30 * operating system provides to the core renderer. The core renderer (Mesa)
31 * will call these functions in order to do memory allocation, simple I/O,
32 * etc.
33 *
34 * Some drivers will want to override/replace this file with something
35 * specialized, but that'll be rare.
36 *
37 * Eventually, I want to move roll the glheader.h file into this.
38 *
39 * The OpenGL SI's __GLimports structure allows per-context specification of
40 * replacements for the standard C lib functions. In practice that's probably
41 * never needed; compile-time replacements are far more likely.
42 *
43 * The _mesa_foo() functions defined here don't in general take a context
44 * parameter. I guess we can change that someday, if need be.
45 * So for now, the __GLimports stuff really isn't used.
46 */
47
48
49 #include "glheader.h"
50 #include "mtypes.h"
51 #include "context.h"
52 #include "imports.h"
53
54
55 #define MAXSTRING 4000 /* for vsnprintf() */
56
57 #ifdef WIN32
58 #define vsnprintf _vsnprintf
59 #elif defined(__IBMC__) || defined(__IBMCPP__) || defined(VMS)
60 extern int vsnprintf(char *str, size_t count, const char *fmt, va_list arg);
61 #endif
62
63
64 /**********************************************************************/
65 /* Wrappers for standard C library functions */
66 /**********************************************************************/
67
68 /*
69 * Functions still needed:
70 * scanf
71 * qsort
72 * bsearch
73 * rand and RAND_MAX
74 */
75
76 void *
77 _mesa_malloc(size_t bytes)
78 {
79 #if defined(XFree86LOADER) && defined(IN_MODULE)
80 return xf86malloc(bytes);
81 #else
82 return malloc(bytes);
83 #endif
84 }
85
86
87 void *
88 _mesa_calloc(size_t bytes)
89 {
90 #if defined(XFree86LOADER) && defined(IN_MODULE)
91 return xf86calloc(1, bytes);
92 #else
93 return calloc(1, bytes);
94 #endif
95 }
96
97
98 void
99 _mesa_free(void *ptr)
100 {
101 #if defined(XFree86LOADER) && defined(IN_MODULE)
102 xf86free(ptr);
103 #else
104 free(ptr);
105 #endif
106 }
107
108
109 void *
110 _mesa_align_malloc(size_t bytes, unsigned long alignment)
111 {
112 unsigned long ptr, buf;
113
114 ASSERT( alignment > 0 );
115
116 /* Allocate extra memory to accomodate rounding up the address for
117 * alignment and to record the real malloc address.
118 */
119 ptr = (unsigned long) _mesa_malloc(bytes + alignment + sizeof(void *));
120 if (!ptr)
121 return NULL;
122
123 buf = (ptr + alignment + sizeof(void *)) & ~(unsigned long)(alignment - 1);
124 *(unsigned long *)(buf - sizeof(void *)) = ptr;
125
126 #ifdef DEBUG
127 /* mark the non-aligned area */
128 while ( ptr < buf - sizeof(void *) ) {
129 *(unsigned long *)ptr = 0xcdcdcdcd;
130 ptr += sizeof(unsigned long);
131 }
132 #endif
133
134 return (void *) buf;
135 }
136
137
138 void *
139 _mesa_align_calloc(size_t bytes, unsigned long alignment)
140 {
141 unsigned long ptr, buf;
142
143 ASSERT( alignment > 0 );
144
145 ptr = (unsigned long) _mesa_calloc(bytes + alignment + sizeof(void *));
146 if (!ptr)
147 return NULL;
148
149 buf = (ptr + alignment + sizeof(void *)) & ~(unsigned long)(alignment - 1);
150 *(unsigned long *)(buf - sizeof(void *)) = ptr;
151
152 #ifdef DEBUG
153 /* mark the non-aligned area */
154 while ( ptr < buf - sizeof(void *) ) {
155 *(unsigned long *)ptr = 0xcdcdcdcd;
156 ptr += sizeof(unsigned long);
157 }
158 #endif
159
160 return (void *)buf;
161 }
162
163
164 void
165 _mesa_align_free(void *ptr)
166 {
167 #if 0
168 _mesa_free( (void *)(*(unsigned long *)((unsigned long)ptr - sizeof(void *))) );
169 #else
170 /* The actuall address to free is stuffed in the word immediately
171 * before the address the client sees.
172 */
173 void **cubbyHole = (void **) ((char *) ptr - sizeof(void *));
174 void *realAddr = *cubbyHole;
175 _mesa_free(realAddr);
176 #endif
177 }
178
179
180 void *
181 _mesa_memcpy(void *dest, const void *src, size_t n)
182 {
183 #if defined(XFree86LOADER) && defined(IN_MODULE)
184 return xf86memcpy(dest, src, n);
185 #elif defined(SUNOS4)
186 return memcpy((char *) dest, (char *) src, (int) n);
187 #else
188 return memcpy(dest, src, n);
189 #endif
190 }
191
192
193 void
194 _mesa_memset( void *dst, int val, size_t n )
195 {
196 #if defined(XFree86LOADER) && defined(IN_MODULE)
197 xf86memset( dst, val, n );
198 #elif defined(SUNOS4)
199 memset( (char *) dst, (int) val, (int) n );
200 #else
201 memset(dst, val, n);
202 #endif
203 }
204
205
206 void
207 _mesa_memset16( unsigned short *dst, unsigned short val, size_t n )
208 {
209 while (n-- > 0)
210 *dst++ = val;
211 }
212
213
214 void
215 _mesa_bzero( void *dst, size_t n )
216 {
217 #if defined(XFree86LOADER) && defined(IN_MODULE)
218 xf86memset( dst, 0, n );
219 #elif defined(__FreeBSD__)
220 bzero( dst, n );
221 #else
222 memset( dst, 0, n );
223 #endif
224 }
225
226
227 double
228 _mesa_sin(double a)
229 {
230 #if defined(XFree86LOADER) && defined(IN_MODULE)
231 return xf86sin(a);
232 #else
233 return sin(a);
234 #endif
235 }
236
237
238 double
239 _mesa_cos(double a)
240 {
241 #if defined(XFree86LOADER) && defined(IN_MODULE)
242 return xf86cos(a);
243 #else
244 return cos(a);
245 #endif
246 }
247
248
249 double
250 _mesa_sqrt(double x)
251 {
252 #if defined(XFree86LOADER) && defined(IN_MODULE)
253 return xf86sqrt(x);
254 #else
255 return sqrt(x);
256 #endif
257 }
258
259
260 double
261 _mesa_pow(double x, double y)
262 {
263 #if defined(XFree86LOADER) && defined(IN_MODULE)
264 return xf86pow(x, y);
265 #else
266 return pow(x, y);
267 #endif
268 }
269
270
271 char *
272 _mesa_getenv( const char *var )
273 {
274 #if defined(XFree86LOADER) && defined(IN_MODULE)
275 return xf86getenv(var);
276 #else
277 return getenv(var);
278 #endif
279 }
280
281
282 char *
283 _mesa_strstr( const char *haystack, const char *needle )
284 {
285 #if defined(XFree86LOADER) && defined(IN_MODULE)
286 return xf86strstr(haystack, needle);
287 #else
288 return strstr(haystack, needle);
289 #endif
290 }
291
292
293 char *
294 _mesa_strncat( char *dest, const char *src, size_t n )
295 {
296 #if defined(XFree86LOADER) && defined(IN_MODULE)
297 return xf86strncat(dest, src, n);
298 #else
299 return strncat(dest, src, n);
300 #endif
301 }
302
303
304 char *
305 _mesa_strcpy( char *dest, const char *src )
306 {
307 #if defined(XFree86LOADER) && defined(IN_MODULE)
308 return xf86strcpy(dest, src);
309 #else
310 return strcpy(dest, src);
311 #endif
312 }
313
314
315 char *
316 _mesa_strncpy( char *dest, const char *src, size_t n )
317 {
318 #if defined(XFree86LOADER) && defined(IN_MODULE)
319 return xf86strncpy(dest, src, n);
320 #else
321 return strncpy(dest, src, n);
322 #endif
323 }
324
325
326 size_t
327 _mesa_strlen( const char *s )
328 {
329 #if defined(XFree86LOADER) && defined(IN_MODULE)
330 return xf86strlen(s);
331 #else
332 return strlen(s);
333 #endif
334 }
335
336
337 int
338 _mesa_strcmp( const char *s1, const char *s2 )
339 {
340 #if defined(XFree86LOADER) && defined(IN_MODULE)
341 return xf86strcmp(s1, s2);
342 #else
343 return strcmp(s1, s2);
344 #endif
345 }
346
347
348 int
349 _mesa_strncmp( const char *s1, const char *s2, size_t n )
350 {
351 #if defined(XFree86LOADER) && defined(IN_MODULE)
352 return xf86strncmp(s1, s2, n);
353 #else
354 return strncmp(s1, s2, n);
355 #endif
356 }
357
358
359 char *
360 _mesa_strdup( const char *s )
361 {
362 int l = _mesa_strlen(s);
363 char *s2 = (char *) _mesa_malloc(l + 1);
364 if (s2)
365 _mesa_strcpy(s2, s);
366 return s2;
367 }
368
369
370 int
371 _mesa_atoi(const char *s)
372 {
373 #if defined(XFree86LOADER) && defined(IN_MODULE)
374 return xf86atoi(s);
375 #else
376 return atoi(s);
377 #endif
378 }
379
380
381 float
382 _mesa_strtof( const char *s, char **end )
383 {
384 #if defined(XFree86LOADER) && defined(IN_MODULE)
385 return xf86strtof(s, end);
386 #else
387 return (float) strtod(s, end);
388 #endif
389 }
390
391
392 int
393 _mesa_sprintf( char *str, const char *fmt, ... )
394 {
395 int r;
396 va_list args;
397 va_start( args, fmt );
398 va_end( args );
399 #if defined(XFree86LOADER) && defined(IN_MODULE)
400 r = xf86vsprintf( str, fmt, args );
401 #else
402 r = vsprintf( str, fmt, args );
403 #endif
404 return r;
405 }
406
407
408 void
409 _mesa_printf( const char *fmtString, ... )
410 {
411 char s[MAXSTRING];
412 va_list args;
413 va_start( args, fmtString );
414 vsnprintf(s, MAXSTRING, fmtString, args);
415 va_end( args );
416 #if defined(XFree86LOADER) && defined(IN_MODULE)
417 xf86printf("%s", s);
418 #else
419 printf("%s", s);
420 #endif
421 }
422
423
424 void
425 _mesa_warning( GLcontext *ctx, const char *fmtString, ... )
426 {
427 GLboolean debug;
428 char str[MAXSTRING];
429 va_list args;
430 (void) ctx;
431 va_start( args, fmtString );
432 (void) vsnprintf( str, MAXSTRING, fmtString, args );
433 va_end( args );
434 #ifdef DEBUG
435 debug = GL_TRUE; /* always print warning */
436 #else
437 debug = _mesa_getenv("MESA_DEBUG") ? GL_TRUE : GL_FALSE;
438 #endif
439 if (debug) {
440 #if defined(XFree86LOADER) && defined(IN_MODULE)
441 xf86fprintf(stderr, "Mesa warning: %s\n", str);
442 #else
443 fprintf(stderr, "Mesa warning: %s\n", str);
444 #endif
445 }
446 }
447
448
449 /*
450 * This function is called when the Mesa user has stumbled into a code
451 * path which may not be implemented fully or correctly.
452 */
453 void
454 _mesa_problem( const GLcontext *ctx, const char *fmtString, ... )
455 {
456 va_list args;
457 char str[MAXSTRING];
458 (void) ctx;
459
460 va_start( args, fmtString );
461 vsnprintf( str, MAXSTRING, fmtString, args );
462 va_end( args );
463
464 #if defined(XFree86LOADER) && defined(IN_MODULE)
465 xf86fprintf(stderr, "Mesa implementation error: %s\n", str);
466 xf86fprintf(stderr, "Please report to the DRI project at dri.sourceforge.net\n");
467 #else
468 fprintf(stderr, "Mesa implementation error: %s\n", str);
469 fprintf(stderr, "Please report to the Mesa bug database at www.mesa3d.org\n" );
470 #endif
471 }
472
473
474 /*
475 * If in debug mode, print error message to stdout.
476 * Also, record the error code by calling _mesa_record_error().
477 * Input: ctx - the GL context
478 * error - the error value
479 * fmtString - printf-style format string, followed by optional args
480 */
481 void
482 _mesa_error( GLcontext *ctx, GLenum error, const char *fmtString, ... )
483 {
484 const char *debugEnv;
485 GLboolean debug;
486
487 debugEnv = _mesa_getenv("MESA_DEBUG");
488
489 #ifdef DEBUG
490 if (debugEnv && _mesa_strstr(debugEnv, "silent"))
491 debug = GL_FALSE;
492 else
493 debug = GL_TRUE;
494 #else
495 if (debugEnv)
496 debug = GL_TRUE;
497 else
498 debug = GL_FALSE;
499 #endif
500
501 if (debug) {
502 va_list args;
503 char where[MAXSTRING];
504 const char *errstr;
505
506 va_start( args, fmtString );
507 vsnprintf( where, MAXSTRING, fmtString, args );
508 va_end( args );
509
510 switch (error) {
511 case GL_NO_ERROR:
512 errstr = "GL_NO_ERROR";
513 break;
514 case GL_INVALID_VALUE:
515 errstr = "GL_INVALID_VALUE";
516 break;
517 case GL_INVALID_ENUM:
518 errstr = "GL_INVALID_ENUM";
519 break;
520 case GL_INVALID_OPERATION:
521 errstr = "GL_INVALID_OPERATION";
522 break;
523 case GL_STACK_OVERFLOW:
524 errstr = "GL_STACK_OVERFLOW";
525 break;
526 case GL_STACK_UNDERFLOW:
527 errstr = "GL_STACK_UNDERFLOW";
528 break;
529 case GL_OUT_OF_MEMORY:
530 errstr = "GL_OUT_OF_MEMORY";
531 break;
532 case GL_TABLE_TOO_LARGE:
533 errstr = "GL_TABLE_TOO_LARGE";
534 break;
535 default:
536 errstr = "unknown";
537 break;
538 }
539 _mesa_debug(ctx, "Mesa user error: %s in %s\n", errstr, where);
540 }
541
542 _mesa_record_error(ctx, error);
543 }
544
545
546 /*
547 * Call this to report debug information. Uses stderr.
548 */
549 void
550 _mesa_debug( const GLcontext *ctx, const char *fmtString, ... )
551 {
552 char s[MAXSTRING];
553 va_list args;
554 va_start(args, fmtString);
555 vsnprintf(s, MAXSTRING, fmtString, args);
556 va_end(args);
557 #if defined(XFree86LOADER) && defined(IN_MODULE)
558 xf86fprintf(stderr, "Mesa: %s", s);
559 #else
560 fprintf(stderr, "Mesa: %s", s);
561 #endif
562 }
563
564
565
566 /**********************************************************************/
567 /* Default Imports Wrapper */
568 /**********************************************************************/
569
570 static void *
571 default_malloc(__GLcontext *gc, size_t size)
572 {
573 (void) gc;
574 return _mesa_malloc(size);
575 }
576
577 static void *
578 default_calloc(__GLcontext *gc, size_t numElem, size_t elemSize)
579 {
580 (void) gc;
581 return _mesa_calloc(numElem * elemSize);
582 }
583
584 static void *
585 default_realloc(__GLcontext *gc, void *oldAddr, size_t newSize)
586 {
587 (void) gc;
588 #if defined(XFree86LOADER) && defined(IN_MODULE)
589 return xf86realloc(oldAddr, newSize);
590 #else
591 return realloc(oldAddr, newSize);
592 #endif
593 }
594
595 static void
596 default_free(__GLcontext *gc, void *addr)
597 {
598 (void) gc;
599 _mesa_free(addr);
600 }
601
602 static char * CAPI
603 default_getenv( __GLcontext *gc, const char *var )
604 {
605 (void) gc;
606 return _mesa_getenv(var);
607 }
608
609 static void
610 default_warning(__GLcontext *gc, char *str)
611 {
612 _mesa_warning(gc, str);
613 }
614
615 static void
616 default_fatal(__GLcontext *gc, char *str)
617 {
618 _mesa_problem(gc, str);
619 abort();
620 }
621
622 static int CAPI
623 default_atoi(__GLcontext *gc, const char *str)
624 {
625 (void) gc;
626 return atoi(str);
627 }
628
629 static int CAPI
630 default_sprintf(__GLcontext *gc, char *str, const char *fmt, ...)
631 {
632 int r;
633 va_list args;
634 va_start( args, fmt );
635 r = vsprintf( str, fmt, args );
636 va_end( args );
637 return r;
638 }
639
640 static void * CAPI
641 default_fopen(__GLcontext *gc, const char *path, const char *mode)
642 {
643 return fopen(path, mode);
644 }
645
646 static int CAPI
647 default_fclose(__GLcontext *gc, void *stream)
648 {
649 return fclose((FILE *) stream);
650 }
651
652 static int CAPI
653 default_fprintf(__GLcontext *gc, void *stream, const char *fmt, ...)
654 {
655 int r;
656 va_list args;
657 va_start( args, fmt );
658 r = vfprintf( (FILE *) stream, fmt, args );
659 va_end( args );
660 return r;
661 }
662
663 /* XXX this really is driver-specific and can't be here */
664 static __GLdrawablePrivate *
665 default_GetDrawablePrivate(__GLcontext *gc)
666 {
667 return NULL;
668 }
669
670
671
672
673 /*
674 * Initialize a __GLimports object to point to the functions in
675 * this file. This is to be called from device drivers.
676 * Input: imports - the object to init
677 * driverCtx - pointer to device driver-specific data
678 */
679 void
680 _mesa_init_default_imports(__GLimports *imports, void *driverCtx)
681 {
682 imports->malloc = default_malloc;
683 imports->calloc = default_calloc;
684 imports->realloc = default_realloc;
685 imports->free = default_free;
686 imports->warning = default_warning;
687 imports->fatal = default_fatal;
688 imports->getenv = default_getenv; /* not used for now */
689 imports->atoi = default_atoi;
690 imports->sprintf = default_sprintf;
691 imports->fopen = default_fopen;
692 imports->fclose = default_fclose;
693 imports->fprintf = default_fprintf;
694 imports->getDrawablePrivate = default_GetDrawablePrivate;
695 imports->other = driverCtx;
696 }