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