egl_dri2: Fix initialization with EGL_DEFAULT_DISPLAY
[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 "glxextensions.h"
39
40 #define WARN_ONCE_GLX_1_3(a, b) { \
41 static int warned=1; \
42 if(warned) { \
43 warn_GLX_1_3((a), b ); \
44 warned=0; \
45 } \
46 }
47
48 /**
49 * Emit a warning when clients use GLX 1.3 functions on pre-1.3 systems.
50 */
51 static void
52 warn_GLX_1_3(Display *dpy, const char *function_name)
53 {
54 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
55
56 if (priv->minorVersion < 3) {
57 fprintf(stderr,
58 "WARNING: Application calling GLX 1.3 function \"%s\" "
59 "when GLX 1.3 is not supported! This is an application bug!\n",
60 function_name);
61 }
62 }
63
64
65 /**
66 * Change a drawable's attribute.
67 *
68 * This function is used to implement \c glXSelectEvent and
69 * \c glXSelectEventSGIX.
70 *
71 * \note
72 * This function dynamically determines whether to use the SGIX_pbuffer
73 * version of the protocol or the GLX 1.3 version of the protocol.
74 *
75 * \todo
76 * This function needs to be modified to work with direct-rendering drivers.
77 */
78 static void
79 ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable,
80 const CARD32 * attribs, size_t num_attribs)
81 {
82 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
83 CARD32 *output;
84 CARD8 opcode;
85
86 if ((dpy == NULL) || (drawable == 0)) {
87 return;
88 }
89
90 opcode = __glXSetupForCommand(dpy);
91 if (!opcode)
92 return;
93
94 LockDisplay(dpy);
95
96 if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
97 xGLXChangeDrawableAttributesReq *req;
98
99 GetReqExtra(GLXChangeDrawableAttributes, 8 + (8 * num_attribs), req);
100 output = (CARD32 *) (req + 1);
101
102 req->reqType = opcode;
103 req->glxCode = X_GLXChangeDrawableAttributes;
104 req->drawable = drawable;
105 req->numAttribs = (CARD32) num_attribs;
106 }
107 else {
108 xGLXVendorPrivateWithReplyReq *vpreq;
109
110 GetReqExtra(GLXVendorPrivateWithReply, 4 + (8 * num_attribs), vpreq);
111 output = (CARD32 *) (vpreq + 1);
112
113 vpreq->reqType = opcode;
114 vpreq->glxCode = X_GLXVendorPrivateWithReply;
115 vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX;
116
117 output[0] = (CARD32) drawable;
118 output++;
119 }
120
121 (void) memcpy(output, attribs, sizeof(CARD32) * 2 * num_attribs);
122
123 UnlockDisplay(dpy);
124 SyncHandle();
125
126 return;
127 }
128
129
130 /**
131 * Destroy a pbuffer.
132 *
133 * This function is used to implement \c glXDestroyPbuffer and
134 * \c glXDestroyGLXPbufferSGIX.
135 *
136 * \note
137 * This function dynamically determines whether to use the SGIX_pbuffer
138 * version of the protocol or the GLX 1.3 version of the protocol.
139 *
140 * \todo
141 * This function needs to be modified to work with direct-rendering drivers.
142 */
143 static void
144 DestroyPbuffer(Display * dpy, GLXDrawable drawable)
145 {
146 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
147 CARD8 opcode;
148
149 if ((dpy == NULL) || (drawable == 0)) {
150 return;
151 }
152
153 opcode = __glXSetupForCommand(dpy);
154 if (!opcode)
155 return;
156
157 LockDisplay(dpy);
158
159 if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
160 xGLXDestroyPbufferReq *req;
161
162 GetReq(GLXDestroyPbuffer, req);
163 req->reqType = opcode;
164 req->glxCode = X_GLXDestroyPbuffer;
165 req->pbuffer = (GLXPbuffer) drawable;
166 }
167 else {
168 xGLXVendorPrivateWithReplyReq *vpreq;
169 CARD32 *data;
170
171 GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
172 data = (CARD32 *) (vpreq + 1);
173
174 data[0] = (CARD32) drawable;
175
176 vpreq->reqType = opcode;
177 vpreq->glxCode = X_GLXVendorPrivateWithReply;
178 vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX;
179 }
180
181 UnlockDisplay(dpy);
182 SyncHandle();
183
184 return;
185 }
186
187
188 #ifdef GLX_DIRECT_RENDERING
189 extern __GLXDRIdrawable *GetGLXDRIDrawable(Display * dpy,
190 GLXDrawable drawable,
191 int *const scrn_num);
192
193 static GLenum
194 determineTextureTarget(const int *attribs, int numAttribs)
195 {
196 GLenum target = 0;
197 int i;
198
199 for (i = 0; i < numAttribs; i++) {
200 if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) {
201 switch (attribs[2 * i + 1]) {
202 case GLX_TEXTURE_2D_EXT:
203 target = GL_TEXTURE_2D;
204 break;
205 case GLX_TEXTURE_RECTANGLE_EXT:
206 target = GL_TEXTURE_RECTANGLE_ARB;
207 break;
208 }
209 }
210 }
211
212 return target;
213 }
214
215
216 static GLenum
217 determineTextureFormat(const int *attribs, int numAttribs)
218 {
219 int i;
220
221 for (i = 0; i < numAttribs; i++) {
222 if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT)
223 return attribs[2 * i + 1];
224 }
225
226 return 0;
227 }
228 #endif
229
230 /**
231 * Get a drawable's attribute.
232 *
233 * This function is used to implement \c glXGetSelectedEvent and
234 * \c glXGetSelectedEventSGIX.
235 *
236 * \note
237 * This function dynamically determines whether to use the SGIX_pbuffer
238 * version of the protocol or the GLX 1.3 version of the protocol.
239 *
240 * \todo
241 * The number of attributes returned is likely to be small, probably less than
242 * 10. Given that, this routine should try to use an array on the stack to
243 * capture the reply rather than always calling Xmalloc.
244 *
245 * \todo
246 * This function needs to be modified to work with direct-rendering drivers.
247 */
248 static int
249 GetDrawableAttribute(Display * dpy, GLXDrawable drawable,
250 int attribute, unsigned int *value)
251 {
252 __GLXdisplayPrivate *priv;
253 xGLXGetDrawableAttributesReply reply;
254 CARD32 *data;
255 CARD8 opcode;
256 unsigned int length;
257 unsigned int i;
258 unsigned int num_attributes;
259 GLboolean use_glx_1_3;
260
261 if ((dpy == NULL) || (drawable == 0)) {
262 return 0;
263 }
264
265 priv = __glXInitialize(dpy);
266 use_glx_1_3 = ((priv->majorVersion > 1) || (priv->minorVersion >= 3));
267
268 *value = 0;
269
270
271 opcode = __glXSetupForCommand(dpy);
272 if (!opcode)
273 return 0;
274
275 LockDisplay(dpy);
276
277 if (use_glx_1_3) {
278 xGLXGetDrawableAttributesReq *req;
279
280 GetReqExtra(GLXGetDrawableAttributes, 4, req);
281 req->reqType = opcode;
282 req->glxCode = X_GLXGetDrawableAttributes;
283 req->drawable = drawable;
284 }
285 else {
286 xGLXVendorPrivateWithReplyReq *vpreq;
287
288 GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
289 data = (CARD32 *) (vpreq + 1);
290 data[0] = (CARD32) drawable;
291
292 vpreq->reqType = opcode;
293 vpreq->glxCode = X_GLXVendorPrivateWithReply;
294 vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
295 }
296
297 _XReply(dpy, (xReply *) & reply, 0, False);
298
299 if (reply.type == X_Error) {
300 UnlockDisplay(dpy);
301 SyncHandle();
302 return 0;
303 }
304
305 length = reply.length;
306 if (length) {
307 num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2;
308 data = (CARD32 *) Xmalloc(length * sizeof(CARD32));
309 if (data == NULL) {
310 /* Throw data on the floor */
311 _XEatData(dpy, length);
312 }
313 else {
314 _XRead(dpy, (char *) data, length * sizeof(CARD32));
315
316 /* Search the set of returned attributes for the attribute requested by
317 * the caller.
318 */
319 for (i = 0; i < num_attributes; i++) {
320 if (data[i * 2] == attribute) {
321 *value = data[(i * 2) + 1];
322 break;
323 }
324 }
325
326 #ifdef GLX_DIRECT_RENDERING
327 {
328 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
329
330 if (pdraw != NULL && !pdraw->textureTarget)
331 pdraw->textureTarget =
332 determineTextureTarget((const int *) data, num_attributes);
333 if (pdraw != NULL && !pdraw->textureFormat)
334 pdraw->textureFormat =
335 determineTextureFormat((const int *) data, num_attributes);
336 }
337 #endif
338
339 Xfree(data);
340 }
341 }
342
343 UnlockDisplay(dpy);
344 SyncHandle();
345
346 return 0;
347 }
348
349 /**
350 * Create a non-pbuffer GLX drawable.
351 *
352 * \todo
353 * This function needs to be modified to work with direct-rendering drivers.
354 */
355 static GLXDrawable
356 CreateDrawable(Display * dpy, const __GLcontextModes * fbconfig,
357 Drawable drawable, const int *attrib_list, CARD8 glxCode)
358 {
359 xGLXCreateWindowReq *req;
360 CARD32 *data;
361 unsigned int i;
362 CARD8 opcode;
363
364 i = 0;
365 if (attrib_list) {
366 while (attrib_list[i * 2] != None)
367 i++;
368 }
369
370 opcode = __glXSetupForCommand(dpy);
371 if (!opcode)
372 return None;
373
374 LockDisplay(dpy);
375 GetReqExtra(GLXCreateWindow, 8 * i, req);
376 data = (CARD32 *) (req + 1);
377
378 req->reqType = opcode;
379 req->glxCode = glxCode;
380 req->screen = (CARD32) fbconfig->screen;
381 req->fbconfig = fbconfig->fbconfigID;
382 req->window = (CARD32) drawable;
383 req->glxwindow = (GLXWindow) XAllocID(dpy);
384 req->numAttribs = (CARD32) i;
385
386 memcpy(data, attrib_list, 8 * i);
387
388 UnlockDisplay(dpy);
389 SyncHandle();
390
391 #ifdef GLX_DIRECT_RENDERING
392 do {
393 /* FIXME: Maybe delay __DRIdrawable creation until the drawable
394 * is actually bound to a context... */
395
396 __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
397 __GLXDRIdrawable *pdraw;
398 __GLXscreenConfigs *psc;
399
400 psc = &priv->screenConfigs[fbconfig->screen];
401 if (psc->driScreen == NULL)
402 break;
403 pdraw = psc->driScreen->createDrawable(psc, drawable,
404 req->glxwindow, fbconfig);
405 if (pdraw == NULL) {
406 fprintf(stderr, "failed to create drawable\n");
407 break;
408 }
409
410 if (__glxHashInsert(psc->drawHash, req->glxwindow, pdraw)) {
411 (*pdraw->destroyDrawable) (pdraw);
412 return None; /* FIXME: Check what we're supposed to do here... */
413 }
414
415 pdraw->textureTarget = determineTextureTarget(attrib_list, i);
416 pdraw->textureFormat = determineTextureFormat(attrib_list, i);
417 } while (0);
418 #endif
419
420 return (GLXDrawable) req->glxwindow;
421 }
422
423
424 /**
425 * Destroy a non-pbuffer GLX drawable.
426 *
427 * \todo
428 * This function needs to be modified to work with direct-rendering drivers.
429 */
430 static void
431 DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode)
432 {
433 xGLXDestroyPbufferReq *req;
434 CARD8 opcode;
435
436 if ((dpy == NULL) || (drawable == 0)) {
437 return;
438 }
439
440
441 opcode = __glXSetupForCommand(dpy);
442 if (!opcode)
443 return;
444
445 LockDisplay(dpy);
446
447 GetReqExtra(GLXDestroyPbuffer, 4, req);
448 req->reqType = opcode;
449 req->glxCode = glxCode;
450 req->pbuffer = (GLXPbuffer) drawable;
451
452 UnlockDisplay(dpy);
453 SyncHandle();
454
455 #ifdef GLX_DIRECT_RENDERING
456 {
457 int screen;
458 __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
459 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
460 __GLXscreenConfigs *psc = &priv->screenConfigs[screen];
461
462 if (pdraw != NULL) {
463 (*pdraw->destroyDrawable) (pdraw);
464 __glxHashDelete(psc->drawHash, drawable);
465 }
466 }
467 #endif
468
469 return;
470 }
471
472
473 /**
474 * Create a pbuffer.
475 *
476 * This function is used to implement \c glXCreatePbuffer and
477 * \c glXCreateGLXPbufferSGIX.
478 *
479 * \note
480 * This function dynamically determines whether to use the SGIX_pbuffer
481 * version of the protocol or the GLX 1.3 version of the protocol.
482 *
483 * \todo
484 * This function needs to be modified to work with direct-rendering drivers.
485 */
486 static GLXDrawable
487 CreatePbuffer(Display * dpy, const __GLcontextModes * fbconfig,
488 unsigned int width, unsigned int height,
489 const int *attrib_list, GLboolean size_in_attribs)
490 {
491 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
492 GLXDrawable id = 0;
493 CARD32 *data;
494 CARD8 opcode;
495 unsigned int i;
496
497 i = 0;
498 if (attrib_list) {
499 while (attrib_list[i * 2])
500 i++;
501 }
502
503 opcode = __glXSetupForCommand(dpy);
504 if (!opcode)
505 return None;
506
507 LockDisplay(dpy);
508 id = XAllocID(dpy);
509
510 if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
511 xGLXCreatePbufferReq *req;
512 unsigned int extra = (size_in_attribs) ? 0 : 2;
513
514 GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req);
515 data = (CARD32 *) (req + 1);
516
517 req->reqType = opcode;
518 req->glxCode = X_GLXCreatePbuffer;
519 req->screen = (CARD32) fbconfig->screen;
520 req->fbconfig = fbconfig->fbconfigID;
521 req->pbuffer = (GLXPbuffer) id;
522 req->numAttribs = (CARD32) (i + extra);
523
524 if (!size_in_attribs) {
525 data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
526 data[(2 * i) + 1] = width;
527 data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
528 data[(2 * i) + 3] = height;
529 data += 4;
530 }
531 }
532 else {
533 xGLXVendorPrivateReq *vpreq;
534
535 GetReqExtra(GLXVendorPrivate, 20 + (8 * i), vpreq);
536 data = (CARD32 *) (vpreq + 1);
537
538 vpreq->reqType = opcode;
539 vpreq->glxCode = X_GLXVendorPrivate;
540 vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
541
542 data[0] = (CARD32) fbconfig->screen;
543 data[1] = (CARD32) fbconfig->fbconfigID;
544 data[2] = (CARD32) id;
545 data[3] = (CARD32) width;
546 data[4] = (CARD32) height;
547 data += 5;
548 }
549
550 (void) memcpy(data, attrib_list, sizeof(CARD32) * 2 * i);
551
552 UnlockDisplay(dpy);
553 SyncHandle();
554
555 return id;
556 }
557
558
559 /**
560 * Create a new pbuffer.
561 */
562 PUBLIC GLXPbufferSGIX
563 glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config,
564 unsigned int width, unsigned int height,
565 int *attrib_list)
566 {
567 return (GLXPbufferSGIX) CreatePbuffer(dpy, (__GLcontextModes *) config,
568 width, height,
569 attrib_list, GL_FALSE);
570 }
571
572
573 /**
574 * Create a new pbuffer.
575 */
576 PUBLIC GLXPbuffer
577 glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list)
578 {
579 int i, width, height;
580
581 width = 0;
582 height = 0;
583
584 WARN_ONCE_GLX_1_3(dpy, __func__);
585
586 for (i = 0; attrib_list[i * 2]; i++) {
587 switch (attrib_list[i * 2]) {
588 case GLX_PBUFFER_WIDTH:
589 width = attrib_list[i * 2 + 1];
590 break;
591 case GLX_PBUFFER_HEIGHT:
592 height = attrib_list[i * 2 + 1];
593 break;
594 }
595 }
596
597 return (GLXPbuffer) CreatePbuffer(dpy, (__GLcontextModes *) config,
598 width, height, attrib_list, GL_TRUE);
599 }
600
601
602 /**
603 * Destroy an existing pbuffer.
604 */
605 PUBLIC void
606 glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf)
607 {
608 DestroyPbuffer(dpy, pbuf);
609 }
610
611
612 /**
613 * Query an attribute of a drawable.
614 */
615 PUBLIC void
616 glXQueryDrawable(Display * dpy, GLXDrawable drawable,
617 int attribute, unsigned int *value)
618 {
619 WARN_ONCE_GLX_1_3(dpy, __func__);
620 GetDrawableAttribute(dpy, drawable, attribute, value);
621 }
622
623
624 /**
625 * Query an attribute of a pbuffer.
626 */
627 PUBLIC int
628 glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX drawable,
629 int attribute, unsigned int *value)
630 {
631 return GetDrawableAttribute(dpy, drawable, attribute, value);
632 }
633
634
635 /**
636 * Select the event mask for a drawable.
637 */
638 PUBLIC void
639 glXSelectEvent(Display * dpy, GLXDrawable drawable, unsigned long mask)
640 {
641 CARD32 attribs[2];
642
643 attribs[0] = (CARD32) GLX_EVENT_MASK;
644 attribs[1] = (CARD32) mask;
645
646 ChangeDrawableAttribute(dpy, drawable, attribs, 1);
647 }
648
649
650 /**
651 * Get the selected event mask for a drawable.
652 */
653 PUBLIC void
654 glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask)
655 {
656 unsigned int value;
657
658
659 /* The non-sense with value is required because on LP64 platforms
660 * sizeof(unsigned int) != sizeof(unsigned long). On little-endian
661 * we could just type-cast the pointer, but why?
662 */
663
664 GetDrawableAttribute(dpy, drawable, GLX_EVENT_MASK_SGIX, &value);
665 *mask = value;
666 }
667
668
669 PUBLIC GLXPixmap
670 glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap,
671 const int *attrib_list)
672 {
673 WARN_ONCE_GLX_1_3(dpy, __func__);
674
675 return CreateDrawable(dpy, (__GLcontextModes *) config,
676 (Drawable) pixmap, attrib_list, X_GLXCreatePixmap);
677 }
678
679
680 PUBLIC GLXWindow
681 glXCreateWindow(Display * dpy, GLXFBConfig config, Window win,
682 const int *attrib_list)
683 {
684 WARN_ONCE_GLX_1_3(dpy, __func__);
685
686 return CreateDrawable(dpy, (__GLcontextModes *) config,
687 (Drawable) win, attrib_list, X_GLXCreateWindow);
688 }
689
690
691 PUBLIC void
692 glXDestroyPixmap(Display * dpy, GLXPixmap pixmap)
693 {
694 WARN_ONCE_GLX_1_3(dpy, __func__);
695
696 DestroyDrawable(dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap);
697 }
698
699
700 PUBLIC void
701 glXDestroyWindow(Display * dpy, GLXWindow win)
702 {
703 WARN_ONCE_GLX_1_3(dpy, __func__);
704
705 DestroyDrawable(dpy, (GLXDrawable) win, X_GLXDestroyWindow);
706 }
707
708
709 PUBLIC
710 GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
711 (Display * dpy, GLXPbufferSGIX pbuf),
712 (dpy, pbuf), glXDestroyPbuffer)
713
714 PUBLIC
715 GLX_ALIAS_VOID(glXSelectEventSGIX,
716 (Display * dpy, GLXDrawable drawable,
717 unsigned long mask), (dpy, drawable, mask), glXSelectEvent)
718
719 PUBLIC
720 GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
721 (Display * dpy, GLXDrawable drawable,
722 unsigned long *mask), (dpy, drawable, mask),
723 glXGetSelectedEvent)
724