upgrade for xorg-server 1.12.99.905 (for 1.13 RC)
[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 "glapitable.h"
52 #include "glapi.h"
53 #include "glthread.h"
54 #include "dispatch.h"
55 #include "extension_string.h"
56
57 /* RTLD_LOCAL is not defined on Cygwin */
58 #ifdef __CYGWIN__
59 #ifndef RTLD_LOCAL
60 #define RTLD_LOCAL 0
61 #endif
62 #endif
63
64 typedef struct __GLXDRIscreen __GLXDRIscreen;
65 typedef struct __GLXDRIcontext __GLXDRIcontext;
66 typedef struct __GLXDRIdrawable __GLXDRIdrawable;
67
68 struct __GLXDRIscreen {
69     __GLXscreen base;
70     __DRIscreen *driScreen;
71     void *driver;
72
73     const __DRIcoreExtension *core;
74     const __DRIswrastExtension *swrast;
75     const __DRIcopySubBufferExtension *copySubBuffer;
76     const __DRItexBufferExtension *texBuffer;
77     const __DRIconfig **driConfigs;
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     FreeGC(private->gc, (GContext) 0);
103     FreeGC(private->swapgc, (GContext) 0);
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, read->driDrawable);
154 }
155
156 static int
157 __glXDRIcontextLoseCurrent(__GLXcontext * baseContext)
158 {
159     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
160     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
161
162     return (*screen->core->unbindContext) (context->driContext);
163 }
164
165 static int
166 __glXDRIcontextCopy(__GLXcontext * baseDst, __GLXcontext * baseSrc,
167                     unsigned long mask)
168 {
169     __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
170     __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
171     __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
172
173     return (*screen->core->copyContext) (dst->driContext,
174                                          src->driContext, mask);
175 }
176
177 #ifdef __DRI_TEX_BUFFER
178
179 static int
180 __glXDRIbindTexImage(__GLXcontext * baseContext,
181                      int buffer, __GLXdrawable * glxPixmap)
182 {
183     __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
184     const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
185     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
186
187     if (texBuffer == NULL)
188         return Success;
189
190 #if __DRI_TEX_BUFFER_VERSION >= 2
191     if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
192         (*texBuffer->setTexBuffer2) (context->driContext,
193                                      glxPixmap->target,
194                                      glxPixmap->format, drawable->driDrawable);
195     }
196     else
197 #endif
198         texBuffer->setTexBuffer(context->driContext,
199                                 glxPixmap->target, drawable->driDrawable);
200
201     return Success;
202 }
203
204 static int
205 __glXDRIreleaseTexImage(__GLXcontext * baseContext,
206                         int buffer, __GLXdrawable * pixmap)
207 {
208     /* FIXME: Just unbind the texture? */
209     return Success;
210 }
211
212 #else
213
214 static int
215 __glXDRIbindTexImage(__GLXcontext * baseContext,
216                      int buffer, __GLXdrawable * glxPixmap)
217 {
218     return Success;
219 }
220
221 static int
222 __glXDRIreleaseTexImage(__GLXcontext * baseContext,
223                         int buffer, __GLXdrawable * pixmap)
224 {
225     return Success;
226 }
227
228 #endif
229
230 static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
231     __glXDRIbindTexImage,
232     __glXDRIreleaseTexImage
233 };
234
235 static void
236 __glXDRIscreenDestroy(__GLXscreen * baseScreen)
237 {
238     int i;
239
240     __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
241
242     (*screen->core->destroyScreen) (screen->driScreen);
243
244     dlclose(screen->driver);
245
246     __glXScreenDestroy(baseScreen);
247
248     if (screen->driConfigs) {
249         for (i = 0; screen->driConfigs[i] != NULL; i++)
250             free((__DRIconfig **) screen->driConfigs[i]);
251         free(screen->driConfigs);
252     }
253
254     free(screen);
255 }
256
257 static __GLXcontext *
258 __glXDRIscreenCreateContext(__GLXscreen * baseScreen,
259                             __GLXconfig * glxConfig,
260                             __GLXcontext * baseShareContext,
261                             unsigned num_attribs,
262                             const uint32_t *attribs,
263                             int *error)
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     /* DRISWRAST won't support createContextAttribs, so these parameters will
272      * never be used.
273      */
274     (void) num_attribs;
275     (void) attribs;
276     (void) error;
277
278     shareContext = (__GLXDRIcontext *) baseShareContext;
279     if (shareContext)
280         driShare = shareContext->driContext;
281     else
282         driShare = NULL;
283
284     context = calloc(1, sizeof *context);
285     if (context == NULL)
286         return NULL;
287
288     context->base.destroy = __glXDRIcontextDestroy;
289     context->base.makeCurrent = __glXDRIcontextMakeCurrent;
290     context->base.loseCurrent = __glXDRIcontextLoseCurrent;
291     context->base.copy = __glXDRIcontextCopy;
292     context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
293
294     context->driContext =
295         (*core->createNewContext) (screen->driScreen,
296                                    config->driConfig, driShare, context);
297
298     return &context->base;
299 }
300
301 static __GLXdrawable *
302 __glXDRIscreenCreateDrawable(ClientPtr client,
303                              __GLXscreen * screen,
304                              DrawablePtr pDraw,
305                              XID drawId,
306                              int type, XID glxDrawId, __GLXconfig * glxConfig)
307 {
308     XID gcvals[2];
309     int status;
310     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
311     __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
312     __GLXDRIdrawable *private;
313
314     private = calloc(1, sizeof *private);
315     if (private == NULL)
316         return NULL;
317
318     private->screen = driScreen;
319     if (!__glXDrawableInit(&private->base, screen,
320                            pDraw, type, glxDrawId, glxConfig)) {
321         free(private);
322         return NULL;
323     }
324
325     private->base.destroy = __glXDRIdrawableDestroy;
326     private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
327     private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
328
329     gcvals[0] = GXcopy;
330     private->gc =
331         CreateGC(pDraw, GCFunction, gcvals, &status, (XID) 0, serverClient);
332     gcvals[1] = FALSE;
333     private->swapgc =
334         CreateGC(pDraw, GCFunction | GCGraphicsExposures, gcvals, &status,
335                  (XID) 0, serverClient);
336
337     private->driDrawable =
338         (*driScreen->swrast->createNewDrawable) (driScreen->driScreen,
339                                                  config->driConfig, private);
340
341     return &private->base;
342 }
343
344 static void
345 swrastGetDrawableInfo(__DRIdrawable * draw,
346                       int *x, int *y, int *w, int *h, void *loaderPrivate)
347 {
348     __GLXDRIdrawable *drawable = loaderPrivate;
349     DrawablePtr pDraw = drawable->base.pDraw;
350
351     *x = pDraw->x;
352     *y = pDraw->x;
353     *w = pDraw->width;
354     *h = pDraw->height;
355 }
356
357 static void
358 swrastPutImage(__DRIdrawable * draw, int op,
359                int x, int y, int w, int h, char *data, 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, x, y, w, h, 0, ZPixmap, data);
379 }
380
381 static void
382 swrastGetImage(__DRIdrawable * draw,
383                int x, int y, int w, int h, char *data, void *loaderPrivate)
384 {
385     __GLXDRIdrawable *drawable = loaderPrivate;
386     DrawablePtr pDraw = drawable->base.pDraw;
387     ScreenPtr pScreen = pDraw->pScreen;
388
389     pScreen->GetImage(pDraw, x, y, w, h, ZPixmap, ~0L, data);
390 }
391
392 static const __DRIswrastLoaderExtension swrastLoaderExtension = {
393     {__DRI_SWRAST_LOADER, __DRI_SWRAST_LOADER_VERSION},
394     swrastGetDrawableInfo,
395     swrastPutImage,
396     swrastGetImage
397 };
398
399 static const __DRIextension *loader_extensions[] = {
400     &systemTimeExtension.base,
401     &swrastLoaderExtension.base,
402     NULL
403 };
404
405 static void
406 initializeExtensions(__GLXDRIscreen * screen)
407 {
408     const __DRIextension **extensions;
409     int i;
410
411     extensions = screen->core->getExtensions(screen->driScreen);
412
413     for (i = 0; extensions[i]; i++) {
414 #ifdef __DRI_COPY_SUB_BUFFER
415         if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
416             screen->copySubBuffer =
417                 (const __DRIcopySubBufferExtension *) extensions[i];
418             /* GLX_MESA_copy_sub_buffer is always enabled. */
419         }
420 #endif
421
422 #ifdef __DRI_TEX_BUFFER
423         if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
424             screen->texBuffer = (const __DRItexBufferExtension *) extensions[i];
425             /* GLX_EXT_texture_from_pixmap is always enabled. */
426         }
427 #endif
428         /* Ignore unknown extensions */
429     }
430 }
431
432 static __GLXscreen *
433 __glXDRIscreenProbe(ScreenPtr pScreen)
434 {
435     const char *driverName = "swrast";
436     __GLXDRIscreen *screen;
437
438     screen = calloc(1, sizeof *screen);
439     if (screen == NULL)
440         return NULL;
441
442     screen->base.destroy = __glXDRIscreenDestroy;
443     screen->base.createContext = __glXDRIscreenCreateContext;
444     screen->base.createDrawable = __glXDRIscreenCreateDrawable;
445     screen->base.swapInterval = NULL;
446     screen->base.pScreen = pScreen;
447
448     screen->driver = glxProbeDriver(driverName,
449                                     (void **) &screen->core,
450                                     __DRI_CORE, __DRI_CORE_VERSION,
451                                     (void **) &screen->swrast,
452                                     __DRI_SWRAST, __DRI_SWRAST_VERSION);
453     if (screen->driver == NULL) {
454         goto handle_error;
455     }
456
457     screen->driScreen =
458         (*screen->swrast->createNewScreen) (pScreen->myNum,
459                                             loader_extensions,
460                                             &screen->driConfigs, screen);
461
462     if (screen->driScreen == NULL) {
463         LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed\n");
464         goto handle_error;
465     }
466
467     initializeExtensions(screen);
468
469     screen->base.fbconfigs = glxConvertConfigs(screen->core, screen->driConfigs,
470                                                GLX_WINDOW_BIT |
471                                                GLX_PIXMAP_BIT |
472                                                GLX_PBUFFER_BIT);
473
474     __glXScreenInit(&screen->base, pScreen);
475
476     screen->base.GLXmajor = 1;
477     screen->base.GLXminor = 4;
478
479     LogMessage(X_INFO, "AIGLX: Loaded and initialized %s\n", driverName);
480
481     return &screen->base;
482
483  handle_error:
484     if (screen->driver)
485         dlclose(screen->driver);
486
487     free(screen);
488
489     LogMessage(X_ERROR, "GLX: could not load software renderer\n");
490
491     return NULL;
492 }
493
494 _X_EXPORT __GLXprovider __glXDRISWRastProvider = {
495     __glXDRIscreenProbe,
496     "DRISWRAST",
497     NULL
498 };