1 /**************************************************************************
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
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
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 **************************************************************************/
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>
42 #include <GL/internal/glcore.h>
43 #include <glxserver.h>
44 #include <glxscreens.h>
45 #include <glxdrawable.h>
46 #include <glxcontext.h>
49 #include "glcontextmodes.h"
52 typedef struct __GLXMESAscreen __GLXMESAscreen
;
53 typedef struct __GLXMESAcontext __GLXMESAcontext
;
54 typedef struct __GLXMESAdrawable __GLXMESAdrawable
;
56 struct __GLXMESAscreen
{
63 struct __GLXMESAcontext
{
68 struct __GLXMESAdrawable
{
73 static XMesaVisual
find_mesa_visual(__GLXscreen
*screen
, VisualID vid
);
77 __glXMesaDrawableDestroy(__GLXdrawable
*base
)
79 __GLXMESAdrawable
*glxPriv
= (__GLXMESAdrawable
*) base
;
81 if (glxPriv
->xm_buf
!= NULL
)
82 XMesaDestroyBuffer(glxPriv
->xm_buf
);
87 __glXMesaDrawableResize(__GLXdrawable
*base
)
89 __GLXMESAdrawable
*glxPriv
= (__GLXMESAdrawable
*) base
;
91 XMesaResizeBuffers(glxPriv
->xm_buf
);
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
);
119 static __GLXdrawable
*
120 __glXMesaScreenCreateDrawable(__GLXscreen
*screen
,
123 __GLcontextModes
*modes
)
125 __GLXMESAdrawable
*glxPriv
;
128 glxPriv
= xalloc(sizeof *glxPriv
);
132 memset(glxPriv
, 0, sizeof *glxPriv
);
134 if (!__glXDrawableInit(&glxPriv
->base
, screen
, pDraw
, drawId
, modes
)) {
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",
151 if (glxPriv
->base
.type
== DRAWABLE_WINDOW
) {
152 glxPriv
->xm_buf
= XMesaCreateWindowBuffer(xm_vis
, (WindowPtr
)pDraw
);
154 glxPriv
->xm_buf
= XMesaCreatePixmapBuffer(xm_vis
, (PixmapPtr
)pDraw
, 0);
157 return &glxPriv
->base
;
161 __glXMesaContextDestroy(__GLXcontext
*baseContext
)
163 __GLXMESAcontext
*context
= (__GLXMESAcontext
*) baseContext
;
165 XMesaDestroyContext(context
->xmesa
);
166 __glXContextDestroy(&context
->base
);
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
,
184 __glXMesaContextLoseCurrent(__GLXcontext
*baseContext
)
186 __GLXMESAcontext
*context
= (__GLXMESAcontext
*) baseContext
;
188 return XMesaLoseCurrent(context
->xmesa
);
192 __glXMesaContextCopy(__GLXcontext
*baseDst
,
193 __GLXcontext
*baseSrc
,
196 __GLXMESAcontext
*dst
= (__GLXMESAcontext
*) baseDst
;
197 __GLXMESAcontext
*src
= (__GLXMESAcontext
*) baseSrc
;
199 return XMesaCopyContext(src
->xmesa
, dst
->xmesa
, mask
);
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
;
220 XMesaContext xm_share
;
222 context
= xalloc (sizeof (__GLXMESAcontext
));
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
);
239 ErrorF("find_mesa_visual returned NULL for visualID = 0x%04x\n",
245 xm_share
= shareContext
? shareContext
->xmesa
: NULL
;
246 context
->xmesa
= XMesaCreateContext(xm_vis
, xm_share
);
247 if (!context
->xmesa
) {
252 return &context
->base
;
256 __glXMesaScreenDestroy(__GLXscreen
*screen
)
258 __GLXMESAscreen
*mesaScreen
= (__GLXMESAscreen
*) screen
;
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
);
276 find_mesa_visual(__GLXscreen
*screen
, VisualID vid
)
278 __GLXMESAscreen
*mesaScreen
= (__GLXMESAscreen
*) screen
;
279 const __GLcontextModes
*modes
;
282 for ( modes
= screen
->modes
; modes
!= NULL
; modes
= modes
->next
) {
283 if ( modes
->visualID
== vid
) {
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
;
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));
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
&&
329 /* Create the XMesa visual */
330 assert(num_vis
< screen
->base
.numVisuals
);
331 pXMesaVisual
[num_vis
] =
332 XMesaCreateVisual(pScreen
,
335 (modes
->alphaBits
> 0),
336 modes
->doubleBufferMode
,
338 GL_TRUE
, /* ximage_flag */
342 modes
->accumGreenBits
,
343 modes
->accumBlueBits
,
344 modes
->accumAlphaBits
,
347 modes
->visualRating
);
348 /* Set the VisualID */
349 modes
->visualID
= pVis
[j
].vid
;
351 /* Mark this visual used */
357 if ( j
== pScreen
->numVisuals
) {
358 ErrorF("No matching visual for __GLcontextMode with "
359 "visual class = %d (%d), nplanes = %u\n",
362 (modes
->rgbBits
- modes
->alphaBits
) );
364 else if ( modes
->visualID
== -1 ) {
365 FatalError( "Matching visual found, but visualID still -1!\n" );
373 screen
->num_vis
= num_vis
;
374 screen
->xm_vis
= pXMesaVisual
;
376 assert(screen
->num_vis
<= screen
->base
.numVisuals
);
380 __glXMesaScreenProbe(ScreenPtr pScreen
)
382 __GLXMESAscreen
*screen
;
384 screen
= xalloc(sizeof *screen
);
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
399 init_screen_visuals(screen
);
401 return &screen
->base
;
404 __GLXprovider __glXMesaProvider
= {
405 __glXMesaScreenProbe
,
411 GlxGetMesaProvider (void)
413 return &__glXMesaProvider
;