First import
[xorg_rtime.git] / xorg-server-1.4 / GL / glx / glxglcore.c
blob679d55c5d1d302891089282018111745dac32122
1 /**************************************************************************
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4 All Rights Reserved.
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sub license, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial portions
16 of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
29 * Authors:
30 * Kevin E. Martin <kevin@precisioninsight.com>
31 * Brian E. Paul <brian@precisioninsight.com>
35 #ifdef HAVE_DIX_CONFIG_H
36 #include <dix-config.h>
37 #endif
39 #include <string.h>
41 #include <GL/xmesa.h>
42 #include <GL/internal/glcore.h>
43 #include <glxserver.h>
44 #include <glxscreens.h>
45 #include <glxdrawable.h>
46 #include <glxcontext.h>
47 #include <glxutil.h>
49 #include "glcontextmodes.h"
50 #include "os.h"
52 typedef struct __GLXMESAscreen __GLXMESAscreen;
53 typedef struct __GLXMESAcontext __GLXMESAcontext;
54 typedef struct __GLXMESAdrawable __GLXMESAdrawable;
56 struct __GLXMESAscreen {
57 __GLXscreen base;
58 int index;
59 int num_vis;
60 XMesaVisual *xm_vis;
63 struct __GLXMESAcontext {
64 __GLXcontext base;
65 XMesaContext xmesa;
68 struct __GLXMESAdrawable {
69 __GLXdrawable base;
70 XMesaBuffer xm_buf;
73 static XMesaVisual find_mesa_visual(__GLXscreen *screen, VisualID vid);
76 static void
77 __glXMesaDrawableDestroy(__GLXdrawable *base)
79 __GLXMESAdrawable *glxPriv = (__GLXMESAdrawable *) base;
81 if (glxPriv->xm_buf != NULL)
82 XMesaDestroyBuffer(glxPriv->xm_buf);
83 xfree(glxPriv);
86 static GLboolean
87 __glXMesaDrawableResize(__GLXdrawable *base)
89 __GLXMESAdrawable *glxPriv = (__GLXMESAdrawable *) base;
91 XMesaResizeBuffers(glxPriv->xm_buf);
93 return GL_TRUE;
96 static GLboolean
97 __glXMesaDrawableSwapBuffers(__GLXdrawable *base)
99 __GLXMESAdrawable *glxPriv = (__GLXMESAdrawable *) base;
101 /* This is terrifying: XMesaSwapBuffers() ends up calling CopyArea
102 * to do the buffer swap, but this assumes that the server holds
103 * the lock and has its context visible. If another screen uses a
104 * DRI driver, that will have installed the DRI enter/leave server
105 * functions, which lifts the lock during GLX dispatch. This is
106 * why we need to re-take the lock and swap in the server context
107 * before calling XMesaSwapBuffers() here. /me shakes head. */
109 __glXenterServer(GL_FALSE);
111 XMesaSwapBuffers(glxPriv->xm_buf);
113 __glXleaveServer(GL_FALSE);
115 return GL_TRUE;
119 static __GLXdrawable *
120 __glXMesaScreenCreateDrawable(__GLXscreen *screen,
121 DrawablePtr pDraw,
122 XID drawId,
123 __GLcontextModes *modes)
125 __GLXMESAdrawable *glxPriv;
126 XMesaVisual xm_vis;
128 glxPriv = xalloc(sizeof *glxPriv);
129 if (glxPriv == NULL)
130 return NULL;
132 memset(glxPriv, 0, sizeof *glxPriv);
134 if (!__glXDrawableInit(&glxPriv->base, screen, pDraw, drawId, modes)) {
135 xfree(glxPriv);
136 return NULL;
139 glxPriv->base.destroy = __glXMesaDrawableDestroy;
140 glxPriv->base.resize = __glXMesaDrawableResize;
141 glxPriv->base.swapBuffers = __glXMesaDrawableSwapBuffers;
143 xm_vis = find_mesa_visual(screen, modes->visualID);
144 if (xm_vis == NULL) {
145 ErrorF("find_mesa_visual returned NULL for visualID = 0x%04x\n",
146 modes->visualID);
147 xfree(glxPriv);
148 return NULL;
151 if (glxPriv->base.type == DRAWABLE_WINDOW) {
152 glxPriv->xm_buf = XMesaCreateWindowBuffer(xm_vis, (WindowPtr)pDraw);
153 } else {
154 glxPriv->xm_buf = XMesaCreatePixmapBuffer(xm_vis, (PixmapPtr)pDraw, 0);
157 return &glxPriv->base;
160 static void
161 __glXMesaContextDestroy(__GLXcontext *baseContext)
163 __GLXMESAcontext *context = (__GLXMESAcontext *) baseContext;
165 XMesaDestroyContext(context->xmesa);
166 __glXContextDestroy(&context->base);
167 xfree(context);
170 static int
171 __glXMesaContextMakeCurrent(__GLXcontext *baseContext)
174 __GLXMESAcontext *context = (__GLXMESAcontext *) baseContext;
175 __GLXMESAdrawable *drawPriv = (__GLXMESAdrawable *) context->base.drawPriv;
176 __GLXMESAdrawable *readPriv = (__GLXMESAdrawable *) context->base.readPriv;
178 return XMesaMakeCurrent2(context->xmesa,
179 drawPriv->xm_buf,
180 readPriv->xm_buf);
183 static int
184 __glXMesaContextLoseCurrent(__GLXcontext *baseContext)
186 __GLXMESAcontext *context = (__GLXMESAcontext *) baseContext;
188 return XMesaLoseCurrent(context->xmesa);
191 static int
192 __glXMesaContextCopy(__GLXcontext *baseDst,
193 __GLXcontext *baseSrc,
194 unsigned long mask)
196 __GLXMESAcontext *dst = (__GLXMESAcontext *) baseDst;
197 __GLXMESAcontext *src = (__GLXMESAcontext *) baseSrc;
199 return XMesaCopyContext(src->xmesa, dst->xmesa, mask);
202 static int
203 __glXMesaContextForceCurrent(__GLXcontext *baseContext)
205 __GLXMESAcontext *context = (__GLXMESAcontext *) baseContext;
207 /* GlxSetRenderTables() call for XGL moved in XMesaForceCurrent() */
209 return XMesaForceCurrent(context->xmesa);
212 static __GLXcontext *
213 __glXMesaScreenCreateContext(__GLXscreen *screen,
214 __GLcontextModes *modes,
215 __GLXcontext *baseShareContext)
217 __GLXMESAcontext *context;
218 __GLXMESAcontext *shareContext = (__GLXMESAcontext *) baseShareContext;
219 XMesaVisual xm_vis;
220 XMesaContext xm_share;
222 context = xalloc (sizeof (__GLXMESAcontext));
223 if (context == NULL)
224 return NULL;
226 memset(context, 0, sizeof *context);
228 context->base.pGlxScreen = screen;
229 context->base.modes = modes;
231 context->base.destroy = __glXMesaContextDestroy;
232 context->base.makeCurrent = __glXMesaContextMakeCurrent;
233 context->base.loseCurrent = __glXMesaContextLoseCurrent;
234 context->base.copy = __glXMesaContextCopy;
235 context->base.forceCurrent = __glXMesaContextForceCurrent;
237 xm_vis = find_mesa_visual(screen, modes->visualID);
238 if (!xm_vis) {
239 ErrorF("find_mesa_visual returned NULL for visualID = 0x%04x\n",
240 modes->visualID);
241 xfree(context);
242 return NULL;
245 xm_share = shareContext ? shareContext->xmesa : NULL;
246 context->xmesa = XMesaCreateContext(xm_vis, xm_share);
247 if (!context->xmesa) {
248 xfree(context);
249 return NULL;
252 return &context->base;
255 static void
256 __glXMesaScreenDestroy(__GLXscreen *screen)
258 __GLXMESAscreen *mesaScreen = (__GLXMESAscreen *) screen;
259 int i;
261 if (mesaScreen->xm_vis) {
262 for (i = 0; i < mesaScreen->num_vis; i++) {
263 if (mesaScreen->xm_vis[i])
264 XMesaDestroyVisual(mesaScreen->xm_vis[i]);
267 xfree(mesaScreen->xm_vis);
270 __glXScreenDestroy(screen);
272 xfree(screen);
275 static XMesaVisual
276 find_mesa_visual(__GLXscreen *screen, VisualID vid)
278 __GLXMESAscreen *mesaScreen = (__GLXMESAscreen *) screen;
279 const __GLcontextModes *modes;
280 unsigned i = 0;
282 for ( modes = screen->modes ; modes != NULL ; modes = modes->next ) {
283 if ( modes->visualID == vid ) {
284 break;
287 i++;
290 return (modes != NULL) ? mesaScreen->xm_vis[i] : NULL;
293 static void init_screen_visuals(__GLXMESAscreen *screen)
295 ScreenPtr pScreen = screen->base.pScreen;
296 __GLcontextModes *modes;
297 XMesaVisual *pXMesaVisual;
298 int *used;
299 int num_vis, j, size;
301 /* Alloc space for the list of XMesa visuals */
302 size = screen->base.numVisuals * sizeof(XMesaVisual);
303 pXMesaVisual = (XMesaVisual *) xalloc(size);
304 memset(pXMesaVisual, 0, size);
306 /* FIXME: Change 'used' to be a array of bits (rather than of ints),
307 * FIXME: create a stack array of 8 or 16 bytes. If 'numVisuals' is less
308 * FIXME: than 64 or 128 the stack array can be used instead of calling
309 * FIXME: __glXMalloc / __glXFree. If nothing else, convert 'used' to
310 * FIXME: array of bytes instead of ints!
312 used = (int *) xalloc(pScreen->numVisuals * sizeof(int));
313 memset(used, 0, pScreen->numVisuals * sizeof(int));
315 num_vis = 0;
316 for ( modes = screen->base.modes; modes != NULL; modes = modes->next ) {
317 const int vis_class = _gl_convert_to_x_visual_type( modes->visualType );
318 const int nplanes = (modes->rgbBits - modes->alphaBits);
319 const VisualPtr pVis = pScreen->visuals;
321 for (j = 0; j < pScreen->numVisuals; j++) {
322 if (pVis[j].class == vis_class &&
323 pVis[j].nplanes == nplanes &&
324 pVis[j].redMask == modes->redMask &&
325 pVis[j].greenMask == modes->greenMask &&
326 pVis[j].blueMask == modes->blueMask &&
327 !used[j]) {
329 /* Create the XMesa visual */
330 assert(num_vis < screen->base.numVisuals);
331 pXMesaVisual[num_vis] =
332 XMesaCreateVisual(pScreen,
333 &pVis[j],
334 modes->rgbMode,
335 (modes->alphaBits > 0),
336 modes->doubleBufferMode,
337 modes->stereoMode,
338 GL_TRUE, /* ximage_flag */
339 modes->depthBits,
340 modes->stencilBits,
341 modes->accumRedBits,
342 modes->accumGreenBits,
343 modes->accumBlueBits,
344 modes->accumAlphaBits,
345 modes->samples,
346 modes->level,
347 modes->visualRating);
348 /* Set the VisualID */
349 modes->visualID = pVis[j].vid;
351 /* Mark this visual used */
352 used[j] = 1;
353 break;
357 if ( j == pScreen->numVisuals ) {
358 ErrorF("No matching visual for __GLcontextMode with "
359 "visual class = %d (%d), nplanes = %u\n",
360 vis_class,
361 modes->visualType,
362 (modes->rgbBits - modes->alphaBits) );
364 else if ( modes->visualID == -1 ) {
365 FatalError( "Matching visual found, but visualID still -1!\n" );
368 num_vis++;
371 xfree(used);
373 screen->num_vis = num_vis;
374 screen->xm_vis = pXMesaVisual;
376 assert(screen->num_vis <= screen->base.numVisuals);
379 static __GLXscreen *
380 __glXMesaScreenProbe(ScreenPtr pScreen)
382 __GLXMESAscreen *screen;
384 screen = xalloc(sizeof *screen);
385 if (screen == NULL)
386 return NULL;
388 __glXScreenInit(&screen->base, pScreen);
390 screen->base.destroy = __glXMesaScreenDestroy;
391 screen->base.createContext = __glXMesaScreenCreateContext;
392 screen->base.createDrawable = __glXMesaScreenCreateDrawable;
393 screen->base.pScreen = pScreen;
396 * Find the GLX visuals that are supported by this screen and create
397 * XMesa's visuals.
399 init_screen_visuals(screen);
401 return &screen->base;
404 __GLXprovider __glXMesaProvider = {
405 __glXMesaScreenProbe,
406 "MESA",
407 NULL
410 __GLXprovider *
411 GlxGetMesaProvider (void)
413 return &__glXMesaProvider;