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