glx: Rename various DRI structs away from obnoxious __GLXfooRec convention
[mesa.git] / src / glx / drisw_glx.c
1 /*
2 * Copyright 2008 George Sapountzis
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 FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
25
26 #include <X11/Xlib.h>
27 #include "glxclient.h"
28 #include <dlfcn.h>
29 #include "dri_common.h"
30
31 struct drisw_display
32 {
33 __GLXDRIdisplay base;
34 };
35
36 struct drisw_context
37 {
38 __GLXDRIcontext base;
39 __DRIcontext *driContext;
40 __GLXscreenConfigs *psc;
41 };
42
43 struct drisw_drawable
44 {
45 __GLXDRIdrawable base;
46
47 GC gc;
48 GC swapgc;
49
50 XVisualInfo *visinfo;
51 XImage *ximage;
52 };
53
54 static Bool
55 XCreateDrawable(struct drisw_drawable * pdp,
56 Display * dpy, XID drawable, int visualid)
57 {
58 XGCValues gcvalues;
59 long visMask;
60 XVisualInfo visTemp;
61 int num_visuals;
62
63 /* create GC's */
64 pdp->gc = XCreateGC(dpy, drawable, 0, NULL);
65 pdp->swapgc = XCreateGC(dpy, drawable, 0, NULL);
66
67 gcvalues.function = GXcopy;
68 gcvalues.graphics_exposures = False;
69 XChangeGC(dpy, pdp->gc, GCFunction, &gcvalues);
70 XChangeGC(dpy, pdp->swapgc, GCFunction, &gcvalues);
71 XChangeGC(dpy, pdp->swapgc, GCGraphicsExposures, &gcvalues);
72
73 /* visual */
74 visTemp.screen = DefaultScreen(dpy);
75 visTemp.visualid = visualid;
76 visMask = (VisualScreenMask | VisualIDMask);
77 pdp->visinfo = XGetVisualInfo(dpy, visMask, &visTemp, &num_visuals);
78
79 /* create XImage */
80 pdp->ximage = XCreateImage(dpy,
81 pdp->visinfo->visual,
82 pdp->visinfo->depth,
83 ZPixmap, 0, /* format, offset */
84 NULL, /* data */
85 0, 0, /* width, height */
86 32, /* bitmap_pad */
87 0); /* bytes_per_line */
88
89 return True;
90 }
91
92 static void
93 XDestroyDrawable(struct drisw_drawable * pdp, Display * dpy, XID drawable)
94 {
95 XDestroyImage(pdp->ximage);
96 XFree(pdp->visinfo);
97
98 XFreeGC(dpy, pdp->gc);
99 XFreeGC(dpy, pdp->swapgc);
100 }
101
102 /**
103 * swrast loader functions
104 */
105
106 static void
107 swrastGetDrawableInfo(__DRIdrawable * draw,
108 int *x, int *y, int *w, int *h,
109 void *loaderPrivate)
110 {
111 struct drisw_drawable *pdp = loaderPrivate;
112 __GLXDRIdrawable *pdraw = &(pdp->base);
113 Display *dpy = pdraw->psc->dpy;
114 Drawable drawable;
115
116 Window root;
117 Status stat;
118 unsigned uw, uh, bw, depth;
119
120 drawable = pdraw->xDrawable;
121
122 stat = XGetGeometry(dpy, drawable, &root,
123 x, y, &uw, &uh, &bw, &depth);
124 *w = uw;
125 *h = uh;
126 }
127
128 /**
129 * Align renderbuffer pitch.
130 *
131 * This should be chosen by the driver and the loader (libGL, xserver/glx)
132 * should use the driver provided pitch.
133 *
134 * It seems that the xorg loader (that is the xserver loading swrast_dri for
135 * indirect rendering, not client-side libGL) requires that the pitch is
136 * exactly the image width padded to 32 bits. XXX
137 *
138 * The above restriction can probably be overcome by using ScratchPixmap and
139 * CopyArea in the xserver, similar to ShmPutImage, and setting the width of
140 * the scratch pixmap to 'pitch / cpp'.
141 */
142 static inline int
143 bytes_per_line(unsigned pitch_bits, unsigned mul)
144 {
145 unsigned mask = mul - 1;
146
147 return ((pitch_bits + mask) & ~mask) / 8;
148 }
149
150 static void
151 swrastPutImage(__DRIdrawable * draw, int op,
152 int x, int y, int w, int h,
153 char *data, void *loaderPrivate)
154 {
155 struct drisw_drawable *pdp = loaderPrivate;
156 __GLXDRIdrawable *pdraw = &(pdp->base);
157 Display *dpy = pdraw->psc->dpy;
158 Drawable drawable;
159 XImage *ximage;
160 GC gc;
161
162 switch (op) {
163 case __DRI_SWRAST_IMAGE_OP_DRAW:
164 gc = pdp->gc;
165 break;
166 case __DRI_SWRAST_IMAGE_OP_SWAP:
167 gc = pdp->swapgc;
168 break;
169 default:
170 return;
171 }
172
173 drawable = pdraw->xDrawable;
174
175 ximage = pdp->ximage;
176 ximage->data = data;
177 ximage->width = w;
178 ximage->height = h;
179 ximage->bytes_per_line = bytes_per_line(w * ximage->bits_per_pixel, 32);
180
181 XPutImage(dpy, drawable, gc, ximage, 0, 0, x, y, w, h);
182
183 ximage->data = NULL;
184 }
185
186 static void
187 swrastGetImage(__DRIdrawable * read,
188 int x, int y, int w, int h,
189 char *data, void *loaderPrivate)
190 {
191 struct drisw_drawable *prp = loaderPrivate;
192 __GLXDRIdrawable *pread = &(prp->base);
193 Display *dpy = pread->psc->dpy;
194 Drawable readable;
195 XImage *ximage;
196
197 readable = pread->xDrawable;
198
199 ximage = prp->ximage;
200 ximage->data = data;
201 ximage->width = w;
202 ximage->height = h;
203 ximage->bytes_per_line = bytes_per_line(w * ximage->bits_per_pixel, 32);
204
205 XGetSubImage(dpy, readable, x, y, w, h, ~0L, ZPixmap, ximage, 0, 0);
206
207 ximage->data = NULL;
208 }
209
210 static const __DRIswrastLoaderExtension swrastLoaderExtension = {
211 {__DRI_SWRAST_LOADER, __DRI_SWRAST_LOADER_VERSION},
212 swrastGetDrawableInfo,
213 swrastPutImage,
214 swrastGetImage
215 };
216
217 static const __DRIextension *loader_extensions[] = {
218 &systemTimeExtension.base,
219 &swrastLoaderExtension.base,
220 NULL
221 };
222
223 /**
224 * GLXDRI functions
225 */
226
227 static void
228 driDestroyContext(__GLXDRIcontext * context,
229 __GLXscreenConfigs * psc, Display * dpy)
230 {
231 struct drisw_context *pcp = (struct drisw_context *) context;
232 const __DRIcoreExtension *core = pcp->psc->core;
233
234 (*core->destroyContext) (pcp->driContext);
235
236 Xfree(pcp);
237 }
238
239 static Bool
240 driBindContext(__GLXDRIcontext * context,
241 __GLXDRIdrawable * draw, __GLXDRIdrawable * read)
242 {
243 struct drisw_context *pcp = (struct drisw_context *) context;
244 const __DRIcoreExtension *core = pcp->psc->core;
245
246 return (*core->bindContext) (pcp->driContext,
247 draw->driDrawable, read->driDrawable);
248 }
249
250 static void
251 driUnbindContext(__GLXDRIcontext * context)
252 {
253 struct drisw_context *pcp = (struct drisw_context *) context;
254 const __DRIcoreExtension *core = pcp->psc->core;
255
256 (*core->unbindContext) (pcp->driContext);
257 }
258
259 static __GLXDRIcontext *
260 driCreateContext(__GLXscreenConfigs * psc,
261 const __GLcontextModes * mode,
262 GLXContext gc, GLXContext shareList, int renderType)
263 {
264 struct drisw_context *pcp, *pcp_shared;
265 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
266 const __DRIcoreExtension *core;
267 __DRIcontext *shared = NULL;
268
269 if (!psc || !psc->driScreen)
270 return NULL;
271
272 core = psc->core;
273
274 if (shareList) {
275 pcp_shared = (struct drisw_context *) shareList->driContext;
276 shared = pcp_shared->driContext;
277 }
278
279 pcp = Xmalloc(sizeof *pcp);
280 if (pcp == NULL)
281 return NULL;
282
283 pcp->psc = psc;
284 pcp->driContext =
285 (*core->createNewContext) (psc->__driScreen,
286 config->driConfig, shared, pcp);
287 if (pcp->driContext == NULL) {
288 Xfree(pcp);
289 return NULL;
290 }
291
292 pcp->base.destroyContext = driDestroyContext;
293 pcp->base.bindContext = driBindContext;
294 pcp->base.unbindContext = driUnbindContext;
295
296 return &pcp->base;
297 }
298
299 static void
300 driDestroyDrawable(__GLXDRIdrawable * pdraw)
301 {
302 struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
303 const __DRIcoreExtension *core = pdraw->psc->core;
304
305 (*core->destroyDrawable) (pdraw->driDrawable);
306
307 XDestroyDrawable(pdp, pdraw->psc->dpy, pdraw->drawable);
308 Xfree(pdp);
309 }
310
311 static __GLXDRIdrawable *
312 driCreateDrawable(__GLXscreenConfigs * psc,
313 XID xDrawable,
314 GLXDrawable drawable, const __GLcontextModes * modes)
315 {
316 __GLXDRIdrawable *pdraw;
317 struct drisw_drawable *pdp;
318 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
319 const __DRIswrastExtension *swrast = psc->swrast;
320
321 /* Old dri can't handle GLX 1.3+ drawable constructors. */
322 if (xDrawable != drawable)
323 return NULL;
324
325 pdp = Xmalloc(sizeof(*pdp));
326 if (!pdp)
327 return NULL;
328
329 pdraw = &(pdp->base);
330 pdraw->xDrawable = xDrawable;
331 pdraw->drawable = drawable;
332 pdraw->psc = psc;
333
334 XCreateDrawable(pdp, psc->dpy, xDrawable, modes->visualID);
335
336 /* Create a new drawable */
337 pdraw->driDrawable =
338 (*swrast->createNewDrawable) (psc->__driScreen, config->driConfig, pdp);
339
340 if (!pdraw->driDrawable) {
341 XDestroyDrawable(pdp, psc->dpy, xDrawable);
342 Xfree(pdp);
343 return NULL;
344 }
345
346 pdraw->destroyDrawable = driDestroyDrawable;
347
348 return pdraw;
349 }
350
351 static int64_t
352 driSwapBuffers(__GLXDRIdrawable * pdraw,
353 int64_t target_msc, int64_t divisor, int64_t remainder)
354 {
355 (void) target_msc;
356 (void) divisor;
357 (void) remainder;
358
359 (*pdraw->psc->core->swapBuffers) (pdraw->driDrawable);
360
361 return 0;
362 }
363
364 static void
365 driDestroyScreen(__GLXscreenConfigs * psc)
366 {
367 /* Free the direct rendering per screen data */
368 (*psc->core->destroyScreen) (psc->__driScreen);
369 psc->__driScreen = NULL;
370 if (psc->driver)
371 dlclose(psc->driver);
372 }
373
374 static void *
375 driOpenSwrast(void)
376 {
377 void *driver = NULL;
378
379 if (driver == NULL)
380 driver = driOpenDriver("swrast");
381
382 if (driver == NULL)
383 driver = driOpenDriver("swrastg");
384
385 return driver;
386 }
387
388 static __GLXDRIscreen *
389 driCreateScreen(__GLXscreenConfigs * psc, int screen,
390 __GLXdisplayPrivate * priv)
391 {
392 __GLXDRIscreen *psp;
393 const __DRIconfig **driver_configs;
394 const __DRIextension **extensions;
395 int i;
396
397 psp = Xcalloc(1, sizeof *psp);
398 if (psp == NULL)
399 return NULL;
400
401 psc->driver = driOpenSwrast();
402 if (psc->driver == NULL)
403 goto handle_error;
404
405 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
406 if (extensions == NULL) {
407 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
408 goto handle_error;
409 }
410
411 for (i = 0; extensions[i]; i++) {
412 if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
413 psc->core = (__DRIcoreExtension *) extensions[i];
414 if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0)
415 psc->swrast = (__DRIswrastExtension *) extensions[i];
416 }
417
418 if (psc->core == NULL || psc->swrast == NULL) {
419 ErrorMessageF("core dri extension not found\n");
420 goto handle_error;
421 }
422
423 psc->__driScreen =
424 psc->swrast->createNewScreen(screen,
425 loader_extensions, &driver_configs, psc);
426 if (psc->__driScreen == NULL) {
427 ErrorMessageF("failed to create dri screen\n");
428 goto handle_error;
429 }
430
431 driBindExtensions(psc);
432 driBindCommonExtensions(psc);
433
434 psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
435 psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
436
437 psc->driver_configs = driver_configs;
438
439 psp->destroyScreen = driDestroyScreen;
440 psp->createContext = driCreateContext;
441 psp->createDrawable = driCreateDrawable;
442 psp->swapBuffers = driSwapBuffers;
443 psp->waitX = NULL;
444 psp->waitGL = NULL;
445
446 return psp;
447
448 handle_error:
449 Xfree(psp);
450
451 if (psc->driver)
452 dlclose(psc->driver);
453
454 ErrorMessageF("reverting to indirect rendering\n");
455
456 return NULL;
457 }
458
459 /* Called from __glXFreeDisplayPrivate.
460 */
461 static void
462 driDestroyDisplay(__GLXDRIdisplay * dpy)
463 {
464 Xfree(dpy);
465 }
466
467 /*
468 * Allocate, initialize and return a __DRIdisplayPrivate object.
469 * This is called from __glXInitialize() when we are given a new
470 * display pointer.
471 */
472 _X_HIDDEN __GLXDRIdisplay *
473 driswCreateDisplay(Display * dpy)
474 {
475 struct drisw_display *pdpyp;
476
477 pdpyp = Xmalloc(sizeof *pdpyp);
478 if (pdpyp == NULL)
479 return NULL;
480
481 pdpyp->base.destroyDisplay = driDestroyDisplay;
482 pdpyp->base.createScreen = driCreateScreen;
483
484 return &pdpyp->base;
485 }
486
487 #endif /* GLX_DIRECT_RENDERING */