afdf710790867f663bb7892650cae4006ca81a68
[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 #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    *value = 0;
204
205    if ( (dpy == NULL) || (drawable == 0) ) {
206       return 0;
207    }
208
209    
210    LockDisplay(dpy);
211
212    if ( use_glx_1_3 ) {
213       xGLXGetDrawableAttributesReq *req;
214
215       GetReqExtra( GLXGetDrawableAttributes, 4, req );
216       req->reqType = __glXSetupForCommand(dpy);
217       req->glxCode = X_GLXGetDrawableAttributes;
218       req->drawable = drawable;
219    }
220    else {
221       xGLXVendorPrivateWithReplyReq *vpreq;
222
223       GetReqExtra( GLXVendorPrivateWithReply, 4, vpreq );
224       data = (CARD32 *) (vpreq + 1);
225       data[0] = (CARD32) drawable;
226
227       vpreq->reqType = __glXSetupForCommand(dpy);
228       vpreq->glxCode = X_GLXVendorPrivateWithReply;
229       vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
230    }
231
232    _XReply(dpy, (xReply*) &reply, 0, False);
233
234    if (reply.type == X_Error)
235    {
236        UnlockDisplay(dpy);
237        SyncHandle();
238        return 0;
239    }
240
241    length = reply.length;
242    if (length)
243    {
244        num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2;
245        data = (CARD32 *) Xmalloc( length * sizeof(CARD32) );
246        if ( data == NULL ) {
247            /* Throw data on the floor */
248            _XEatData(dpy, length);
249        } else {
250            _XRead(dpy, (char *)data, length * sizeof(CARD32) );
251
252            /* Search the set of returned attributes for the attribute requested by
253             * the caller.
254             */
255            for ( i = 0 ; i < num_attributes ; i++ ) {
256                if ( data[i*2] == attribute ) {
257                    *value = data[ (i*2) + 1 ];
258                    break;
259                }
260            }
261
262            Xfree( data );
263        }
264    }
265
266    UnlockDisplay(dpy);
267    SyncHandle();
268
269    return 0;
270 }
271
272
273 /**
274  * Create a non-pbuffer GLX drawable.
275  *
276  * \todo
277  * This function needs to be modified to work with direct-rendering drivers.
278  */
279 static GLXDrawable
280 CreateDrawable( Display *dpy, const __GLcontextModes * fbconfig,
281                 Drawable drawable, const int *attrib_list,
282                 CARD8 glxCode )
283 {
284    xGLXCreateWindowReq * req;
285    CARD32 * data;
286    unsigned int i;
287
288    i = 0;
289    if (attrib_list) {
290        while (attrib_list[i * 2] != None)
291            i++;
292    }
293
294    LockDisplay(dpy);
295    GetReqExtra( GLXCreateWindow, 8 * i, req );
296    data = (CARD32 *) (req + 1);
297
298    req->reqType = __glXSetupForCommand(dpy);
299    req->glxCode = glxCode;
300    req->screen = (CARD32) fbconfig->screen;
301    req->fbconfig = fbconfig->fbconfigID;
302    req->window = (GLXPbuffer) drawable;
303    req->glxwindow = (GLXWindow) XAllocID(dpy);
304    req->numAttribs = (CARD32) i;
305
306    memcpy( data, attrib_list, 8 * i );
307    
308    UnlockDisplay(dpy);
309    SyncHandle();
310    
311    return (GLXDrawable)req->glxwindow;
312 }
313
314
315 /**
316  * Destroy a non-pbuffer GLX drawable.
317  *
318  * \todo
319  * This function needs to be modified to work with direct-rendering drivers.
320  */
321 static void
322 DestroyDrawable( Display * dpy, GLXDrawable drawable, CARD32 glxCode )
323 {
324    xGLXDestroyPbufferReq * req;
325
326    if ( (dpy == NULL) || (drawable == 0) ) {
327       return;
328    }
329
330
331    LockDisplay(dpy);
332
333    GetReqExtra( GLXDestroyPbuffer, 4, req );
334    req->reqType = __glXSetupForCommand(dpy);
335    req->glxCode = glxCode;
336    req->pbuffer = (GLXPbuffer) drawable;
337
338    UnlockDisplay(dpy);
339    SyncHandle();
340
341    return;
342 }
343
344
345 /**
346  * Create a pbuffer.
347  *
348  * This function is used to implement \c glXCreatePbuffer and
349  * \c glXCreateGLXPbufferSGIX.
350  *
351  * \note
352  * This function dynamically determines whether to use the SGIX_pbuffer
353  * version of the protocol or the GLX 1.3 version of the protocol.
354  *
355  * \todo
356  * This function needs to be modified to work with direct-rendering drivers.
357  */
358 static GLXDrawable
359 CreatePbuffer( Display *dpy, const __GLcontextModes * fbconfig,
360                unsigned int width, unsigned int height, 
361                const int *attrib_list, GLboolean size_in_attribs )
362 {
363    __GLXdisplayPrivate *priv = __glXInitialize(dpy);
364    GLXDrawable id = 0;
365    CARD32 * data;
366    unsigned int  i;
367
368    i = 0;
369    if (attrib_list) {
370        while (attrib_list[i * 2])
371            i++;
372    }
373
374    LockDisplay(dpy);
375    id = XAllocID(dpy);
376
377    if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
378       xGLXCreatePbufferReq * req;
379       unsigned int extra = (size_in_attribs) ? 0 : 2;
380
381       GetReqExtra( GLXCreatePbuffer, (8 * (i + extra)), req );
382       data = (CARD32 *) (req + 1);
383
384       req->reqType = __glXSetupForCommand(dpy);
385       req->glxCode = X_GLXCreatePbuffer;
386       req->screen = (CARD32) fbconfig->screen;
387       req->fbconfig = fbconfig->fbconfigID;
388       req->pbuffer = (GLXPbuffer) id;
389       req->numAttribs = (CARD32) (i + extra);
390
391       if ( ! size_in_attribs ) {
392          data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
393          data[(2 * i) + 1] = width;
394          data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
395          data[(2 * i) + 3] = height;
396          data += 4;
397       }
398    }
399    else {
400       xGLXVendorPrivateReq *vpreq;
401
402       GetReqExtra( GLXVendorPrivate, 20 + (8 * i), vpreq );
403       data = (CARD32 *) (vpreq + 1);
404
405       vpreq->reqType = __glXSetupForCommand(dpy);
406       vpreq->glxCode = X_GLXVendorPrivate;
407       vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
408
409       data[0] = (CARD32) fbconfig->screen;
410       data[1] = (CARD32) fbconfig->fbconfigID;
411       data[2] = (CARD32) id;
412       data[3] = (CARD32) width;
413       data[4] = (CARD32) height;
414       data += 5;
415    }
416
417    (void) memcpy( data, attrib_list, sizeof(CARD32) * 2 * i );
418
419    UnlockDisplay(dpy);
420    SyncHandle();
421
422    return id;
423 }
424
425
426 /**
427  * Create a new pbuffer.
428  */
429 PUBLIC GLXPbufferSGIX
430 glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
431                         unsigned int width, unsigned int height,
432                         int *attrib_list)
433 {
434    return (GLXPbufferSGIX) CreatePbuffer( dpy, (__GLcontextModes *) config,
435                                           width, height,
436                                           attrib_list, GL_FALSE );
437 }
438
439
440 /**
441  * Create a new pbuffer.
442  */
443 PUBLIC GLXPbuffer
444 glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attrib_list)
445 {
446    return (GLXPbuffer) CreatePbuffer( dpy, (__GLcontextModes *) config,
447                                       0, 0,
448                                       attrib_list, GL_TRUE );
449 }
450
451
452 /**
453  * Destroy an existing pbuffer.
454  */
455 PUBLIC void
456 glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf)
457 {
458    DestroyPbuffer( dpy, pbuf );
459 }
460
461
462 /**
463  * Query an attribute of a drawable.
464  */
465 PUBLIC void
466 glXQueryDrawable(Display *dpy, GLXDrawable drawable,
467                  int attribute, unsigned int *value)
468 {
469    GetDrawableAttribute( dpy, drawable, attribute, value );
470 }
471
472
473 /**
474  * Query an attribute of a pbuffer.
475  */
476 PUBLIC int
477 glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX drawable,
478                        int attribute, unsigned int *value)
479 {
480    return GetDrawableAttribute( dpy, drawable, attribute, value );
481 }
482
483
484 /**
485  * Select the event mask for a drawable.
486  */
487 PUBLIC void
488 glXSelectEvent(Display *dpy, GLXDrawable drawable, unsigned long mask)
489 {
490    CARD32 attribs[2];
491
492    attribs[0] = (CARD32) GLX_EVENT_MASK;
493    attribs[1] = (CARD32) mask;
494
495    ChangeDrawableAttribute( dpy, drawable, attribs, 1 );
496 }
497
498
499 /**
500  * Get the selected event mask for a drawable.
501  */
502 PUBLIC void
503 glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask)
504 {
505    unsigned int value;
506
507
508    /* The non-sense with value is required because on LP64 platforms
509     * sizeof(unsigned int) != sizeof(unsigned long).  On little-endian
510     * we could just type-cast the pointer, but why?
511     */
512
513    GetDrawableAttribute( dpy, drawable, GLX_EVENT_MASK_SGIX, & value );
514    *mask = value;
515 }
516
517
518 PUBLIC GLXPixmap
519 glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
520                  const int *attrib_list )
521 {
522    return CreateDrawable( dpy, (__GLcontextModes *) config,
523                           (Drawable) pixmap, attrib_list,
524                           X_GLXCreatePixmap );
525 }
526
527
528 PUBLIC GLXWindow
529 glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
530                  const int *attrib_list )
531 {
532    return CreateDrawable( dpy, (__GLcontextModes *) config,
533                           (Drawable) win, attrib_list,
534                           X_GLXCreateWindow );
535 }
536
537
538 PUBLIC void
539 glXDestroyPixmap(Display *dpy, GLXPixmap pixmap)
540 {
541    DestroyDrawable( dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap );
542 }
543
544
545 PUBLIC void
546 glXDestroyWindow(Display *dpy, GLXWindow win)
547 {
548    DestroyDrawable( dpy, (GLXDrawable) win, X_GLXDestroyWindow );
549 }
550
551
552 PUBLIC GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
553           (Display *dpy, GLXPbufferSGIX pbuf),
554           (dpy, pbuf),
555           glXDestroyPbuffer)
556
557 PUBLIC GLX_ALIAS_VOID(glXSelectEventSGIX,
558           (Display *dpy, GLXDrawable drawable, unsigned long mask),
559           (dpy, drawable, mask),
560           glXSelectEvent)
561
562 PUBLIC GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
563           (Display *dpy, GLXDrawable drawable, unsigned long *mask),
564           (dpy, drawable, mask),
565           glXGetSelectedEvent)