s/16/32/ (Josh Vanderhoof)
[mesa.git] / src / mesa / main / imports.c
1 /* $Id: imports.c,v 1.27 2002/12/06 03:10:59 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 int
360 _mesa_atoi(const char *s)
361 {
362 #if defined(XFree86LOADER) && defined(IN_MODULE)
363 return xf86atoi(s);
364 #else
365 return atoi(s);
366 #endif
367 }
368
369
370 int
371 _mesa_sprintf( char *str, const char *fmt, ... )
372 {
373 int r;
374 va_list args;
375 va_start( args, fmt );
376 va_end( args );
377 #if defined(XFree86LOADER) && defined(IN_MODULE)
378 r = xf86vsprintf( str, fmt, args );
379 #else
380 r = vsprintf( str, fmt, args );
381 #endif
382 return r;
383 }
384
385
386 void
387 _mesa_printf( const char *fmtString, ... )
388 {
389 char s[MAXSTRING];
390 va_list args;
391 va_start( args, fmtString );
392 vsnprintf(s, MAXSTRING, fmtString, args);
393 va_end( args );
394 #if defined(XFree86LOADER) && defined(IN_MODULE)
395 xf86printf("%s", s);
396 #else
397 printf("%s", s);
398 #endif
399 }
400
401
402 void
403 _mesa_warning( GLcontext *ctx, const char *fmtString, ... )
404 {
405 GLboolean debug;
406 char str[MAXSTRING];
407 va_list args;
408 (void) ctx;
409 va_start( args, fmtString );
410 (void) vsnprintf( str, MAXSTRING, fmtString, args );
411 va_end( args );
412 #ifdef DEBUG
413 debug = GL_TRUE; /* always print warning */
414 #else
415 debug = _mesa_getenv("MESA_DEBUG") ? GL_TRUE : GL_FALSE;
416 #endif
417 if (debug) {
418 #if defined(XFree86LOADER) && defined(IN_MODULE)
419 xf86fprintf(stderr, "Mesa warning: %s\n", str);
420 #else
421 fprintf(stderr, "Mesa warning: %s\n", str);
422 #endif
423 }
424 }
425
426
427 /*
428 * This function is called when the Mesa user has stumbled into a code
429 * path which may not be implemented fully or correctly.
430 */
431 void
432 _mesa_problem( const GLcontext *ctx, const char *fmtString, ... )
433 {
434 va_list args;
435 char str[MAXSTRING];
436 (void) ctx;
437
438 va_start( args, fmtString );
439 vsnprintf( str, MAXSTRING, fmtString, args );
440 va_end( args );
441
442 #if defined(XFree86LOADER) && defined(IN_MODULE)
443 xf86fprintf(stderr, "Mesa implementation error: %s\n", str);
444 xf86fprintf(stderr, "Please report to the DRI project at dri.sourceforge.net\n");
445 #else
446 fprintf(stderr, "Mesa implementation error: %s\n", str);
447 fprintf(stderr, "Please report to the Mesa bug database at www.mesa3d.org\n" );
448 #endif
449 }
450
451
452 /*
453 * If in debug mode, print error message to stdout.
454 * Also, record the error code by calling _mesa_record_error().
455 * Input: ctx - the GL context
456 * error - the error value
457 * fmtString - printf-style format string, followed by optional args
458 */
459 void
460 _mesa_error( GLcontext *ctx, GLenum error, const char *fmtString, ... )
461 {
462 const char *debugEnv;
463 GLboolean debug;
464
465 debugEnv = _mesa_getenv("MESA_DEBUG");
466
467 #ifdef DEBUG
468 if (debugEnv && _mesa_strstr(debugEnv, "silent"))
469 debug = GL_FALSE;
470 else
471 debug = GL_TRUE;
472 #else
473 if (debugEnv)
474 debug = GL_TRUE;
475 else
476 debug = GL_FALSE;
477 #endif
478
479 if (debug) {
480 va_list args;
481 char where[MAXSTRING];
482 const char *errstr;
483
484 va_start( args, fmtString );
485 vsnprintf( where, MAXSTRING, fmtString, args );
486 va_end( args );
487
488 switch (error) {
489 case GL_NO_ERROR:
490 errstr = "GL_NO_ERROR";
491 break;
492 case GL_INVALID_VALUE:
493 errstr = "GL_INVALID_VALUE";
494 break;
495 case GL_INVALID_ENUM:
496 errstr = "GL_INVALID_ENUM";
497 break;
498 case GL_INVALID_OPERATION:
499 errstr = "GL_INVALID_OPERATION";
500 break;
501 case GL_STACK_OVERFLOW:
502 errstr = "GL_STACK_OVERFLOW";
503 break;
504 case GL_STACK_UNDERFLOW:
505 errstr = "GL_STACK_UNDERFLOW";
506 break;
507 case GL_OUT_OF_MEMORY:
508 errstr = "GL_OUT_OF_MEMORY";
509 break;
510 case GL_TABLE_TOO_LARGE:
511 errstr = "GL_TABLE_TOO_LARGE";
512 break;
513 default:
514 errstr = "unknown";
515 break;
516 }
517 _mesa_debug(ctx, "Mesa user error: %s in %s\n", errstr, where);
518 }
519
520 _mesa_record_error(ctx, error);
521 }
522
523
524 /*
525 * Call this to report debug information. Uses stderr.
526 */
527 void
528 _mesa_debug( const GLcontext *ctx, const char *fmtString, ... )
529 {
530 char s[MAXSTRING];
531 va_list args;
532 va_start(args, fmtString);
533 vsnprintf(s, MAXSTRING, fmtString, args);
534 va_end(args);
535 #if defined(XFree86LOADER) && defined(IN_MODULE)
536 xf86fprintf(stderr, "Mesa: %s", s);
537 #else
538 fprintf(stderr, "Mesa: %s", s);
539 #endif
540 }
541
542
543
544 /**********************************************************************/
545 /* Default Imports Wrapper */
546 /**********************************************************************/
547
548 static void *
549 default_malloc(__GLcontext *gc, size_t size)
550 {
551 (void) gc;
552 return _mesa_malloc(size);
553 }
554
555 static void *
556 default_calloc(__GLcontext *gc, size_t numElem, size_t elemSize)
557 {
558 (void) gc;
559 return _mesa_calloc(numElem * elemSize);
560 }
561
562 static void *
563 default_realloc(__GLcontext *gc, void *oldAddr, size_t newSize)
564 {
565 (void) gc;
566 #if defined(XFree86LOADER) && defined(IN_MODULE)
567 return xf86realloc(oldAddr, newSize);
568 #else
569 return realloc(oldAddr, newSize);
570 #endif
571 }
572
573 static void
574 default_free(__GLcontext *gc, void *addr)
575 {
576 (void) gc;
577 _mesa_free(addr);
578 }
579
580 static char * CAPI
581 default_getenv( __GLcontext *gc, const char *var )
582 {
583 (void) gc;
584 return _mesa_getenv(var);
585 }
586
587 static void
588 default_warning(__GLcontext *gc, char *str)
589 {
590 _mesa_warning(gc, str);
591 }
592
593 static void
594 default_fatal(__GLcontext *gc, char *str)
595 {
596 _mesa_problem(gc, str);
597 abort();
598 }
599
600 static int CAPI
601 default_atoi(__GLcontext *gc, const char *str)
602 {
603 (void) gc;
604 return atoi(str);
605 }
606
607 static int CAPI
608 default_sprintf(__GLcontext *gc, char *str, const char *fmt, ...)
609 {
610 int r;
611 va_list args;
612 va_start( args, fmt );
613 r = vsprintf( str, fmt, args );
614 va_end( args );
615 return r;
616 }
617
618 static void * CAPI
619 default_fopen(__GLcontext *gc, const char *path, const char *mode)
620 {
621 return fopen(path, mode);
622 }
623
624 static int CAPI
625 default_fclose(__GLcontext *gc, void *stream)
626 {
627 return fclose((FILE *) stream);
628 }
629
630 static int CAPI
631 default_fprintf(__GLcontext *gc, void *stream, const char *fmt, ...)
632 {
633 int r;
634 va_list args;
635 va_start( args, fmt );
636 r = vfprintf( (FILE *) stream, fmt, args );
637 va_end( args );
638 return r;
639 }
640
641 /* XXX this really is driver-specific and can't be here */
642 static __GLdrawablePrivate *
643 default_GetDrawablePrivate(__GLcontext *gc)
644 {
645 return NULL;
646 }
647
648
649
650
651 /*
652 * Initialize a __GLimports object to point to the functions in
653 * this file. This is to be called from device drivers.
654 * Input: imports - the object to init
655 * driverCtx - pointer to device driver-specific data
656 */
657 void
658 _mesa_init_default_imports(__GLimports *imports, void *driverCtx)
659 {
660 imports->malloc = default_malloc;
661 imports->calloc = default_calloc;
662 imports->realloc = default_realloc;
663 imports->free = default_free;
664 imports->warning = default_warning;
665 imports->fatal = default_fatal;
666 imports->getenv = default_getenv; /* not used for now */
667 imports->atoi = default_atoi;
668 imports->sprintf = default_sprintf;
669 imports->fopen = default_fopen;
670 imports->fclose = default_fclose;
671 imports->fprintf = default_fprintf;
672 imports->getDrawablePrivate = default_GetDrawablePrivate;
673 imports->other = driverCtx;
674 }