glxglcore.c 11.9 KB
Newer Older
Eric Anholt's avatar
Eric Anholt committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**************************************************************************

Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
All Rights Reserved.

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sub license, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial portions
of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

**************************************************************************/

/*
 * Authors:
 *   Kevin E. Martin <kevin@precisioninsight.com>
 *   Brian E. Paul <brian@precisioninsight.com>
 *
 */

35
36
37
38
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif

39
#include <string.h>
40
41
42

#include <GL/xmesa.h>
#include <GL/internal/glcore.h>
Eric Anholt's avatar
Eric Anholt committed
43
44
45
46
47
48
#include <glxserver.h>
#include <glxscreens.h>
#include <glxdrawable.h>
#include <glxcontext.h>
#include <glxutil.h>

49
50
51
52
53
54
#include "glcontextmodes.h"
#include "os.h"

typedef struct __GLXMESAscreen   __GLXMESAscreen;
typedef struct __GLXMESAcontext  __GLXMESAcontext;
typedef struct __GLXMESAdrawable __GLXMESAdrawable;
Eric Anholt's avatar
Eric Anholt committed
55

56
57
58
struct __GLXMESAscreen {
    __GLXscreen   base;
    int           index;
59
    int		  num_vis;
60
    XMesaVisual  *xm_vis;
Eric Anholt's avatar
Eric Anholt committed
61
62
};

63
64
65
66
struct __GLXMESAcontext {
    __GLXcontext base;
    XMesaContext xmesa;
};
67

68
69
70
struct __GLXMESAdrawable {
    __GLXdrawable base;
    XMesaBuffer   xm_buf;
Eric Anholt's avatar
Eric Anholt committed
71
72
};

73
static XMesaVisual find_mesa_visual(__GLXscreen *screen, XID fbconfigID);
74

Eric Anholt's avatar
Eric Anholt committed
75

76
77
78
79
static void
__glXMesaDrawableDestroy(__GLXdrawable *base)
{
    __GLXMESAdrawable *glxPriv = (__GLXMESAdrawable *) base;
Eric Anholt's avatar
Eric Anholt committed
80

81
82
    if (glxPriv->xm_buf != NULL)
      XMesaDestroyBuffer(glxPriv->xm_buf);
83
84
    xfree(glxPriv);
}
Eric Anholt's avatar
Eric Anholt committed
85

86
87
static GLboolean
__glXMesaDrawableResize(__GLXdrawable *base)
Eric Anholt's avatar
Eric Anholt committed
88
{
89
    __GLXMESAdrawable *glxPriv = (__GLXMESAdrawable *) base;
Eric Anholt's avatar
Eric Anholt committed
90

91
    XMesaResizeBuffers(glxPriv->xm_buf);
Eric Anholt's avatar
Eric Anholt committed
92

93
94
    return GL_TRUE;
}
Eric Anholt's avatar
Eric Anholt committed
95

96
97
static GLboolean
__glXMesaDrawableSwapBuffers(__GLXdrawable *base)
Eric Anholt's avatar
Eric Anholt committed
98
{
99
    __GLXMESAdrawable *glxPriv = (__GLXMESAdrawable *) base;
Eric Anholt's avatar
Eric Anholt committed
100

101
102
103
104
105
106
107
    /* This is terrifying: XMesaSwapBuffers() ends up calling CopyArea
     * to do the buffer swap, but this assumes that the server holds
     * the lock and has its context visible.  If another screen uses a
     * DRI driver, that will have installed the DRI enter/leave server
     * functions, which lifts the lock during GLX dispatch.  This is
     * why we need to re-take the lock and swap in the server context
     * before calling XMesaSwapBuffers() here.  /me shakes head. */
Eric Anholt's avatar
Eric Anholt committed
108

109
    __glXenterServer(GL_FALSE);
Eric Anholt's avatar
Eric Anholt committed
110

111
    XMesaSwapBuffers(glxPriv->xm_buf);
Eric Anholt's avatar
Eric Anholt committed
112

113
    __glXleaveServer(GL_FALSE);
Eric Anholt's avatar
Eric Anholt committed
114

115
116
    return GL_TRUE;
}
Eric Anholt's avatar
Eric Anholt committed
117
118


119
static __GLXdrawable *
120
__glXMesaScreenCreateDrawable(__GLXscreen *screen,
Kristian Høgsberg's avatar
Kristian Høgsberg committed
121
			      DrawablePtr pDraw, int type,
122
123
			      XID drawId,
			      __GLcontextModes *modes)
Eric Anholt's avatar
Eric Anholt committed
124
{
125
126
    __GLXMESAdrawable *glxPriv;
    XMesaVisual xm_vis;
Eric Anholt's avatar
Eric Anholt committed
127

128
129
130
    glxPriv = xalloc(sizeof *glxPriv);
    if (glxPriv == NULL)
	return NULL;
Eric Anholt's avatar
Eric Anholt committed
131

132
    memset(glxPriv, 0, sizeof *glxPriv);
Eric Anholt's avatar
Eric Anholt committed
133

Kristian Høgsberg's avatar
Kristian Høgsberg committed
134
135
    if (!__glXDrawableInit(&glxPriv->base, screen,
			   pDraw, type, drawId, modes)) {
136
137
        xfree(glxPriv);
	return NULL;
Eric Anholt's avatar
Eric Anholt committed
138
139
    }

140
141
142
    glxPriv->base.destroy     = __glXMesaDrawableDestroy;
    glxPriv->base.resize      = __glXMesaDrawableResize;
    glxPriv->base.swapBuffers = __glXMesaDrawableSwapBuffers;
Eric Anholt's avatar
Eric Anholt committed
143

144
    xm_vis = find_mesa_visual(screen, modes->fbconfigID);
145
146
    if (xm_vis == NULL) {
	ErrorF("find_mesa_visual returned NULL for visualID = 0x%04x\n",
147
	       modes->visualID);
148
149
	xfree(glxPriv);
	return NULL;
Eric Anholt's avatar
Eric Anholt committed
150
151
    }

152
153
154
155
    if (glxPriv->base.type == DRAWABLE_WINDOW) {
	glxPriv->xm_buf = XMesaCreateWindowBuffer(xm_vis, (WindowPtr)pDraw);
    } else {
	glxPriv->xm_buf = XMesaCreatePixmapBuffer(xm_vis, (PixmapPtr)pDraw, 0);
Eric Anholt's avatar
Eric Anholt committed
156
157
    }

158
159
160
161
162
    if (glxPriv->xm_buf == NULL) {
	xfree(glxPriv);
	return NULL;
    }

163
164
    return &glxPriv->base;
}
Eric Anholt's avatar
Eric Anholt committed
165

166
167
168
169
static void
__glXMesaContextDestroy(__GLXcontext *baseContext)
{
    __GLXMESAcontext *context = (__GLXMESAcontext *) baseContext;
Eric Anholt's avatar
Eric Anholt committed
170

171
    XMesaDestroyContext(context->xmesa);
172
    __glXContextDestroy(&context->base);
173
174
    xfree(context);
}
Eric Anholt's avatar
Eric Anholt committed
175

176
177
static int
__glXMesaContextMakeCurrent(__GLXcontext *baseContext)
Eric Anholt's avatar
Eric Anholt committed
178

179
180
181
182
{
    __GLXMESAcontext *context = (__GLXMESAcontext *) baseContext;
    __GLXMESAdrawable *drawPriv = (__GLXMESAdrawable *) context->base.drawPriv;
    __GLXMESAdrawable *readPriv = (__GLXMESAdrawable *) context->base.readPriv;
Eric Anholt's avatar
Eric Anholt committed
183

184
185
186
187
    return XMesaMakeCurrent2(context->xmesa,
			     drawPriv->xm_buf,
			     readPriv->xm_buf);
}
Eric Anholt's avatar
Eric Anholt committed
188

189
190
191
192
static int
__glXMesaContextLoseCurrent(__GLXcontext *baseContext)
{
    __GLXMESAcontext *context = (__GLXMESAcontext *) baseContext;
Eric Anholt's avatar
Eric Anholt committed
193

194
195
    return XMesaLoseCurrent(context->xmesa);
}
Eric Anholt's avatar
Eric Anholt committed
196

197
198
199
200
201
202
203
static int
__glXMesaContextCopy(__GLXcontext *baseDst,
		     __GLXcontext *baseSrc,
		     unsigned long mask)
{
    __GLXMESAcontext *dst = (__GLXMESAcontext *) baseDst;
    __GLXMESAcontext *src = (__GLXMESAcontext *) baseSrc;
Eric Anholt's avatar
Eric Anholt committed
204

205
    return XMesaCopyContext(src->xmesa, dst->xmesa, mask);
206
}
Eric Anholt's avatar
Eric Anholt committed
207

208
209
210
211
static int
__glXMesaContextForceCurrent(__GLXcontext *baseContext)
{
    __GLXMESAcontext *context = (__GLXMESAcontext *) baseContext;
Eric Anholt's avatar
Eric Anholt committed
212

213
    /* GlxSetRenderTables() call for XGL moved in XMesaForceCurrent() */
214

215
    return XMesaForceCurrent(context->xmesa);
Eric Anholt's avatar
Eric Anholt committed
216
217
}

218
219
220
221
static __GLXcontext *
__glXMesaScreenCreateContext(__GLXscreen *screen,
			     __GLcontextModes *modes,
			     __GLXcontext *baseShareContext)
Eric Anholt's avatar
Eric Anholt committed
222
{
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
    __GLXMESAcontext *context;
    __GLXMESAcontext *shareContext = (__GLXMESAcontext *) baseShareContext;
    XMesaVisual xm_vis;
    XMesaContext xm_share;

    context = xalloc (sizeof (__GLXMESAcontext));
    if (context == NULL)
	return NULL;

    memset(context, 0, sizeof *context);

    context->base.pGlxScreen = screen;
    context->base.modes      = modes;

    context->base.destroy        = __glXMesaContextDestroy;
    context->base.makeCurrent    = __glXMesaContextMakeCurrent;
    context->base.loseCurrent    = __glXMesaContextLoseCurrent;
    context->base.copy           = __glXMesaContextCopy;
    context->base.forceCurrent   = __glXMesaContextForceCurrent;

243
    xm_vis = find_mesa_visual(screen, modes->fbconfigID);
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
    if (!xm_vis) {
	ErrorF("find_mesa_visual returned NULL for visualID = 0x%04x\n",
	       modes->visualID);
	xfree(context);
	return NULL;
    }

    xm_share = shareContext ? shareContext->xmesa : NULL;
    context->xmesa = XMesaCreateContext(xm_vis, xm_share);
    if (!context->xmesa) {
	xfree(context);
	return NULL;
    }

    return &context->base;
Eric Anholt's avatar
Eric Anholt committed
259
260
}

261
262
static void
__glXMesaScreenDestroy(__GLXscreen *screen)
Eric Anholt's avatar
Eric Anholt committed
263
{
264
265
266
    __GLXMESAscreen *mesaScreen = (__GLXMESAscreen *) screen;
    int i;

267
    if (mesaScreen->xm_vis) {
268
	for (i = 0; i < mesaScreen->base.numFBConfigs; i++) {
269
270
271
	    if (mesaScreen->xm_vis[i])
		XMesaDestroyVisual(mesaScreen->xm_vis[i]);
	}
272

273
274
	xfree(mesaScreen->xm_vis);
    }
275
276
277
278

    __glXScreenDestroy(screen);

    xfree(screen);
Eric Anholt's avatar
Eric Anholt committed
279
280
}

281
static XMesaVisual
282
find_mesa_visual(__GLXscreen *screen, XID fbconfigID)
Eric Anholt's avatar
Eric Anholt committed
283
{
284
285
286
    __GLXMESAscreen *mesaScreen = (__GLXMESAscreen *) screen;
    const __GLcontextModes *modes;
    unsigned i = 0;
Eric Anholt's avatar
Eric Anholt committed
287

288
289
290
    for (modes = screen->fbconfigs; modes != NULL; modes = modes->next) {
 	if (modes->fbconfigID == fbconfigID)
	    return mesaScreen->xm_vis[i];
291
	i++;
Eric Anholt's avatar
Eric Anholt committed
292
    }
293

294
    return NULL;
Eric Anholt's avatar
Eric Anholt committed
295
296
}

297
298
299
300
301
302
303
const static int numBack = 2;
const static int numDepth = 2;
const static int numStencil = 2;

static __GLcontextModes *
createFBConfigsForVisual(__GLXscreen *screen, ScreenPtr pScreen,
			 VisualPtr visual, __GLcontextModes *config)
Eric Anholt's avatar
Eric Anholt committed
304
{
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
    int back, depth, stencil;

    /* FIXME: Ok, I'm making all this up... anybody has a better idea? */

    for (back = numBack - 1; back >= 0; back--)
	for (depth = 0; depth < numDepth; depth++)
	    for (stencil = 0; stencil < numStencil; stencil++) {
		config->visualType = _gl_convert_from_x_visual_type(visual->class);
		config->xRenderable = GL_TRUE;
		config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT;
		config->rgbMode = (visual->class >= TrueColor);
		config->colorIndexMode = !config->rgbMode;
		config->renderType =
		    (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
		config->doubleBufferMode = back;
		config->haveDepthBuffer = depth;
		config->depthBits = depth ? visual->nplanes : 0;
		config->haveStencilBuffer = stencil;
		config->stencilBits = stencil ? visual->bitsPerRGBValue : 0;
		config->haveAccumBuffer = 0;

		config->redBits = Ones(visual->redMask);
		config->greenBits = Ones(visual->greenMask);
		config->blueBits = Ones(visual->blueMask);
		config->alphaBits = 0;
		config->redMask = visual->redMask;
		config->greenMask = visual->greenMask;
		config->blueMask = visual->blueMask;
		config->alphaMask = 0;
		config->rgbBits = config->rgbMode ? visual->nplanes : 0;
		config->indexBits = config->colorIndexMode ? visual->nplanes : 0;
		config = config->next;
Eric Anholt's avatar
Eric Anholt committed
337
338
	    }

339
340
    return config;
}
Eric Anholt's avatar
Eric Anholt committed
341

342
343
344
345
346
static void
createFBConfigs(__GLXscreen *pGlxScreen, ScreenPtr pScreen)
{
    __GLcontextModes *configs;
    int i;
Eric Anholt's avatar
Eric Anholt committed
347

348
349
350
351
352
353
354
355
356
357
358
359
    /* We assume here that each existing visual correspond to a
     * different visual class.  Note, this runs before COMPOSITE adds
     * its visual, so it's not entirely crazy. */
    pGlxScreen->numFBConfigs = pScreen->numVisuals * numBack * numDepth * numStencil;
    pGlxScreen->fbconfigs = _gl_context_modes_create(pGlxScreen->numFBConfigs,
						     sizeof *configs);

    configs = pGlxScreen->fbconfigs;
    for (i = 0; i < pScreen->numVisuals; i++)
	configs = createFBConfigsForVisual(pGlxScreen, pScreen,
					   &pScreen->visuals[i], configs);
}
Eric Anholt's avatar
Eric Anholt committed
360

361
362
363
364
365
static void
createMesaVisuals(__GLXMESAscreen *pMesaScreen)
{
    __GLcontextModes *config;
    ScreenPtr pScreen;
366
    VisualPtr visual = NULL;
367
368
369
370
371
372
373
374
375
376
377
378
    int i, j;

    i = 0;
    pScreen = pMesaScreen->base.pScreen;
    pMesaScreen->xm_vis =
	xcalloc(pMesaScreen->base.numFBConfigs, sizeof (XMesaVisual));
    for (config = pMesaScreen->base.fbconfigs; config != NULL; config = config->next) {
	for (j = 0; j < pScreen->numVisuals; j++)
	    if (pScreen->visuals[j].vid == config->visualID) {
		visual = &pScreen->visuals[j];
		break;
	    }
379

380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
	pMesaScreen->xm_vis[i++] =
	    XMesaCreateVisual(pScreen,
			      visual,
			      config->rgbMode,
			      (config->alphaBits > 0),
			      config->doubleBufferMode,
			      config->stereoMode,
			      GL_TRUE, /* ximage_flag */
			      config->depthBits,
			      config->stencilBits,
			      config->accumRedBits,
			      config->accumGreenBits,
			      config->accumBlueBits,
			      config->accumAlphaBits,
			      config->samples,
			      config->level,
			      config->visualRating);
    }
Eric Anholt's avatar
Eric Anholt committed
398
399
}

400
401
static __GLXscreen *
__glXMesaScreenProbe(ScreenPtr pScreen)
Eric Anholt's avatar
Eric Anholt committed
402
{
403
    __GLXMESAscreen *screen;
Eric Anholt's avatar
Eric Anholt committed
404

405
406
407
    screen = xalloc(sizeof *screen);
    if (screen == NULL)
	return NULL;
Eric Anholt's avatar
Eric Anholt committed
408

409
410
411
412
413
414
    /*
     * Find the GLX visuals that are supported by this screen and create
     * XMesa's visuals.
     */
    createFBConfigs(&screen->base, pScreen);

415
416
    __glXScreenInit(&screen->base, pScreen);

417
418
419
    /* Now that GLX has created the corresponding X visual, create the mesa visuals. */
    createMesaVisuals(screen);

420
421
422
    screen->base.destroy        = __glXMesaScreenDestroy;
    screen->base.createContext  = __glXMesaScreenCreateContext;
    screen->base.createDrawable = __glXMesaScreenCreateDrawable;
423
    screen->base.pScreen       = pScreen;
Eric Anholt's avatar
Eric Anholt committed
424

425
    return &screen->base;
Eric Anholt's avatar
Eric Anholt committed
426
427
}

428
429
430
431
432
__GLXprovider __glXMesaProvider = {
    __glXMesaScreenProbe,
    "MESA",
    NULL
};
433
434
435
436
437
438

__GLXprovider *
GlxGetMesaProvider (void)
{
    return &__glXMesaProvider;
}