1 /*
2  * Copyright © 2014 Jon Turney
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 /* THIS IS NOT AN X CONSORTIUM STANDARD */
25 
26 #include <X11/Xlibint.h>
27 #include <X11/extensions/Xext.h>
28 #include <X11/extensions/extutil.h>
29 #include "windowsdristr.h"
30 #include "xwindowsdri.h"
31 #include <stdio.h>
32 
33 static XExtensionInfo _windowsdri_info_data;
34 static XExtensionInfo *windowsdri_info = &_windowsdri_info_data;
35 static char *windowsdri_extension_name = WINDOWSDRINAME;
36 
37 #define WindowsDRICheckExtension(dpy,i,val) \
38   XextCheckExtension (dpy, i, windowsdri_extension_name, val)
39 
40 /*****************************************************************************
41  *                                                                           *
42  *                         private utility routines                          *
43  *                                                                           *
44  *****************************************************************************/
45 
46 static int close_display(Display * dpy, XExtCodes * extCodes);
47 
48 static /* const */ XExtensionHooks windowsdri_extension_hooks = {
49    NULL,                        /* create_gc */
50    NULL,                        /* copy_gc */
51    NULL,                        /* flush_gc */
52    NULL,                        /* free_gc */
53    NULL,                        /* create_font */
54    NULL,                        /* free_font */
55    close_display,               /* close_display */
56    NULL,                        /* wire_to_event */
57    NULL,                        /* event_to_wire */
58    NULL,                        /* error */
59    NULL,                        /* error_string */
60 };
61 
62 static
63 XEXT_GENERATE_FIND_DISPLAY(find_display, windowsdri_info,
64                            windowsdri_extension_name,
65                            &windowsdri_extension_hooks,
66                            WindowsDRINumberEvents, NULL)
67 
68 static
69 XEXT_GENERATE_CLOSE_DISPLAY(close_display, windowsdri_info)
70 
71 /*****************************************************************************
72  *                                                                           *
73  *                 public Windows-DRI Extension routines                     *
74  *                                                                           *
75  *****************************************************************************/
76 
77 #if 0
78 #include <stdio.h>
79 #define TRACE(msg, ...)  fprintf(stderr, "WindowsDRI" msg "\n", ##__VA_ARGS__);
80 #else
81 #define TRACE(msg, ...)
82 #endif
83 
84 Bool
85 XWindowsDRIQueryExtension(dpy, event_basep, error_basep)
86      Display *dpy;
87      int *event_basep, *error_basep;
88 {
89    XExtDisplayInfo *info = find_display(dpy);
90 
91    TRACE("QueryExtension:");
92    if (XextHasExtension(info)) {
93       *event_basep = info->codes->first_event;
94       *error_basep = info->codes->first_error;
95       TRACE("QueryExtension: return True");
96       return True;
97    }
98    else {
99       TRACE("QueryExtension: return False");
100       return False;
101    }
102 }
103 
104 Bool
XWindowsDRIQueryVersion(dpy,majorVersion,minorVersion,patchVersion)105 XWindowsDRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
106      Display *dpy;
107      int *majorVersion;
108      int *minorVersion;
109      int *patchVersion;
110 {
111    XExtDisplayInfo *info = find_display(dpy);
112    xWindowsDRIQueryVersionReply rep;
113    xWindowsDRIQueryVersionReq *req;
114 
115    TRACE("QueryVersion:");
116    WindowsDRICheckExtension(dpy, info, False);
117 
118    LockDisplay(dpy);
119    GetReq(WindowsDRIQueryVersion, req);
120    req->reqType = info->codes->major_opcode;
121    req->driReqType = X_WindowsDRIQueryVersion;
122    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
123       UnlockDisplay(dpy);
124       SyncHandle();
125       TRACE("QueryVersion: return False");
126       return False;
127    }
128    *majorVersion = rep.majorVersion;
129    *minorVersion = rep.minorVersion;
130    *patchVersion = rep.patchVersion;
131    UnlockDisplay(dpy);
132    SyncHandle();
133    TRACE("QueryVersion: %d.%d.%d", *majorVersion, *minorVersion, *patchVersion);
134    return True;
135 }
136 
137 Bool
XWindowsDRIQueryDirectRenderingCapable(dpy,screen,isCapable)138 XWindowsDRIQueryDirectRenderingCapable(dpy, screen, isCapable)
139      Display *dpy;
140      int screen;
141      Bool *isCapable;
142 {
143    XExtDisplayInfo *info = find_display(dpy);
144    xWindowsDRIQueryDirectRenderingCapableReply rep;
145    xWindowsDRIQueryDirectRenderingCapableReq *req;
146 
147    TRACE("QueryDirectRenderingCapable:");
148    WindowsDRICheckExtension(dpy, info, False);
149 
150    LockDisplay(dpy);
151    GetReq(WindowsDRIQueryDirectRenderingCapable, req);
152    req->reqType = info->codes->major_opcode;
153    req->driReqType = X_WindowsDRIQueryDirectRenderingCapable;
154    req->screen = screen;
155    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
156       UnlockDisplay(dpy);
157       SyncHandle();
158       TRACE("QueryDirectRenderingCapable: return False");
159       return False;
160    }
161    *isCapable = rep.isCapable;
162    UnlockDisplay(dpy);
163    SyncHandle();
164    TRACE("QueryDirectRenderingCapable:return True");
165    return True;
166 }
167 
168 Bool
XWindowsDRIQueryDrawable(Display * dpy,int screen,Drawable drawable,unsigned int * type,void ** handle)169 XWindowsDRIQueryDrawable(Display *dpy, int screen, Drawable drawable,
170                         unsigned int * type, void ** handle)
171 {
172    XExtDisplayInfo *info = find_display(dpy);
173    xWindowsDRIQueryDrawableReply rep;
174    xWindowsDRIQueryDrawableReq *req;
175 
176    TRACE("QueryDrawable: XID %lx", drawable);
177    WindowsDRICheckExtension(dpy, info, False);
178 
179    LockDisplay(dpy);
180    GetReq(WindowsDRIQueryDrawable, req);
181    req->reqType = info->codes->major_opcode;
182    req->driReqType = X_WindowsDRIQueryDrawable;
183    req->screen = screen;
184    req->drawable = drawable;
185 
186    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
187       UnlockDisplay(dpy);
188       SyncHandle();
189       TRACE("QueryDrawable: return False");
190       return False;
191    }
192 
193    *type = rep.drawable_type;
194 
195    // Note that despite being a derived type of void *, HANDLEs are defined to
196    // be a sign-extended 32 bit value (so they can be passed to 32-bit
197    // processes safely)
198    *handle = (void *)(intptr_t)rep.handle;
199 
200    UnlockDisplay(dpy);
201    SyncHandle();
202    TRACE("QueryDrawable: type %d, handle %p", *type, *handle);
203    return True;
204 }
205 
206 Bool
XWindowsDRIFBConfigToPixelFormat(Display * dpy,int screen,int fbConfigID,int * pxfi)207 XWindowsDRIFBConfigToPixelFormat(Display *dpy, int screen, int fbConfigID,
208                                 int *pxfi)
209 {
210    XExtDisplayInfo *info = find_display(dpy);
211    xWindowsDRIFBConfigToPixelFormatReply rep;
212    xWindowsDRIFBConfigToPixelFormatReq *req;
213 
214    TRACE("FBConfigToPixelFormat: fbConfigID 0x%x", fbConfigID);
215    WindowsDRICheckExtension(dpy, info, False);
216 
217    LockDisplay(dpy);
218    GetReq(WindowsDRIFBConfigToPixelFormat, req);
219    req->reqType = info->codes->major_opcode;
220    req->driReqType = X_WindowsDRIFBConfigToPixelFormat;
221    req->screen = screen;
222    req->fbConfigID = fbConfigID;
223 
224    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
225       UnlockDisplay(dpy);
226       SyncHandle();
227       TRACE("FBConfigToPixelFormat: return False");
228       return False;
229    }
230 
231    *pxfi = rep.pixelFormatIndex;
232 
233    UnlockDisplay(dpy);
234    SyncHandle();
235    TRACE("FBConfigToPixelFormat: pixelformatindex %d", *pxfi);
236    return True;
237 }
238