blob: 74afa60301d6123879da9b1177b51e78be1669fd [file] [log] [blame]
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001/**************************************************************************
2
3Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4All Rights Reserved.
5
6Permission is hereby granted, free of charge, to any person obtaining a
7copy of this software and associated documentation files (the
8"Software"), to deal in the Software without restriction, including
9without limitation the rights to use, copy, modify, merge, publish,
10distribute, sub license, and/or sell copies of the Software, and to
11permit persons to whom the Software is furnished to do so, subject to
12the following conditions:
13
14The above copyright notice and this permission notice (including the
15next paragraph) shall be included in all copies or substantial portions
16of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26**************************************************************************/
Adam Jacksoncb3610e2004-10-25 21:09:16 +000027
28/*
29 * Authors:
30 * Kevin E. Martin <kevin@precisioninsight.com>
31 * Brian Paul <brian@precisioninsight.com>
32 *
33 */
34
Jeremy Huddleston80b280d2010-04-02 01:35:19 -070035#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
Adam Jacksoncb3610e2004-10-25 21:09:16 +000036
Alan Hourihane6497d502008-04-23 15:59:23 +010037#include <X11/Xlib.h>
Xiang, Haihao42c279a2008-03-14 15:27:15 +080038#include <X11/extensions/Xfixes.h>
39#include <X11/extensions/Xdamage.h>
Adam Jacksoncb3610e2004-10-25 21:09:16 +000040#include "glxclient.h"
41#include "xf86dri.h"
Adam Jacksona3c3c1f2009-04-14 17:56:29 -040042#include "dri2.h"
Adam Jacksoncb3610e2004-10-25 21:09:16 +000043#include "sarea.h"
Adam Jacksoncb3610e2004-10-25 21:09:16 +000044#include <dlfcn.h>
Adam Jacksoncb3610e2004-10-25 21:09:16 +000045#include <sys/types.h>
Kristian Høgsberg890d44e2008-03-07 00:45:54 -050046#include <sys/mman.h>
47#include "xf86drm.h"
George Sapountzis07934572008-06-09 17:47:09 +030048#include "dri_common.h"
Adam Jacksoncb3610e2004-10-25 21:09:16 +000049
Kristian Høgsberg425f9ed2008-03-08 19:02:10 -050050typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
Kristian Høgsberg020c64b2008-03-08 21:57:29 -050051typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
52
RALOVICH, Kristóf08962682009-08-12 12:41:22 +020053struct __GLXDRIdisplayPrivateRec
54{
55 __GLXDRIdisplay base;
Kristian Høgsberg425f9ed2008-03-08 19:02:10 -050056
RALOVICH, Kristóf08962682009-08-12 12:41:22 +020057 /*
Kristian Høgsberg425f9ed2008-03-08 19:02:10 -050058 ** XFree86-DRI version information
59 */
RALOVICH, Kristóf08962682009-08-12 12:41:22 +020060 int driMajor;
61 int driMinor;
62 int driPatch;
Kristian Høgsberg425f9ed2008-03-08 19:02:10 -050063};
Adam Jacksoncb3610e2004-10-25 21:09:16 +000064
RALOVICH, Kristóf08962682009-08-12 12:41:22 +020065struct __GLXDRIcontextPrivateRec
66{
67 __GLXDRIcontext base;
68 __DRIcontext *driContext;
69 XID hwContextID;
70 __GLXscreenConfigs *psc;
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -040071};
72
Adam Jacksoncb3610e2004-10-25 21:09:16 +000073/*
74 * Given a display pointer and screen number, determine the name of
75 * the DRI driver for the screen. (I.e. "r128", "tdfx", etc).
76 * Return True for success, False for failure.
77 */
RALOVICH, Kristóf08962682009-08-12 12:41:22 +020078static Bool
79driGetDriverName(Display * dpy, int scrNum, char **driverName)
Adam Jacksoncb3610e2004-10-25 21:09:16 +000080{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +020081 int directCapable;
82 Bool b;
83 int event, error;
84 int driverMajor, driverMinor, driverPatch;
Adam Jacksoncb3610e2004-10-25 21:09:16 +000085
RALOVICH, Kristóf08962682009-08-12 12:41:22 +020086 *driverName = NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +000087
RALOVICH, Kristóf08962682009-08-12 12:41:22 +020088 if (XF86DRIQueryExtension(dpy, &event, &error)) { /* DRI1 */
89 if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
90 ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
91 return False;
92 }
93 if (!directCapable) {
94 ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
95 return False;
96 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +000097
RALOVICH, Kristóf08962682009-08-12 12:41:22 +020098 b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
99 &driverPatch, driverName);
100 if (!b) {
101 ErrorMessageF("Cannot determine driver name for screen %d\n",
102 scrNum);
103 return False;
104 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000105
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200106 InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
107 driverMajor, driverMinor, driverPatch, *driverName,
108 scrNum);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000109
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200110 return True;
111 }
112 else if (DRI2QueryExtension(dpy, &event, &error)) { /* DRI2 */
113 char *dev;
114 Bool ret = DRI2Connect(dpy, RootWindow(dpy, scrNum), driverName, &dev);
Adam Jacksona3c3c1f2009-04-14 17:56:29 -0400115
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200116 if (ret)
117 Xfree(dev);
Adam Jacksona3c3c1f2009-04-14 17:56:29 -0400118
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200119 return ret;
120 }
Adam Jacksona3c3c1f2009-04-14 17:56:29 -0400121
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200122 return False;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000123}
124
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000125/*
126 * Exported function for querying the DRI driver for a given screen.
127 *
128 * The returned char pointer points to a static array that will be
129 * overwritten by subsequent calls.
130 */
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200131PUBLIC const char *
132glXGetScreenDriver(Display * dpy, int scrNum)
133{
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000134 static char ret[32];
135 char *driverName;
George Sapountzis07934572008-06-09 17:47:09 +0300136 if (driGetDriverName(dpy, scrNum, &driverName)) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000137 int len;
138 if (!driverName)
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200139 return NULL;
140 len = strlen(driverName);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000141 if (len >= 31)
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200142 return NULL;
143 memcpy(ret, driverName, len + 1);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000144 Xfree(driverName);
145 return ret;
146 }
147 return NULL;
148}
149
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000150/*
151 * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
152 *
153 * The returned char pointer points directly into the driver. Therefore
154 * it should be treated as a constant.
155 *
156 * If the driver was not found or does not support configuration NULL is
157 * returned.
158 *
159 * Note: The driver remains opened after this function returns.
160 */
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200161PUBLIC const char *
162glXGetDriverConfig(const char *driverName)
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400163{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200164 void *handle = driOpenDriver(driverName);
Kristian Høgsberg0f2723c2008-03-07 01:37:08 -0500165 if (handle)
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200166 return dlsym(handle, "__driConfigOptions");
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000167 else
168 return NULL;
169}
170
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500171#ifdef XDAMAGE_1_1_INTERFACE
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400172
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200173static GLboolean
174has_damage_post(Display * dpy)
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500175{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200176 static GLboolean inited = GL_FALSE;
177 static GLboolean has_damage;
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500178
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200179 if (!inited) {
180 int major, minor;
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500181
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200182 if (XDamageQueryVersion(dpy, &major, &minor) &&
183 major == 1 && minor >= 1) {
184 has_damage = GL_TRUE;
185 }
186 else {
187 has_damage = GL_FALSE;
188 }
189 inited = GL_TRUE;
190 }
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500191
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200192 return has_damage;
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500193}
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500194
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200195static void
196__glXReportDamage(__DRIdrawable * driDraw,
197 int x, int y,
198 drm_clip_rect_t * rects, int num_rects,
199 GLboolean front_buffer, void *loaderPrivate)
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500200{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200201 XRectangle *xrects;
202 XserverRegion region;
203 int i;
204 int x_off, y_off;
205 __GLXDRIdrawable *glxDraw = loaderPrivate;
206 __GLXscreenConfigs *psc = glxDraw->psc;
207 Display *dpy = psc->dpy;
208 Drawable drawable;
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500209
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200210 if (!has_damage_post(dpy))
211 return;
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500212
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200213 if (front_buffer) {
214 x_off = x;
215 y_off = y;
216 drawable = RootWindow(dpy, psc->scr);
217 }
218 else {
219 x_off = 0;
220 y_off = 0;
221 drawable = glxDraw->xDrawable;
222 }
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500223
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200224 xrects = malloc(sizeof(XRectangle) * num_rects);
225 if (xrects == NULL)
226 return;
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500227
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200228 for (i = 0; i < num_rects; i++) {
229 xrects[i].x = rects[i].x1 + x_off;
230 xrects[i].y = rects[i].y1 + y_off;
231 xrects[i].width = rects[i].x2 - rects[i].x1;
232 xrects[i].height = rects[i].y2 - rects[i].y1;
233 }
234 region = XFixesCreateRegion(dpy, xrects, num_rects);
235 free(xrects);
236 XDamageAdd(dpy, drawable, region);
237 XFixesDestroyRegion(dpy, region);
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500238}
239
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400240static const __DRIdamageExtension damageExtension = {
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200241 {__DRI_DAMAGE, __DRI_DAMAGE_VERSION},
242 __glXReportDamage,
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400243};
244
245#endif
246
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500247static GLboolean
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200248__glXDRIGetDrawableInfo(__DRIdrawable * drawable,
249 unsigned int *index, unsigned int *stamp,
250 int *X, int *Y, int *W, int *H,
251 int *numClipRects, drm_clip_rect_t ** pClipRects,
252 int *backX, int *backY,
253 int *numBackClipRects,
254 drm_clip_rect_t ** pBackClipRects,
255 void *loaderPrivate)
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500256{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200257 __GLXDRIdrawable *glxDraw = loaderPrivate;
258 __GLXscreenConfigs *psc = glxDraw->psc;
259 Display *dpy = psc->dpy;
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500260
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200261 return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable,
262 index, stamp, X, Y, W, H,
263 numClipRects, pClipRects,
264 backX, backY,
265 numBackClipRects, pBackClipRects);
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500266}
267
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500268static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = {
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200269 {__DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION},
270 __glXDRIGetDrawableInfo
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500271};
272
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500273static const __DRIextension *loader_extensions[] = {
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200274 &systemTimeExtension.base,
275 &getDrawableInfoExtension.base,
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400276#ifdef XDAMAGE_1_1_INTERFACE
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200277 &damageExtension.base,
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400278#endif
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200279 NULL
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500280};
281
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500282/**
283 * Perform the required libGL-side initialization and call the client-side
284 * driver's \c __driCreateNewScreen function.
285 *
286 * \param dpy Display pointer.
287 * \param scrn Screen number on the display.
288 * \param psc DRI screen information.
289 * \param driDpy DRI display information.
290 * \param createNewScreen Pointer to the client-side driver's
291 * \c __driCreateNewScreen function.
Kristian Høgsbergd61f0732010-01-01 17:09:12 -0500292 * \returns A pointer to the \c __DRIscreen structure returned by
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500293 * the client-side driver on success, or \c NULL on failure.
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500294 */
295static void *
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200296CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc,
297 __GLXDRIdisplayPrivate * driDpy)
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500298{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200299 void *psp = NULL;
300 drm_handle_t hSAREA;
301 drmAddress pSAREA = MAP_FAILED;
302 char *BusID;
303 __DRIversion ddx_version;
304 __DRIversion dri_version;
305 __DRIversion drm_version;
306 __DRIframebuffer framebuffer;
307 int fd = -1;
308 int status;
George Sapountzis906e1892008-06-09 17:47:49 +0300309
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200310 drm_magic_t magic;
311 drmVersionPtr version;
312 int newlyopened;
313 char *driverName;
314 drm_handle_t hFB;
315 int junk;
316 const __DRIconfig **driver_configs;
317 __GLcontextModes *visual;
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500318
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200319 /* DRI protocol version. */
320 dri_version.major = driDpy->driMajor;
321 dri_version.minor = driDpy->driMinor;
322 dri_version.patch = driDpy->driPatch;
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500323
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200324 framebuffer.base = MAP_FAILED;
325 framebuffer.dev_priv = NULL;
Vinson Lee86d98fa2010-02-14 21:02:18 -0800326 framebuffer.size = 0;
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500327
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200328 if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
329 ErrorMessageF("XF86DRIOpenConnection failed\n");
330 goto handle_error;
331 }
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500332
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200333 fd = drmOpenOnce(NULL, BusID, &newlyopened);
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500334
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200335 Xfree(BusID); /* No longer needed */
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500336
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200337 if (fd < 0) {
338 ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd));
339 goto handle_error;
340 }
George Sapountzis906e1892008-06-09 17:47:49 +0300341
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200342 if (drmGetMagic(fd, &magic)) {
343 ErrorMessageF("drmGetMagic failed\n");
344 goto handle_error;
345 }
George Sapountzis906e1892008-06-09 17:47:49 +0300346
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200347 version = drmGetVersion(fd);
348 if (version) {
349 drm_version.major = version->version_major;
350 drm_version.minor = version->version_minor;
351 drm_version.patch = version->version_patchlevel;
352 drmFreeVersion(version);
353 }
354 else {
355 drm_version.major = -1;
356 drm_version.minor = -1;
357 drm_version.patch = -1;
358 }
George Sapountzis906e1892008-06-09 17:47:49 +0300359
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200360 if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) {
361 ErrorMessageF("XF86DRIAuthConnection failed\n");
362 goto handle_error;
363 }
George Sapountzis906e1892008-06-09 17:47:49 +0300364
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200365 /* Get device name (like "tdfx") and the ddx version numbers.
366 * We'll check the version in each DRI driver's "createNewScreen"
367 * function. */
368 if (!XF86DRIGetClientDriverName(dpy, scrn,
369 &ddx_version.major,
370 &ddx_version.minor,
371 &ddx_version.patch, &driverName)) {
372 ErrorMessageF("XF86DRIGetClientDriverName failed\n");
373 goto handle_error;
374 }
George Sapountzis906e1892008-06-09 17:47:49 +0300375
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200376 Xfree(driverName); /* No longer needed. */
George Sapountzis906e1892008-06-09 17:47:49 +0300377
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200378 /*
379 * Get device-specific info. pDevPriv will point to a struct
380 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
381 * has information about the screen size, depth, pitch, ancilliary
382 * buffers, DRM mmap handles, etc.
383 */
384 if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk,
385 &framebuffer.size, &framebuffer.stride,
386 &framebuffer.dev_priv_size,
387 &framebuffer.dev_priv)) {
388 ErrorMessageF("XF86DRIGetDeviceInfo failed");
389 goto handle_error;
390 }
George Sapountzis906e1892008-06-09 17:47:49 +0300391
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200392 framebuffer.width = DisplayWidth(dpy, scrn);
393 framebuffer.height = DisplayHeight(dpy, scrn);
George Sapountzis906e1892008-06-09 17:47:49 +0300394
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200395 /* Map the framebuffer region. */
396 status = drmMap(fd, hFB, framebuffer.size,
397 (drmAddressPtr) & framebuffer.base);
398 if (status != 0) {
399 ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status));
400 goto handle_error;
401 }
George Sapountzis906e1892008-06-09 17:47:49 +0300402
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200403 /* Map the SAREA region. Further mmap regions may be setup in
404 * each DRI driver's "createNewScreen" function.
405 */
406 status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
407 if (status != 0) {
408 ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status));
409 goto handle_error;
410 }
George Sapountzis906e1892008-06-09 17:47:49 +0300411
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200412 psp = (*psc->legacy->createNewScreen) (scrn,
413 &ddx_version,
414 &dri_version,
415 &drm_version,
416 &framebuffer,
417 pSAREA,
418 fd,
419 loader_extensions,
420 &driver_configs, psc);
George Sapountzis906e1892008-06-09 17:47:49 +0300421
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200422 if (psp == NULL) {
423 ErrorMessageF("Calling driver entry point failed");
424 goto handle_error;
425 }
George Sapountzis906e1892008-06-09 17:47:49 +0300426
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200427 psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
428 psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500429
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200430 psc->driver_configs = driver_configs;
RALOVICH, Kristófd090ba92009-07-23 17:05:50 +0200431
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200432 /* Visuals with depth != screen depth are subject to automatic compositing
433 * in the X server, so DRI1 can't render to them properly. Mark them as
434 * non-conformant to prevent apps from picking them up accidentally.
435 */
436 for (visual = psc->visuals; visual; visual = visual->next) {
437 XVisualInfo template;
438 XVisualInfo *visuals;
439 int num_visuals;
440 long mask;
Michel Dänzer25b492b2009-07-07 13:52:35 +0200441
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200442 template.visualid = visual->visualID;
443 mask = VisualIDMask;
444 visuals = XGetVisualInfo(dpy, mask, &template, &num_visuals);
Michel Dänzer25b492b2009-07-07 13:52:35 +0200445
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200446 if (visuals) {
447 if (num_visuals > 0 && visuals->depth != DefaultDepth(dpy, scrn))
448 visual->visualRating = GLX_NON_CONFORMANT_CONFIG;
Michel Dänzer25b492b2009-07-07 13:52:35 +0200449
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200450 XFree(visuals);
451 }
452 }
Michel Dänzer25b492b2009-07-07 13:52:35 +0200453
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200454 return psp;
George Sapountzis906e1892008-06-09 17:47:49 +0300455
456 handle_error:
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200457 if (pSAREA != MAP_FAILED)
458 drmUnmap(pSAREA, SAREA_MAX);
George Sapountzis906e1892008-06-09 17:47:49 +0300459
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200460 if (framebuffer.base != MAP_FAILED)
461 drmUnmap((drmAddress) framebuffer.base, framebuffer.size);
George Sapountzis906e1892008-06-09 17:47:49 +0300462
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200463 if (framebuffer.dev_priv != NULL)
464 Xfree(framebuffer.dev_priv);
George Sapountzis906e1892008-06-09 17:47:49 +0300465
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200466 if (fd >= 0)
467 drmCloseOnce(fd);
George Sapountzis906e1892008-06-09 17:47:49 +0300468
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200469 XF86DRICloseConnection(dpy, scrn);
George Sapountzis906e1892008-06-09 17:47:49 +0300470
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200471 ErrorMessageF("reverting to software direct rendering\n");
George Sapountzis906e1892008-06-09 17:47:49 +0300472
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200473 return NULL;
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500474}
475
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200476static void
477driDestroyContext(__GLXDRIcontext * context,
478 __GLXscreenConfigs * psc, Display * dpy)
Kristian Høgsberg53dc8632008-03-08 20:02:22 -0500479{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200480 __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
Kristian Høgsberg020c64b2008-03-08 21:57:29 -0500481
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200482 (*psc->core->destroyContext) (pcp->driContext);
483
484 XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
485 Xfree(pcp);
Kristian Høgsberg020c64b2008-03-08 21:57:29 -0500486}
487
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200488static Bool
489driBindContext(__GLXDRIcontext * context,
490 __GLXDRIdrawable * draw, __GLXDRIdrawable * read)
Kristian Høgsberg020c64b2008-03-08 21:57:29 -0500491{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200492 __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
493 const __DRIcoreExtension *core = pcp->psc->core;
Kristian Høgsberg020c64b2008-03-08 21:57:29 -0500494
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200495 return (*core->bindContext) (pcp->driContext,
496 draw->driDrawable, read->driDrawable);
Kristian Høgsberg020c64b2008-03-08 21:57:29 -0500497}
498
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200499static void
500driUnbindContext(__GLXDRIcontext * context)
Kristian Høgsberg020c64b2008-03-08 21:57:29 -0500501{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200502 __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
503 const __DRIcoreExtension *core = pcp->psc->core;
Kristian Høgsberg020c64b2008-03-08 21:57:29 -0500504
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200505 (*core->unbindContext) (pcp->driContext);
Kristian Høgsberg020c64b2008-03-08 21:57:29 -0500506}
507
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200508static __GLXDRIcontext *
509driCreateContext(__GLXscreenConfigs * psc,
510 const __GLcontextModes * mode,
511 GLXContext gc, GLXContext shareList, int renderType)
Kristian Høgsberg020c64b2008-03-08 21:57:29 -0500512{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200513 __GLXDRIcontextPrivate *pcp, *pcp_shared;
514 drm_context_t hwContext;
515 __DRIcontext *shared = NULL;
516 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
Kristian Høgsberg53dc8632008-03-08 20:02:22 -0500517
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200518 if (!psc || !psc->driScreen)
519 return NULL;
Kristian Høgsberg020c64b2008-03-08 21:57:29 -0500520
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200521 if (shareList) {
522 pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
523 shared = pcp_shared->driContext;
524 }
Kristian Høgsberg020c64b2008-03-08 21:57:29 -0500525
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200526 pcp = Xmalloc(sizeof *pcp);
527 if (pcp == NULL)
528 return NULL;
George Sapountzis07934572008-06-09 17:47:09 +0300529
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200530 pcp->psc = psc;
531 if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr,
532 mode->visualID,
533 &pcp->hwContextID, &hwContext)) {
534 Xfree(pcp);
535 return NULL;
536 }
George Sapountzis07934572008-06-09 17:47:09 +0300537
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200538 pcp->driContext =
539 (*psc->legacy->createNewContext) (psc->__driScreen,
540 config->driConfig,
541 renderType, shared, hwContext, pcp);
542 if (pcp->driContext == NULL) {
543 XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
544 Xfree(pcp);
545 return NULL;
546 }
George Sapountzis07934572008-06-09 17:47:09 +0300547
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200548 pcp->base.destroyContext = driDestroyContext;
549 pcp->base.bindContext = driBindContext;
550 pcp->base.unbindContext = driUnbindContext;
George Sapountzis07934572008-06-09 17:47:09 +0300551
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200552 return &pcp->base;
Kristian Høgsberg53dc8632008-03-08 20:02:22 -0500553}
554
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200555static void
556driDestroyDrawable(__GLXDRIdrawable * pdraw)
Kristian Høgsberg91104252008-03-12 02:18:12 -0400557{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200558 __GLXscreenConfigs *psc = pdraw->psc;
Kristian Høgsberg91104252008-03-12 02:18:12 -0400559
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200560 (*psc->core->destroyDrawable) (pdraw->driDrawable);
561 XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable);
562 Xfree(pdraw);
Kristian Høgsberg91104252008-03-12 02:18:12 -0400563}
Kristian Høgsberg20b92302008-03-08 21:02:23 -0500564
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200565static __GLXDRIdrawable *
566driCreateDrawable(__GLXscreenConfigs * psc,
567 XID xDrawable,
568 GLXDrawable drawable, const __GLcontextModes * modes)
Kristian Høgsberg20b92302008-03-08 21:02:23 -0500569{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200570 __GLXDRIdrawable *pdraw;
571 drm_drawable_t hwDrawable;
572 void *empty_attribute_list = NULL;
573 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400574
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200575 /* Old dri can't handle GLX 1.3+ drawable constructors. */
576 if (xDrawable != drawable)
577 return NULL;
Kristian Høgsberg20b92302008-03-08 21:02:23 -0500578
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200579 pdraw = Xmalloc(sizeof(*pdraw));
580 if (!pdraw)
581 return NULL;
Kristian Høgsberg20b92302008-03-08 21:02:23 -0500582
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200583 pdraw->drawable = drawable;
584 pdraw->psc = psc;
Kristian Høgsberg20b92302008-03-08 21:02:23 -0500585
Vinson Leee0556652009-11-02 12:35:47 -0700586 if (!XF86DRICreateDrawable(psc->dpy, psc->scr, drawable, &hwDrawable)) {
587 Xfree(pdraw);
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200588 return NULL;
Vinson Leee0556652009-11-02 12:35:47 -0700589 }
Kristian Høgsberg20b92302008-03-08 21:02:23 -0500590
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200591 /* Create a new drawable */
592 pdraw->driDrawable =
593 (*psc->legacy->createNewDrawable) (psc->__driScreen,
594 config->driConfig,
595 hwDrawable,
596 GLX_WINDOW_BIT,
597 empty_attribute_list, pdraw);
Kristian Høgsberg20b92302008-03-08 21:02:23 -0500598
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200599 if (!pdraw->driDrawable) {
600 XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable);
601 Xfree(pdraw);
602 return NULL;
603 }
Kristian Høgsberg20b92302008-03-08 21:02:23 -0500604
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200605 pdraw->destroyDrawable = driDestroyDrawable;
Kristian Høgsberg20b92302008-03-08 21:02:23 -0500606
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200607 return pdraw;
Kristian Høgsberg20b92302008-03-08 21:02:23 -0500608}
609
Jesse Barnesdaf7fe62009-09-15 23:23:09 -0700610static int64_t
611driSwapBuffers(__GLXDRIdrawable * pdraw, int64_t unused1, int64_t unused2,
612 int64_t unused3)
Kristian Høgsbergf56b5692008-08-13 11:46:25 -0400613{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200614 (*pdraw->psc->core->swapBuffers) (pdraw->driDrawable);
Jesse Barnesdaf7fe62009-09-15 23:23:09 -0700615 return 0;
Kristian Høgsbergf56b5692008-08-13 11:46:25 -0400616}
617
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200618static void
619driCopySubBuffer(__GLXDRIdrawable * pdraw,
620 int x, int y, int width, int height)
Kristian Høgsberg48308092008-10-11 20:41:14 -0400621{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200622 (*pdraw->psc->driCopySubBuffer->copySubBuffer) (pdraw->driDrawable,
623 x, y, width, height);
Kristian Høgsberg48308092008-10-11 20:41:14 -0400624}
625
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200626static void
627driDestroyScreen(__GLXscreenConfigs * psc)
Kristian Høgsberga1ea6f62008-03-08 19:15:50 -0500628{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200629 /* Free the direct rendering per screen data */
630 if (psc->__driScreen)
631 (*psc->core->destroyScreen) (psc->__driScreen);
632 psc->__driScreen = NULL;
633 if (psc->driver)
634 dlclose(psc->driver);
Kristian Høgsberga1ea6f62008-03-08 19:15:50 -0500635}
636
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200637static __GLXDRIscreen *
638driCreateScreen(__GLXscreenConfigs * psc, int screen,
639 __GLXdisplayPrivate * priv)
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500640{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200641 __GLXDRIdisplayPrivate *pdp;
642 __GLXDRIscreen *psp;
643 const __DRIextension **extensions;
644 char *driverName;
645 int i;
Kristian Høgsberg0f2723c2008-03-07 01:37:08 -0500646
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200647 psp = Xcalloc(1, sizeof *psp);
648 if (psp == NULL)
649 return NULL;
Kristian Høgsberg0f2723c2008-03-07 01:37:08 -0500650
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200651 if (!driGetDriverName(priv->dpy, screen, &driverName)) {
652 Xfree(psp);
653 return NULL;
654 }
George Sapountzis07934572008-06-09 17:47:09 +0300655
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200656 psc->driver = driOpenDriver(driverName);
657 Xfree(driverName);
658 if (psc->driver == NULL) {
659 Xfree(psp);
660 return NULL;
661 }
Kristian Høgsberg0f2723c2008-03-07 01:37:08 -0500662
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200663 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
664 if (extensions == NULL) {
665 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
666 Xfree(psp);
667 return NULL;
668 }
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400669
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200670 for (i = 0; extensions[i]; i++) {
671 if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
Jesse Barnesdaf7fe62009-09-15 23:23:09 -0700672 psc->core = (__DRIcoreExtension *) extensions[i];
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200673 if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0)
Jesse Barnesdaf7fe62009-09-15 23:23:09 -0700674 psc->legacy = (__DRIlegacyExtension *) extensions[i];
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200675 }
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400676
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200677 if (psc->core == NULL || psc->legacy == NULL) {
678 Xfree(psp);
679 return NULL;
680 }
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400681
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200682 pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay;
683 psc->__driScreen = CallCreateNewScreen(psc->dpy, screen, psc, pdp);
684 if (psc->__driScreen == NULL) {
685 dlclose(psc->driver);
686 Xfree(psp);
687 return NULL;
688 }
Kristian Høgsberg0f2723c2008-03-07 01:37:08 -0500689
Jesse Barnesdaf7fe62009-09-15 23:23:09 -0700690 driBindExtensions(psc);
691 driBindCommonExtensions(psc);
692
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200693 if (psc->driCopySubBuffer)
694 psp->copySubBuffer = driCopySubBuffer;
Kristian Høgsberg92d2a782008-03-08 20:34:24 -0500695
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200696 psp->destroyScreen = driDestroyScreen;
697 psp->createContext = driCreateContext;
698 psp->createDrawable = driCreateDrawable;
699 psp->swapBuffers = driSwapBuffers;
700 psp->waitX = NULL;
701 psp->waitGL = NULL;
702
703 return psp;
Kristian Høgsberg890d44e2008-03-07 00:45:54 -0500704}
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000705
Michel Dänzer8628b382007-02-01 10:45:51 +0100706/* Called from __glXFreeDisplayPrivate.
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000707 */
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200708static void
709driDestroyDisplay(__GLXDRIdisplay * dpy)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000710{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200711 Xfree(dpy);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000712}
713
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000714/*
715 * Allocate, initialize and return a __DRIdisplayPrivate object.
716 * This is called from __glXInitialize() when we are given a new
717 * display pointer.
718 */
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200719_X_HIDDEN __GLXDRIdisplay *
720driCreateDisplay(Display * dpy)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000721{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200722 __GLXDRIdisplayPrivate *pdpyp;
723 int eventBase, errorBase;
724 int major, minor, patch;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000725
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200726 if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
727 return NULL;
728 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000729
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200730 if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
731 return NULL;
732 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000733
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200734 pdpyp = Xmalloc(sizeof *pdpyp);
735 if (!pdpyp) {
736 return NULL;
737 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000738
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200739 pdpyp->driMajor = major;
740 pdpyp->driMinor = minor;
741 pdpyp->driPatch = patch;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000742
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200743 pdpyp->base.destroyDisplay = driDestroyDisplay;
744 pdpyp->base.createScreen = driCreateScreen;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000745
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200746 return &pdpyp->base;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000747}
748
749#endif /* GLX_DIRECT_RENDERING */