fix potential bug in _mesa_align_calloc/malloc (Frank van Heesch)
[mesa.git] / src / mesa / main / imports.c
1 /* $Id: imports.c,v 1.23 2002/10/30 19:40:20 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.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 #endif
60
61
62 /**********************************************************************/
63 /* Wrappers for standard C library functions */
64 /**********************************************************************/
65
66
67 void *
68 _mesa_malloc(size_t bytes)
69 {
70 #ifdef XFree86LOADER
71 return xf86malloc(bytes);
72 #else
73 return malloc(bytes);
74 #endif
75 }
76
77
78 void *
79 _mesa_calloc(size_t bytes)
80 {
81 #ifdef XFree86LOADER
82 return xf86calloc(1, bytes);
83 #else
84 return calloc(1, bytes);
85 #endif
86 }
87
88
89 void
90 _mesa_free(void *ptr)
91 {
92 #ifdef XFree86LOADER
93 xf86free(ptr);
94 #else
95 free(ptr);
96 #endif
97 }
98
99
100 void *
101 _mesa_align_malloc(size_t bytes, unsigned long alignment)
102 {
103 unsigned long ptr, buf;
104
105 ASSERT( alignment > 0 );
106
107 /* Allocate extra memory to accomodate rounding up the address for
108 * alignment and to record the real malloc address.
109 */
110 ptr = (unsigned long) _mesa_malloc(bytes + alignment + sizeof(void *));
111 if (!ptr)
112 return NULL;
113
114 buf = (ptr + alignment + sizeof(void *)) & ~(unsigned long)(alignment - 1);
115 *(unsigned long *)(buf - sizeof(void *)) = ptr;
116
117 #ifdef DEBUG
118 /* mark the non-aligned area */
119 while ( ptr < buf - sizeof(void *) ) {
120 *(unsigned long *)ptr = 0xcdcdcdcd;
121 ptr += sizeof(unsigned long);
122 }
123 #endif
124
125 return (void *) buf;
126 }
127
128
129 void *
130 _mesa_align_calloc(size_t bytes, unsigned long alignment)
131 {
132 unsigned long ptr, buf;
133
134 ASSERT( alignment > 0 );
135
136 ptr = (unsigned long) _mesa_calloc(bytes + alignment + sizeof(void *));
137 if (!ptr)
138 return NULL;
139
140 buf = (ptr + alignment + sizeof(void *)) & ~(unsigned long)(alignment - 1);
141 *(unsigned long *)(buf - sizeof(void *)) = ptr;
142
143 #ifdef DEBUG
144 /* mark the non-aligned area */
145 while ( ptr < buf - sizeof(void *) ) {
146 *(unsigned long *)ptr = 0xcdcdcdcd;
147 ptr += sizeof(unsigned long);
148 }
149 #endif
150
151 return (void *)buf;
152 }
153
154
155 void
156 _mesa_align_free(void *ptr)
157 {
158 #if 0
159 _mesa_free( (void *)(*(unsigned long *)((unsigned long)ptr - sizeof(void *))) );
160 #else
161 /* The actuall address to free is stuffed in the word immediately
162 * before the address the client sees.
163 */
164 void **cubbyHole = (void **) ((char *) ptr - sizeof(void *));
165 void *realAddr = *cubbyHole;
166 _mesa_free(realAddr);
167 #endif
168 }
169
170
171 void *
172 _mesa_memcpy(void *dest, const void *src, size_t n)
173 {
174 #ifdef XFree86LOADER
175 return xf86memcpy(dest, src, n);
176 #elif defined(SUNOS4)
177 return memcpy((char *) dest, (char *) src, (int) n);
178 #else
179 return memcpy(dest, src, n);
180 #endif
181 }
182
183
184 void
185 _mesa_memset( void *dst, int val, size_t n )
186 {
187 #ifdef XFree86LOADER
188 xf86memset( dst, val, n );
189 #elif defined(SUNOS4)
190 memset( (char *) dst, (int) val, (int) n );
191 #else
192 memset(dst, val, n);
193 #endif
194 }
195
196
197 void
198 _mesa_memset16( unsigned short *dst, unsigned short val, size_t n )
199 {
200 while (n-- > 0)
201 *dst++ = val;
202 }
203
204
205 void
206 _mesa_bzero( void *dst, size_t n )
207 {
208 #ifdef XFree86LOADER
209 xf86memset( dst, 0, n );
210 #elif defined(__FreeBSD__)
211 bzero( dst, n );
212 #else
213 memset( dst, 0, n );
214 #endif
215 }
216
217
218 double
219 _mesa_sin(double a)
220 {
221 #ifdef XFree86LOADER
222 return xf86sin(a);
223 #else
224 return sin(a);
225 #endif
226 }
227
228
229 double
230 _mesa_cos(double a)
231 {
232 #ifdef XFree86LOADER
233 return xf86cos(a);
234 #else
235 return cos(a);
236 #endif
237 }
238
239
240 double
241 _mesa_sqrt(double x)
242 {
243 #ifdef XFree86LOADER
244 return xf86sqrt(x);
245 #else
246 return sqrt(x);
247 #endif
248 }
249
250
251 double
252 _mesa_pow(double x, double y)
253 {
254 #ifdef XFree86LOADER
255 return xf86pow(x, y);
256 #else
257 return pow(x, y);
258 #endif
259 }
260
261
262 char *
263 _mesa_getenv( const char *var )
264 {
265 #ifdef XFree86LOADER
266 return xf86getenv(var);
267 #else
268 return getenv(var);
269 #endif
270 }
271
272
273 char *
274 _mesa_strstr( const char *haystack, const char *needle )
275 {
276 #ifdef XFree86LOADER
277 return xf86strstr(haystack, needle);
278 #else
279 return strstr(haystack, needle);
280 #endif
281 }
282
283
284 char *
285 _mesa_strncat( char *dest, const char *src, size_t n )
286 {
287 #ifdef XFree86LOADER
288 return xf86strncat(dest, src, n);
289 #else
290 return strncat(dest, src, n);
291 #endif
292 }
293
294
295 char *
296 _mesa_strcpy( char *dest, const char *src )
297 {
298 #ifdef XFree86LOADER
299 return xf86strcpy(dest, src);
300 #else
301 return strcpy(dest, src);
302 #endif
303 }
304
305
306 char *
307 _mesa_strncpy( char *dest, const char *src, size_t n )
308 {
309 #ifdef XFree86LOADER
310 return xf86strncpy(dest, src, n);
311 #else
312 return strncpy(dest, src, n);
313 #endif
314 }
315
316
317 size_t
318 _mesa_strlen( const char *s )
319 {
320 #ifdef XFree86LOADER
321 return xf86strlen(s);
322 #else
323 return strlen(s);
324 #endif
325 }
326
327
328 int
329 _mesa_strcmp( const char *s1, const char *s2 )
330 {
331 #ifdef XFree86LOADER
332 return xf86strcmp(s1, s2);
333 #else
334 return strcmp(s1, s2);
335 #endif
336 }
337
338
339 int
340 _mesa_strncmp( const char *s1, const char *s2, size_t n )
341 {
342 #ifdef XFree86LOADER
343 return xf86strncmp(s1, s2, n);
344 #else
345 return strncmp(s1, s2, n);
346 #endif
347 }
348
349
350 int
351 _mesa_atoi(const char *s)
352 {
353 #ifdef XFree86LOADER
354 return xf86atoi(s);
355 #else
356 return atoi(s);
357 #endif
358 }
359
360
361 int
362 _mesa_sprintf( char *str, const char *fmt, ... )
363 {
364 int r;
365 va_list args;
366 va_start( args, fmt );
367 va_end( args );
368 #ifdef XFree86LOADER
369 r = xf86vsprintf( str, fmt, args );
370 #else
371 r = vsprintf( str, fmt, args );
372 #endif
373 return r;
374 }
375
376
377 void
378 _mesa_printf( const char *fmtString, ... )
379 {
380 char s[MAXSTRING];
381 va_list args;
382 va_start( args, fmtString );
383 vsnprintf(s, MAXSTRING, fmtString, args);
384 va_end( args );
385 #ifdef XFree86LOADER
386 xf86printf("%s", s);
387 #else
388 printf("%s", s);
389 #endif
390 }
391
392
393 void
394 _mesa_warning( GLcontext *ctx, const char *fmtString, ... )
395 {
396 GLboolean debug;
397 char str[MAXSTRING];
398 va_list args;
399 (void) ctx;
400 va_start( args, fmtString );
401 (void) vsnprintf( str, MAXSTRING, fmtString, args );
402 va_end( args );
403 #ifdef DEBUG
404 debug = GL_TRUE; /* always print warning */
405 #else
406 debug = _mesa_getenv("MESA_DEBUG") ? GL_TRUE : GL_FALSE;
407 #endif
408 if (debug) {
409 #ifdef XFree86LOADER
410 xf86fprintf(stderr, "Mesa warning: %s\n", str);
411 #else
412 fprintf(stderr, "Mesa warning: %s\n", str);
413 #endif
414 }
415 }
416
417
418 /*
419 * This function is called when the Mesa user has stumbled into a code
420 * path which may not be implemented fully or correctly.
421 */
422 void
423 _mesa_problem( const GLcontext *ctx, const char *s )
424 {
425 (void) ctx;
426 #ifdef XFree86LOADER
427 xf86fprintf(stderr, "Mesa implementation error: %s\n", s);
428 xf86fprintf(stderr, "Please report to the DRI project at dri.sourceforge.net\n");
429 #else
430 fprintf(stderr, "Mesa implementation error: %s\n", s);
431 fprintf(stderr, "Please report to the Mesa bug database at www.mesa3d.org\n" );
432 #endif
433 }
434
435
436 /*
437 * If in debug mode, print error message to stdout.
438 * Also, record the error code by calling _mesa_record_error().
439 * Input: ctx - the GL context
440 * error - the error value
441 * fmtString - printf-style format string, followed by optional args
442 */
443 void
444 _mesa_error( GLcontext *ctx, GLenum error, const char *fmtString, ... )
445 {
446 const char *debugEnv;
447 GLboolean debug;
448
449 debugEnv = _mesa_getenv("MESA_DEBUG");
450
451 #ifdef DEBUG
452 if (debugEnv && _mesa_strstr(debugEnv, "silent"))
453 debug = GL_FALSE;
454 else
455 debug = GL_TRUE;
456 #else
457 if (debugEnv)
458 debug = GL_TRUE;
459 else
460 debug = GL_FALSE;
461 #endif
462
463 if (debug) {
464 va_list args;
465 char where[MAXSTRING];
466 const char *errstr;
467
468 va_start( args, fmtString );
469 vsnprintf( where, MAXSTRING, fmtString, args );
470 va_end( args );
471
472 switch (error) {
473 case GL_NO_ERROR:
474 errstr = "GL_NO_ERROR";
475 break;
476 case GL_INVALID_VALUE:
477 errstr = "GL_INVALID_VALUE";
478 break;
479 case GL_INVALID_ENUM:
480 errstr = "GL_INVALID_ENUM";
481 break;
482 case GL_INVALID_OPERATION:
483 errstr = "GL_INVALID_OPERATION";
484 break;
485 case GL_STACK_OVERFLOW:
486 errstr = "GL_STACK_OVERFLOW";
487 break;
488 case GL_STACK_UNDERFLOW:
489 errstr = "GL_STACK_UNDERFLOW";
490 break;
491 case GL_OUT_OF_MEMORY:
492 errstr = "GL_OUT_OF_MEMORY";
493 break;
494 case GL_TABLE_TOO_LARGE:
495 errstr = "GL_TABLE_TOO_LARGE";
496 break;
497 default:
498 errstr = "unknown";
499 break;
500 }
501 _mesa_debug(ctx, "Mesa user error: %s in %s\n", errstr, where);
502 }
503
504 _mesa_record_error(ctx, error);
505 }
506
507
508 /*
509 * Call this to report debug information. Uses stderr.
510 */
511 void
512 _mesa_debug( const GLcontext *ctx, const char *fmtString, ... )
513 {
514 char s[MAXSTRING];
515 va_list args;
516 va_start(args, fmtString);
517 vsnprintf(s, MAXSTRING, fmtString, args);
518 va_end(args);
519 #ifdef XFree86LOADER
520 xf86fprintf(stderr, "Mesa: %s", s);
521 #else
522 fprintf(stderr, "Mesa: %s", s);
523 #endif
524 }
525
526
527
528 /**********************************************************************/
529 /* Default Imports Wrapper */
530 /**********************************************************************/
531
532 static void *
533 default_malloc(__GLcontext *gc, size_t size)
534 {
535 (void) gc;
536 return _mesa_malloc(size);
537 }
538
539 static void *
540 default_calloc(__GLcontext *gc, size_t numElem, size_t elemSize)
541 {
542 (void) gc;
543 return _mesa_calloc(numElem * elemSize);
544 }
545
546 static void *
547 default_realloc(__GLcontext *gc, void *oldAddr, size_t newSize)
548 {
549 (void) gc;
550 #ifdef XFree86LOADER
551 return xf86realloc(oldAddr, newSize);
552 #else
553 return realloc(oldAddr, newSize);
554 #endif
555 }
556
557 static void
558 default_free(__GLcontext *gc, void *addr)
559 {
560 (void) gc;
561 _mesa_free(addr);
562 }
563
564 static char * CAPI
565 default_getenv( __GLcontext *gc, const char *var )
566 {
567 (void) gc;
568 return _mesa_getenv(var);
569 }
570
571 static void
572 default_warning(__GLcontext *gc, char *str)
573 {
574 _mesa_warning(gc, str);
575 }
576
577 static void
578 default_fatal(__GLcontext *gc, char *str)
579 {
580 _mesa_problem(gc, str);
581 abort();
582 }
583
584 static int CAPI
585 default_atoi(__GLcontext *gc, const char *str)
586 {
587 (void) gc;
588 return atoi(str);
589 }
590
591 static int CAPI
592 default_sprintf(__GLcontext *gc, char *str, const char *fmt, ...)
593 {
594 int r;
595 va_list args;
596 va_start( args, fmt );
597 r = vsprintf( str, fmt, args );
598 va_end( args );
599 return r;
600 }
601
602 static void * CAPI
603 default_fopen(__GLcontext *gc, const char *path, const char *mode)
604 {
605 return fopen(path, mode);
606 }
607
608 static int CAPI
609 default_fclose(__GLcontext *gc, void *stream)
610 {
611 return fclose((FILE *) stream);
612 }
613
614 static int CAPI
615 default_fprintf(__GLcontext *gc, void *stream, const char *fmt, ...)
616 {
617 int r;
618 va_list args;
619 va_start( args, fmt );
620 r = vfprintf( (FILE *) stream, fmt, args );
621 va_end( args );
622 return r;
623 }
624
625 /* XXX this really is driver-specific and can't be here */
626 static __GLdrawablePrivate *
627 default_GetDrawablePrivate(__GLcontext *gc)
628 {
629 return NULL;
630 }
631
632
633
634
635 /*
636 * Initialize a __GLimports object to point to the functions in
637 * this file. This is to be called from device drivers.
638 * Input: imports - the object to init
639 * driverCtx - pointer to device driver-specific data
640 */
641 void
642 _mesa_init_default_imports(__GLimports *imports, void *driverCtx)
643 {
644 imports->malloc = default_malloc;
645 imports->calloc = default_calloc;
646 imports->realloc = default_realloc;
647 imports->free = default_free;
648 imports->warning = default_warning;
649 imports->fatal = default_fatal;
650 imports->getenv = default_getenv; /* not used for now */
651 imports->atoi = default_atoi;
652 imports->sprintf = default_sprintf;
653 imports->fopen = default_fopen;
654 imports->fclose = default_fclose;
655 imports->fprintf = default_fprintf;
656 imports->getDrawablePrivate = default_GetDrawablePrivate;
657 imports->other = driverCtx;
658 }