2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 /* Minimal swrast-based DRI-loadable driver.
28 * Derived from fb_dri.c, the difference being that one works for
29 * framebuffers without X, whereas this points Mesa at an X surface
32 * This is basically just a wrapper around src/mesa/drivers/x11 to make it
33 * look like a DRI driver.
36 #define GLX_DIRECT_RENDERING
47 #include <sys/ioctl.h>
49 #include <sys/types.h>
62 #include "extensions.h"
65 #include "texformat.h"
68 #include "array_cache/acache.h"
69 #include "swrast/swrast.h"
70 #include "swrast_setup/swrast_setup.h"
72 #include "tnl/t_context.h"
73 #include "tnl/t_pipeline.h"
74 #include "drivers/common/driverfuncs.h"
79 GLcontext
*glCtx
; /* Mesa context */
82 __DRIcontextPrivate
*context
;
83 __DRIscreenPrivate
*screen
;
84 __DRIdrawablePrivate
*drawable
; /* drawable bound to this ctx */
86 } x11Context
, *x11ContextPtr
;
88 #define X11_CONTEXT(ctx) ((x11ContextPtr)(ctx->DriverCtx))
90 static const GLubyte
*
91 get_string(GLcontext
*ctx
, GLenum pname
)
96 return (const GLubyte
*) "Mesa X11 hack";
103 update_state(GLcontext
*ctx
, GLuint new_state
)
105 /* not much to do here - pass it on */
106 _swrast_InvalidateState(ctx
, new_state
);
107 _swsetup_InvalidateState(ctx
, new_state
);
108 _ac_InvalidateState(ctx
, new_state
);
109 _tnl_InvalidateState(ctx
, new_state
);
113 * Called by ctx->Driver.GetBufferSize from in core Mesa to query the
114 * current framebuffer size.
117 get_buffer_size(GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
119 GET_CURRENT_CONTEXT(ctx
);
120 x11ContextPtr x11mesa
= X11_CONTEXT(ctx
);
122 *width
= x11mesa
->dri
.drawable
->w
;
123 *height
= x11mesa
->dri
.drawable
->h
;
127 init_core_functions(struct dd_function_table
*functions
)
129 functions
->GetString
= get_string
;
130 functions
->UpdateState
= update_state
;
131 functions
->ResizeBuffers
= _swrast_alloc_buffers
;
132 functions
->GetBufferSize
= get_buffer_size
;
134 functions
->Clear
= _swrast_Clear
; /* could accelerate with blits */
137 /* Initialize the driver specific screen private data.
140 x11InitDriver(__DRIscreenPrivate
*sPriv
)
142 sPriv
->private = NULL
;
147 x11DestroyScreen(__DRIscreenPrivate
*sPriv
)
151 /* placeholders, disables rendering */
153 nullwrite(void *a
, int b
, int c
, int d
, void *e
, void *f
)
158 set_buffer( GLcontext
*ctx
, GLframebuffer
*buffer
, GLuint bufferBit
)
162 /* Create the device specific context. */
164 x11CreateContext(const __GLcontextModes
*glVisual
,
165 __DRIcontextPrivate
*driContextPriv
,
166 void *sharedContextPrivate
)
168 x11ContextPtr x11mesa
;
169 GLcontext
*ctx
, *shareCtx
;
170 struct dd_function_table functions
;
173 assert(driContextPriv
);
175 /* Allocate the Fb context */
176 x11mesa
= (x11ContextPtr
) CALLOC(sizeof(*x11mesa
));
180 /* Init default driver functions then plug in our own functions */
181 _mesa_init_driver_functions(&functions
);
182 init_core_functions(&functions
);
184 /* Allocate the Mesa context */
185 if (sharedContextPrivate
)
186 shareCtx
= ((x11ContextPtr
) sharedContextPrivate
)->glCtx
;
190 ctx
= x11mesa
->glCtx
= _mesa_create_context(glVisual
, shareCtx
,
191 &functions
, (void *) x11mesa
);
192 if (!x11mesa
->glCtx
) {
196 driContextPriv
->driverPrivate
= x11mesa
;
198 /* Create module contexts */
199 _swrast_CreateContext(ctx
);
200 _ac_CreateContext(ctx
);
201 _tnl_CreateContext(ctx
);
202 _swsetup_CreateContext(ctx
);
203 _swsetup_Wakeup(ctx
);
207 struct swrast_device_driver
*swdd
;
208 swdd
= _swrast_GetDeviceDriverReference(ctx
);
209 swdd
->SetBuffer
= set_buffer
;
210 if (!glVisual
->rgbMode
) {
211 swdd
->WriteCI32Span
=
212 swdd
->WriteCI32Span
=
214 swdd
->WriteMonoCISpan
=
215 swdd
->WriteCI32Pixels
=
216 swdd
->WriteMonoCIPixels
=
218 swdd
->ReadCI32Pixels
= nullwrite
;
220 else if (glVisual
->rgbBits
== 24 &&
221 glVisual
->alphaBits
== 0) {
222 swdd
->WriteRGBASpan
=
224 swdd
->WriteMonoRGBASpan
=
225 swdd
->WriteRGBAPixels
=
226 swdd
->WriteMonoRGBAPixels
=
228 swdd
->ReadRGBAPixels
= nullwrite
;
230 else if (glVisual
->rgbBits
== 32 &&
231 glVisual
->alphaBits
== 8) {
232 swdd
->WriteRGBASpan
=
234 swdd
->WriteMonoRGBASpan
=
235 swdd
->WriteRGBAPixels
=
236 swdd
->WriteMonoRGBAPixels
=
238 swdd
->ReadRGBAPixels
= nullwrite
;
240 else if (glVisual
->rgbBits
== 16 &&
241 glVisual
->alphaBits
== 0) {
242 swdd
->WriteRGBASpan
=
244 swdd
->WriteMonoRGBASpan
=
245 swdd
->WriteRGBAPixels
=
246 swdd
->WriteMonoRGBAPixels
=
248 swdd
->ReadRGBAPixels
= nullwrite
;
250 else if (glVisual
->rgbBits
== 15 &&
251 glVisual
->alphaBits
== 0) {
252 swdd
->WriteRGBASpan
=
254 swdd
->WriteMonoRGBASpan
=
255 swdd
->WriteRGBAPixels
=
256 swdd
->WriteMonoRGBAPixels
=
258 swdd
->ReadRGBAPixels
= nullwrite
;
261 _mesa_printf("bad pixelformat rgb %d alpha %d\n",
263 glVisual
->alphaBits
);
267 /* use default TCL pipeline */
269 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
270 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
273 _mesa_enable_sw_extensions(ctx
);
280 x11DestroyContext(__DRIcontextPrivate
*driContextPriv
)
282 GET_CURRENT_CONTEXT(ctx
);
283 x11ContextPtr x11mesa
= (x11ContextPtr
) driContextPriv
->driverPrivate
;
284 x11ContextPtr current
= ctx
? X11_CONTEXT(ctx
) : NULL
;
286 /* check if we're deleting the currently bound context */
287 if (x11mesa
== current
) {
288 _mesa_make_current2(NULL
, NULL
, NULL
);
291 /* Free x11 context resources */
293 _swsetup_DestroyContext(x11mesa
->glCtx
);
294 _tnl_DestroyContext(x11mesa
->glCtx
);
295 _ac_DestroyContext(x11mesa
->glCtx
);
296 _swrast_DestroyContext(x11mesa
->glCtx
);
298 /* free the Mesa context */
299 x11mesa
->glCtx
->DriverCtx
= NULL
;
300 _mesa_destroy_context(x11mesa
->glCtx
);
307 /* Create and initialize the Mesa and driver specific pixmap buffer
311 x11CreateBuffer(__DRIscreenPrivate
*driScrnPriv
,
312 __DRIdrawablePrivate
*driDrawPriv
,
313 const __GLcontextModes
*mesaVis
,
317 return GL_FALSE
; /* not implemented */
320 const GLboolean swDepth
= mesaVis
->depthBits
> 0;
321 const GLboolean swAlpha
= mesaVis
->alphaBits
> 0;
322 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
323 const GLboolean swStencil
= mesaVis
->stencilBits
> 0;
324 driDrawPriv
->driverPrivate
= (void *)
325 _mesa_create_framebuffer(mesaVis
,
331 if (!driDrawPriv
->driverPrivate
)
334 /* Replace the framebuffer back buffer with a malloc'ed one --
338 if (driDrawPriv->backBuffer)
339 driDrawPriv->backBuffer = malloc(driDrawPriv->currentPitch * driDrawPriv->h);
348 x11DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
350 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
351 /* free(driDrawPriv->backBuffer); */
356 /* If the backbuffer is on a videocard, this is extraordinarily slow!
359 x11SwapBuffers(__DRIdrawablePrivate
*dPriv
)
362 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
363 x11ContextPtr x11mesa
;
365 x11mesa
= (x11ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
366 ctx
= x11mesa
->glCtx
;
367 if (ctx
->Visual
.doubleBufferMode
) {
370 char *tmp
/*= malloc(dPriv->currentPitch) */ ;
372 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
375 ASSERT(dPriv->frontBuffer);
376 ASSERT(dPriv->backBuffer);
378 for (i = 0 ; i < dPriv->h ; i++ ) {
379 memcpy(tmp, (char *)dPriv->frontBuffer + offset, dPriv->currentPitch);
380 memcpy((char *)dPriv->backBuffer + offset, tmp, dPriv->currentPitch);
381 offset += dPriv->currentPitch;
389 /* XXX this shouldn't be an error but we can't handle it for now */
390 _mesa_problem(NULL
, "x11SwapBuffers: drawable has no context!\n");
395 /* Force the context `c' to be the current context and associate with it
399 x11MakeCurrent(__DRIcontextPrivate
*driContextPriv
,
400 __DRIdrawablePrivate
*driDrawPriv
,
401 __DRIdrawablePrivate
*driReadPriv
)
403 if (driContextPriv
) {
404 x11ContextPtr newFbCtx
=
405 (x11ContextPtr
) driContextPriv
->driverPrivate
;
407 newFbCtx
->dri
.drawable
= driDrawPriv
;
409 _mesa_make_current2(newFbCtx
->glCtx
,
410 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
411 (GLframebuffer
*) driReadPriv
->driverPrivate
);
413 if (!newFbCtx
->glCtx
->Viewport
.Width
) {
414 _mesa_set_viewport(newFbCtx
->glCtx
, 0, 0,
415 driDrawPriv
->w
, driDrawPriv
->h
);
418 _mesa_make_current(0, 0);
425 /* Force the context `c' to be unbound from its buffer.
428 x11UnbindContext(__DRIcontextPrivate
*driContextPriv
)
433 static struct __DriverAPIRec x11API
= {
446 * This is the bootstrap function for the driver.
447 * The __driCreateScreen name is the symbol that libGL.so fetches.
448 * Return: pointer to a __DRIscreenPrivate.
451 __driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
452 int numConfigs
, __GLXvisualConfig
*config
)
454 __DRIscreenPrivate
*psp
;
455 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &x11API
);
460 * \brief Establish the set of modes available for the display.
462 * \param ctx display handle.
463 * \param numModes will receive the number of supported modes.
464 * \param modes will point to the list of supported modes.
466 * \return one on success, or zero on failure.
468 * Allocates a single visual and fills it with information according to the
469 * display bit depth. Supports only 16 and 32 bpp bit depths, aborting
472 const __GLcontextModes __glModes
[] = {
473 /* 32 bit, RGBA Depth=24 Stencil=8 */
474 {.rgbMode
= GL_TRUE
, .colorIndexMode
= GL_FALSE
, .doubleBufferMode
= GL_TRUE
, .stereoMode
= GL_FALSE
,
475 .haveAccumBuffer
= GL_FALSE
, .haveDepthBuffer
= GL_TRUE
, .haveStencilBuffer
= GL_TRUE
,
476 .redBits
= 8, .greenBits
= 8, .blueBits
= 8, .alphaBits
= 8,
477 .redMask
= 0xff0000, .greenMask
= 0xff00, .blueMask
= 0xff, .alphaMask
= 0xff000000,
478 .rgbBits
= 32, .indexBits
= 0,
479 .accumRedBits
= 0, .accumGreenBits
= 0, .accumBlueBits
= 0, .accumAlphaBits
= 0,
480 .depthBits
= 24, .stencilBits
= 8,
481 .numAuxBuffers
= 0, .level
= 0, .pixmapMode
= GL_FALSE
, },
483 /* 16 bit, RGB Depth=16 */
484 {.rgbMode
= GL_TRUE
, .colorIndexMode
= GL_FALSE
, .doubleBufferMode
= GL_TRUE
, .stereoMode
= GL_FALSE
,
485 .haveAccumBuffer
= GL_FALSE
, .haveDepthBuffer
= GL_TRUE
, .haveStencilBuffer
= GL_FALSE
,
486 .redBits
= 5, .greenBits
= 6, .blueBits
= 5, .alphaBits
= 0,
487 .redMask
= 0xf800, .greenMask
= 0x07e0, .blueMask
= 0x001f, .alphaMask
= 0x0,
488 .rgbBits
= 16, .indexBits
= 0,
489 .accumRedBits
= 0, .accumGreenBits
= 0, .accumBlueBits
= 0, .accumAlphaBits
= 0,
490 .depthBits
= 16, .stencilBits
= 0,
491 .numAuxBuffers
= 0, .level
= 0, .pixmapMode
= GL_FALSE
, },