1848b8605Smrg/**
2848b8605Smrg * \file imports.c
3848b8605Smrg * Standard C library function wrappers.
4848b8605Smrg *
5848b8605Smrg * Imports are services which the device driver or window system or
6848b8605Smrg * operating system provides to the core renderer.  The core renderer (Mesa)
7848b8605Smrg * will call these functions in order to do memory allocation, simple I/O,
8848b8605Smrg * etc.
9848b8605Smrg *
10848b8605Smrg * Some drivers will want to override/replace this file with something
11848b8605Smrg * specialized, but that'll be rare.
12848b8605Smrg *
13848b8605Smrg * Eventually, I want to move roll the glheader.h file into this.
14848b8605Smrg *
15848b8605Smrg * \todo Functions still needed:
16848b8605Smrg * - scanf
17848b8605Smrg * - qsort
18848b8605Smrg * - rand and RAND_MAX
19848b8605Smrg */
20848b8605Smrg
21848b8605Smrg/*
22848b8605Smrg * Mesa 3-D graphics library
23848b8605Smrg *
24848b8605Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
25848b8605Smrg *
26848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
27848b8605Smrg * copy of this software and associated documentation files (the "Software"),
28848b8605Smrg * to deal in the Software without restriction, including without limitation
29848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
30848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
31848b8605Smrg * Software is furnished to do so, subject to the following conditions:
32848b8605Smrg *
33848b8605Smrg * The above copyright notice and this permission notice shall be included
34848b8605Smrg * in all copies or substantial portions of the Software.
35848b8605Smrg *
36848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
37848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
39848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
40848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
41848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
42848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
43848b8605Smrg */
44848b8605Smrg
45b8e80941Smrg#include <stdio.h>
46b8e80941Smrg#include <stdarg.h>
47b8e80941Smrg#include "c99_math.h"
48b8e80941Smrg#include "util/rounding.h" /* for _mesa_roundeven */
49848b8605Smrg#include "imports.h"
50848b8605Smrg#include "context.h"
51848b8605Smrg#include "version.h"
52848b8605Smrg
53848b8605Smrg#ifdef _GNU_SOURCE
54848b8605Smrg#include <locale.h>
55848b8605Smrg#ifdef __APPLE__
56848b8605Smrg#include <xlocale.h>
57848b8605Smrg#endif
58848b8605Smrg#endif
59848b8605Smrg
60848b8605Smrg
61848b8605Smrg#ifdef _WIN32
62848b8605Smrg#define vsnprintf _vsnprintf
63848b8605Smrg#elif defined(__IBMC__) || defined(__IBMCPP__)
64848b8605Smrgextern int vsnprintf(char *str, size_t count, const char *fmt, va_list arg);
65848b8605Smrg#endif
66848b8605Smrg
67848b8605Smrg/**********************************************************************/
68848b8605Smrg/** \name Memory */
69848b8605Smrg/*@{*/
70848b8605Smrg
71848b8605Smrg/**
72848b8605Smrg * Allocate aligned memory.
73848b8605Smrg *
74848b8605Smrg * \param bytes number of bytes to allocate.
75848b8605Smrg * \param alignment alignment (must be greater than zero).
76848b8605Smrg *
77848b8605Smrg * Allocates extra memory to accommodate rounding up the address for
78848b8605Smrg * alignment and to record the real malloc address.
79848b8605Smrg *
80848b8605Smrg * \sa _mesa_align_free().
81848b8605Smrg */
82848b8605Smrgvoid *
83848b8605Smrg_mesa_align_malloc(size_t bytes, unsigned long alignment)
84848b8605Smrg{
85848b8605Smrg#if defined(HAVE_POSIX_MEMALIGN)
86848b8605Smrg   void *mem;
87848b8605Smrg   int err = posix_memalign(& mem, alignment, bytes);
88848b8605Smrg   if (err)
89848b8605Smrg      return NULL;
90848b8605Smrg   return mem;
91b8e80941Smrg#elif defined(_WIN32)
92848b8605Smrg   return _aligned_malloc(bytes, alignment);
93848b8605Smrg#else
94848b8605Smrg   uintptr_t ptr, buf;
95848b8605Smrg
96b8e80941Smrg   assert( alignment > 0 );
97848b8605Smrg
98848b8605Smrg   ptr = (uintptr_t)malloc(bytes + alignment + sizeof(void *));
99848b8605Smrg   if (!ptr)
100848b8605Smrg      return NULL;
101848b8605Smrg
102848b8605Smrg   buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1);
103848b8605Smrg   *(uintptr_t *)(buf - sizeof(void *)) = ptr;
104848b8605Smrg
105848b8605Smrg#ifdef DEBUG
106848b8605Smrg   /* mark the non-aligned area */
107848b8605Smrg   while ( ptr < buf - sizeof(void *) ) {
108848b8605Smrg      *(unsigned long *)ptr = 0xcdcdcdcd;
109848b8605Smrg      ptr += sizeof(unsigned long);
110848b8605Smrg   }
111848b8605Smrg#endif
112848b8605Smrg
113848b8605Smrg   return (void *) buf;
114848b8605Smrg#endif /* defined(HAVE_POSIX_MEMALIGN) */
115848b8605Smrg}
116848b8605Smrg
117848b8605Smrg/**
118848b8605Smrg * Same as _mesa_align_malloc(), but using calloc(1, ) instead of
119848b8605Smrg * malloc()
120848b8605Smrg */
121848b8605Smrgvoid *
122848b8605Smrg_mesa_align_calloc(size_t bytes, unsigned long alignment)
123848b8605Smrg{
124848b8605Smrg#if defined(HAVE_POSIX_MEMALIGN)
125848b8605Smrg   void *mem;
126848b8605Smrg
127848b8605Smrg   mem = _mesa_align_malloc(bytes, alignment);
128848b8605Smrg   if (mem != NULL) {
129848b8605Smrg      (void) memset(mem, 0, bytes);
130848b8605Smrg   }
131848b8605Smrg
132848b8605Smrg   return mem;
133b8e80941Smrg#elif defined(_WIN32)
134848b8605Smrg   void *mem;
135848b8605Smrg
136848b8605Smrg   mem = _aligned_malloc(bytes, alignment);
137848b8605Smrg   if (mem != NULL) {
138848b8605Smrg      (void) memset(mem, 0, bytes);
139848b8605Smrg   }
140848b8605Smrg
141848b8605Smrg   return mem;
142848b8605Smrg#else
143848b8605Smrg   uintptr_t ptr, buf;
144848b8605Smrg
145b8e80941Smrg   assert( alignment > 0 );
146848b8605Smrg
147848b8605Smrg   ptr = (uintptr_t)calloc(1, bytes + alignment + sizeof(void *));
148848b8605Smrg   if (!ptr)
149848b8605Smrg      return NULL;
150848b8605Smrg
151848b8605Smrg   buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1);
152848b8605Smrg   *(uintptr_t *)(buf - sizeof(void *)) = ptr;
153848b8605Smrg
154848b8605Smrg#ifdef DEBUG
155848b8605Smrg   /* mark the non-aligned area */
156848b8605Smrg   while ( ptr < buf - sizeof(void *) ) {
157848b8605Smrg      *(unsigned long *)ptr = 0xcdcdcdcd;
158848b8605Smrg      ptr += sizeof(unsigned long);
159848b8605Smrg   }
160848b8605Smrg#endif
161848b8605Smrg
162848b8605Smrg   return (void *)buf;
163848b8605Smrg#endif /* defined(HAVE_POSIX_MEMALIGN) */
164848b8605Smrg}
165848b8605Smrg
166848b8605Smrg/**
167848b8605Smrg * Free memory which was allocated with either _mesa_align_malloc()
168848b8605Smrg * or _mesa_align_calloc().
169848b8605Smrg * \param ptr pointer to the memory to be freed.
170848b8605Smrg * The actual address to free is stored in the word immediately before the
171848b8605Smrg * address the client sees.
172848b8605Smrg * Note that it is legal to pass NULL pointer to this function and will be
173848b8605Smrg * handled accordingly.
174848b8605Smrg */
175848b8605Smrgvoid
176848b8605Smrg_mesa_align_free(void *ptr)
177848b8605Smrg{
178848b8605Smrg#if defined(HAVE_POSIX_MEMALIGN)
179848b8605Smrg   free(ptr);
180b8e80941Smrg#elif defined(_WIN32)
181848b8605Smrg   _aligned_free(ptr);
182848b8605Smrg#else
183848b8605Smrg   if (ptr) {
184848b8605Smrg      void **cubbyHole = (void **) ((char *) ptr - sizeof(void *));
185848b8605Smrg      void *realAddr = *cubbyHole;
186848b8605Smrg      free(realAddr);
187848b8605Smrg   }
188848b8605Smrg#endif /* defined(HAVE_POSIX_MEMALIGN) */
189848b8605Smrg}
190848b8605Smrg
191848b8605Smrg/**
192848b8605Smrg * Reallocate memory, with alignment.
193848b8605Smrg */
194848b8605Smrgvoid *
195848b8605Smrg_mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize,
196848b8605Smrg                    unsigned long alignment)
197848b8605Smrg{
198b8e80941Smrg#if defined(_WIN32)
199848b8605Smrg   (void) oldSize;
200848b8605Smrg   return _aligned_realloc(oldBuffer, newSize, alignment);
201848b8605Smrg#else
202848b8605Smrg   const size_t copySize = (oldSize < newSize) ? oldSize : newSize;
203848b8605Smrg   void *newBuf = _mesa_align_malloc(newSize, alignment);
204848b8605Smrg   if (newBuf && oldBuffer && copySize > 0) {
205848b8605Smrg      memcpy(newBuf, oldBuffer, copySize);
206848b8605Smrg   }
207848b8605Smrg
208848b8605Smrg   _mesa_align_free(oldBuffer);
209848b8605Smrg   return newBuf;
210848b8605Smrg#endif
211848b8605Smrg}
212848b8605Smrg
213848b8605Smrg/*@}*/
214848b8605Smrg
215848b8605Smrg
216848b8605Smrg/** Needed due to #ifdef's, above. */
217848b8605Smrgint
218848b8605Smrg_mesa_vsnprintf(char *str, size_t size, const char *fmt, va_list args)
219848b8605Smrg{
220848b8605Smrg   return vsnprintf( str, size, fmt, args);
221848b8605Smrg}
222848b8605Smrg
223848b8605Smrg/** Wrapper around vsnprintf() */
224848b8605Smrgint
225848b8605Smrg_mesa_snprintf( char *str, size_t size, const char *fmt, ... )
226848b8605Smrg{
227848b8605Smrg   int r;
228848b8605Smrg   va_list args;
229848b8605Smrg   va_start( args, fmt );
230848b8605Smrg   r = vsnprintf( str, size, fmt, args );
231848b8605Smrg   va_end( args );
232848b8605Smrg   return r;
233848b8605Smrg}
234848b8605Smrg
235848b8605Smrg
236