glx: indent -br -i3 -npcs --no-tabs dri2_glx.c
[mesa.git] / src / glx / x11 / glx_pbuffer.c
1 /* -*- mode: c; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3; coding: utf-8-unix -*- */
2 /*
3 * (C) Copyright IBM Corporation 2004
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * on the rights to use, copy, modify, merge, publish, distribute, sub
10 * license, and/or sell copies of the Software, and to permit persons to whom
11 * the Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26 /**
27 * \file glx_pbuffer.c
28 * Implementation of pbuffer related functions.
29 *
30 * \author Ian Romanick <idr@us.ibm.com>
31 */
32
33 #include <inttypes.h>
34 #include "glxclient.h"
35 #include <X11/extensions/extutil.h>
36 #include <X11/extensions/Xext.h>
37 #include <assert.h>
38 #include <string.h>
39 #include "glapi.h"
40 #include "glxextensions.h"
41 #include "glcontextmodes.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 #ifdef GLX_DIRECT_RENDERING
168 extern __GLXDRIdrawable *
169 GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num);
170
171 static GLenum
172 determineTextureTarget(const int *attribs, int numAttribs)
173 {
174 GLenum target = 0;
175 int i;
176
177 for (i = 0; i < numAttribs; i++) {
178 if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) {
179 switch (attribs[2 * i + 1]) {
180 case GLX_TEXTURE_2D_EXT:
181 target = GL_TEXTURE_2D;
182 break;
183 case GLX_TEXTURE_RECTANGLE_EXT:
184 target = GL_TEXTURE_RECTANGLE_ARB;
185 break;
186 }
187 }
188 }
189
190 return target;
191 }
192 #endif
193
194 /**
195 * Get a drawable's attribute.
196 *
197 * This function is used to implement \c glXGetSelectedEvent and
198 * \c glXGetSelectedEventSGIX.
199 *
200 * \note
201 * This function dynamically determines whether to use the SGIX_pbuffer
202 * version of the protocol or the GLX 1.3 version of the protocol.
203 *
204 * \todo
205 * The number of attributes returned is likely to be small, probably less than
206 * 10. Given that, this routine should try to use an array on the stack to
207 * capture the reply rather than always calling Xmalloc.
208 *
209 * \todo
210 * This function needs to be modified to work with direct-rendering drivers.
211 */
212 static int
213 GetDrawableAttribute( Display *dpy, GLXDrawable drawable,
214 int attribute, unsigned int *value )
215 {
216 __GLXdisplayPrivate *priv;
217 xGLXGetDrawableAttributesReply reply;
218 CARD32 * data;
219 CARD8 opcode;
220 unsigned int length;
221 unsigned int i;
222 unsigned int num_attributes;
223
224 if ( (dpy == NULL) || (drawable == 0) ) {
225 return 0;
226 }
227
228 priv = __glXInitialize(dpy);
229 GLboolean use_glx_1_3 = ((priv->majorVersion > 1)
230 || (priv->minorVersion >= 3));
231
232 *value = 0;
233
234
235 opcode = __glXSetupForCommand(dpy);
236 if (!opcode)
237 return 0;
238
239 LockDisplay(dpy);
240
241 if ( use_glx_1_3 ) {
242 xGLXGetDrawableAttributesReq *req;
243
244 GetReqExtra( GLXGetDrawableAttributes, 4, req );
245 req->reqType = opcode;
246 req->glxCode = X_GLXGetDrawableAttributes;
247 req->drawable = drawable;
248 }
249 else {
250 xGLXVendorPrivateWithReplyReq *vpreq;
251
252 GetReqExtra( GLXVendorPrivateWithReply, 4, vpreq );
253 data = (CARD32 *) (vpreq + 1);
254 data[0] = (CARD32) drawable;
255
256 vpreq->reqType = opcode;
257 vpreq->glxCode = X_GLXVendorPrivateWithReply;
258 vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
259 }
260
261 _XReply(dpy, (xReply*) &reply, 0, False);
262
263 if (reply.type == X_Error)
264 {
265 UnlockDisplay(dpy);
266 SyncHandle();
267 return 0;
268 }
269
270 length = reply.length;
271 if (length)
272 {
273 num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2;
274 data = (CARD32 *) Xmalloc( length * sizeof(CARD32) );
275 if ( data == NULL ) {
276 /* Throw data on the floor */
277 _XEatData(dpy, length);
278 } else {
279 _XRead(dpy, (char *)data, length * sizeof(CARD32) );
280
281 /* Search the set of returned attributes for the attribute requested by
282 * the caller.
283 */
284 for ( i = 0 ; i < num_attributes ; i++ ) {
285 if ( data[i*2] == attribute ) {
286 *value = data[ (i*2) + 1 ];
287 break;
288 }
289 }
290
291 #ifdef GLX_DIRECT_RENDERING
292 {
293 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
294
295 if (pdraw != NULL && !pdraw->textureTarget)
296 pdraw->textureTarget = determineTextureTarget((const int *)data,
297 num_attributes);
298 }
299 #endif
300
301 Xfree( data );
302 }
303 }
304
305 UnlockDisplay(dpy);
306 SyncHandle();
307
308 return 0;
309 }
310
311 /**
312 * Create a non-pbuffer GLX drawable.
313 *
314 * \todo
315 * This function needs to be modified to work with direct-rendering drivers.
316 */
317 static GLXDrawable
318 CreateDrawable( Display *dpy, const __GLcontextModes * fbconfig,
319 Drawable drawable, const int *attrib_list,
320 CARD8 glxCode )
321 {
322 xGLXCreateWindowReq * req;
323 CARD32 * data;
324 unsigned int i;
325 CARD8 opcode;
326
327 i = 0;
328 if (attrib_list) {
329 while (attrib_list[i * 2] != None)
330 i++;
331 }
332
333 opcode = __glXSetupForCommand(dpy);
334 if (!opcode)
335 return None;
336
337 LockDisplay(dpy);
338 GetReqExtra( GLXCreateWindow, 8 * i, req );
339 data = (CARD32 *) (req + 1);
340
341 req->reqType = opcode;
342 req->glxCode = glxCode;
343 req->screen = (CARD32) fbconfig->screen;
344 req->fbconfig = fbconfig->fbconfigID;
345 req->window = (CARD32) drawable;
346 req->glxwindow = (GLXWindow) XAllocID(dpy);
347 req->numAttribs = (CARD32) i;
348
349 memcpy( data, attrib_list, 8 * i );
350
351 UnlockDisplay(dpy);
352 SyncHandle();
353
354 #ifdef GLX_DIRECT_RENDERING
355 do {
356 /* FIXME: Maybe delay __DRIdrawable creation until the drawable
357 * is actually bound to a context... */
358
359 __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
360 __GLXDRIdrawable *pdraw;
361 __GLXscreenConfigs *psc;
362
363 psc = &priv->screenConfigs[fbconfig->screen];
364 if (psc->driScreen == NULL)
365 break;
366 pdraw = psc->driScreen->createDrawable(psc, drawable,
367 req->glxwindow, fbconfig);
368 if (pdraw == NULL) {
369 fprintf(stderr, "failed to create drawable\n");
370 break;
371 }
372
373 if (__glxHashInsert(psc->drawHash, req->glxwindow, pdraw)) {
374 (*pdraw->destroyDrawable)(pdraw);
375 return None; /* FIXME: Check what we're supposed to do here... */
376 }
377
378 pdraw->textureTarget = determineTextureTarget(attrib_list, i);
379 } while (0);
380 #endif
381
382 return (GLXDrawable)req->glxwindow;
383 }
384
385
386 /**
387 * Destroy a non-pbuffer GLX drawable.
388 *
389 * \todo
390 * This function needs to be modified to work with direct-rendering drivers.
391 */
392 static void
393 DestroyDrawable( Display * dpy, GLXDrawable drawable, CARD32 glxCode )
394 {
395 xGLXDestroyPbufferReq * req;
396 CARD8 opcode;
397
398 if ( (dpy == NULL) || (drawable == 0) ) {
399 return;
400 }
401
402
403 opcode = __glXSetupForCommand(dpy);
404 if (!opcode)
405 return;
406
407 LockDisplay(dpy);
408
409 GetReqExtra( GLXDestroyPbuffer, 4, req );
410 req->reqType = opcode;
411 req->glxCode = glxCode;
412 req->pbuffer = (GLXPbuffer) drawable;
413
414 UnlockDisplay(dpy);
415 SyncHandle();
416
417 #ifdef GLX_DIRECT_RENDERING
418 {
419 int screen;
420 __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
421 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
422 __GLXscreenConfigs *psc = &priv->screenConfigs[screen];
423
424 if (pdraw != NULL) {
425 (*pdraw->destroyDrawable)(pdraw);
426 __glxHashDelete(psc->drawHash, drawable);
427 }
428 }
429 #endif
430
431 return;
432 }
433
434
435 /**
436 * Create a pbuffer.
437 *
438 * This function is used to implement \c glXCreatePbuffer and
439 * \c glXCreateGLXPbufferSGIX.
440 *
441 * \note
442 * This function dynamically determines whether to use the SGIX_pbuffer
443 * version of the protocol or the GLX 1.3 version of the protocol.
444 *
445 * \todo
446 * This function needs to be modified to work with direct-rendering drivers.
447 */
448 static GLXDrawable
449 CreatePbuffer( Display *dpy, const __GLcontextModes * fbconfig,
450 unsigned int width, unsigned int height,
451 const int *attrib_list, GLboolean size_in_attribs )
452 {
453 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
454 GLXDrawable id = 0;
455 CARD32 * data;
456 CARD8 opcode;
457 unsigned int i;
458
459 i = 0;
460 if (attrib_list) {
461 while (attrib_list[i * 2])
462 i++;
463 }
464
465 opcode = __glXSetupForCommand(dpy);
466 if (!opcode)
467 return None;
468
469 LockDisplay(dpy);
470 id = XAllocID(dpy);
471
472 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
473 xGLXCreatePbufferReq * req;
474 unsigned int extra = (size_in_attribs) ? 0 : 2;
475
476 GetReqExtra( GLXCreatePbuffer, (8 * (i + extra)), req );
477 data = (CARD32 *) (req + 1);
478
479 req->reqType = opcode;
480 req->glxCode = X_GLXCreatePbuffer;
481 req->screen = (CARD32) fbconfig->screen;
482 req->fbconfig = fbconfig->fbconfigID;
483 req->pbuffer = (GLXPbuffer) id;
484 req->numAttribs = (CARD32) (i + extra);
485
486 if ( ! size_in_attribs ) {
487 data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
488 data[(2 * i) + 1] = width;
489 data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
490 data[(2 * i) + 3] = height;
491 data += 4;
492 }
493 }
494 else {
495 xGLXVendorPrivateReq *vpreq;
496
497 GetReqExtra( GLXVendorPrivate, 20 + (8 * i), vpreq );
498 data = (CARD32 *) (vpreq + 1);
499
500 vpreq->reqType = opcode;
501 vpreq->glxCode = X_GLXVendorPrivate;
502 vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
503
504 data[0] = (CARD32) fbconfig->screen;
505 data[1] = (CARD32) fbconfig->fbconfigID;
506 data[2] = (CARD32) id;
507 data[3] = (CARD32) width;
508 data[4] = (CARD32) height;
509 data += 5;
510 }
511
512 (void) memcpy( data, attrib_list, sizeof(CARD32) * 2 * i );
513
514 UnlockDisplay(dpy);
515 SyncHandle();
516
517 return id;
518 }
519
520
521 /**
522 * Create a new pbuffer.
523 */
524 PUBLIC GLXPbufferSGIX
525 glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
526 unsigned int width, unsigned int height,
527 int *attrib_list)
528 {
529 return (GLXPbufferSGIX) CreatePbuffer( dpy, (__GLcontextModes *) config,
530 width, height,
531 attrib_list, GL_FALSE );
532 }
533
534
535 /**
536 * Create a new pbuffer.
537 */
538 PUBLIC GLXPbuffer
539 glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attrib_list)
540 {
541 int i, width, height;
542
543 width = 0;
544 height = 0;
545
546 for (i = 0; attrib_list[i * 2]; i++) {
547 switch (attrib_list[i * 2]) {
548 case GLX_PBUFFER_WIDTH:
549 width = attrib_list[i * 2 + 1];
550 break;
551 case GLX_PBUFFER_HEIGHT:
552 height = attrib_list[i * 2 + 1];
553 break;
554 }
555 }
556
557 return (GLXPbuffer) CreatePbuffer( dpy, (__GLcontextModes *) config,
558 width, height,
559 attrib_list, GL_TRUE );
560 }
561
562
563 /**
564 * Destroy an existing pbuffer.
565 */
566 PUBLIC void
567 glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf)
568 {
569 DestroyPbuffer( dpy, pbuf );
570 }
571
572
573 /**
574 * Query an attribute of a drawable.
575 */
576 PUBLIC void
577 glXQueryDrawable(Display *dpy, GLXDrawable drawable,
578 int attribute, unsigned int *value)
579 {
580 GetDrawableAttribute( dpy, drawable, attribute, value );
581 }
582
583
584 /**
585 * Query an attribute of a pbuffer.
586 */
587 PUBLIC int
588 glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX drawable,
589 int attribute, unsigned int *value)
590 {
591 return GetDrawableAttribute( dpy, drawable, attribute, value );
592 }
593
594
595 /**
596 * Select the event mask for a drawable.
597 */
598 PUBLIC void
599 glXSelectEvent(Display *dpy, GLXDrawable drawable, unsigned long mask)
600 {
601 CARD32 attribs[2];
602
603 attribs[0] = (CARD32) GLX_EVENT_MASK;
604 attribs[1] = (CARD32) mask;
605
606 ChangeDrawableAttribute( dpy, drawable, attribs, 1 );
607 }
608
609
610 /**
611 * Get the selected event mask for a drawable.
612 */
613 PUBLIC void
614 glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask)
615 {
616 unsigned int value;
617
618
619 /* The non-sense with value is required because on LP64 platforms
620 * sizeof(unsigned int) != sizeof(unsigned long). On little-endian
621 * we could just type-cast the pointer, but why?
622 */
623
624 GetDrawableAttribute( dpy, drawable, GLX_EVENT_MASK_SGIX, & value );
625 *mask = value;
626 }
627
628
629 PUBLIC GLXPixmap
630 glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
631 const int *attrib_list )
632 {
633 return CreateDrawable( dpy, (__GLcontextModes *) config,
634 (Drawable) pixmap, attrib_list,
635 X_GLXCreatePixmap );
636 }
637
638
639 PUBLIC GLXWindow
640 glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
641 const int *attrib_list )
642 {
643 return CreateDrawable( dpy, (__GLcontextModes *) config,
644 (Drawable) win, attrib_list,
645 X_GLXCreateWindow );
646 }
647
648
649 PUBLIC void
650 glXDestroyPixmap(Display *dpy, GLXPixmap pixmap)
651 {
652 DestroyDrawable( dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap );
653 }
654
655
656 PUBLIC void
657 glXDestroyWindow(Display *dpy, GLXWindow win)
658 {
659 DestroyDrawable( dpy, (GLXDrawable) win, X_GLXDestroyWindow );
660 }
661
662
663 PUBLIC GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
664 (Display *dpy, GLXPbufferSGIX pbuf),
665 (dpy, pbuf),
666 glXDestroyPbuffer)
667
668 PUBLIC GLX_ALIAS_VOID(glXSelectEventSGIX,
669 (Display *dpy, GLXDrawable drawable, unsigned long mask),
670 (dpy, drawable, mask),
671 glXSelectEvent)
672
673 PUBLIC GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
674 (Display *dpy, GLXDrawable drawable, unsigned long *mask),
675 (dpy, drawable, mask),
676 glXGetSelectedEvent)