1 /*
2 	OSMesa LDG loader
3 
4 	Copyright (C) 2004	Patrice Mandin
5 
6 	This software is provided 'as-is', without any express or implied
7 	warranty.  In no event will the authors be held liable for any damages
8 	arising from the use of this software.
9 
10 	Permission is granted to anyone to use this software for any purpose,
11 	including commercial applications, and to alter it and redistribute it
12 	freely, subject to the following restrictions:
13 
14 	1. The origin of this software must not be misrepresented; you must not
15 	   claim that you wrote the original software. If you use this software
16 	   in a product, an acknowledgment in the product documentation would be
17 	   appreciated but is not required.
18 	2. Altered source versions must be plainly marked as such, and must not be
19 	   misrepresented as being the original software.
20 	3. This notice may not be removed or altered from any source distribution.
21 */
22 
23 /*--- Includes ---*/
24 
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <mint/cookie.h>
28 #include <mint/osbind.h>
29 #include <mint/mintbind.h>
30 
31 #include "lib-osmesa.h"
32 #include "lib-misc.h"
33 #include "../natfeat/nf_ops.h"
34 #include "nfosmesa_nfapi.h"
35 
36 /*--- Defines ---*/
37 
38 #define NFOSMESA_DEVICE	"u:\\dev\\nfosmesa"
39 
40 /*--- Local variables ---*/
41 
42 static const struct nf_ops *nfOps;
43 static unsigned long nfOSMesaId=0;
44 
do_nothing(unsigned long function_number,OSMesaContext ctx,void * first_param)45 static long do_nothing(unsigned long function_number, OSMesaContext ctx, void *first_param)
46 {
47 	(void) function_number;
48 	(void) ctx;
49 	(void) first_param;
50 	return 0;
51 }
52 
53 long (*HostCall_p)(unsigned long function_number, OSMesaContext ctx, void *first_param) = do_nothing;
54 void (*HostCall64_p)(unsigned long function_number, OSMesaContext ctx, void *first_param, GLuint64 *retvalue);
55 
56 /*--- OSMesa functions redirectors ---*/
57 
58 
err_init(const char * str)59 void err_init(const char *str)
60 {
61 	/*
62 	 * FIXME: figure out how to get at the apid of the
63 	 * the app that loaded us (LDG->id), and perform
64 	 * either Cconws() or form_alert()
65 	 */
66 	(void) Cconws(str);
67 	(void) Cconws("\r\n");
68 	/* if (__mint) */ Salert(str);
69 }
70 
71 
InitNatfeat(void)72 static void InitNatfeat(void)
73 {
74 	long ver;
75 
76 	nfOps = nf_init();
77 	if (!nfOps) {
78 		err_init("__NF cookie not present on this system");
79 		return;
80 	}
81 
82 	nfOSMesaId=nfOps->get_id("OSMESA");
83 	if (nfOSMesaId==0) {
84 		err_init("NF OSMesa functions not present on this system");
85 		return;
86 	}
87 	ver = nfOps->call(nfOSMesaId+GET_VERSION, 0l, 0l);
88 	if (ver < ARANFOSMESA_NFAPI_VERSION)
89 	{
90 		if (err_old_nfapi())
91 		{
92 			err_init("NF OSMesa functions in ARAnyM too old");
93 			nfOSMesaId = 0;
94 			return;
95 		}
96 	}
97 	if (ver > ARANFOSMESA_NFAPI_VERSION)
98 	{
99 		/*
100 		 * they should be backward compatible, but give a warning
101 		 */
102 	    (void) Cconws("Warning: NF OSMesa functions in ARAnyM newer than library\r\n");
103 	}
104 }
105 
HostCall_natfeats(unsigned long function_number,OSMesaContext ctx,void * first_param)106 static long HostCall_natfeats(unsigned long function_number, OSMesaContext ctx, void *first_param)
107 {
108 	return nfOps->call(nfOSMesaId+function_number,ctx,first_param);
109 }
110 
HostCall_natfeats64(unsigned long function_number,OSMesaContext ctx,void * first_param,GLuint64 * retvalue)111 static void HostCall_natfeats64(unsigned long function_number, OSMesaContext ctx, void *first_param, GLuint64 *retvalue)
112 {
113 	nfOps->call(nfOSMesaId+function_number, ctx, first_param, retvalue);
114 }
115 
InstallHostCall(void)116 static int InstallHostCall(void)
117 {
118 	/* TOS maybe, try the cookie */
119 	if (nfOSMesaId==0) {
120 		InitNatfeat();
121 	}
122 	if (nfOSMesaId!=0) {
123 		HostCall_p = HostCall_natfeats;
124 		HostCall64_p = HostCall_natfeats64;
125 		return 1;
126 	}
127 
128 	return 0;
129 }
130 
internal_OSMesaCreateContext(gl_private * private,GLenum format,OSMesaContext sharelist)131 OSMesaContext APIENTRY internal_OSMesaCreateContext(gl_private *private, GLenum format, OSMesaContext sharelist)
132 {
133 	if (!InstallHostCall()) {
134 		return NULL;
135 	}
136 
137 	return (OSMesaContext)(*HostCall_p)(NFOSMESA_OSMESACREATECONTEXT, private->cur_context, &format);
138 }
139 
internal_OSMesaCreateContextExt(gl_private * private,GLenum format,GLint depthBits,GLint stencilBits,GLint accumBits,OSMesaContext sharelist)140 OSMesaContext APIENTRY internal_OSMesaCreateContextExt(gl_private *private, GLenum format, GLint depthBits, GLint stencilBits, GLint accumBits, OSMesaContext sharelist)
141 {
142 	if (!InstallHostCall()) {
143 		return NULL;
144 	}
145 
146 	return (OSMesaContext)(*HostCall_p)(NFOSMESA_OSMESACREATECONTEXTEXT, private->cur_context, &format);
147 }
148 
internal_OSMesaCreateContextAttribs(gl_private * private,const GLint * attribList,OSMesaContext sharelist)149 OSMesaContext APIENTRY internal_OSMesaCreateContextAttribs(gl_private *private, const GLint *attribList, OSMesaContext sharelist)
150 {
151 	if (!InstallHostCall()) {
152 		return NULL;
153 	}
154 
155 	return (OSMesaContext)(*HostCall_p)(NFOSMESA_OSMESACREATECONTEXTATTRIBS, private->cur_context, &attribList);
156 }
157 
internal_OSMesaDestroyContext(gl_private * private,OSMesaContext ctx)158 void APIENTRY internal_OSMesaDestroyContext(gl_private *private, OSMesaContext ctx)
159 {
160 	(*HostCall_p)(NFOSMESA_OSMESADESTROYCONTEXT, private->cur_context, &ctx);
161 	freeglGetString(private, ctx);
162 	if (ctx == private->cur_context)
163 		private->cur_context = 0;
164 }
165 
internal_OSMesaMakeCurrent(gl_private * private,OSMesaContext ctx,void * buffer,GLenum type,GLsizei width,GLsizei height)166 GLboolean APIENTRY internal_OSMesaMakeCurrent(gl_private *private, OSMesaContext ctx, void *buffer, GLenum type, GLsizei width, GLsizei height)
167 {
168 	GLboolean ret = (GLboolean)(*HostCall_p)(NFOSMESA_OSMESAMAKECURRENT, private->cur_context, &ctx);
169 	if (ret)
170 		private->cur_context = ctx;
171 	return ret;
172 }
173 
internal_OSMesaGetCurrentContext(gl_private * private)174 OSMesaContext APIENTRY internal_OSMesaGetCurrentContext(gl_private *private)
175 {
176 #if 0
177 	/*
178 	 * wrong; the host manages his current context for all processes using NFOSMesa;
179 	 * return local copy instead
180 	 */
181 	return (OSMesaContext)(*HostCall_p)(NFOSMESA_OSMESAGETCURRENTCONTEXT, private->cur_context, NULL);
182 #else
183 	return private->cur_context;
184 #endif
185 }
186 
internal_OSMesaPixelStore(gl_private * private,GLint pname,GLint value)187 void APIENTRY internal_OSMesaPixelStore(gl_private *private, GLint pname, GLint value)
188 {
189 	(*HostCall_p)(NFOSMESA_OSMESAPIXELSTORE, private->cur_context, &pname);
190 }
191 
internal_OSMesaGetIntegerv(gl_private * private,GLint pname,GLint * value)192 void APIENTRY internal_OSMesaGetIntegerv(gl_private *private, GLint pname, GLint *value)
193 {
194 	(*HostCall_p)(NFOSMESA_OSMESAGETINTEGERV, private->cur_context, &pname);
195 }
196 
internal_OSMesaGetDepthBuffer(gl_private * private,OSMesaContext c,GLint * width,GLint * height,GLint * bytesPerValue,void ** buffer)197 GLboolean APIENTRY internal_OSMesaGetDepthBuffer(gl_private *private, OSMesaContext c, GLint *width, GLint *height, GLint *bytesPerValue, void **buffer )
198 {
199 	return (GLboolean)(*HostCall_p)(NFOSMESA_OSMESAGETDEPTHBUFFER, private->cur_context, &c);
200 }
201 
internal_OSMesaGetColorBuffer(gl_private * private,OSMesaContext c,GLint * width,GLint * height,GLint * format,void ** buffer)202 GLboolean APIENTRY internal_OSMesaGetColorBuffer(gl_private *private, OSMesaContext c, GLint *width, GLint *height, GLint *format, void **buffer )
203 {
204 	return (GLboolean)(*HostCall_p)(NFOSMESA_OSMESAGETCOLORBUFFER, private->cur_context, &c);
205 }
206 
internal_OSMesaGetProcAddress(gl_private * private,const char * funcName)207 OSMESAproc APIENTRY internal_OSMesaGetProcAddress(gl_private *private, const char *funcName)
208 {
209 	long func = (*HostCall_p)(NFOSMESA_OSMESAGETPROCADDRESS, private->cur_context, &funcName);
210 	if (func == 0 || func > NFOSMESA_LAST)
211 		return 0;
212 	return (OSMESAproc)func;
213 }
214 
internal_OSMesaColorClamp(gl_private * private,GLboolean32 enable)215 void APIENTRY internal_OSMesaColorClamp(gl_private *private, GLboolean32 enable)
216 {
217 	(*HostCall_p)(NFOSMESA_OSMESACOLORCLAMP, private->cur_context, &enable);
218 }
219 
internal_OSMesaPostprocess(gl_private * private,OSMesaContext osmesa,const char * filter,GLuint enable_value)220 void APIENTRY internal_OSMesaPostprocess(gl_private *private, OSMesaContext osmesa, const char *filter, GLuint enable_value)
221 {
222 	(*HostCall_p)(NFOSMESA_OSMESAPOSTPROCESS, private->cur_context, &osmesa);
223 }
224 
225 
internal_glInit(gl_private * private)226 void internal_glInit(gl_private *private)
227 {
228 	unsigned int i, j;
229 
230 	if (!private)
231 		return;
232 	private->cur_context = 0;
233 	private->gl_exception = 0;
234 	for (i = 0; i < MAX_OSMESA_CONTEXTS; i++)
235 	{
236 		private->contexts[i].oldmesa_buffer = 0;
237 		for (j = 0; j < sizeof(private->contexts[i].gl_strings) / sizeof(private->contexts[i].gl_strings[0]); j++)
238 			private->contexts[i].gl_strings[j] = 0;
239 	}
240 	InstallHostCall();
241 }
242