tizen 2.4 release
[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 "extension_string.h"
52
53 /* RTLD_LOCAL is not defined on Cygwin */
54 #ifdef __CYGWIN__
55 #ifndef RTLD_LOCAL
56 #define RTLD_LOCAL 0
57 #endif
58 #endif
59
60 typedef struct __GLXDRIscreen __GLXDRIscreen;
61 typedef struct __GLXDRIcontext __GLXDRIcontext;
62 typedef struct __GLXDRIdrawable __GLXDRIdrawable;
63
64 struct __GLXDRIscreen {
65     __GLXscreen base;
66     __DRIscreen *driScreen;
67     void *driver;
68
69     const __DRIcoreExtension *core;
70     const __DRIswrastExtension *swrast;
71     const __DRIcopySubBufferExtension *copySubBuffer;
72     const __DRItexBufferExtension *texBuffer;
73     const __DRIconfig **driConfigs;
74 };
75
76 struct __GLXDRIcontext {
77     __GLXcontext base;
78     __DRIcontext *driContext;
79 };
80
81 struct __GLXDRIdrawable {
82     __GLXdrawable base;
83     __DRIdrawable *driDrawable;
84     __GLXDRIscreen *screen;
85
86     GCPtr gc;                   /* scratch GC for span drawing */
87     GCPtr swapgc;               /* GC for swapping the color buffers */
88 };
89
90 static void
91 __glXDRIdrawableDestroy(__GLXdrawable * drawable)
92 {
93     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
94     const __DRIcoreExtension *core = private->screen->core;
95
96     (*core->destroyDrawable) (private->driDrawable);
97
98     FreeGC(private->gc, (GContext) 0);
99     FreeGC(private->swapgc, (GContext) 0);
100
101     __glXDrawableRelease(drawable);
102
103     free(private);
104 }
105
106 static GLboolean
107 __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable * drawable)
108 {
109     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
110     const __DRIcoreExtension *core = private->screen->core;
111
112     (*core->swapBuffers) (private->driDrawable);
113
114     return TRUE;
115 }
116
117 static void
118 __glXDRIdrawableCopySubBuffer(__GLXdrawable * basePrivate,
119                               int x, int y, int w, int h)
120 {
121     __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
122     const __DRIcopySubBufferExtension *copySubBuffer =
123         private->screen->copySubBuffer;
124
125     if (copySubBuffer)
126         (*copySubBuffer->copySubBuffer) (private->driDrawable, x, y, w, h);
127 }
128
129 static void
130 __glXDRIcontextDestroy(__GLXcontext * baseContext)
131 {
132     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
133     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
134
135     (*screen->core->destroyContext) (context->driContext);
136     __glXContextDestroy(&context->base);
137     free(context);
138 }
139
140 static int
141 __glXDRIcontextMakeCurrent(__GLXcontext * baseContext)
142 {
143     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
144     __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
145     __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
146     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
147
148     return (*screen->core->bindContext) (context->driContext,
149                                          draw->driDrawable, read->driDrawable);
150 }
151
152 static int
153 __glXDRIcontextLoseCurrent(__GLXcontext * baseContext)
154 {
155     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
156     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
157
158     return (*screen->core->unbindContext) (context->driContext);
159 }
160
161 static int
162 __glXDRIcontextCopy(__GLXcontext * baseDst, __GLXcontext * baseSrc,
163                     unsigned long mask)
164 {
165     __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
166     __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
167     __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
168
169     return (*screen->core->copyContext) (dst->driContext,
170                                          src->driContext, mask);
171 }
172
173 static int
174 __glXDRIbindTexImage(__GLXcontext * baseContext,
175                      int buffer, __GLXdrawable * glxPixmap)
176 {
177     __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
178     const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
179     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
180
181     if (texBuffer == NULL)
182         return Success;
183
184 #if __DRI_TEX_BUFFER_VERSION >= 2
185     if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
186         (*texBuffer->setTexBuffer2) (context->driContext,
187                                      glxPixmap->target,
188                                      glxPixmap->format, drawable->driDrawable);
189     }
190     else
191 #endif
192         texBuffer->setTexBuffer(context->driContext,
193                                 glxPixmap->target, drawable->driDrawable);
194
195     return Success;
196 }
197
198 static int
199 __glXDRIreleaseTexImage(__GLXcontext * baseContext,
200                         int buffer, __GLXdrawable * pixmap)
201 {
202     /* FIXME: Just unbind the texture? */
203     return Success;
204 }
205
206 static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
207     __glXDRIbindTexImage,
208     __glXDRIreleaseTexImage
209 };
210
211 static void
212 __glXDRIscreenDestroy(__GLXscreen * baseScreen)
213 {
214     int i;
215
216     __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
217
218     (*screen->core->destroyScreen) (screen->driScreen);
219
220     dlclose(screen->driver);
221
222     __glXScreenDestroy(baseScreen);
223
224     if (screen->driConfigs) {
225         for (i = 0; screen->driConfigs[i] != NULL; i++)
226             free((__DRIconfig **) screen->driConfigs[i]);
227         free(screen->driConfigs);
228     }
229
230     free(screen);
231 }
232
233 static __GLXcontext *
234 __glXDRIscreenCreateContext(__GLXscreen * baseScreen,
235                             __GLXconfig * glxConfig,
236                             __GLXcontext * baseShareContext,
237                             unsigned num_attribs,
238                             const uint32_t *attribs,
239                             int *error)
240 {
241     __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
242     __GLXDRIcontext *context, *shareContext;
243     __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
244     const __DRIcoreExtension *core = screen->core;
245     __DRIcontext *driShare;
246
247     /* DRISWRAST won't support createContextAttribs, so these parameters will
248      * never be used.
249      */
250     (void) num_attribs;
251     (void) attribs;
252     (void) error;
253
254     shareContext = (__GLXDRIcontext *) baseShareContext;
255     if (shareContext)
256         driShare = shareContext->driContext;
257     else
258         driShare = NULL;
259
260     context = calloc(1, sizeof *context);
261     if (context == NULL)
262         return NULL;
263
264     context->base.destroy = __glXDRIcontextDestroy;
265     context->base.makeCurrent = __glXDRIcontextMakeCurrent;
266     context->base.loseCurrent = __glXDRIcontextLoseCurrent;
267     context->base.copy = __glXDRIcontextCopy;
268     context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
269
270     context->driContext =
271         (*core->createNewContext) (screen->driScreen,
272                                    config->driConfig, driShare, context);
273
274     return &context->base;
275 }
276
277 static __GLXdrawable *
278 __glXDRIscreenCreateDrawable(ClientPtr client,
279                              __GLXscreen * screen,
280                              DrawablePtr pDraw,
281                              XID drawId,
282                              int type, XID glxDrawId, __GLXconfig * glxConfig)
283 {
284     XID gcvals[2];
285     int status;
286     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
287     __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
288     __GLXDRIdrawable *private;
289
290     private = calloc(1, sizeof *private);
291     if (private == NULL)
292         return NULL;
293
294     private->screen = driScreen;
295     if (!__glXDrawableInit(&private->base, screen,
296                            pDraw, type, glxDrawId, glxConfig)) {
297         free(private);
298         return NULL;
299     }
300
301     private->base.destroy = __glXDRIdrawableDestroy;
302     private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
303     private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
304
305     gcvals[0] = GXcopy;
306     private->gc =
307         CreateGC(pDraw, GCFunction, gcvals, &status, (XID) 0, serverClient);
308     gcvals[1] = FALSE;
309     private->swapgc =
310         CreateGC(pDraw, GCFunction | GCGraphicsExposures, gcvals, &status,
311                  (XID) 0, serverClient);
312
313     private->driDrawable =
314         (*driScreen->swrast->createNewDrawable) (driScreen->driScreen,
315                                                  config->driConfig, private);
316
317     return &private->base;
318 }
319
320 static void
321 swrastGetDrawableInfo(__DRIdrawable * draw,
322                       int *x, int *y, int *w, int *h, void *loaderPrivate)
323 {
324     __GLXDRIdrawable *drawable = loaderPrivate;
325     DrawablePtr pDraw = drawable->base.pDraw;
326
327     *x = pDraw->x;
328     *y = pDraw->x;
329     *w = pDraw->width;
330     *h = pDraw->height;
331 }
332
333 static void
334 swrastPutImage(__DRIdrawable * draw, int op,
335                int x, int y, int w, int h, char *data, void *loaderPrivate)
336 {
337     __GLXDRIdrawable *drawable = loaderPrivate;
338     DrawablePtr pDraw = drawable->base.pDraw;
339     GCPtr gc;
340     __GLXcontext *cx = lastGLContext;
341
342     switch (op) {
343     case __DRI_SWRAST_IMAGE_OP_DRAW:
344         gc = drawable->gc;
345         break;
346     case __DRI_SWRAST_IMAGE_OP_SWAP:
347         gc = drawable->swapgc;
348         break;
349     default:
350         return;
351     }
352
353     ValidateGC(pDraw, gc);
354
355     gc->ops->PutImage(pDraw, gc, pDraw->depth, x, y, w, h, 0, ZPixmap, data);
356     if (cx != lastGLContext) {
357         lastGLContext = cx;
358         cx->makeCurrent(cx);
359     }
360 }
361
362 static void
363 swrastGetImage(__DRIdrawable * draw,
364                int x, int y, int w, int h, char *data, void *loaderPrivate)
365 {
366     __GLXDRIdrawable *drawable = loaderPrivate;
367     DrawablePtr pDraw = drawable->base.pDraw;
368     ScreenPtr pScreen = pDraw->pScreen;
369     __GLXcontext *cx = lastGLContext;
370
371     pScreen->GetImage(pDraw, x, y, w, h, ZPixmap, ~0L, data);
372     if (cx != lastGLContext) {
373         lastGLContext = cx;
374         cx->makeCurrent(cx);
375     }
376 }
377
378 static const __DRIswrastLoaderExtension swrastLoaderExtension = {
379     {__DRI_SWRAST_LOADER, 1},
380     swrastGetDrawableInfo,
381     swrastPutImage,
382     swrastGetImage
383 };
384
385 static const __DRIextension *loader_extensions[] = {
386     &systemTimeExtension.base,
387     &swrastLoaderExtension.base,
388     NULL
389 };
390
391 static void
392 initializeExtensions(__GLXDRIscreen * screen)
393 {
394     const __DRIextension **extensions;
395     int i;
396
397     extensions = screen->core->getExtensions(screen->driScreen);
398
399     for (i = 0; extensions[i]; i++) {
400         if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
401             screen->copySubBuffer =
402                 (const __DRIcopySubBufferExtension *) extensions[i];
403             /* GLX_MESA_copy_sub_buffer is always enabled. */
404         }
405
406         if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
407             screen->texBuffer = (const __DRItexBufferExtension *) extensions[i];
408             /* GLX_EXT_texture_from_pixmap is always enabled. */
409         }
410
411         /* Ignore unknown extensions */
412     }
413 }
414
415 /* white lie */
416 extern glx_func_ptr glXGetProcAddressARB(const char *);
417
418 static __GLXscreen *
419 __glXDRIscreenProbe(ScreenPtr pScreen)
420 {
421     const char *driverName = "swrast";
422     __GLXDRIscreen *screen;
423
424     screen = calloc(1, sizeof *screen);
425     if (screen == NULL)
426         return NULL;
427
428     screen->base.destroy = __glXDRIscreenDestroy;
429     screen->base.createContext = __glXDRIscreenCreateContext;
430     screen->base.createDrawable = __glXDRIscreenCreateDrawable;
431     screen->base.swapInterval = NULL;
432     screen->base.pScreen = pScreen;
433
434     screen->driver = glxProbeDriver(driverName,
435                                     (void **) &screen->core,
436                                     __DRI_CORE, 1,
437                                     (void **) &screen->swrast,
438                                     __DRI_SWRAST, 1);
439     if (screen->driver == NULL) {
440         goto handle_error;
441     }
442
443     screen->driScreen =
444         (*screen->swrast->createNewScreen) (pScreen->myNum,
445                                             loader_extensions,
446                                             &screen->driConfigs, screen);
447
448     if (screen->driScreen == NULL) {
449         LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed\n");
450         goto handle_error;
451     }
452
453     initializeExtensions(screen);
454
455     screen->base.fbconfigs = glxConvertConfigs(screen->core, screen->driConfigs,
456                                                GLX_WINDOW_BIT |
457                                                GLX_PIXMAP_BIT |
458                                                GLX_PBUFFER_BIT);
459
460     __glXScreenInit(&screen->base, pScreen);
461
462     screen->base.GLXmajor = 1;
463     screen->base.GLXminor = 4;
464
465     __glXsetGetProcAddress(glXGetProcAddressARB);
466
467     LogMessage(X_INFO, "AIGLX: Loaded and initialized %s\n", driverName);
468
469     return &screen->base;
470
471  handle_error:
472     if (screen->driver)
473         dlclose(screen->driver);
474
475     free(screen);
476
477     LogMessage(X_ERROR, "GLX: could not load software renderer\n");
478
479     return NULL;
480 }
481
482 _X_EXPORT __GLXprovider __glXDRISWRastProvider = {
483     __glXDRIscreenProbe,
484     "DRISWRAST",
485     NULL
486 };