source: trunk/src/opengl/glucb32.cpp@ 2592

Last change on this file since 2592 was 2532, checked in by sandervl, 26 years ago

JvdH: Created opengl dll

File size: 10.8 KB
Line 
1/* $Id: glucb32.cpp,v 1.1 2000-01-27 21:49:12 sandervl Exp $ */
2/*****************************************************************************/
3/* */
4/* GLU/GLUT callback handler */
5/* */
6/* Both GLU and GLUT make heavy use of callbacks to notify the application */
7/* of certain events. The event is registered for an object, and only an */
8/* event code is passed back to the application. Since *no* object or other */
9/* handle is passed back, we have no way of determining where to dispatch */
10/* the event to! Directly calling into the application wreaks havoc, since */
11/* the calling convention is different, and hence we'll nuke the stack!! */
12/* */
13/* The code herein allocates a memory page and dynamically generates machine */
14/* code to push the parameters on the stack, call the registered EP and */
15/* return. */
16/* */
17/*****************************************************************************/
18
19#define INCL_BASE
20#include <os2.h>
21#include <os2wrap.h>
22#include <misc.h>
23#include <malloc.h>
24#include "glos2.h"
25#include "gluos2.h"
26#include "glucb32.h"
27
28/*****************************************************************************/
29/* */
30/* Globals - exported */
31/* */
32/*****************************************************************************/
33
34HMTX hmtxGlucb;
35GLUCB *Glucbs = NULL;
36
37/*****************************************************************************/
38/* */
39/* Callback Handler - Pass on the call to the registered functions */
40/* */
41/*****************************************************************************/
42
43GLUCB *OS2glucbQueryGlucb(GLbyte objtype,void *object,GLenum which)
44{
45 GLUCB *glucb=Glucbs;
46
47 while(glucb)
48 {
49 if(glucb->objtype==objtype &&
50 glucb->object==object &&
51 glucb->which==which)
52 return glucb;
53
54 glucb=glucb->Next;
55 }
56
57 return NULL;
58}
59
60GLUCB *OS2glucbCreateGlucb(GLenum objtype,void *object,GLenum which,GLint num_parms)
61{
62 GLUCB *glucb;
63 int i;
64
65 glucb=(GLUCB *)malloc(sizeof(GLUCB));
66
67 glucb->objtype=objtype;
68 glucb->object=object;
69 glucb->which=which;
70 glucb->parms_on_stack=num_parms;
71
72 DosAllocMem((PPVOID)(&glucb->entryAddress),
73 4096,
74 PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE);
75
76 /* Setup the actual machine-code in this page... */
77 /* Insert a number of 'PUSH DWORD PTR [ESP+08H]' to set the stack */
78 for(i=0; i<num_parms; i++)
79 ((ULONG *)((BYTE *)glucb->entryAddress))[i]=0x082474FF;
80
81 /* Insert a CALL instruction */
82 ((BYTE *)glucb->entryAddress)[num_parms*4]=0xE8;
83 /* Next 4 bytes will eventually hold return address! */
84 /* Finally insert a RET instruction */
85 ((BYTE *)glucb->entryAddress)[num_parms*4+5]=0xC3;
86
87 glucb->Next=Glucbs;
88
89 Glucbs=glucb;
90
91 return glucb;
92}
93
94void OS2glucbDestroyGlucb(GLUCB *glucb)
95{
96 /* Destroy a glucb! */
97 GLUCB *glucbPrev;
98
99 if(glucb==Glucbs)
100 glucbPrev=NULL;
101 else
102 {
103 /* Don't check pointer - it must exist so there is at least one Glucbs member */
104 glucbPrev=Glucbs;
105
106 while(glucbPrev->Next!=glucb)
107 glucbPrev=glucbPrev->Next;
108 }
109
110 DosFreeMem(glucb->entryAddress);
111
112 if(glucbPrev)
113 glucbPrev->Next=glucb->Next;
114 else
115 Glucbs=glucb->Next;
116
117 free(glucb);
118}
119
120void OS2glucbSetGlucbAddress(GLUCB *glucb,GLvoid (* WIN32API Address)())
121{
122 ULONG addr=(ULONG)Address;
123 ULONG addr_e=(ULONG)glucb->entryAddress+4*glucb->parms_on_stack;
124 ULONG addr_offset=addr_e-addr-5;
125 BYTE *code=(BYTE *)glucb->entryAddress;
126
127 *((ULONG *)code[addr_e+1])=addr_offset;
128}
129
130GLUOS2CALLBACK OS2glucbGenerateCallbackFunc(GLbyte objtype,
131 void *object,
132 GLenum which,
133 GLUWINCALLBACK CallBackFunc,
134 int NumParameters)
135{
136 /* NOTE: All parms are 4-byte in size */
137 GLUCB *glucb;
138
139 DosRequestMutexSem(hmtxGlucb,SEM_INDEFINITE_WAIT);
140
141 glucb=OS2glucbQueryGlucb(objtype,object,which);
142
143 if(glucb)
144 {
145 if(CallBackFunc)
146 {
147 OS2glucbSetGlucbAddress(glucb,CallBackFunc);
148
149 DosReleaseMutexSem(hmtxGlucb);
150
151 return glucb->entryAddress;
152 }
153 else
154 {
155 OS2glucbDestroyGlucb(glucb);
156
157 DosReleaseMutexSem(hmtxGlucb);
158
159 return 0;
160 }
161 }
162 else
163 {
164 if(CallBackFunc)
165 {
166 /* Setup a page in memory with the required code */
167 glucb=OS2glucbCreateGlucb(objtype,object,which,NumParameters);
168
169 OS2glucbSetGlucbAddress(glucb,CallBackFunc);
170
171 DosReleaseMutexSem(hmtxGlucb);
172
173 return glucb->entryAddress;
174 }
175 else
176 dprintf(("GLUCALLBACK (ERROR): Callback remove, but no callback registered!\n"));
177 }
178
179 DosReleaseMutexSem(hmtxGlucb);
180
181 return 0;
182}
183
184/*****************************************************************************/
185/* */
186/* OS2glucbRegisterCallback sets up a memory page with machine code. */
187/* */
188/* When called from GLU the object type is GLUCB_TESS, GLUCB_NURBS or */
189/* GLUCB_QUADRIC and the parameters are self explanatory. The number of */
190/* params on the stack is determined by this code. If the function is called */
191/* by GLUT the objtype is GLUTCB_xxxx, and the object points to the WINDOW */
192/* the resistration was required for. */
193/* */
194/*****************************************************************************/
195
196GLUOS2CALLBACK OS2glucbRegisterCallback(GLbyte objtype,
197 void *object,
198 GLenum which,
199 GLUWINCALLBACK CallBackFunc)
200{
201 dprintf(("GLUCALLBACK: Registering Callback!\n"));
202
203 switch(objtype)
204 {
205 case GLUCB_NURBS:
206 switch (which)
207 {
208 case GLU_ERROR:
209 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,1);
210
211 default: /* All legal callback values defined!*/
212 return 0;
213 }
214 break;
215
216 case GLUCB_QUADRIC:
217 switch (which)
218 {
219 case GLU_ERROR:
220 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,1);
221
222 default: /* All legal callback values defined!*/
223 return 0;
224 }
225 break;
226
227 case GLUCB_TESS:
228 switch (which)
229 {
230 case GLU_TESS_BEGIN:
231 case GLU_TESS_VERTEX:
232 case GLU_TESS_ERROR:
233 case GLU_TESS_EDGE_FLAG:
234 case GLU_TESS_COMBINE:
235 case GLU_TESS_BEGIN_DATA:
236 case GLU_TESS_VERTEX_DATA:
237 case GLU_TESS_END_DATA:
238 case GLU_TESS_ERROR_DATA:
239 case GLU_TESS_EDGE_FLAG_DATA:
240 case GLU_TESS_COMBINE_DATA:
241 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,1);
242
243 case GLU_TESS_END:
244 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,0);
245
246 default: /* All legal callback values defined!*/
247 return 0;
248 }
249 break;
250
251 case GLUTCB_DISPLAY:
252 case GLUTCB_IDLE:
253 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,0);
254
255 case GLUTCB_MENUSTATE:
256 case GLUTCB_VISIBILITY:
257 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,1);
258
259 case GLUTCB_PASSIVEMOTION:
260 case GLUTCB_RESHAPE:
261 case GLUTCB_MOTION:
262 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,2);
263
264 case GLUTCB_KEYBOARD:
265 case GLUTCB_SPECIAL:
266 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,3);
267
268 case GLUTCB_MOUSE:
269 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,4);
270
271 case GLUTCB_MENU: /* Special case - do not deregister existing ones!*/
272 case GLUTCB_TIMER:/* Timers cannot be deregistered - simply add one !*/
273 {
274 GLUCB *glucb;
275
276 DosRequestMutexSem(hmtxGlucb,SEM_INDEFINITE_WAIT);
277
278 glucb=OS2glucbCreateGlucb(GLUTCB_TIMER,0,0,1);
279
280 OS2glucbSetGlucbAddress(glucb,CallBackFunc);
281
282 DosReleaseMutexSem(hmtxGlucb);
283
284 return glucb->entryAddress;
285 }
286
287 default:
288 dprintf(("GLUCALLBACK: Default action in SWITCH!\n"));
289 break;
290 }
291
292 return 0;
293}
294
295void OS2glucbDestroyCallbackForObject(GLbyte objtype,
296 void *object)
297{
298 GLUCB *glucb,*glucbNext;
299
300 DosRequestMutexSem(hmtxGlucb,SEM_INDEFINITE_WAIT);
301
302 glucb=Glucbs;
303
304 if(!glucb)
305 return;
306
307 do{
308 glucbNext=glucb->Next;
309
310 if(objtype==GLUT_OBJECT)
311 {
312 if(glucb->object==object)
313 OS2glucbDestroyGlucb(glucb);
314 }
315 else
316 if(glucb->objtype==objtype &&
317 glucb->object==object)
318 OS2glucbDestroyGlucb(glucb);
319
320 glucb=glucbNext;
321 }while(glucb);
322
323 DosReleaseMutexSem(hmtxGlucb);
324}
325
326void OS2glucbDestroyCallbackForObjectWhich(GLbyte objtype,
327 void *object,
328 GLenum which)
329{
330 GLUCB *glucb,*glucbNext;
331
332 DosRequestMutexSem(hmtxGlucb,SEM_INDEFINITE_WAIT);
333
334 glucb=Glucbs;
335
336 if(!glucb)
337 return;
338
339 do{
340 glucbNext=glucb->Next;
341
342 if(glucb->objtype==objtype &&
343 glucb->object==object &&
344 glucb->which==which)
345 OS2glucbDestroyGlucb(glucb);
346
347 glucb=glucbNext;
348 }while(glucb);
349
350 DosReleaseMutexSem(hmtxGlucb);
351}
352
353void OS2glucbSetWhich(GLUOS2CALLBACK pfn,GLenum which)
354{
355 GLUCB *glucb;
356
357 DosRequestMutexSem(hmtxGlucb,SEM_INDEFINITE_WAIT);
358
359 glucb=Glucbs;
360
361 while(glucb)
362 {
363 if(glucb->entryAddress==pfn)
364
365 {
366 glucb->which=which;
367
368 DosReleaseMutexSem(hmtxGlucb);
369 return;
370 }
371
372 glucb=glucb->Next;
373 }
374
375 DosReleaseMutexSem(hmtxGlucb);
376}
Note: See TracBrowser for help on using the repository browser.