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