1/* $XFree86: xc/lib/GL/dri/XF86dri.c,v 1.13 2002/10/30 12:51:25 alanh Exp $ */
2/**************************************************************************
3
4Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
5Copyright 2000 VA Linux Systems, Inc.
6Copyright 2007 Intel Corporation
7All Rights Reserved.
8
9Permission is hereby granted, free of charge, to any person obtaining a
10copy of this software and associated documentation files (the
11"Software"), to deal in the Software without restriction, including
12without limitation the rights to use, copy, modify, merge, publish,
13distribute, sub license, and/or sell copies of the Software, and to
14permit persons to whom the Software is furnished to do so, subject to
15the following conditions:
16
17The above copyright notice and this permission notice (including the
18next paragraph) shall be included in all copies or substantial portions
19of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29**************************************************************************/
30
31/*
32 * Authors:
33 *   Kevin E. Martin <martin@valinux.com>
34 *   Jens Owen <jens@tungstengraphics.com>
35 *   Rickard E. (Rik) Faith <faith@valinux.com>
36 *
37 */
38
39/* THIS IS NOT AN X CONSORTIUM STANDARD */
40
41#define NEED_REPLIES
42#include <X11/Xlibint.h>
43#include <X11/extensions/Xext.h>
44#include <X11/extensions/extutil.h>
45#include "va_dristr.h"
46
47#define PUBLIC
48
49static XExtensionInfo _va_dri_info_data;
50static XExtensionInfo *va_dri_info = &_va_dri_info_data;
51static char va_dri_extension_name[] = VA_DRINAME;
52
53#define VA_DRICheckExtension(dpy,i,val) \
54  XextCheckExtension (dpy, i, va_dri_extension_name, val)
55
56/*****************************************************************************
57 *                                                                           *
58 *			   private utility routines                          *
59 *                                                                           *
60 *****************************************************************************/
61
62static int close_display(Display *dpy, XExtCodes *extCodes);
63static /* const */ XExtensionHooks va_dri_extension_hooks = {
64    NULL,				/* create_gc */
65    NULL,				/* copy_gc */
66    NULL,				/* flush_gc */
67    NULL,				/* free_gc */
68    NULL,				/* create_font */
69    NULL,				/* free_font */
70    close_display,			/* close_display */
71    NULL,				/* wire_to_event */
72    NULL,				/* event_to_wire */
73    NULL,				/* error */
74    NULL,				/* error_string */
75};
76
77static XEXT_GENERATE_FIND_DISPLAY (find_display, va_dri_info,
78				   va_dri_extension_name,
79				   &va_dri_extension_hooks,
80				   0, NULL)
81
82static XEXT_GENERATE_CLOSE_DISPLAY (close_display, va_dri_info)
83
84
85/*****************************************************************************
86 *                                                                           *
87 *		    public XFree86-DRI Extension routines                    *
88 *                                                                           *
89 *****************************************************************************/
90
91#if 0
92#include <stdio.h>
93#define TRACE(msg)  fprintf(stderr,"XF86DRI%s\n", msg);
94#else
95#define TRACE(msg)
96#endif
97
98
99PUBLIC Bool VA_DRIQueryExtension (dpy, event_basep, error_basep)
100    Display *dpy;
101    int *event_basep, *error_basep;
102{
103    XExtDisplayInfo *info = find_display (dpy);
104
105    TRACE("QueryExtension...");
106    if (XextHasExtension(info)) {
107	*event_basep = info->codes->first_event;
108	*error_basep = info->codes->first_error;
109        TRACE("QueryExtension... return True");
110	return True;
111    } else {
112        TRACE("QueryExtension... return False");
113	return False;
114    }
115}
116
117PUBLIC Bool VA_DRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
118    Display* dpy;
119    int* majorVersion;
120    int* minorVersion;
121    int* patchVersion;
122{
123    XExtDisplayInfo *info = find_display (dpy);
124    xVA_DRIQueryVersionReply rep;
125    xVA_DRIQueryVersionReq *req;
126
127    TRACE("QueryVersion...");
128    VA_DRICheckExtension (dpy, info, False);
129
130    LockDisplay(dpy);
131    GetReq(VA_DRIQueryVersion, req);
132    req->reqType = info->codes->major_opcode;
133    req->driReqType = X_VA_DRIQueryVersion;
134    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
135	UnlockDisplay(dpy);
136	SyncHandle();
137        TRACE("QueryVersion... return False");
138	return False;
139    }
140    *majorVersion = rep.majorVersion;
141    *minorVersion = rep.minorVersion;
142    *patchVersion = rep.patchVersion;
143    UnlockDisplay(dpy);
144    SyncHandle();
145    TRACE("QueryVersion... return True");
146    return True;
147}
148
149PUBLIC Bool VA_DRIQueryDirectRenderingCapable(dpy, screen, isCapable)
150    Display* dpy;
151    int screen;
152    Bool* isCapable;
153{
154    XExtDisplayInfo *info = find_display (dpy);
155    xVA_DRIQueryDirectRenderingCapableReply rep;
156    xVA_DRIQueryDirectRenderingCapableReq *req;
157
158    TRACE("QueryDirectRenderingCapable...");
159    VA_DRICheckExtension (dpy, info, False);
160
161    LockDisplay(dpy);
162    GetReq(VA_DRIQueryDirectRenderingCapable, req);
163    req->reqType = info->codes->major_opcode;
164    req->driReqType = X_VA_DRIQueryDirectRenderingCapable;
165    req->screen = screen;
166    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
167	UnlockDisplay(dpy);
168	SyncHandle();
169        TRACE("QueryDirectRenderingCapable... return False");
170	return False;
171    }
172    *isCapable = rep.isCapable;
173    UnlockDisplay(dpy);
174    SyncHandle();
175    TRACE("QueryDirectRenderingCapable... return True");
176    return True;
177}
178
179PUBLIC Bool VA_DRIOpenConnection(dpy, screen, hSAREA, busIdString)
180    Display* dpy;
181    int screen;
182    drm_handle_t * hSAREA;
183    char **busIdString;
184{
185    XExtDisplayInfo *info = find_display (dpy);
186    xVA_DRIOpenConnectionReply rep;
187    xVA_DRIOpenConnectionReq *req;
188
189    TRACE("OpenConnection...");
190    VA_DRICheckExtension (dpy, info, False);
191
192    LockDisplay(dpy);
193    GetReq(VA_DRIOpenConnection, req);
194    req->reqType = info->codes->major_opcode;
195    req->driReqType = X_VA_DRIOpenConnection;
196    req->screen = screen;
197    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
198	UnlockDisplay(dpy);
199	SyncHandle();
200        TRACE("OpenConnection... return False");
201	return False;
202    }
203
204    *hSAREA = rep.hSAREALow;
205    if (sizeof(drm_handle_t) == 8) {
206       int shift = 32; /* var to prevent warning on next line */
207       *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift;
208    }
209
210    if (rep.length) {
211        if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) {
212            _XEatData(dpy, ((rep.busIdStringLength+3) & ~3));
213            UnlockDisplay(dpy);
214            SyncHandle();
215            TRACE("OpenConnection... return False");
216            return False;
217        }
218	_XReadPad(dpy, *busIdString, rep.busIdStringLength);
219    } else {
220        *busIdString = NULL;
221    }
222    UnlockDisplay(dpy);
223    SyncHandle();
224    TRACE("OpenConnection... return True");
225    return True;
226}
227
228PUBLIC Bool VA_DRIAuthConnection(dpy, screen, magic)
229    Display* dpy;
230    int screen;
231    drm_magic_t magic;
232{
233    XExtDisplayInfo *info = find_display (dpy);
234    xVA_DRIAuthConnectionReq *req;
235    xVA_DRIAuthConnectionReply rep;
236
237    TRACE("AuthConnection...");
238    VA_DRICheckExtension (dpy, info, False);
239
240    LockDisplay(dpy);
241    GetReq(VA_DRIAuthConnection, req);
242    req->reqType = info->codes->major_opcode;
243    req->driReqType = X_VA_DRIAuthConnection;
244    req->screen = screen;
245    req->magic = magic;
246    rep.authenticated = 0;
247    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.authenticated) {
248	UnlockDisplay(dpy);
249	SyncHandle();
250        TRACE("AuthConnection... return False");
251	return False;
252    }
253    UnlockDisplay(dpy);
254    SyncHandle();
255    TRACE("AuthConnection... return True");
256    return True;
257}
258
259PUBLIC Bool VA_DRICloseConnection(dpy, screen)
260    Display* dpy;
261    int screen;
262{
263    XExtDisplayInfo *info = find_display (dpy);
264    xVA_DRICloseConnectionReq *req;
265
266    TRACE("CloseConnection...");
267
268    VA_DRICheckExtension (dpy, info, False);
269
270    LockDisplay(dpy);
271    GetReq(VA_DRICloseConnection, req);
272    req->reqType = info->codes->major_opcode;
273    req->driReqType = X_VA_DRICloseConnection;
274    req->screen = screen;
275    UnlockDisplay(dpy);
276    SyncHandle();
277    TRACE("CloseConnection... return True");
278    return True;
279}
280
281PUBLIC Bool VA_DRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion,
282	ddxDriverMinorVersion, ddxDriverPatchVersion, clientDriverName)
283    Display* dpy;
284    int screen;
285    int* ddxDriverMajorVersion;
286    int* ddxDriverMinorVersion;
287    int* ddxDriverPatchVersion;
288    char** clientDriverName;
289{
290    XExtDisplayInfo *info = find_display (dpy);
291    xVA_DRIGetClientDriverNameReply rep;
292    xVA_DRIGetClientDriverNameReq *req;
293
294    TRACE("GetClientDriverName...");
295    VA_DRICheckExtension (dpy, info, False);
296
297    LockDisplay(dpy);
298    GetReq(VA_DRIGetClientDriverName, req);
299    req->reqType = info->codes->major_opcode;
300    req->driReqType = X_VA_DRIGetClientDriverName;
301    req->screen = screen;
302    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
303	UnlockDisplay(dpy);
304	SyncHandle();
305        TRACE("GetClientDriverName... return False");
306	return False;
307    }
308
309    *ddxDriverMajorVersion = rep.ddxDriverMajorVersion;
310    *ddxDriverMinorVersion = rep.ddxDriverMinorVersion;
311    *ddxDriverPatchVersion = rep.ddxDriverPatchVersion;
312
313    if (rep.length) {
314        if (!(*clientDriverName = (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) {
315            _XEatData(dpy, ((rep.clientDriverNameLength+3) & ~3));
316            UnlockDisplay(dpy);
317            SyncHandle();
318            TRACE("GetClientDriverName... return False");
319            return False;
320        }
321	_XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength);
322    } else {
323        *clientDriverName = NULL;
324    }
325    UnlockDisplay(dpy);
326    SyncHandle();
327    TRACE("GetClientDriverName... return True");
328    return True;
329}
330
331PUBLIC Bool VA_DRICreateContextWithConfig(dpy, screen, configID, context,
332	hHWContext)
333    Display* dpy;
334    int screen;
335    int configID;
336    XID* context;
337    drm_context_t * hHWContext;
338{
339    XExtDisplayInfo *info = find_display (dpy);
340    xVA_DRICreateContextReply rep;
341    xVA_DRICreateContextReq *req;
342
343    TRACE("CreateContext...");
344    VA_DRICheckExtension (dpy, info, False);
345
346    LockDisplay(dpy);
347    GetReq(VA_DRICreateContext, req);
348    req->reqType = info->codes->major_opcode;
349    req->driReqType = X_VA_DRICreateContext;
350    req->visual = configID;
351    req->screen = screen;
352    *context = XAllocID(dpy);
353    req->context = *context;
354    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
355	UnlockDisplay(dpy);
356	SyncHandle();
357        TRACE("CreateContext... return False");
358	return False;
359    }
360    *hHWContext = rep.hHWContext;
361    UnlockDisplay(dpy);
362    SyncHandle();
363    TRACE("CreateContext... return True");
364    return True;
365}
366
367PUBLIC Bool VA_DRICreateContext(dpy, screen, visual, context, hHWContext)
368    Display* dpy;
369    int screen;
370    Visual* visual;
371    XID* context;
372    drm_context_t * hHWContext;
373{
374    return VA_DRICreateContextWithConfig( dpy, screen, visual->visualid,
375					   context, hHWContext );
376}
377
378PUBLIC Bool VA_DRIDestroyContext( __DRInativeDisplay * ndpy, int screen,
379    __DRIid context )
380{
381    Display * const dpy = (Display *) ndpy;
382    XExtDisplayInfo *info = find_display (dpy);
383    xVA_DRIDestroyContextReq *req;
384
385    TRACE("DestroyContext...");
386    VA_DRICheckExtension (dpy, info, False);
387
388    LockDisplay(dpy);
389    GetReq(VA_DRIDestroyContext, req);
390    req->reqType = info->codes->major_opcode;
391    req->driReqType = X_VA_DRIDestroyContext;
392    req->screen = screen;
393    req->context = context;
394    UnlockDisplay(dpy);
395    SyncHandle();
396    TRACE("DestroyContext... return True");
397    return True;
398}
399
400PUBLIC Bool VA_DRICreateDrawable( __DRInativeDisplay * ndpy, int screen,
401    __DRIid drawable, drm_drawable_t * hHWDrawable )
402{
403    Display * const dpy = (Display *) ndpy;
404    XExtDisplayInfo *info = find_display (dpy);
405    xVA_DRICreateDrawableReply rep;
406    xVA_DRICreateDrawableReq *req;
407
408    TRACE("CreateDrawable...");
409    VA_DRICheckExtension (dpy, info, False);
410
411    LockDisplay(dpy);
412    GetReq(VA_DRICreateDrawable, req);
413    req->reqType = info->codes->major_opcode;
414    req->driReqType = X_VA_DRICreateDrawable;
415    req->screen = screen;
416    req->drawable = drawable;
417    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
418	UnlockDisplay(dpy);
419	SyncHandle();
420        TRACE("CreateDrawable... return False");
421	return False;
422    }
423    *hHWDrawable = rep.hHWDrawable;
424    UnlockDisplay(dpy);
425    SyncHandle();
426    TRACE("CreateDrawable... return True");
427    return True;
428}
429
430PUBLIC Bool VA_DRIDestroyDrawable( __DRInativeDisplay * ndpy, int screen,
431    __DRIid drawable )
432{
433    Display * const dpy = (Display *) ndpy;
434    XExtDisplayInfo *info = find_display (dpy);
435    xVA_DRIDestroyDrawableReq *req;
436
437    TRACE("DestroyDrawable...");
438    VA_DRICheckExtension (dpy, info, False);
439
440    LockDisplay(dpy);
441    GetReq(VA_DRIDestroyDrawable, req);
442    req->reqType = info->codes->major_opcode;
443    req->driReqType = X_VA_DRIDestroyDrawable;
444    req->screen = screen;
445    req->drawable = drawable;
446    UnlockDisplay(dpy);
447    SyncHandle();
448    TRACE("DestroyDrawable... return True");
449    return True;
450}
451
452PUBLIC Bool VA_DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable,
453    unsigned int* index, unsigned int* stamp,
454    int* X, int* Y, int* W, int* H,
455    int* numClipRects, drm_clip_rect_t ** pClipRects,
456    int* backX, int* backY,
457    int* numBackClipRects, drm_clip_rect_t ** pBackClipRects )
458{
459    XExtDisplayInfo *info = find_display (dpy);
460    xVA_DRIGetDrawableInfoReply rep;
461    xVA_DRIGetDrawableInfoReq *req;
462    int total_rects;
463
464    TRACE("GetDrawableInfo...");
465    VA_DRICheckExtension (dpy, info, False);
466
467    LockDisplay(dpy);
468    GetReq(VA_DRIGetDrawableInfo, req);
469    req->reqType = info->codes->major_opcode;
470    req->driReqType = X_VA_DRIGetDrawableInfo;
471    req->screen = screen;
472    req->drawable = drawable;
473
474    if (!_XReply(dpy, (xReply *)&rep, 1, xFalse))
475    {
476	UnlockDisplay(dpy);
477	SyncHandle();
478        TRACE("GetDrawableInfo... return False");
479	return False;
480    }
481    *index = rep.drawableTableIndex;
482    *stamp = rep.drawableTableStamp;
483    *X = (int)rep.drawableX;
484    *Y = (int)rep.drawableY;
485    *W = (int)rep.drawableWidth;
486    *H = (int)rep.drawableHeight;
487    *numClipRects = rep.numClipRects;
488    total_rects = *numClipRects;
489
490    *backX = rep.backX;
491    *backY = rep.backY;
492    *numBackClipRects = rep.numBackClipRects;
493    total_rects += *numBackClipRects;
494
495#if 0
496    /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
497     * backwards compatibility (Because of the >> 2 shift) but the fix
498     * enables multi-threaded apps to work.
499     */
500    if (rep.length !=  ((((SIZEOF(xVA_DRIGetDrawableInfoReply) -
501		       SIZEOF(xGenericReply) +
502		       total_rects * sizeof(drm_clip_rect_t)) + 3) & ~3) >> 2)) {
503        _XEatData(dpy, rep.length);
504	UnlockDisplay(dpy);
505	SyncHandle();
506        TRACE("GetDrawableInfo... return False");
507        return False;
508    }
509#endif
510
511    if (*numClipRects) {
512       int len = sizeof(drm_clip_rect_t) * (*numClipRects);
513
514       *pClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
515       if (*pClipRects)
516	  _XRead(dpy, (char*)*pClipRects, len);
517    } else {
518        *pClipRects = NULL;
519    }
520
521    if (*numBackClipRects) {
522       int len = sizeof(drm_clip_rect_t) * (*numBackClipRects);
523
524       *pBackClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
525       if (*pBackClipRects)
526	  _XRead(dpy, (char*)*pBackClipRects, len);
527    } else {
528        *pBackClipRects = NULL;
529    }
530
531    UnlockDisplay(dpy);
532    SyncHandle();
533    TRACE("GetDrawableInfo... return True");
534    return True;
535}
536
537PUBLIC Bool VA_DRIGetDeviceInfo(dpy, screen, hFrameBuffer,
538	fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate)
539    Display* dpy;
540    int screen;
541    drm_handle_t * hFrameBuffer;
542    int* fbOrigin;
543    int* fbSize;
544    int* fbStride;
545    int* devPrivateSize;
546    void** pDevPrivate;
547{
548    XExtDisplayInfo *info = find_display (dpy);
549    xVA_DRIGetDeviceInfoReply rep;
550    xVA_DRIGetDeviceInfoReq *req;
551
552    TRACE("GetDeviceInfo...");
553    VA_DRICheckExtension (dpy, info, False);
554
555    LockDisplay(dpy);
556    GetReq(VA_DRIGetDeviceInfo, req);
557    req->reqType = info->codes->major_opcode;
558    req->driReqType = X_VA_DRIGetDeviceInfo;
559    req->screen = screen;
560    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
561	UnlockDisplay(dpy);
562	SyncHandle();
563        TRACE("GetDeviceInfo... return False");
564	return False;
565    }
566
567    *hFrameBuffer = rep.hFrameBufferLow;
568    if (sizeof(drm_handle_t) == 8) {
569       int shift = 32; /* var to prevent warning on next line */
570       *hFrameBuffer |= ((drm_handle_t) rep.hFrameBufferHigh) << shift;
571    }
572
573    *fbOrigin = rep.framebufferOrigin;
574    *fbSize = rep.framebufferSize;
575    *fbStride = rep.framebufferStride;
576    *devPrivateSize = rep.devPrivateSize;
577
578    if (rep.length) {
579        if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) {
580            _XEatData(dpy, ((rep.devPrivateSize+3) & ~3));
581            UnlockDisplay(dpy);
582            SyncHandle();
583            TRACE("GetDeviceInfo... return False");
584            return False;
585        }
586	_XRead(dpy, (char*)*pDevPrivate, rep.devPrivateSize);
587    } else {
588        *pDevPrivate = NULL;
589    }
590
591    UnlockDisplay(dpy);
592    SyncHandle();
593    TRACE("GetDeviceInfo... return True");
594    return True;
595}
596
597PUBLIC Bool VA_DRIOpenFullScreen(dpy, screen, drawable)
598    Display* dpy;
599    int screen;
600    Drawable drawable;
601{
602    /* This function and the underlying X protocol are deprecated.
603     */
604    (void) dpy;
605    (void) screen;
606    (void) drawable;
607    return False;
608}
609
610PUBLIC Bool VA_DRICloseFullScreen(dpy, screen, drawable)
611    Display* dpy;
612    int screen;
613    Drawable drawable;
614{
615    /* This function and the underlying X protocol are deprecated.
616     */
617    (void) dpy;
618    (void) screen;
619    (void) drawable;
620    return True;
621}
622
623#undef TRACE
624
625