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