Make the transition to script-genereated GLX code easier.
[mesa.git] / src / glx / x11 / glx_pbuffer.c
1 /*
2 * (C) Copyright IBM Corporation 2004
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file glx_pbuffer.c
27 * Implementation of pbuffer related functions.
28 *
29 * \author Ian Romanick <idr@us.ibm.com>
30 */
31
32 #include <inttypes.h>
33 #include "glxclient.h"
34 #include <extutil.h>
35 #include <Xext.h>
36 #include <assert.h>
37 #include <string.h>
38 #include "glapi.h"
39 #include "glxextensions.h"
40 #include "glcontextmodes.h"
41
42 #ifdef IN_DOXYGEN
43 #define GLX_PREFIX(x) x
44 #endif /* IN_DOXYGEN */
45
46 static void ChangeDrawableAttribute( Display * dpy, GLXDrawable drawable,
47 const CARD32 * attribs, size_t num_attribs );
48
49 static void DestroyPbuffer( Display * dpy, GLXDrawable drawable );
50
51 static GLXDrawable CreatePbuffer( Display *dpy,
52 const __GLcontextModes * fbconfig, unsigned int width, unsigned int height,
53 const int *attrib_list, GLboolean size_in_attribs );
54
55 static int GetDrawableAttribute( Display *dpy, GLXDrawable drawable,
56 int attribute, unsigned int *value );
57
58
59 /**
60 * Change a drawable's attribute.
61 *
62 * This function is used to implement \c glXSelectEvent and
63 * \c glXSelectEventSGIX.
64 *
65 * \note
66 * This function dynamically determines whether to use the SGIX_pbuffer
67 * version of the protocol or the GLX 1.3 version of the protocol.
68 *
69 * \todo
70 * This function needs to be modified to work with direct-rendering drivers.
71 */
72 static void
73 ChangeDrawableAttribute( Display * dpy, GLXDrawable drawable,
74 const CARD32 * attribs, size_t num_attribs )
75 {
76 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
77 CARD32 * output;
78
79
80 if ( (dpy == NULL) || (drawable == 0) ) {
81 return;
82 }
83
84
85 LockDisplay(dpy);
86
87 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
88 xGLXChangeDrawableAttributesReq *req;
89
90 GetReqExtra( GLXChangeDrawableAttributes, 8 + (8 * num_attribs), req );
91 output = (CARD32 *) (req + 1);
92
93 req->reqType = __glXSetupForCommand(dpy);
94 req->glxCode = X_GLXChangeDrawableAttributes;
95 req->drawable = drawable;
96 req->numAttribs = (CARD32) num_attribs;
97 }
98 else {
99 xGLXVendorPrivateWithReplyReq *vpreq;
100
101 GetReqExtra( GLXVendorPrivateWithReply, 4 + (8 * num_attribs), vpreq );
102 output = (CARD32 *) (vpreq + 1);
103
104 vpreq->reqType = __glXSetupForCommand(dpy);
105 vpreq->glxCode = X_GLXVendorPrivateWithReply;
106 vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX;
107
108 output[0] = (CARD32) drawable;
109 output++;
110 }
111
112 (void) memcpy( output, attribs, sizeof( CARD32 ) * 2 * num_attribs );
113
114 UnlockDisplay(dpy);
115 SyncHandle();
116
117 return;
118 }
119
120
121 /**
122 * Destroy a pbuffer.
123 *
124 * This function is used to implement \c glXDestroyPbuffer and
125 * \c glXDestroyGLXPbufferSGIX.
126 *
127 * \note
128 * This function dynamically determines whether to use the SGIX_pbuffer
129 * version of the protocol or the GLX 1.3 version of the protocol.
130 *
131 * \todo
132 * This function needs to be modified to work with direct-rendering drivers.
133 */
134 static void
135 DestroyPbuffer( Display * dpy, GLXDrawable drawable )
136 {
137 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
138
139 if ( (dpy == NULL) || (drawable == 0) ) {
140 return;
141 }
142
143
144 LockDisplay(dpy);
145
146 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
147 xGLXDestroyPbufferReq * req;
148
149 GetReqExtra( GLXDestroyPbuffer, 4, req );
150 req->reqType = __glXSetupForCommand(dpy);
151 req->glxCode = X_GLXDestroyPbuffer;
152 req->pbuffer = (GLXPbuffer) drawable;
153 }
154 else {
155 xGLXVendorPrivateWithReplyReq *vpreq;
156 CARD32 * data;
157
158 GetReqExtra( GLXVendorPrivateWithReply, 4, vpreq );
159 data = (CARD32 *) (vpreq + 1);
160
161 data[0] = (CARD32) drawable;
162
163 vpreq->reqType = __glXSetupForCommand(dpy);
164 vpreq->glxCode = X_GLXVendorPrivateWithReply;
165 vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX;
166 }
167
168 UnlockDisplay(dpy);
169 SyncHandle();
170
171 return;
172 }
173
174
175 /**
176 * Get a drawable's attribute.
177 *
178 * This function is used to implement \c glXGetSelectedEvent and
179 * \c glXGetSelectedEventSGIX.
180 *
181 * \note
182 * This function dynamically determines whether to use the SGIX_pbuffer
183 * version of the protocol or the GLX 1.3 version of the protocol.
184 *
185 * \todo
186 * The number of attributes returned is likely to be small, probably less than
187 * 10. Given that, this routine should try to use an array on the stack to
188 * capture the reply rather than always calling Xmalloc.
189 *
190 * \todo
191 * This function needs to be modified to work with direct-rendering drivers.
192 */
193 static int
194 GetDrawableAttribute( Display *dpy, GLXDrawable drawable,
195 int attribute, unsigned int *value )
196 {
197 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
198 xGLXGetDrawableAttributesReply reply;
199 CARD32 * data;
200 unsigned int length;
201 unsigned int i;
202 unsigned int num_attributes;
203 GLboolean use_glx_1_3 = ((priv->majorVersion > 1)
204 || (priv->minorVersion >= 3));
205
206
207 if ( (dpy == NULL) || (drawable == 0) ) {
208 return 0;
209 }
210
211
212 LockDisplay(dpy);
213
214 if ( use_glx_1_3 ) {
215 xGLXGetDrawableAttributesReq *req;
216
217 GetReqExtra( GLXGetDrawableAttributes, 4, req );
218 req->reqType = __glXSetupForCommand(dpy);
219 req->glxCode = X_GLXGetDrawableAttributes;
220 req->drawable = drawable;
221 }
222 else {
223 xGLXVendorPrivateWithReplyReq *vpreq;
224
225 GetReqExtra( GLXVendorPrivateWithReply, 4, vpreq );
226 data = (CARD32 *) (vpreq + 1);
227 data[0] = (CARD32) drawable;
228
229 vpreq->reqType = __glXSetupForCommand(dpy);
230 vpreq->glxCode = X_GLXVendorPrivateWithReply;
231 vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
232 }
233
234 _XReply(dpy, (xReply*) &reply, 0, False);
235
236 length = reply.length;
237 num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2;
238 data = (CARD32 *) Xmalloc( length * sizeof(CARD32) );
239 if ( data == NULL ) {
240 /* Throw data on the floor */
241 _XEatData(dpy, length);
242 } else {
243 _XRead(dpy, (char *)data, length * sizeof(CARD32) );
244 }
245
246 UnlockDisplay(dpy);
247 SyncHandle();
248
249
250 /* Search the set of returned attributes for the attribute requested by
251 * the caller.
252 */
253
254 for ( i = 0 ; i < num_attributes ; i++ ) {
255 if ( data[i*2] == attribute ) {
256 *value = data[ (i*2) + 1 ];
257 break;
258 }
259 }
260
261 Xfree( data );
262
263 return 0;
264 }
265
266
267 /**
268 * Create a non-pbuffer GLX drawable.
269 *
270 * \todo
271 * This function needs to be modified to work with direct-rendering drivers.
272 */
273 static GLXDrawable
274 CreateDrawable( Display *dpy, const __GLcontextModes * fbconfig,
275 Drawable drawable, const int *attrib_list,
276 CARD8 glxCode )
277 {
278 xGLXCreateWindowReq * req;
279 CARD32 * data;
280 unsigned int i;
281
282
283 for ( i = 0 ; attrib_list[i * 2] != None ; i++ )
284 /* empty */ ;
285
286 LockDisplay(dpy);
287 GetReqExtra( GLXCreateWindow, 20 + (8 * i), req );
288 data = (CARD32 *) (req + 1);
289
290 req->reqType = __glXSetupForCommand(dpy);
291 req->glxCode = glxCode;
292 req->screen = (CARD32) fbconfig->screen;
293 req->fbconfig = fbconfig->fbconfigID;
294 req->window = (GLXPbuffer) drawable;
295 req->numAttribs = (CARD32) i;
296
297 UnlockDisplay(dpy);
298 SyncHandle();
299
300 return drawable;
301 }
302
303
304 /**
305 * Destroy a non-pbuffer GLX drawable.
306 *
307 * \todo
308 * This function needs to be modified to work with direct-rendering drivers.
309 */
310 static void
311 DestroyDrawable( Display * dpy, GLXDrawable drawable, CARD32 glxCode )
312 {
313 xGLXDestroyPbufferReq * req;
314
315 if ( (dpy == NULL) || (drawable == 0) ) {
316 return;
317 }
318
319
320 LockDisplay(dpy);
321
322 GetReqExtra( GLXDestroyPbuffer, 4, req );
323 req->reqType = __glXSetupForCommand(dpy);
324 req->glxCode = glxCode;
325 req->pbuffer = (GLXPbuffer) drawable;
326
327 UnlockDisplay(dpy);
328 SyncHandle();
329
330 return;
331 }
332
333
334 /**
335 * Create a pbuffer.
336 *
337 * This function is used to implement \c glXCreatePbuffer and
338 * \c glXCreateGLXPbufferSGIX.
339 *
340 * \note
341 * This function dynamically determines whether to use the SGIX_pbuffer
342 * version of the protocol or the GLX 1.3 version of the protocol.
343 *
344 * \todo
345 * This function needs to be modified to work with direct-rendering drivers.
346 */
347 static GLXDrawable
348 CreatePbuffer( Display *dpy, const __GLcontextModes * fbconfig,
349 unsigned int width, unsigned int height,
350 const int *attrib_list, GLboolean size_in_attribs )
351 {
352 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
353 GLXDrawable id = 0;
354 CARD32 * data;
355 unsigned int i;
356
357
358 for ( i = 0 ; attrib_list[i * 2] != None ; i++ )
359 /* empty */ ;
360
361
362 LockDisplay(dpy);
363 id = XAllocID(dpy);
364
365 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
366 xGLXCreatePbufferReq * req;
367 unsigned int extra = (size_in_attribs) ? 0 : 2;
368
369 GetReqExtra( GLXCreatePbuffer, (8 * (i + extra)), req );
370 data = (CARD32 *) (req + 1);
371
372 req->reqType = __glXSetupForCommand(dpy);
373 req->glxCode = X_GLXCreatePbuffer;
374 req->screen = (CARD32) fbconfig->screen;
375 req->fbconfig = fbconfig->fbconfigID;
376 req->pbuffer = (GLXPbuffer) id;
377 req->numAttribs = (CARD32) (i + extra);
378
379 if ( ! size_in_attribs ) {
380 data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
381 data[(2 * i) + 1] = width;
382 data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
383 data[(2 * i) + 3] = height;
384 data += 4;
385 }
386 }
387 else {
388 xGLXVendorPrivateReq *vpreq;
389
390 GetReqExtra( GLXVendorPrivate, 20 + (8 * i), vpreq );
391 data = (CARD32 *) (vpreq + 1);
392
393 vpreq->reqType = __glXSetupForCommand(dpy);
394 vpreq->glxCode = X_GLXVendorPrivate;
395 vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
396
397 data[0] = (CARD32) fbconfig->screen;
398 data[1] = (CARD32) fbconfig->fbconfigID;
399 data[2] = (CARD32) id;
400 data[3] = (CARD32) width;
401 data[4] = (CARD32) height;
402 data += 5;
403 }
404
405 (void) memcpy( data, attrib_list, sizeof(CARD32) * 2 * i );
406
407 UnlockDisplay(dpy);
408 SyncHandle();
409
410 return id;
411 }
412
413
414 /**
415 * Create a new pbuffer.
416 */
417 GLXPbufferSGIX
418 GLX_PREFIX(glXCreateGLXPbufferSGIX)(Display *dpy, GLXFBConfigSGIX config,
419 unsigned int width, unsigned int height,
420 int *attrib_list)
421 {
422 return (GLXPbufferSGIX) CreatePbuffer( dpy, (__GLcontextModes *) config,
423 width, height,
424 attrib_list, GL_FALSE );
425 }
426
427
428 /**
429 * Create a new pbuffer.
430 */
431 GLXPbuffer
432 GLX_PREFIX(glXCreatePbuffer)(Display *dpy, GLXFBConfig config,
433 const int *attrib_list)
434 {
435 return (GLXPbuffer) CreatePbuffer( dpy, (__GLcontextModes *) config,
436 0, 0,
437 attrib_list, GL_TRUE );
438 }
439
440
441 /**
442 * Destroy an existing pbuffer.
443 */
444 void
445 GLX_PREFIX(glXDestroyPbuffer)(Display *dpy, GLXPbuffer pbuf)
446 {
447 DestroyPbuffer( dpy, pbuf );
448 }
449
450
451 /**
452 * Query an attribute of a drawable.
453 */
454 void
455 GLX_PREFIX(glXQueryDrawable)(Display *dpy, GLXDrawable drawable,
456 int attribute, unsigned int *value)
457 {
458 GetDrawableAttribute( dpy, drawable, attribute, value );
459 }
460
461
462 /**
463 * Query an attribute of a pbuffer.
464 */
465 int
466 GLX_PREFIX(glXQueryGLXPbufferSGIX)(Display *dpy, GLXPbufferSGIX drawable,
467 int attribute, unsigned int *value)
468 {
469 return GetDrawableAttribute( dpy, drawable, attribute, value );
470 }
471
472
473 /**
474 * Select the event mask for a drawable.
475 */
476 void
477 GLX_PREFIX(glXSelectEvent)(Display *dpy, GLXDrawable drawable,
478 unsigned long mask)
479 {
480 CARD32 attribs[2];
481
482 attribs[0] = (CARD32) GLX_EVENT_MASK;
483 attribs[1] = (CARD32) mask;
484
485 ChangeDrawableAttribute( dpy, drawable, attribs, 1 );
486 }
487
488
489 /**
490 * Get the selected event mask for a drawable.
491 */
492 void
493 GLX_PREFIX(glXGetSelectedEvent)(Display *dpy, GLXDrawable drawable,
494 unsigned long *mask)
495 {
496 unsigned int value;
497
498
499 /* The non-sense with value is required because on LP64 platforms
500 * sizeof(unsigned int) != sizeof(unsigned long). On little-endian
501 * we could just type-cast the pointer, but why?
502 */
503
504 GetDrawableAttribute( dpy, drawable, GLX_EVENT_MASK_SGIX, & value );
505 *mask = value;
506 }
507
508
509 GLXPixmap
510 GLX_PREFIX(glXCreatePixmap)( Display *dpy, GLXFBConfig config, Pixmap pixmap,
511 const int *attrib_list )
512 {
513 return CreateDrawable( dpy, (__GLcontextModes *) config,
514 (Drawable) pixmap, attrib_list,
515 X_GLXCreatePixmap );
516 }
517
518
519 GLXWindow
520 GLX_PREFIX(glXCreateWindow)( Display *dpy, GLXFBConfig config, Window win,
521 const int *attrib_list )
522 {
523 return CreateDrawable( dpy, (__GLcontextModes *) config,
524 (Drawable) win, attrib_list,
525 X_GLXCreateWindow );
526 }
527
528
529 void
530 GLX_PREFIX(glXDestroyPixmap)(Display *dpy, GLXPixmap pixmap)
531 {
532 DestroyDrawable( dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap );
533 }
534
535
536 void
537 GLX_PREFIX(glXDestroyWindow)(Display *dpy, GLXWindow win)
538 {
539 DestroyDrawable( dpy, (GLXDrawable) win, X_GLXDestroyWindow );
540 }
541
542
543 GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
544 (Display *dpy, GLXPbufferSGIX pbuf),
545 (dpy, pbuf),
546 glXDestroyPbuffer)
547
548 GLX_ALIAS_VOID(glXSelectEventSGIX,
549 (Display *dpy, GLXDrawable drawable, unsigned long mask),
550 (dpy, drawable, mask),
551 glXSelectEvent)
552
553 GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
554 (Display *dpy, GLXDrawable drawable, unsigned long *mask),
555 (dpy, drawable, mask),
556 glXGetSelectedEvent)