setupapi: Add an internal helper for SetupDiSetDeviceRegistryProperty().
[wine.git] / dlls / glu32 / glu.c
blob8f0a360ff93c41f03863ce3f0b8aee49d1d844e2
1 /*
2 * Copyright 2001 Marcus Meissner
3 * Copyright 2017 Alexandre Julliard
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "config.h"
21 #include "wine/port.h"
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
28 #include "wine/wgl.h"
29 #include "wine/glu.h"
30 #include "wine/library.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(glu);
35 static const struct { GLuint err; const char *str; } errors[] =
37 { GL_NO_ERROR, "no error" },
38 { GL_INVALID_ENUM, "invalid enumerant" },
39 { GL_INVALID_VALUE, "invalid value" },
40 { GL_INVALID_OPERATION, "invalid operation" },
41 { GL_STACK_OVERFLOW, "stack overflow" },
42 { GL_STACK_UNDERFLOW, "stack underflow" },
43 { GL_OUT_OF_MEMORY, "out of memory" },
44 { GL_TABLE_TOO_LARGE, "table too large" },
45 { GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "invalid framebuffer operation" },
46 { GLU_INVALID_ENUM, "invalid enumerant" },
47 { GLU_INVALID_VALUE, "invalid value" },
48 { GLU_OUT_OF_MEMORY, "out of memory" },
49 { GLU_INCOMPATIBLE_GL_VERSION, "incompatible gl version" },
50 { GLU_TESS_ERROR1, "gluTessBeginPolygon() must precede a gluTessEndPolygon()" },
51 { GLU_TESS_ERROR2, "gluTessBeginContour() must precede a gluTessEndContour()" },
52 { GLU_TESS_ERROR3, "gluTessEndPolygon() must follow a gluTessBeginPolygon()" },
53 { GLU_TESS_ERROR4, "gluTessEndContour() must follow a gluTessBeginContour()" },
54 { GLU_TESS_ERROR5, "a coordinate is too large" },
55 { GLU_TESS_ERROR6, "need combine callback" },
56 { GLU_NURBS_ERROR1, "spline order un-supported" },
57 { GLU_NURBS_ERROR2, "too few knots" },
58 { GLU_NURBS_ERROR3, "valid knot range is empty" },
59 { GLU_NURBS_ERROR4, "decreasing knot sequence knot" },
60 { GLU_NURBS_ERROR5, "knot multiplicity greater than order of spline" },
61 { GLU_NURBS_ERROR6, "gluEndCurve() must follow gluBeginCurve()" },
62 { GLU_NURBS_ERROR7, "gluBeginCurve() must precede gluEndCurve()" },
63 { GLU_NURBS_ERROR8, "missing or extra geometric data" },
64 { GLU_NURBS_ERROR9, "can't draw piecewise linear trimming curves" },
65 { GLU_NURBS_ERROR10, "missing or extra domain data" },
66 { GLU_NURBS_ERROR11, "missing or extra domain data" },
67 { GLU_NURBS_ERROR12, "gluEndTrim() must precede gluEndSurface()" },
68 { GLU_NURBS_ERROR13, "gluBeginSurface() must precede gluEndSurface()" },
69 { GLU_NURBS_ERROR14, "curve of improper type passed as trim curve" },
70 { GLU_NURBS_ERROR15, "gluBeginSurface() must precede gluBeginTrim()" },
71 { GLU_NURBS_ERROR16, "gluEndTrim() must follow gluBeginTrim()" },
72 { GLU_NURBS_ERROR17, "gluBeginTrim() must precede gluEndTrim()" },
73 { GLU_NURBS_ERROR18, "invalid or missing trim curve" },
74 { GLU_NURBS_ERROR19, "gluBeginTrim() must precede gluPwlCurve()" },
75 { GLU_NURBS_ERROR20, "piecewise linear trimming curve referenced twice" },
76 { GLU_NURBS_ERROR21, "piecewise linear trimming curve and nurbs curve mixed" },
77 { GLU_NURBS_ERROR22, "improper usage of trim data type" },
78 { GLU_NURBS_ERROR23, "nurbs curve referenced twice" },
79 { GLU_NURBS_ERROR24, "nurbs curve and piecewise linear trimming curve mixed" },
80 { GLU_NURBS_ERROR25, "nurbs surface referenced twice" },
81 { GLU_NURBS_ERROR26, "invalid property" },
82 { GLU_NURBS_ERROR27, "gluEndSurface() must follow gluBeginSurface()" },
83 { GLU_NURBS_ERROR28, "intersecting or misoriented trim curves" },
84 { GLU_NURBS_ERROR29, "intersecting trim curves" },
85 { GLU_NURBS_ERROR30, "UNUSED" },
86 { GLU_NURBS_ERROR31, "unconnected trim curves" },
87 { GLU_NURBS_ERROR32, "unknown knot error" },
88 { GLU_NURBS_ERROR33, "negative vertex count encountered" },
89 { GLU_NURBS_ERROR34, "negative byte-stride encountered" },
90 { GLU_NURBS_ERROR35, "unknown type descriptor" },
91 { GLU_NURBS_ERROR36, "null control point reference" },
92 { GLU_NURBS_ERROR37, "duplicate point on piecewise linear trimming curve" },
95 typedef void (*_GLUfuncptr)(void);
97 static void (*p_gluBeginCurve)( GLUnurbs* nurb );
98 static void (*p_gluBeginSurface)( GLUnurbs* nurb );
99 static void (*p_gluBeginTrim)( GLUnurbs* nurb );
100 static void (*p_gluDeleteNurbsRenderer)( GLUnurbs* nurb );
101 static void (*p_gluEndCurve)( GLUnurbs* nurb );
102 static void (*p_gluEndSurface)( GLUnurbs* nurb );
103 static void (*p_gluEndTrim)( GLUnurbs* nurb );
104 static void (*p_gluGetNurbsProperty)( GLUnurbs* nurb, GLenum property, GLfloat* data );
105 static void (*p_gluLoadSamplingMatrices)( GLUnurbs* nurb, const GLfloat *model, const GLfloat *perspective, const GLint *view );
106 static GLUnurbs* (*p_gluNewNurbsRenderer)(void);
107 static void (*p_gluNurbsCallback)( GLUnurbs* nurb, GLenum which, _GLUfuncptr CallBackFunc );
108 static void (*p_gluNurbsCurve)( GLUnurbs* nurb, GLint knotCount, GLfloat *knots, GLint stride, GLfloat *control, GLint order, GLenum type );
109 static void (*p_gluNurbsProperty)( GLUnurbs* nurb, GLenum property, GLfloat value );
110 static void (*p_gluNurbsSurface)( GLUnurbs* nurb, GLint sKnotCount, GLfloat* sKnots, GLint tKnotCount, GLfloat* tKnots, GLint sStride, GLint tStride, GLfloat* control, GLint sOrder, GLint tOrder, GLenum type );
111 static void (*p_gluPwlCurve)( GLUnurbs* nurb, GLint count, GLfloat* data, GLint stride, GLenum type );
113 static void *libglu_handle;
114 static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
116 static BOOL WINAPI load_libglu( INIT_ONCE *once, void *param, void **context )
118 #ifdef SONAME_LIBGLU
119 char error[256];
121 if ((libglu_handle = wine_dlopen( SONAME_LIBGLU, RTLD_NOW, error, sizeof(error) )))
122 TRACE( "loaded %s\n", SONAME_LIBGLU );
123 else
124 ERR( "Failed to load %s: %s\n", SONAME_LIBGLU, error );
125 #else
126 ERR( "libGLU is needed but support was not included at build time\n" );
127 #endif
128 return libglu_handle != NULL;
131 static void *load_glufunc( const char *name )
133 void *ret;
135 if (!InitOnceExecuteOnce( &init_once, load_libglu, NULL, NULL )) return NULL;
136 if (!(ret = wine_dlsym( libglu_handle, name, NULL, 0 ))) ERR( "Can't find %s\n", name );
137 return ret;
140 #define LOAD_FUNCPTR(f) (p_##f || (p_##f = load_glufunc( #f )))
143 /***********************************************************************
144 * gluErrorString (GLU32.@)
146 const GLubyte * WINAPI wine_gluErrorString( GLenum errCode )
148 unsigned int i;
150 for (i = 0; i < ARRAY_SIZE(errors); i++)
151 if (errors[i].err == errCode) return (const GLubyte *)errors[i].str;
153 return NULL;
156 /***********************************************************************
157 * gluErrorUnicodeStringEXT (GLU32.@)
159 const WCHAR * WINAPI wine_gluErrorUnicodeStringEXT( GLenum errCode )
161 static WCHAR errorsW[ARRAY_SIZE(errors)][64];
162 unsigned int i, j;
164 for (i = 0; i < ARRAY_SIZE(errors); i++)
166 if (errors[i].err != errCode) continue;
167 if (!errorsW[i][0]) /* errors use only ASCII, do a simple mapping */
168 for (j = 0; errors[i].str[j]; j++) errorsW[i][j] = (WCHAR)errors[i].str[j];
169 return errorsW[i];
171 return NULL;
174 /***********************************************************************
175 * gluNewNurbsRenderer (GLU32.@)
177 GLUnurbs * WINAPI wine_gluNewNurbsRenderer(void)
179 if (!LOAD_FUNCPTR( gluNewNurbsRenderer )) return NULL;
180 return p_gluNewNurbsRenderer();
183 /***********************************************************************
184 * gluDeleteNurbsRenderer (GLU32.@)
186 void WINAPI wine_gluDeleteNurbsRenderer( GLUnurbs *nobj )
188 if (!LOAD_FUNCPTR( gluDeleteNurbsRenderer )) return;
189 p_gluDeleteNurbsRenderer( nobj );
192 /***********************************************************************
193 * gluLoadSamplingMatrices (GLU32.@)
195 void WINAPI wine_gluLoadSamplingMatrices( GLUnurbs *nobj, const GLfloat modelMatrix[16],
196 const GLfloat projMatrix[16], const GLint viewport[4] )
198 if (!LOAD_FUNCPTR( gluLoadSamplingMatrices )) return;
199 p_gluLoadSamplingMatrices( nobj, modelMatrix, projMatrix, viewport );
202 /***********************************************************************
203 * gluNurbsProperty (GLU32.@)
205 void WINAPI wine_gluNurbsProperty( GLUnurbs *nobj, GLenum property, GLfloat value )
207 if (!LOAD_FUNCPTR( gluNurbsProperty )) return;
208 p_gluNurbsProperty( nobj, property, value );
211 /***********************************************************************
212 * gluGetNurbsProperty (GLU32.@)
214 void WINAPI wine_gluGetNurbsProperty( GLUnurbs *nobj, GLenum property, GLfloat *value )
216 if (!LOAD_FUNCPTR( gluGetNurbsProperty )) return;
217 p_gluGetNurbsProperty( nobj, property, value );
220 /***********************************************************************
221 * gluBeginCurve (GLU32.@)
223 void WINAPI wine_gluBeginCurve( GLUnurbs *nobj )
225 if (!LOAD_FUNCPTR( gluBeginCurve )) return;
226 p_gluBeginCurve( nobj );
229 /***********************************************************************
230 * gluEndCurve (GLU32.@)
232 void WINAPI wine_gluEndCurve( GLUnurbs *nobj )
234 if (!LOAD_FUNCPTR( gluEndCurve )) return;
235 p_gluEndCurve( nobj );
238 /***********************************************************************
239 * gluNurbsCurve (GLU32.@)
241 void WINAPI wine_gluNurbsCurve( GLUnurbs *nobj, GLint nknots, GLfloat *knot,
242 GLint stride, GLfloat *ctlarray, GLint order, GLenum type )
244 if (!LOAD_FUNCPTR( gluNurbsCurve )) return;
245 p_gluNurbsCurve( nobj, nknots, knot, stride, ctlarray, order, type );
248 /***********************************************************************
249 * gluBeginSurface (GLU32.@)
251 void WINAPI wine_gluBeginSurface( GLUnurbs *nobj )
253 if (!LOAD_FUNCPTR( gluBeginSurface )) return;
254 p_gluBeginSurface( nobj );
257 /***********************************************************************
258 * gluEndSurface (GLU32.@)
260 void WINAPI wine_gluEndSurface( GLUnurbs *nobj )
262 if (!LOAD_FUNCPTR( gluEndSurface )) return;
263 p_gluEndSurface( nobj );
266 /***********************************************************************
267 * gluNurbsSurface (GLU32.@)
269 void WINAPI wine_gluNurbsSurface( GLUnurbs *nobj, GLint sknot_count, float *sknot, GLint tknot_count,
270 GLfloat *tknot, GLint s_stride, GLint t_stride, GLfloat *ctlarray,
271 GLint sorder, GLint torder, GLenum type )
273 if (!LOAD_FUNCPTR( gluNurbsSurface )) return;
274 p_gluNurbsSurface( nobj, sknot_count, sknot, tknot_count, tknot,
275 s_stride, t_stride, ctlarray, sorder, torder, type );
278 /***********************************************************************
279 * gluBeginTrim (GLU32.@)
281 void WINAPI wine_gluBeginTrim( GLUnurbs *nobj )
283 if (!LOAD_FUNCPTR( gluBeginTrim )) return;
284 p_gluBeginTrim( nobj );
287 /***********************************************************************
288 * gluEndTrim (GLU32.@)
290 void WINAPI wine_gluEndTrim( GLUnurbs *nobj )
292 if (!LOAD_FUNCPTR( gluEndTrim )) return;
293 p_gluEndTrim( nobj );
296 /***********************************************************************
297 * gluPwlCurve (GLU32.@)
299 void WINAPI wine_gluPwlCurve( GLUnurbs *nobj, GLint count, GLfloat *array, GLint stride, GLenum type )
301 if (!LOAD_FUNCPTR( gluPwlCurve )) return;
302 p_gluPwlCurve( nobj, count, array, stride, type );
305 /***********************************************************************
306 * gluNurbsCallback (GLU32.@)
308 void WINAPI wine_gluNurbsCallback( GLUnurbs *nobj, GLenum which, void (CALLBACK *fn)(void) )
310 if (!LOAD_FUNCPTR( gluNurbsCallback )) return;
311 /* FIXME: callback calling convention */
312 p_gluNurbsCallback( nobj, which, (_GLUfuncptr)fn );
315 /***********************************************************************
316 * gluGetString (GLU32.@)
318 const GLubyte * WINAPI wine_gluGetString( GLenum name )
320 switch (name)
322 case GLU_VERSION: return (const GLubyte *)"1.2.2.0 Microsoft Corporation"; /* sic */
323 case GLU_EXTENSIONS: return (const GLubyte *)"";
325 return NULL;
328 /***********************************************************************
329 * gluCheckExtension (GLU32.@)
331 GLboolean WINAPI wine_gluCheckExtension( const GLubyte *extName, const GLubyte *extString )
333 const char *list = (const char *)extString;
334 const char *ext = (const char *)extName;
335 size_t len = strlen( ext );
337 while (list)
339 while (*list == ' ') list++;
340 if (!strncmp( list, ext, len ) && (!list[len] || list[len] == ' ')) return GLU_TRUE;
341 list = strchr( list, ' ' );
343 return GLU_FALSE;