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

Last change on this file since 2661 was 2595, checked in by sandervl, 26 years ago

JvdH:Ported SGI GLUT sources + Opengl update

File size: 11.0 KB
Line 
1/* $Id: glucb32.cpp,v 1.2 2000-02-01 19:41:54 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 APIRET rc;
64 int i;
65
66 glucb=(GLUCB *)malloc(sizeof(GLUCB));
67
68 glucb->objtype=objtype;
69 glucb->object=object;
70 glucb->which=which;
71 glucb->parms_on_stack=num_parms;
72
73 rc=DosAllocMem((PPVOID)(&glucb->entryAddress),
74 4096,
75 PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE);
76
77 /* Setup the actual machine-code in this page... */
78 /* Insert a number of 'PUSH DWORD PTR [ESP+08H]' to set the stack */
79 for(i=0; i<num_parms; i++)
80 ((ULONG *)((BYTE *)glucb->entryAddress))[i]=0x082474FF;
81
82 /* Insert a CALL instruction */
83 ((BYTE *)glucb->entryAddress)[num_parms*4]=0xE8;
84 /* Next 4 bytes will eventually hold return address! */
85 /* Finally insert a RET instruction */
86 ((BYTE *)glucb->entryAddress)[num_parms*4+5]=0xC3;
87
88 glucb->Next=Glucbs;
89
90 Glucbs=glucb;
91
92 return glucb;
93}
94
95void OS2glucbDestroyGlucb(GLUCB *glucb)
96{
97 /* Destroy a glucb! */
98 GLUCB *glucbPrev;
99
100 if(glucb==Glucbs)
101 glucbPrev=NULL;
102 else
103 {
104 /* Don't check pointer - it must exist so there is at least one Glucbs member */
105 glucbPrev=Glucbs;
106
107 while(glucbPrev->Next!=glucb)
108 glucbPrev=glucbPrev->Next;
109 }
110
111 DosFreeMem(glucb->entryAddress);
112
113 if(glucbPrev)
114 glucbPrev->Next=glucb->Next;
115 else
116 Glucbs=glucb->Next;
117
118 free(glucb);
119}
120
121void OS2glucbSetGlucbAddress(GLUCB *glucb,GLvoid (* WIN32API Address)())
122{
123 ULONG addr=(ULONG)Address;
124 ULONG addr_call=4*glucb->parms_on_stack+1;
125 BYTE *code=(BYTE *)glucb->entryAddress;
126 ULONG addr_e=(ULONG)code+addr_call;
127 LONG addr_offset=addr-addr_e-4;
128
129 (((ULONG *)addr_e)[0])=addr_offset;
130}
131
132GLUOS2CALLBACK OS2glucbGenerateCallbackFunc(GLbyte objtype,
133 void *object,
134 GLenum which,
135 GLUWINCALLBACK CallBackFunc,
136 int NumParameters)
137{
138 /* NOTE: All parms are 4-byte in size */
139 GLUCB *glucb;
140
141 DosRequestMutexSem(hmtxGlucb,SEM_INDEFINITE_WAIT);
142
143 glucb=OS2glucbQueryGlucb(objtype,object,which);
144
145 if(glucb)
146 {
147 if(CallBackFunc)
148 {
149 OS2glucbSetGlucbAddress(glucb,CallBackFunc);
150
151 DosReleaseMutexSem(hmtxGlucb);
152
153 return glucb->entryAddress;
154 }
155 else
156 {
157 OS2glucbDestroyGlucb(glucb);
158
159 DosReleaseMutexSem(hmtxGlucb);
160
161 return 0;
162 }
163 }
164 else
165 {
166 if(CallBackFunc)
167 {
168 /* Setup a page in memory with the required code */
169 glucb=OS2glucbCreateGlucb(objtype,object,which,NumParameters);
170
171 OS2glucbSetGlucbAddress(glucb,CallBackFunc);
172
173 DosReleaseMutexSem(hmtxGlucb);
174
175 return glucb->entryAddress;
176 }
177 else
178 dprintf(("GLUCALLBACK (ERROR): Callback remove, but no callback registered!\n"));
179 }
180
181 DosReleaseMutexSem(hmtxGlucb);
182
183 return 0;
184}
185
186/*****************************************************************************/
187/* */
188/* OS2glucbRegisterCallback sets up a memory page with machine code. */
189/* */
190/* When called from GLU the object type is GLUCB_TESS, GLUCB_NURBS or */
191/* GLUCB_QUADRIC and the parameters are self explanatory. The number of */
192/* params on the stack is determined by this code. If the function is called */
193/* by GLUT the objtype is GLUTCB_xxxx, and the object points to the WINDOW */
194/* the resistration was required for. */
195/* */
196/*****************************************************************************/
197
198GLUOS2CALLBACK OS2glucbRegisterCallback(GLbyte objtype,
199 void *object,
200 GLenum which,
201 GLUWINCALLBACK CallBackFunc)
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_END:
231 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,0);
232
233 case GLU_TESS_BEGIN:
234 case GLU_TESS_EDGE_FLAG:
235 case GLU_TESS_END_DATA:
236 case GLU_TESS_ERROR:
237 case GLU_TESS_VERTEX:
238 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,1);
239
240 case GLU_TESS_BEGIN_DATA:
241 case GLU_TESS_EDGE_FLAG_DATA:
242 case GLU_TESS_ERROR_DATA:
243 case GLU_TESS_VERTEX_DATA:
244 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,2);
245
246 case GLU_TESS_COMBINE:
247 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,4);
248
249 case GLU_TESS_COMBINE_DATA:
250 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,5);
251
252 default: /* All legal callback values defined!*/
253 return 0;
254 }
255 break;
256
257 case GLUTCB_DISPLAY:
258 case GLUTCB_IDLE:
259 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,0);
260
261 case GLUTCB_MENUSTATE:
262 case GLUTCB_VISIBILITY:
263 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,1);
264
265 case GLUTCB_PASSIVEMOTION:
266 case GLUTCB_RESHAPE:
267 case GLUTCB_MOTION:
268 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,2);
269
270 case GLUTCB_KEYBOARD:
271 case GLUTCB_SPECIAL:
272 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,3);
273
274 case GLUTCB_MOUSE:
275 return OS2glucbGenerateCallbackFunc(objtype,object,which,CallBackFunc,4);
276
277 case GLUTCB_MENU: /* Special case - do not deregister existing ones!*/
278 case GLUTCB_TIMER:/* Timers cannot be deregistered - simply add one !*/
279 {
280 GLUCB *glucb;
281
282 DosRequestMutexSem(hmtxGlucb,SEM_INDEFINITE_WAIT);
283
284 glucb=OS2glucbCreateGlucb(GLUTCB_TIMER,0,0,1);
285
286 OS2glucbSetGlucbAddress(glucb,CallBackFunc);
287
288 DosReleaseMutexSem(hmtxGlucb);
289
290 return glucb->entryAddress;
291 }
292
293 default:
294 dprintf(("GLUCALLBACK: Default action in SWITCH!\n"));
295 break;
296 }
297
298 return 0;
299}
300
301void OS2glucbDestroyCallbackForObject(GLbyte objtype,
302 void *object)
303{
304 GLUCB *glucb,*glucbNext;
305
306 DosRequestMutexSem(hmtxGlucb,SEM_INDEFINITE_WAIT);
307
308 glucb=Glucbs;
309
310 if(!glucb)
311 return;
312
313 do{
314 glucbNext=glucb->Next;
315
316 if(objtype==GLUT_OBJECT)
317 {
318 if(glucb->object==object)
319 OS2glucbDestroyGlucb(glucb);
320 }
321 else
322 if(glucb->objtype==objtype &&
323 glucb->object==object)
324 OS2glucbDestroyGlucb(glucb);
325
326 glucb=glucbNext;
327 }while(glucb);
328
329 DosReleaseMutexSem(hmtxGlucb);
330}
331
332void OS2glucbDestroyCallbackForObjectWhich(GLbyte objtype,
333 void *object,
334 GLenum which)
335{
336 GLUCB *glucb,*glucbNext;
337
338 DosRequestMutexSem(hmtxGlucb,SEM_INDEFINITE_WAIT);
339
340 glucb=Glucbs;
341
342 if(!glucb)
343 return;
344
345 do{
346 glucbNext=glucb->Next;
347
348 if(glucb->objtype==objtype &&
349 glucb->object==object &&
350 glucb->which==which)
351 OS2glucbDestroyGlucb(glucb);
352
353 glucb=glucbNext;
354 }while(glucb);
355
356 DosReleaseMutexSem(hmtxGlucb);
357}
358
359void OS2glucbSetWhich(GLUOS2CALLBACK pfn,GLenum which)
360{
361 GLUCB *glucb;
362
363 DosRequestMutexSem(hmtxGlucb,SEM_INDEFINITE_WAIT);
364
365 glucb=Glucbs;
366
367 while(glucb)
368 {
369 if(glucb->entryAddress==pfn)
370
371 {
372 glucb->which=which;
373
374 DosReleaseMutexSem(hmtxGlucb);
375 return;
376 }
377
378 glucb=glucb->Next;
379 }
380
381 DosReleaseMutexSem(hmtxGlucb);
382}
Note: See TracBrowser for help on using the repository browser.