Git init
[framework/uifw/xorg/server/xorg-server.git] / glx / glxdriswrast.c
1 /*
2  * Copyright © 2008 George Sapountzis <gsap7@yahoo.gr>
3  * Copyright © 2008 Red Hat, Inc
4  *
5  * Permission to use, copy, modify, distribute, and sell this software
6  * and its documentation for any purpose is hereby granted without
7  * fee, provided that the above copyright notice appear in all copies
8  * and that both that copyright notice and this permission notice
9  * appear in supporting documentation, and that the name of the
10  * copyright holders not be used in advertising or publicity
11  * pertaining to distribution of the software without specific,
12  * written prior permission.  The copyright holders make no
13  * representations about the suitability of this software for any
14  * purpose.  It is provided "as is" without express or implied
15  * warranty.
16  *
17  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
18  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
19  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
22  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
23  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
24  * SOFTWARE.
25  */
26
27 #ifdef HAVE_DIX_CONFIG_H
28 #include <dix-config.h>
29 #endif
30
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <sys/time.h>
36 #include <dlfcn.h>
37
38 #include <GL/gl.h>
39 #include <GL/internal/dri_interface.h>
40 #include <GL/glxtokens.h>
41
42 #include "scrnintstr.h"
43 #include "pixmapstr.h"
44 #include "gcstruct.h"
45 #include "os.h"
46
47 #include "glxserver.h"
48 #include "glxutil.h"
49 #include "glxdricommon.h"
50
51 #include "g_disptab.h"
52 #include "glapitable.h"
53 #include "glapi.h"
54 #include "glthread.h"
55 #include "dispatch.h"
56 #include "extension_string.h"
57
58 /* RTLD_LOCAL is not defined on Cygwin */
59 #ifdef __CYGWIN__
60 #ifndef RTLD_LOCAL
61 #define RTLD_LOCAL 0
62 #endif
63 #endif
64
65 typedef struct __GLXDRIscreen   __GLXDRIscreen;
66 typedef struct __GLXDRIcontext  __GLXDRIcontext;
67 typedef struct __GLXDRIdrawable __GLXDRIdrawable;
68
69 struct __GLXDRIscreen {
70     __GLXscreen          base;
71     __DRIscreen         *driScreen;
72     void                *driver;
73
74     const __DRIcoreExtension *core;
75     const __DRIswrastExtension *swrast;
76     const __DRIcopySubBufferExtension *copySubBuffer;
77     const __DRItexBufferExtension *texBuffer;
78 };
79
80 struct __GLXDRIcontext {
81     __GLXcontext         base;
82     __DRIcontext        *driContext;
83 };
84
85 struct __GLXDRIdrawable {
86     __GLXdrawable        base;
87     __DRIdrawable       *driDrawable;
88     __GLXDRIscreen      *screen;
89
90     GCPtr gc;           /* scratch GC for span drawing */
91     GCPtr swapgc;       /* GC for swapping the color buffers */
92 };
93
94 static void
95 __glXDRIdrawableDestroy(__GLXdrawable *drawable)
96 {
97     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
98     const __DRIcoreExtension *core = private->screen->core;
99
100     (*core->destroyDrawable)(private->driDrawable);
101
102     FreeScratchGC(private->gc);
103     FreeScratchGC(private->swapgc);
104
105     __glXDrawableRelease(drawable);
106
107     free(private);
108 }
109
110 static GLboolean
111 __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
112 {
113     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
114     const __DRIcoreExtension *core = private->screen->core;
115
116     (*core->swapBuffers)(private->driDrawable);
117
118     return TRUE;
119 }
120
121 static void
122 __glXDRIdrawableCopySubBuffer(__GLXdrawable *basePrivate,
123                                int x, int y, int w, int h)
124 {
125     __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
126     const __DRIcopySubBufferExtension *copySubBuffer =
127             private->screen->copySubBuffer;
128
129     if (copySubBuffer)
130         (*copySubBuffer->copySubBuffer)(private->driDrawable, x, y, w, h);
131 }
132
133 static void
134 __glXDRIcontextDestroy(__GLXcontext *baseContext)
135 {
136     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
137     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
138
139     (*screen->core->destroyContext)(context->driContext);
140     __glXContextDestroy(&context->base);
141     free(context);
142 }
143
144 static int
145 __glXDRIcontextMakeCurrent(__GLXcontext *baseContext)
146 {
147     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
148     __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
149     __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
150     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
151
152     return (*screen->core->bindContext)(context->driContext,
153                                         draw->driDrawable,
154                                         read->driDrawable);
155 }
156
157 static int
158 __glXDRIcontextLoseCurrent(__GLXcontext *baseContext)
159 {
160     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
161     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
162
163     return (*screen->core->unbindContext)(context->driContext);
164 }
165
166 static int
167 __glXDRIcontextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
168                     unsigned long mask)
169 {
170     __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
171     __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
172     __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
173
174     return (*screen->core->copyContext)(dst->driContext,
175                                         src->driContext, mask);
176 }
177
178 static int
179 __glXDRIcontextForceCurrent(__GLXcontext *baseContext)
180 {
181     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
182     __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
183     __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
184     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
185
186     return (*screen->core->bindContext)(context->driContext,
187                                         draw->driDrawable,
188                                         read->driDrawable);
189 }
190
191 #ifdef __DRI_TEX_BUFFER
192
193 static int
194 __glXDRIbindTexImage(__GLXcontext *baseContext,
195                      int buffer,
196                      __GLXdrawable *glxPixmap)
197 {
198     __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
199     const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
200     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
201
202     if (texBuffer == NULL)
203         return Success;
204
205     texBuffer->setTexBuffer(context->driContext,
206                             glxPixmap->target,
207                             drawable->driDrawable);
208
209     return Success;
210 }
211
212 static int
213 __glXDRIreleaseTexImage(__GLXcontext *baseContext,
214                         int buffer,
215                         __GLXdrawable *pixmap)
216 {
217     /* FIXME: Just unbind the texture? */
218     return Success;
219 }
220
221 #else
222
223 static int
224 __glXDRIbindTexImage(__GLXcontext *baseContext,
225                      int buffer,
226                      __GLXdrawable *glxPixmap)
227 {
228     return Success;
229 }
230
231 static int
232 __glXDRIreleaseTexImage(__GLXcontext *baseContext,
233                         int buffer,
234                         __GLXdrawable *pixmap)
235 {
236     return Success;
237 }
238
239 #endif
240
241 static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
242     __glXDRIbindTexImage,
243     __glXDRIreleaseTexImage
244 };
245
246 static void
247 __glXDRIscreenDestroy(__GLXscreen *baseScreen)
248 {
249     __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
250
251     (*screen->core->destroyScreen)(screen->driScreen);
252
253     dlclose(screen->driver);
254
255     __glXScreenDestroy(baseScreen);
256
257     free(screen);
258 }
259
260 static __GLXcontext *
261 __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
262                             __GLXconfig *glxConfig,
263                             __GLXcontext *baseShareContext)
264 {
265     __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
266     __GLXDRIcontext *context, *shareContext;
267     __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
268     const __DRIcoreExtension *core = screen->core;
269     __DRIcontext *driShare;
270
271     shareContext = (__GLXDRIcontext *) baseShareContext;
272     if (shareContext)
273         driShare = shareContext->driContext;
274     else
275         driShare = NULL;
276
277     context = calloc(1, sizeof *context);
278     if (context == NULL)
279         return NULL;
280
281     context->base.destroy           = __glXDRIcontextDestroy;
282     context->base.makeCurrent       = __glXDRIcontextMakeCurrent;
283     context->base.loseCurrent       = __glXDRIcontextLoseCurrent;
284     context->base.copy              = __glXDRIcontextCopy;
285     context->base.forceCurrent      = __glXDRIcontextForceCurrent;
286     context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
287
288     context->driContext =
289         (*core->createNewContext)(screen->driScreen,
290                                   config->driConfig, driShare, context);
291
292     return &context->base;
293 }
294
295 static __GLXdrawable *
296 __glXDRIscreenCreateDrawable(ClientPtr client,
297                              __GLXscreen *screen,
298                              DrawablePtr pDraw,
299                              XID drawId,
300                              int type,
301                              XID glxDrawId,
302                              __GLXconfig *glxConfig)
303 {
304     ChangeGCVal gcvals[2];
305     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
306     __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
307     __GLXDRIdrawable *private;
308
309     ScreenPtr pScreen = driScreen->base.pScreen;
310
311     private = calloc(1, sizeof *private);
312     if (private == NULL)
313         return NULL;
314
315     private->screen = driScreen;
316     if (!__glXDrawableInit(&private->base, screen,
317                            pDraw, type, glxDrawId, glxConfig)) {
318         free(private);
319         return NULL;
320     }
321
322     private->base.destroy       = __glXDRIdrawableDestroy;
323     private->base.swapBuffers   = __glXDRIdrawableSwapBuffers;
324     private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
325
326     private->gc = CreateScratchGC(pScreen, pDraw->depth);
327     private->swapgc = CreateScratchGC(pScreen, pDraw->depth);
328
329     gcvals[0].val = GXcopy;
330     ChangeGC(NullClient, private->gc, GCFunction, gcvals);
331     gcvals[1].val = FALSE;
332     ChangeGC(NullClient, private->swapgc, GCFunction | GCGraphicsExposures, gcvals);
333
334     private->driDrawable =
335         (*driScreen->swrast->createNewDrawable)(driScreen->driScreen,
336                                                 config->driConfig,
337                                                 private);
338
339     return &private->base;
340 }
341
342 static void
343 swrastGetDrawableInfo(__DRIdrawable *draw,
344                       int *x, int *y, int *w, int *h,
345                       void *loaderPrivate)
346 {
347     __GLXDRIdrawable *drawable = loaderPrivate;
348     DrawablePtr pDraw = drawable->base.pDraw;
349
350     *x = pDraw->x;
351     *y = pDraw->x;
352     *w = pDraw->width;
353     *h = pDraw->height;
354 }
355
356 static void
357 swrastPutImage(__DRIdrawable *draw, int op,
358              int x, int y, int w, int h, char *data,
359              void *loaderPrivate)
360 {
361     __GLXDRIdrawable *drawable = loaderPrivate;
362     DrawablePtr pDraw = drawable->base.pDraw;
363     GCPtr gc;
364
365     switch (op) {
366     case __DRI_SWRAST_IMAGE_OP_DRAW:
367         gc = drawable->gc;
368         break;
369     case __DRI_SWRAST_IMAGE_OP_SWAP:
370         gc = drawable->swapgc;
371         break;
372     default:
373         return;
374     }
375
376     ValidateGC(pDraw, gc);
377
378     gc->ops->PutImage(pDraw, gc, pDraw->depth,
379                       x, y, w, h, 0, ZPixmap, data);
380 }
381
382 static void
383 swrastGetImage(__DRIdrawable *draw,
384              int x, int y, int w, int h, char *data,
385              void *loaderPrivate)
386 {
387     __GLXDRIdrawable *drawable = loaderPrivate;
388     DrawablePtr pDraw = drawable->base.pDraw;
389     ScreenPtr pScreen = pDraw->pScreen;
390
391     pScreen->GetImage(pDraw, x, y, w, h, ZPixmap, ~0L, data);
392 }
393
394 static const __DRIswrastLoaderExtension swrastLoaderExtension = {
395     { __DRI_SWRAST_LOADER, __DRI_SWRAST_LOADER_VERSION },
396     swrastGetDrawableInfo,
397     swrastPutImage,
398     swrastGetImage
399 };
400
401 static const __DRIextension *loader_extensions[] = {
402     &systemTimeExtension.base,
403     &swrastLoaderExtension.base,
404     NULL
405 };
406
407 static void
408 initializeExtensions(__GLXDRIscreen *screen)
409 {
410     const __DRIextension **extensions;
411     int i;
412
413     extensions = screen->core->getExtensions(screen->driScreen);
414
415     for (i = 0; extensions[i]; i++) {
416 #ifdef __DRI_COPY_SUB_BUFFER
417         if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
418             screen->copySubBuffer =
419                 (const __DRIcopySubBufferExtension *) extensions[i];
420             /* GLX_MESA_copy_sub_buffer is always enabled. */
421         }
422 #endif
423
424 #ifdef __DRI_TEX_BUFFER
425         if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
426             screen->texBuffer =
427                 (const __DRItexBufferExtension *) extensions[i];
428             /* GLX_EXT_texture_from_pixmap is always enabled. */
429         }
430 #endif
431         /* Ignore unknown extensions */
432     }
433 }
434
435 static const char dri_driver_path[] = DRI_DRIVER_PATH;
436
437 static __GLXscreen *
438 __glXDRIscreenProbe(ScreenPtr pScreen)
439 {
440     const char *driverName = "swrast";
441     __GLXDRIscreen *screen;
442     char filename[128];
443     const __DRIextension **extensions;
444     const __DRIconfig **driConfigs;
445     int i;
446
447     screen = calloc(1, sizeof *screen);
448     if (screen == NULL)
449         return NULL;
450
451     screen->base.destroy        = __glXDRIscreenDestroy;
452     screen->base.createContext  = __glXDRIscreenCreateContext;
453     screen->base.createDrawable = __glXDRIscreenCreateDrawable;
454     screen->base.swapInterval   = NULL;
455     screen->base.pScreen       = pScreen;
456
457     snprintf(filename, sizeof filename,
458              "%s/%s_dri.so", dri_driver_path, driverName);
459
460     screen->driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
461     if (screen->driver == NULL) {
462         LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n",
463                    filename, dlerror());
464         goto handle_error;
465     }
466
467     extensions = dlsym(screen->driver, __DRI_DRIVER_EXTENSIONS);
468     if (extensions == NULL) {
469         LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n",
470                    driverName, dlerror());
471         goto handle_error;
472     }
473
474     for (i = 0; extensions[i]; i++) {
475         if (strcmp(extensions[i]->name, __DRI_CORE) == 0 &&
476             extensions[i]->version >= __DRI_CORE_VERSION) {
477                 screen->core = (const __DRIcoreExtension *) extensions[i];
478         }
479         if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0 &&
480             extensions[i]->version >= __DRI_SWRAST_VERSION) {
481                 screen->swrast = (const __DRIswrastExtension *) extensions[i];
482         }
483     }
484
485     if (screen->core == NULL || screen->swrast == NULL) {
486         LogMessage(X_ERROR, "AIGLX error: %s exports no DRI extension\n",
487                    driverName);
488         goto handle_error;
489     }
490
491     screen->driScreen =
492         (*screen->swrast->createNewScreen)(pScreen->myNum,
493                                            loader_extensions,
494                                            &driConfigs,
495                                            screen);
496
497     if (screen->driScreen == NULL) {
498         LogMessage(X_ERROR,
499                    "AIGLX error: Calling driver entry point failed\n");
500         goto handle_error;
501     }
502
503     initializeExtensions(screen);
504
505     screen->base.fbconfigs = glxConvertConfigs(screen->core, driConfigs,
506                                                GLX_WINDOW_BIT |
507                                                GLX_PIXMAP_BIT |
508                                                GLX_PBUFFER_BIT);
509
510     __glXScreenInit(&screen->base, pScreen);
511
512     screen->base.GLXmajor = 1;
513     screen->base.GLXminor = 4;
514
515     LogMessage(X_INFO,
516                "AIGLX: Loaded and initialized %s\n", filename);
517
518     return &screen->base;
519
520  handle_error:
521     if (screen->driver)
522         dlclose(screen->driver);
523
524     free(screen);
525
526     LogMessage(X_ERROR, "GLX: could not load software renderer\n");
527
528     return NULL;
529 }
530
531 _X_EXPORT __GLXprovider __glXDRISWRastProvider = {
532     __glXDRIscreenProbe,
533     "DRISWRAST",
534     NULL
535 };