Imported Upstream version 1.15.1
[deb_xorg-server.git] / glx / glxdriswrast.c
CommitLineData
a09e091a
JB
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
60typedef struct __GLXDRIscreen __GLXDRIscreen;
61typedef struct __GLXDRIcontext __GLXDRIcontext;
62typedef struct __GLXDRIdrawable __GLXDRIdrawable;
63
64struct __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
76struct __GLXDRIcontext {
77 __GLXcontext base;
78 __DRIcontext *driContext;
79};
80
81struct __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
90static 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
106static 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
117static 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
129static 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
140static 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
152static 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
161static 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#ifdef __DRI_TEX_BUFFER
174
175static int
176__glXDRIbindTexImage(__GLXcontext * baseContext,
177 int buffer, __GLXdrawable * glxPixmap)
178{
179 __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
180 const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
181 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
182
183 if (texBuffer == NULL)
184 return Success;
185
186#if __DRI_TEX_BUFFER_VERSION >= 2
187 if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
188 (*texBuffer->setTexBuffer2) (context->driContext,
189 glxPixmap->target,
190 glxPixmap->format, drawable->driDrawable);
191 }
192 else
193#endif
194 texBuffer->setTexBuffer(context->driContext,
195 glxPixmap->target, drawable->driDrawable);
196
197 return Success;
198}
199
200static int
201__glXDRIreleaseTexImage(__GLXcontext * baseContext,
202 int buffer, __GLXdrawable * pixmap)
203{
204 /* FIXME: Just unbind the texture? */
205 return Success;
206}
207
208#else
209
210static int
211__glXDRIbindTexImage(__GLXcontext * baseContext,
212 int buffer, __GLXdrawable * glxPixmap)
213{
214 return Success;
215}
216
217static int
218__glXDRIreleaseTexImage(__GLXcontext * baseContext,
219 int buffer, __GLXdrawable * pixmap)
220{
221 return Success;
222}
223
224#endif
225
226static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
227 __glXDRIbindTexImage,
228 __glXDRIreleaseTexImage
229};
230
231static void
232__glXDRIscreenDestroy(__GLXscreen * baseScreen)
233{
234 int i;
235
236 __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
237
238 (*screen->core->destroyScreen) (screen->driScreen);
239
240 dlclose(screen->driver);
241
242 __glXScreenDestroy(baseScreen);
243
244 if (screen->driConfigs) {
245 for (i = 0; screen->driConfigs[i] != NULL; i++)
246 free((__DRIconfig **) screen->driConfigs[i]);
247 free(screen->driConfigs);
248 }
249
250 free(screen);
251}
252
253static __GLXcontext *
254__glXDRIscreenCreateContext(__GLXscreen * baseScreen,
255 __GLXconfig * glxConfig,
256 __GLXcontext * baseShareContext,
257 unsigned num_attribs,
258 const uint32_t *attribs,
259 int *error)
260{
261 __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
262 __GLXDRIcontext *context, *shareContext;
263 __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
264 const __DRIcoreExtension *core = screen->core;
265 __DRIcontext *driShare;
266
267 /* DRISWRAST won't support createContextAttribs, so these parameters will
268 * never be used.
269 */
270 (void) num_attribs;
271 (void) attribs;
272 (void) error;
273
274 shareContext = (__GLXDRIcontext *) baseShareContext;
275 if (shareContext)
276 driShare = shareContext->driContext;
277 else
278 driShare = NULL;
279
280 context = calloc(1, sizeof *context);
281 if (context == NULL)
282 return NULL;
283
284 context->base.destroy = __glXDRIcontextDestroy;
285 context->base.makeCurrent = __glXDRIcontextMakeCurrent;
286 context->base.loseCurrent = __glXDRIcontextLoseCurrent;
287 context->base.copy = __glXDRIcontextCopy;
288 context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
289
290 context->driContext =
291 (*core->createNewContext) (screen->driScreen,
292 config->driConfig, driShare, context);
293
294 return &context->base;
295}
296
297static __GLXdrawable *
298__glXDRIscreenCreateDrawable(ClientPtr client,
299 __GLXscreen * screen,
300 DrawablePtr pDraw,
301 XID drawId,
302 int type, XID glxDrawId, __GLXconfig * glxConfig)
303{
304 XID gcvals[2];
305 int status;
306 __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
307 __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
308 __GLXDRIdrawable *private;
309
310 private = calloc(1, sizeof *private);
311 if (private == NULL)
312 return NULL;
313
314 private->screen = driScreen;
315 if (!__glXDrawableInit(&private->base, screen,
316 pDraw, type, glxDrawId, glxConfig)) {
317 free(private);
318 return NULL;
319 }
320
321 private->base.destroy = __glXDRIdrawableDestroy;
322 private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
323 private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
324
325 gcvals[0] = GXcopy;
326 private->gc =
327 CreateGC(pDraw, GCFunction, gcvals, &status, (XID) 0, serverClient);
328 gcvals[1] = FALSE;
329 private->swapgc =
330 CreateGC(pDraw, GCFunction | GCGraphicsExposures, gcvals, &status,
331 (XID) 0, serverClient);
332
333 private->driDrawable =
334 (*driScreen->swrast->createNewDrawable) (driScreen->driScreen,
335 config->driConfig, private);
336
337 return &private->base;
338}
339
340static void
341swrastGetDrawableInfo(__DRIdrawable * draw,
342 int *x, int *y, int *w, int *h, void *loaderPrivate)
343{
344 __GLXDRIdrawable *drawable = loaderPrivate;
345 DrawablePtr pDraw = drawable->base.pDraw;
346
347 *x = pDraw->x;
348 *y = pDraw->x;
349 *w = pDraw->width;
350 *h = pDraw->height;
351}
352
353static void
354swrastPutImage(__DRIdrawable * draw, int op,
355 int x, int y, int w, int h, char *data, void *loaderPrivate)
356{
357 __GLXDRIdrawable *drawable = loaderPrivate;
358 DrawablePtr pDraw = drawable->base.pDraw;
359 GCPtr gc;
360
361 switch (op) {
362 case __DRI_SWRAST_IMAGE_OP_DRAW:
363 gc = drawable->gc;
364 break;
365 case __DRI_SWRAST_IMAGE_OP_SWAP:
366 gc = drawable->swapgc;
367 break;
368 default:
369 return;
370 }
371
372 ValidateGC(pDraw, gc);
373
374 gc->ops->PutImage(pDraw, gc, pDraw->depth, x, y, w, h, 0, ZPixmap, data);
375}
376
377static void
378swrastGetImage(__DRIdrawable * draw,
379 int x, int y, int w, int h, char *data, void *loaderPrivate)
380{
381 __GLXDRIdrawable *drawable = loaderPrivate;
382 DrawablePtr pDraw = drawable->base.pDraw;
383 ScreenPtr pScreen = pDraw->pScreen;
384
385 pScreen->GetImage(pDraw, x, y, w, h, ZPixmap, ~0L, data);
386}
387
388static const __DRIswrastLoaderExtension swrastLoaderExtension = {
389 {__DRI_SWRAST_LOADER, 1},
390 swrastGetDrawableInfo,
391 swrastPutImage,
392 swrastGetImage
393};
394
395static const __DRIextension *loader_extensions[] = {
396 &systemTimeExtension.base,
397 &swrastLoaderExtension.base,
398 NULL
399};
400
401static void
402initializeExtensions(__GLXDRIscreen * screen)
403{
404 const __DRIextension **extensions;
405 int i;
406
407 extensions = screen->core->getExtensions(screen->driScreen);
408
409 for (i = 0; extensions[i]; i++) {
410#ifdef __DRI_COPY_SUB_BUFFER
411 if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
412 screen->copySubBuffer =
413 (const __DRIcopySubBufferExtension *) extensions[i];
414 /* GLX_MESA_copy_sub_buffer is always enabled. */
415 }
416#endif
417
418#ifdef __DRI_TEX_BUFFER
419 if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
420 screen->texBuffer = (const __DRItexBufferExtension *) extensions[i];
421 /* GLX_EXT_texture_from_pixmap is always enabled. */
422 }
423#endif
424 /* Ignore unknown extensions */
425 }
426}
427
428/* white lie */
429extern glx_func_ptr glXGetProcAddressARB(const char *);
430
431static __GLXscreen *
432__glXDRIscreenProbe(ScreenPtr pScreen)
433{
434 const char *driverName = "swrast";
435 __GLXDRIscreen *screen;
436
437 screen = calloc(1, sizeof *screen);
438 if (screen == NULL)
439 return NULL;
440
441 screen->base.destroy = __glXDRIscreenDestroy;
442 screen->base.createContext = __glXDRIscreenCreateContext;
443 screen->base.createDrawable = __glXDRIscreenCreateDrawable;
444 screen->base.swapInterval = NULL;
445 screen->base.pScreen = pScreen;
446
447 screen->driver = glxProbeDriver(driverName,
448 (void **) &screen->core,
449 __DRI_CORE, 1,
450 (void **) &screen->swrast,
451 __DRI_SWRAST, 1);
452 if (screen->driver == NULL) {
453 goto handle_error;
454 }
455
456 screen->driScreen =
457 (*screen->swrast->createNewScreen) (pScreen->myNum,
458 loader_extensions,
459 &screen->driConfigs, screen);
460
461 if (screen->driScreen == NULL) {
462 LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed\n");
463 goto handle_error;
464 }
465
466 initializeExtensions(screen);
467
468 screen->base.fbconfigs = glxConvertConfigs(screen->core, screen->driConfigs,
469 GLX_WINDOW_BIT |
470 GLX_PIXMAP_BIT |
471 GLX_PBUFFER_BIT);
472
473 __glXScreenInit(&screen->base, pScreen);
474
475 screen->base.GLXmajor = 1;
476 screen->base.GLXminor = 4;
477
478 __glXsetGetProcAddress(glXGetProcAddressARB);
479
480 LogMessage(X_INFO, "AIGLX: Loaded and initialized %s\n", driverName);
481
482 return &screen->base;
483
484 handle_error:
485 if (screen->driver)
486 dlclose(screen->driver);
487
488 free(screen);
489
490 LogMessage(X_ERROR, "GLX: could not load software renderer\n");
491
492 return NULL;
493}
494
495_X_EXPORT __GLXprovider __glXDRISWRastProvider = {
496 __glXDRIscreenProbe,
497 "DRISWRAST",
498 NULL
499};