2 * Copyright © 2008 George Sapountzis <gsap7@yahoo.gr>
3 * Copyright © 2008 Red Hat, Inc
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
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
27 #ifdef HAVE_DIX_CONFIG_H
28 #include <dix-config.h>
39 #include <GL/internal/dri_interface.h>
40 #include <GL/glxtokens.h>
42 #include "scrnintstr.h"
43 #include "pixmapstr.h"
47 #include "glxserver.h"
49 #include "glxdricommon.h"
51 #include "g_disptab.h"
52 #include "glapitable.h"
56 #include "extension_string.h"
58 /* RTLD_LOCAL is not defined on Cygwin */
65 typedef struct __GLXDRIscreen __GLXDRIscreen;
66 typedef struct __GLXDRIcontext __GLXDRIcontext;
67 typedef struct __GLXDRIdrawable __GLXDRIdrawable;
69 struct __GLXDRIscreen {
71 __DRIscreen *driScreen;
74 const __DRIcoreExtension *core;
75 const __DRIswrastExtension *swrast;
76 const __DRIcopySubBufferExtension *copySubBuffer;
77 const __DRItexBufferExtension *texBuffer;
80 struct __GLXDRIcontext {
82 __DRIcontext *driContext;
85 struct __GLXDRIdrawable {
87 __DRIdrawable *driDrawable;
88 __GLXDRIscreen *screen;
90 GCPtr gc; /* scratch GC for span drawing */
91 GCPtr swapgc; /* GC for swapping the color buffers */
95 __glXDRIdrawableDestroy(__GLXdrawable *drawable)
97 __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
98 const __DRIcoreExtension *core = private->screen->core;
100 (*core->destroyDrawable)(private->driDrawable);
102 FreeScratchGC(private->gc);
103 FreeScratchGC(private->swapgc);
105 __glXDrawableRelease(drawable);
111 __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
113 __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
114 const __DRIcoreExtension *core = private->screen->core;
116 (*core->swapBuffers)(private->driDrawable);
122 __glXDRIdrawableCopySubBuffer(__GLXdrawable *basePrivate,
123 int x, int y, int w, int h)
125 __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
126 const __DRIcopySubBufferExtension *copySubBuffer =
127 private->screen->copySubBuffer;
130 (*copySubBuffer->copySubBuffer)(private->driDrawable, x, y, w, h);
134 __glXDRIcontextDestroy(__GLXcontext *baseContext)
136 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
137 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
139 (*screen->core->destroyContext)(context->driContext);
140 __glXContextDestroy(&context->base);
145 __glXDRIcontextMakeCurrent(__GLXcontext *baseContext)
147 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
148 __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
149 __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
150 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
152 return (*screen->core->bindContext)(context->driContext,
158 __glXDRIcontextLoseCurrent(__GLXcontext *baseContext)
160 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
161 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
163 return (*screen->core->unbindContext)(context->driContext);
167 __glXDRIcontextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
170 __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
171 __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
172 __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
174 return (*screen->core->copyContext)(dst->driContext,
175 src->driContext, mask);
179 __glXDRIcontextForceCurrent(__GLXcontext *baseContext)
181 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
182 __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
183 __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
184 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
186 return (*screen->core->bindContext)(context->driContext,
191 #ifdef __DRI_TEX_BUFFER
194 __glXDRIbindTexImage(__GLXcontext *baseContext,
196 __GLXdrawable *glxPixmap)
198 __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
199 const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
200 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
202 if (texBuffer == NULL)
205 texBuffer->setTexBuffer(context->driContext,
207 drawable->driDrawable);
213 __glXDRIreleaseTexImage(__GLXcontext *baseContext,
215 __GLXdrawable *pixmap)
217 /* FIXME: Just unbind the texture? */
224 __glXDRIbindTexImage(__GLXcontext *baseContext,
226 __GLXdrawable *glxPixmap)
232 __glXDRIreleaseTexImage(__GLXcontext *baseContext,
234 __GLXdrawable *pixmap)
241 static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
242 __glXDRIbindTexImage,
243 __glXDRIreleaseTexImage
247 __glXDRIscreenDestroy(__GLXscreen *baseScreen)
249 __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
251 (*screen->core->destroyScreen)(screen->driScreen);
253 dlclose(screen->driver);
255 __glXScreenDestroy(baseScreen);
260 static __GLXcontext *
261 __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
262 __GLXconfig *glxConfig,
263 __GLXcontext *baseShareContext)
265 __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
266 __GLXDRIcontext *context, *shareContext;
267 __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
268 const __DRIcoreExtension *core = screen->core;
269 __DRIcontext *driShare;
271 shareContext = (__GLXDRIcontext *) baseShareContext;
273 driShare = shareContext->driContext;
277 context = calloc(1, sizeof *context);
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;
288 context->driContext =
289 (*core->createNewContext)(screen->driScreen,
290 config->driConfig, driShare, context);
292 return &context->base;
295 static __GLXdrawable *
296 __glXDRIscreenCreateDrawable(ClientPtr client,
302 __GLXconfig *glxConfig)
304 ChangeGCVal gcvals[2];
305 __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
306 __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
307 __GLXDRIdrawable *private;
309 ScreenPtr pScreen = driScreen->base.pScreen;
311 private = calloc(1, sizeof *private);
315 private->screen = driScreen;
316 if (!__glXDrawableInit(&private->base, screen,
317 pDraw, type, glxDrawId, glxConfig)) {
322 private->base.destroy = __glXDRIdrawableDestroy;
323 private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
324 private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
326 private->gc = CreateScratchGC(pScreen, pDraw->depth);
327 private->swapgc = CreateScratchGC(pScreen, pDraw->depth);
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);
334 private->driDrawable =
335 (*driScreen->swrast->createNewDrawable)(driScreen->driScreen,
339 return &private->base;
343 swrastGetDrawableInfo(__DRIdrawable *draw,
344 int *x, int *y, int *w, int *h,
347 __GLXDRIdrawable *drawable = loaderPrivate;
348 DrawablePtr pDraw = drawable->base.pDraw;
357 swrastPutImage(__DRIdrawable *draw, int op,
358 int x, int y, int w, int h, char *data,
361 __GLXDRIdrawable *drawable = loaderPrivate;
362 DrawablePtr pDraw = drawable->base.pDraw;
366 case __DRI_SWRAST_IMAGE_OP_DRAW:
369 case __DRI_SWRAST_IMAGE_OP_SWAP:
370 gc = drawable->swapgc;
376 ValidateGC(pDraw, gc);
378 gc->ops->PutImage(pDraw, gc, pDraw->depth,
379 x, y, w, h, 0, ZPixmap, data);
383 swrastGetImage(__DRIdrawable *draw,
384 int x, int y, int w, int h, char *data,
387 __GLXDRIdrawable *drawable = loaderPrivate;
388 DrawablePtr pDraw = drawable->base.pDraw;
389 ScreenPtr pScreen = pDraw->pScreen;
391 pScreen->GetImage(pDraw, x, y, w, h, ZPixmap, ~0L, data);
394 static const __DRIswrastLoaderExtension swrastLoaderExtension = {
395 { __DRI_SWRAST_LOADER, __DRI_SWRAST_LOADER_VERSION },
396 swrastGetDrawableInfo,
401 static const __DRIextension *loader_extensions[] = {
402 &systemTimeExtension.base,
403 &swrastLoaderExtension.base,
408 initializeExtensions(__GLXDRIscreen *screen)
410 const __DRIextension **extensions;
413 extensions = screen->core->getExtensions(screen->driScreen);
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. */
424 #ifdef __DRI_TEX_BUFFER
425 if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
427 (const __DRItexBufferExtension *) extensions[i];
428 /* GLX_EXT_texture_from_pixmap is always enabled. */
431 /* Ignore unknown extensions */
435 static const char dri_driver_path[] = DRI_DRIVER_PATH;
438 __glXDRIscreenProbe(ScreenPtr pScreen)
440 const char *driverName = "swrast";
441 __GLXDRIscreen *screen;
443 const __DRIextension **extensions;
444 const __DRIconfig **driConfigs;
447 screen = calloc(1, sizeof *screen);
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;
457 snprintf(filename, sizeof filename,
458 "%s/%s_dri.so", dri_driver_path, driverName);
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());
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());
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];
479 if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0 &&
480 extensions[i]->version >= __DRI_SWRAST_VERSION) {
481 screen->swrast = (const __DRIswrastExtension *) extensions[i];
485 if (screen->core == NULL || screen->swrast == NULL) {
486 LogMessage(X_ERROR, "AIGLX error: %s exports no DRI extension\n",
492 (*screen->swrast->createNewScreen)(pScreen->myNum,
497 if (screen->driScreen == NULL) {
499 "AIGLX error: Calling driver entry point failed\n");
503 initializeExtensions(screen);
505 screen->base.fbconfigs = glxConvertConfigs(screen->core, driConfigs,
510 __glXScreenInit(&screen->base, pScreen);
512 screen->base.GLXmajor = 1;
513 screen->base.GLXminor = 4;
516 "AIGLX: Loaded and initialized %s\n", filename);
518 return &screen->base;
522 dlclose(screen->driver);
526 LogMessage(X_ERROR, "GLX: could not load software renderer\n");
531 _X_EXPORT __GLXprovider __glXDRISWRastProvider = {