Remove the last remnants of GLX_BUILT_IN_XMESA. This allows the removal of
[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 #include "glheader.h"
42
43 static void ChangeDrawableAttribute( Display * dpy, GLXDrawable drawable,
44 const CARD32 * attribs, size_t num_attribs );
45
46 static void DestroyPbuffer( Display * dpy, GLXDrawable drawable );
47
48 static GLXDrawable CreatePbuffer( Display *dpy,
49 const __GLcontextModes * fbconfig, unsigned int width, unsigned int height,
50 const int *attrib_list, GLboolean size_in_attribs );
51
52 static int GetDrawableAttribute( Display *dpy, GLXDrawable drawable,
53 int attribute, unsigned int *value );
54
55
56 /**
57 * Change a drawable's attribute.
58 *
59 * This function is used to implement \c glXSelectEvent and
60 * \c glXSelectEventSGIX.
61 *
62 * \note
63 * This function dynamically determines whether to use the SGIX_pbuffer
64 * version of the protocol or the GLX 1.3 version of the protocol.
65 *
66 * \todo
67 * This function needs to be modified to work with direct-rendering drivers.
68 */
69 static void
70 ChangeDrawableAttribute( Display * dpy, GLXDrawable drawable,
71 const CARD32 * attribs, size_t num_attribs )
72 {
73 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
74 CARD32 * output;
75
76
77 if ( (dpy == NULL) || (drawable == 0) ) {
78 return;
79 }
80
81
82 LockDisplay(dpy);
83
84 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
85 xGLXChangeDrawableAttributesReq *req;
86
87 GetReqExtra( GLXChangeDrawableAttributes, 8 + (8 * num_attribs), req );
88 output = (CARD32 *) (req + 1);
89
90 req->reqType = __glXSetupForCommand(dpy);
91 req->glxCode = X_GLXChangeDrawableAttributes;
92 req->drawable = drawable;
93 req->numAttribs = (CARD32) num_attribs;
94 }
95 else {
96 xGLXVendorPrivateWithReplyReq *vpreq;
97
98 GetReqExtra( GLXVendorPrivateWithReply, 4 + (8 * num_attribs), vpreq );
99 output = (CARD32 *) (vpreq + 1);
100
101 vpreq->reqType = __glXSetupForCommand(dpy);
102 vpreq->glxCode = X_GLXVendorPrivateWithReply;
103 vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX;
104
105 output[0] = (CARD32) drawable;
106 output++;
107 }
108
109 (void) memcpy( output, attribs, sizeof( CARD32 ) * 2 * num_attribs );
110
111 UnlockDisplay(dpy);
112 SyncHandle();
113
114 return;
115 }
116
117
118 /**
119 * Destroy a pbuffer.
120 *
121 * This function is used to implement \c glXDestroyPbuffer and
122 * \c glXDestroyGLXPbufferSGIX.
123 *
124 * \note
125 * This function dynamically determines whether to use the SGIX_pbuffer
126 * version of the protocol or the GLX 1.3 version of the protocol.
127 *
128 * \todo
129 * This function needs to be modified to work with direct-rendering drivers.
130 */
131 static void
132 DestroyPbuffer( Display * dpy, GLXDrawable drawable )
133 {
134 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
135
136 if ( (dpy == NULL) || (drawable == 0) ) {
137 return;
138 }
139
140
141 LockDisplay(dpy);
142
143 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
144 xGLXDestroyPbufferReq * req;
145
146 GetReqExtra( GLXDestroyPbuffer, 4, req );
147 req->reqType = __glXSetupForCommand(dpy);
148 req->glxCode = X_GLXDestroyPbuffer;
149 req->pbuffer = (GLXPbuffer) drawable;
150 }
151 else {
152 xGLXVendorPrivateWithReplyReq *vpreq;
153 CARD32 * data;
154
155 GetReqExtra( GLXVendorPrivateWithReply, 4, vpreq );
156 data = (CARD32 *) (vpreq + 1);
157
158 data[0] = (CARD32) drawable;
159
160 vpreq->reqType = __glXSetupForCommand(dpy);
161 vpreq->glxCode = X_GLXVendorPrivateWithReply;
162 vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX;
163 }
164
165 UnlockDisplay(dpy);
166 SyncHandle();
167
168 return;
169 }
170
171
172 /**
173 * Get a drawable's attribute.
174 *
175 * This function is used to implement \c glXGetSelectedEvent and
176 * \c glXGetSelectedEventSGIX.
177 *
178 * \note
179 * This function dynamically determines whether to use the SGIX_pbuffer
180 * version of the protocol or the GLX 1.3 version of the protocol.
181 *
182 * \todo
183 * The number of attributes returned is likely to be small, probably less than
184 * 10. Given that, this routine should try to use an array on the stack to
185 * capture the reply rather than always calling Xmalloc.
186 *
187 * \todo
188 * This function needs to be modified to work with direct-rendering drivers.
189 */
190 static int
191 GetDrawableAttribute( Display *dpy, GLXDrawable drawable,
192 int attribute, unsigned int *value )
193 {
194 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
195 xGLXGetDrawableAttributesReply reply;
196 CARD32 * data;
197 unsigned int length;
198 unsigned int i;
199 unsigned int num_attributes;
200 GLboolean use_glx_1_3 = ((priv->majorVersion > 1)
201 || (priv->minorVersion >= 3));
202
203
204 if ( (dpy == NULL) || (drawable == 0) ) {
205 return 0;
206 }
207
208
209 LockDisplay(dpy);
210
211 if ( use_glx_1_3 ) {
212 xGLXGetDrawableAttributesReq *req;
213
214 GetReqExtra( GLXGetDrawableAttributes, 4, req );
215 req->reqType = __glXSetupForCommand(dpy);
216 req->glxCode = X_GLXGetDrawableAttributes;
217 req->drawable = drawable;
218 }
219 else {
220 xGLXVendorPrivateWithReplyReq *vpreq;
221
222 GetReqExtra( GLXVendorPrivateWithReply, 4, vpreq );
223 data = (CARD32 *) (vpreq + 1);
224 data[0] = (CARD32) drawable;
225
226 vpreq->reqType = __glXSetupForCommand(dpy);
227 vpreq->glxCode = X_GLXVendorPrivateWithReply;
228 vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
229 }
230
231 _XReply(dpy, (xReply*) &reply, 0, False);
232
233 length = reply.length;
234 num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2;
235 data = (CARD32 *) Xmalloc( length * sizeof(CARD32) );
236 if ( data == NULL ) {
237 /* Throw data on the floor */
238 _XEatData(dpy, length);
239 } else {
240 _XRead(dpy, (char *)data, length * sizeof(CARD32) );
241 }
242
243 UnlockDisplay(dpy);
244 SyncHandle();
245
246
247 /* Search the set of returned attributes for the attribute requested by
248 * the caller.
249 */
250
251 for ( i = 0 ; i < num_attributes ; i++ ) {
252 if ( data[i*2] == attribute ) {
253 *value = data[ (i*2) + 1 ];
254 break;
255 }
256 }
257
258 Xfree( data );
259
260 return 0;
261 }
262
263
264 /**
265 * Create a non-pbuffer GLX drawable.
266 *
267 * \todo
268 * This function needs to be modified to work with direct-rendering drivers.
269 */
270 static GLXDrawable
271 CreateDrawable( Display *dpy, const __GLcontextModes * fbconfig,
272 Drawable drawable, const int *attrib_list,
273 CARD8 glxCode )
274 {
275 xGLXCreateWindowReq * req;
276 CARD32 * data;
277 unsigned int i;
278
279 i = 0;
280 if (attrib_list) {
281 while (attrib_list[i * 2] != None)
282 i++;
283 }
284
285 LockDisplay(dpy);
286 GetReqExtra( GLXCreateWindow, 8 * i, req );
287 data = (CARD32 *) (req + 1);
288
289 req->reqType = __glXSetupForCommand(dpy);
290 req->glxCode = glxCode;
291 req->screen = (CARD32) fbconfig->screen;
292 req->fbconfig = fbconfig->fbconfigID;
293 req->window = (GLXPbuffer) drawable;
294 req->glxwindow = (GLXWindow) XAllocID(dpy);
295 req->numAttribs = (CARD32) i;
296
297 memcpy( data, attrib_list, 8 * i );
298
299 UnlockDisplay(dpy);
300 SyncHandle();
301
302 return (GLXDrawable)req->glxwindow;
303 }
304
305
306 /**
307 * Destroy a non-pbuffer GLX drawable.
308 *
309 * \todo
310 * This function needs to be modified to work with direct-rendering drivers.
311 */
312 static void
313 DestroyDrawable( Display * dpy, GLXDrawable drawable, CARD32 glxCode )
314 {
315 xGLXDestroyPbufferReq * req;
316
317 if ( (dpy == NULL) || (drawable == 0) ) {
318 return;
319 }
320
321
322 LockDisplay(dpy);
323
324 GetReqExtra( GLXDestroyPbuffer, 4, req );
325 req->reqType = __glXSetupForCommand(dpy);
326 req->glxCode = glxCode;
327 req->pbuffer = (GLXPbuffer) drawable;
328
329 UnlockDisplay(dpy);
330 SyncHandle();
331
332 return;
333 }
334
335
336 /**
337 * Create a pbuffer.
338 *
339 * This function is used to implement \c glXCreatePbuffer and
340 * \c glXCreateGLXPbufferSGIX.
341 *
342 * \note
343 * This function dynamically determines whether to use the SGIX_pbuffer
344 * version of the protocol or the GLX 1.3 version of the protocol.
345 *
346 * \todo
347 * This function needs to be modified to work with direct-rendering drivers.
348 */
349 static GLXDrawable
350 CreatePbuffer( Display *dpy, const __GLcontextModes * fbconfig,
351 unsigned int width, unsigned int height,
352 const int *attrib_list, GLboolean size_in_attribs )
353 {
354 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
355 GLXDrawable id = 0;
356 CARD32 * data;
357 unsigned int i;
358
359 i = 0;
360 if (attrib_list) {
361 while (attrib_list[i * 2])
362 i++;
363 }
364
365 LockDisplay(dpy);
366 id = XAllocID(dpy);
367
368 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
369 xGLXCreatePbufferReq * req;
370 unsigned int extra = (size_in_attribs) ? 0 : 2;
371
372 GetReqExtra( GLXCreatePbuffer, (8 * (i + extra)), req );
373 data = (CARD32 *) (req + 1);
374
375 req->reqType = __glXSetupForCommand(dpy);
376 req->glxCode = X_GLXCreatePbuffer;
377 req->screen = (CARD32) fbconfig->screen;
378 req->fbconfig = fbconfig->fbconfigID;
379 req->pbuffer = (GLXPbuffer) id;
380 req->numAttribs = (CARD32) (i + extra);
381
382 if ( ! size_in_attribs ) {
383 data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
384 data[(2 * i) + 1] = width;
385 data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
386 data[(2 * i) + 3] = height;
387 data += 4;
388 }
389 }
390 else {
391 xGLXVendorPrivateReq *vpreq;
392
393 GetReqExtra( GLXVendorPrivate, 20 + (8 * i), vpreq );
394 data = (CARD32 *) (vpreq + 1);
395
396 vpreq->reqType = __glXSetupForCommand(dpy);
397 vpreq->glxCode = X_GLXVendorPrivate;
398 vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
399
400 data[0] = (CARD32) fbconfig->screen;
401 data[1] = (CARD32) fbconfig->fbconfigID;
402 data[2] = (CARD32) id;
403 data[3] = (CARD32) width;
404 data[4] = (CARD32) height;
405 data += 5;
406 }
407
408 (void) memcpy( data, attrib_list, sizeof(CARD32) * 2 * i );
409
410 UnlockDisplay(dpy);
411 SyncHandle();
412
413 return id;
414 }
415
416
417 /**
418 * Create a new pbuffer.
419 */
420 PUBLIC GLXPbufferSGIX
421 glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
422 unsigned int width, unsigned int height,
423 int *attrib_list)
424 {
425 return (GLXPbufferSGIX) CreatePbuffer( dpy, (__GLcontextModes *) config,
426 width, height,
427 attrib_list, GL_FALSE );
428 }
429
430
431 /**
432 * Create a new pbuffer.
433 */
434 PUBLIC GLXPbuffer
435 glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attrib_list)
436 {
437 return (GLXPbuffer) CreatePbuffer( dpy, (__GLcontextModes *) config,
438 0, 0,
439 attrib_list, GL_TRUE );
440 }
441
442
443 /**
444 * Destroy an existing pbuffer.
445 */
446 PUBLIC void
447 glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf)
448 {
449 DestroyPbuffer( dpy, pbuf );
450 }
451
452
453 /**
454 * Query an attribute of a drawable.
455 */
456 PUBLIC void
457 glXQueryDrawable(Display *dpy, GLXDrawable drawable,
458 int attribute, unsigned int *value)
459 {
460 GetDrawableAttribute( dpy, drawable, attribute, value );
461 }
462
463
464 /**
465 * Query an attribute of a pbuffer.
466 */
467 PUBLIC int
468 glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX drawable,
469 int attribute, unsigned int *value)
470 {
471 return GetDrawableAttribute( dpy, drawable, attribute, value );
472 }
473
474
475 /**
476 * Select the event mask for a drawable.
477 */
478 PUBLIC void
479 glXSelectEvent(Display *dpy, GLXDrawable drawable, unsigned long mask)
480 {
481 CARD32 attribs[2];
482
483 attribs[0] = (CARD32) GLX_EVENT_MASK;
484 attribs[1] = (CARD32) mask;
485
486 ChangeDrawableAttribute( dpy, drawable, attribs, 1 );
487 }
488
489
490 /**
491 * Get the selected event mask for a drawable.
492 */
493 PUBLIC void
494 glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, 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 PUBLIC GLXPixmap
510 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 PUBLIC GLXWindow
520 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 PUBLIC void
530 glXDestroyPixmap(Display *dpy, GLXPixmap pixmap)
531 {
532 DestroyDrawable( dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap );
533 }
534
535
536 PUBLIC void
537 glXDestroyWindow(Display *dpy, GLXWindow win)
538 {
539 DestroyDrawable( dpy, (GLXDrawable) win, X_GLXDestroyWindow );
540 }
541
542
543 PUBLIC GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
544 (Display *dpy, GLXPbufferSGIX pbuf),
545 (dpy, pbuf),
546 glXDestroyPbuffer)
547
548 PUBLIC GLX_ALIAS_VOID(glXSelectEventSGIX,
549 (Display *dpy, GLXDrawable drawable, unsigned long mask),
550 (dpy, drawable, mask),
551 glXSelectEvent)
552
553 PUBLIC GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
554 (Display *dpy, GLXDrawable drawable, unsigned long *mask),
555 (dpy, drawable, mask),
556 glXGetSelectedEvent)