1 /* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_xmesa.c,v 1.4 2002/02/22 21:32:59 dawes Exp $
3 * GLX Hardware Device Driver for Sun Creator/Creator3D
4 * Copyright (C) 2000, 2001 David S. Miller
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * DAVID MILLER, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 * David S. Miller <davem@redhat.com>
28 #ifdef GLX_DIRECT_RENDERING
30 #include "ffb_xmesa.h"
33 #include "simple_list.h"
36 #include "swrast/swrast.h"
37 #include "swrast_setup/swrast_setup.h"
39 #include "tnl/t_pipeline.h"
40 #include "array_cache/acache.h"
41 #include "drivers/common/driverfuncs.h"
43 #include "ffb_context.h"
46 #include "ffb_depth.h"
47 #include "ffb_stencil.h"
48 #include "ffb_clear.h"
51 #include "ffb_lines.h"
52 #include "ffb_points.h"
53 #include "ffb_state.h"
56 #include "ffb_vtxfmt.h"
57 #include "ffb_bitmap.h"
60 ffbInitDriver(__DRIscreenPrivate
*sPriv
)
62 ffbScreenPrivate
*ffbScreen
;
63 FFBDRIPtr gDRIPriv
= (FFBDRIPtr
) sPriv
->pDevPriv
;
65 if (getenv("LIBGL_FORCE_XSERVER"))
68 /* Allocate the private area. */
69 ffbScreen
= (ffbScreenPrivate
*) Xmalloc(sizeof(ffbScreenPrivate
));
73 /* Map FBC registers. */
77 &gDRIPriv
->mFbcRegs
)) {
81 ffbScreen
->regs
= (ffb_fbcPtr
) gDRIPriv
->mFbcRegs
;
83 /* Map ramdac registers. */
87 &gDRIPriv
->mDacRegs
)) {
88 drmUnmap(gDRIPriv
->mFbcRegs
, gDRIPriv
->sFbcRegs
);
92 ffbScreen
->dac
= (ffb_dacPtr
) gDRIPriv
->mDacRegs
;
94 /* Map "Smart" framebuffer views. */
99 drmUnmap(gDRIPriv
->mFbcRegs
, gDRIPriv
->sFbcRegs
);
100 drmUnmap(gDRIPriv
->mDacRegs
, gDRIPriv
->sDacRegs
);
104 ffbScreen
->sfb8r
= (volatile char *) gDRIPriv
->mSfb8r
;
106 if (drmMap(sPriv
->fd
,
109 &gDRIPriv
->mSfb32
)) {
110 drmUnmap(gDRIPriv
->mFbcRegs
, gDRIPriv
->sFbcRegs
);
111 drmUnmap(gDRIPriv
->mDacRegs
, gDRIPriv
->sDacRegs
);
112 drmUnmap(gDRIPriv
->mSfb8r
, gDRIPriv
->sSfb8r
);
116 ffbScreen
->sfb32
= (volatile char *) gDRIPriv
->mSfb32
;
118 if (drmMap(sPriv
->fd
,
121 &gDRIPriv
->mSfb64
)) {
122 drmUnmap(gDRIPriv
->mFbcRegs
, gDRIPriv
->sFbcRegs
);
123 drmUnmap(gDRIPriv
->mDacRegs
, gDRIPriv
->sDacRegs
);
124 drmUnmap(gDRIPriv
->mSfb8r
, gDRIPriv
->sSfb8r
);
125 drmUnmap(gDRIPriv
->mSfb32
, gDRIPriv
->sSfb32
);
129 ffbScreen
->sfb64
= (volatile char *) gDRIPriv
->mSfb64
;
131 ffbScreen
->fifo_cache
= 0;
132 ffbScreen
->rp_active
= 0;
134 ffbScreen
->sPriv
= sPriv
;
135 sPriv
->private = (void *) ffbScreen
;
138 ffbDDPointfuncInit();
145 ffbDestroyScreen(__DRIscreenPrivate
*sPriv
)
147 ffbScreenPrivate
*ffbScreen
= sPriv
->private;
148 FFBDRIPtr gDRIPriv
= (FFBDRIPtr
) sPriv
->pDevPriv
;
150 drmUnmap(gDRIPriv
->mFbcRegs
, gDRIPriv
->sFbcRegs
);
151 drmUnmap(gDRIPriv
->mDacRegs
, gDRIPriv
->sDacRegs
);
152 drmUnmap(gDRIPriv
->mSfb8r
, gDRIPriv
->sSfb8r
);
153 drmUnmap(gDRIPriv
->mSfb32
, gDRIPriv
->sSfb32
);
154 drmUnmap(gDRIPriv
->mSfb64
, gDRIPriv
->sSfb64
);
159 static const struct gl_pipeline_stage
*ffb_pipeline
[] = {
160 &_tnl_vertex_transform_stage
,
161 &_tnl_normal_transform_stage
,
162 &_tnl_lighting_stage
,
163 /* REMOVE: fog coord stage */
165 &_tnl_texture_transform_stage
,
166 /* REMOVE: point attenuation stage */
171 /* Create and initialize the Mesa and driver specific context data */
173 ffbCreateContext(const __GLcontextModes
*mesaVis
,
174 __DRIcontextPrivate
*driContextPriv
,
175 void *sharedContextPrivate
)
178 GLcontext
*ctx
, *shareCtx
;
179 __DRIscreenPrivate
*sPriv
;
180 ffbScreenPrivate
*ffbScreen
;
182 struct dd_function_table functions
;
184 /* Allocate ffb context */
185 fmesa
= (ffbContextPtr
) CALLOC(sizeof(ffbContextRec
));
189 _mesa_init_driver_functions(&functions
);
191 /* Allocate Mesa context */
192 if (sharedContextPrivate
)
193 shareCtx
= ((ffbContextPtr
) sharedContextPrivate
)->glCtx
;
196 fmesa
->glCtx
= _mesa_create_context(mesaVis
, shareCtx
,
202 driContextPriv
->driverPrivate
= fmesa
;
205 sPriv
= driContextPriv
->driScreenPriv
;
206 ffbScreen
= (ffbScreenPrivate
*) sPriv
->private;
209 fmesa
->hHWContext
= driContextPriv
->hHWContext
;
210 fmesa
->driFd
= sPriv
->fd
;
211 fmesa
->driHwLock
= &sPriv
->pSAREA
->lock
;
213 fmesa
->ffbScreen
= ffbScreen
;
214 fmesa
->driScreen
= sPriv
;
215 fmesa
->ffb_sarea
= FFB_DRISHARE(sPriv
->pSAREA
);
217 /* Register and framebuffer hw pointers. */
218 fmesa
->regs
= ffbScreen
->regs
;
219 fmesa
->sfb32
= ffbScreen
->sfb32
;
221 ffbDDInitContextHwState(ctx
);
223 /* Default clear and depth colors. */
225 GLubyte r
= (GLint
) (ctx
->Color
.ClearColor
[0] * 255.0F
);
226 GLubyte g
= (GLint
) (ctx
->Color
.ClearColor
[1] * 255.0F
);
227 GLubyte b
= (GLint
) (ctx
->Color
.ClearColor
[2] * 255.0F
);
229 fmesa
->clear_pixel
= ((r
<< 0) |
233 fmesa
->clear_depth
= Z_FROM_MESA(ctx
->Depth
.Clear
* 4294967295.0f
);
234 fmesa
->clear_stencil
= ctx
->Stencil
.Clear
& 0xf;
236 /* No wide points. */
237 ctx
->Const
.MinPointSize
= 1.0;
238 ctx
->Const
.MinPointSizeAA
= 1.0;
239 ctx
->Const
.MaxPointSize
= 1.0;
240 ctx
->Const
.MaxPointSizeAA
= 1.0;
242 /* Disable wide lines as we can't antialias them correctly in
245 ctx
->Const
.MinLineWidth
= 1.0;
246 ctx
->Const
.MinLineWidthAA
= 1.0;
247 ctx
->Const
.MaxLineWidth
= 1.0;
248 ctx
->Const
.MaxLineWidthAA
= 1.0;
249 ctx
->Const
.LineWidthGranularity
= 1.0;
251 /* Instead of having GCC emit these constants a zillion times
252 * everywhere in the driver, put them here.
254 fmesa
->ffb_2_30_fixed_scale
= __FFB_2_30_FIXED_SCALE
;
255 fmesa
->ffb_one_over_2_30_fixed_scale
= (1.0 / __FFB_2_30_FIXED_SCALE
);
256 fmesa
->ffb_16_16_fixed_scale
= __FFB_16_16_FIXED_SCALE
;
257 fmesa
->ffb_one_over_16_16_fixed_scale
= (1.0 / __FFB_16_16_FIXED_SCALE
);
258 fmesa
->ffb_ubyte_color_scale
= 255.0f
;
259 fmesa
->ffb_zero
= 0.0f
;
261 fmesa
->debugFallbacks
= GL_FALSE
;
262 debug
= getenv("LIBGL_DEBUG");
263 if (debug
&& strstr(debug
, "fallbacks"))
264 fmesa
->debugFallbacks
= GL_TRUE
;
266 /* Initialize the software rasterizer and helper modules. */
267 _swrast_CreateContext( ctx
);
268 _ac_CreateContext( ctx
);
269 _tnl_CreateContext( ctx
);
270 _swsetup_CreateContext( ctx
);
272 /* All of this need only be done once for a new context. */
273 /* XXX these should be moved right after the
274 * _mesa_init_driver_functions() call above.
276 ffbDDExtensionsInit(ctx
);
277 ffbDDInitDriverFuncs(ctx
);
278 ffbDDInitStateFuncs(ctx
);
279 ffbDDInitSpanFuncs(ctx
);
280 ffbDDInitDepthFuncs(ctx
);
281 ffbDDInitStencilFuncs(ctx
);
282 ffbDDInitRenderFuncs(ctx
);
283 /*ffbDDInitTexFuncs(ctx); not needed */
284 ffbDDInitBitmapFuncs(ctx
);
287 ffbInitTnlModule(ctx
);
289 _tnl_destroy_pipeline(ctx
);
290 _tnl_install_pipeline(ctx
, ffb_pipeline
);
296 ffbDestroyContext(__DRIcontextPrivate
*driContextPriv
)
298 ffbContextPtr fmesa
= (ffbContextPtr
) driContextPriv
->driverPrivate
;
301 ffbFreeVB(fmesa
->glCtx
);
303 _swsetup_DestroyContext( fmesa
->glCtx
);
304 _tnl_DestroyContext( fmesa
->glCtx
);
305 _ac_DestroyContext( fmesa
->glCtx
);
306 _swrast_DestroyContext( fmesa
->glCtx
);
308 /* free the Mesa context */
309 fmesa
->glCtx
->DriverCtx
= NULL
;
310 _mesa_destroy_context(fmesa
->glCtx
);
316 /* Create and initialize the Mesa and driver specific pixmap buffer data */
318 ffbCreateBuffer(__DRIscreenPrivate
*driScrnPriv
,
319 __DRIdrawablePrivate
*driDrawPriv
,
320 const __GLcontextModes
*mesaVis
,
324 return GL_FALSE
; /* not implemented */
327 driDrawPriv
->driverPrivate
= (void *)
328 _mesa_create_framebuffer(mesaVis
,
329 GL_FALSE
, /* software depth buffer? */
330 mesaVis
->stencilBits
> 0,
331 mesaVis
->accumRedBits
> 0,
332 mesaVis
->alphaBits
> 0);
333 return (driDrawPriv
->driverPrivate
!= NULL
);
339 ffbDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
341 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
345 #define USE_FAST_SWAP
348 ffbSwapBuffers( __DRIdrawablePrivate
*dPriv
)
350 ffbContextPtr fmesa
= (ffbContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
351 unsigned int fbc
, wid
, wid_reg_val
, dac_db_bit
;
352 unsigned int shadow_dac_addr
, active_dac_addr
;
357 fmesa
->glCtx
->Visual
.doubleBufferMode
== 0)
360 /* Flush pending rendering commands */
361 _mesa_notifySwapBuffers(fmesa
->glCtx
);
364 dac
= fmesa
->ffbScreen
->dac
;
369 /* Swap the buffer we render into and read pixels from. */
370 fmesa
->back_buffer
^= 1;
372 /* If we are writing into both buffers, don't mess with
375 if ((fbc
& FFB_FBC_WB_AB
) != FFB_FBC_WB_AB
) {
376 if ((fbc
& FFB_FBC_WB_A
) != 0)
377 fbc
= (fbc
& ~FFB_FBC_WB_A
) | FFB_FBC_WB_B
;
379 fbc
= (fbc
& ~FFB_FBC_WB_B
) | FFB_FBC_WB_A
;
382 /* But either way, we must flip the read buffer setting. */
383 if ((fbc
& FFB_FBC_RB_A
) != 0)
384 fbc
= (fbc
& ~FFB_FBC_RB_A
) | FFB_FBC_RB_B
;
386 fbc
= (fbc
& ~FFB_FBC_RB_B
) | FFB_FBC_RB_A
;
388 LOCK_HARDWARE(fmesa
);
390 if (fmesa
->fbc
!= fbc
) {
392 ffb
->fbc
= fmesa
->fbc
= fbc
;
393 fmesa
->ffbScreen
->rp_active
= 1;
396 /* And swap the buffer displayed in the WID. */
397 if (fmesa
->ffb_sarea
->flags
& FFB_DRI_PAC1
) {
398 shadow_dac_addr
= FFBDAC_PAC1_SPWLUT(wid
);
399 active_dac_addr
= FFBDAC_PAC1_APWLUT(wid
);
400 dac_db_bit
= FFBDAC_PAC1_WLUT_DB
;
402 shadow_dac_addr
= FFBDAC_PAC2_SPWLUT(wid
);
403 active_dac_addr
= FFBDAC_PAC2_APWLUT(wid
);
404 dac_db_bit
= FFBDAC_PAC2_WLUT_DB
;
409 wid_reg_val
= DACCFG_READ(dac
, active_dac_addr
);
410 if (fmesa
->back_buffer
== 0)
411 wid_reg_val
|= dac_db_bit
;
413 wid_reg_val
&= ~dac_db_bit
;
415 DACCFG_WRITE(dac
, active_dac_addr
, wid_reg_val
);
417 DACCFG_WRITE(dac
, shadow_dac_addr
, wid_reg_val
);
419 /* Schedule the window transfer. */
420 DACCFG_WRITE(dac
, FFBDAC_CFG_WTCTRL
,
421 (FFBDAC_CFG_WTCTRL_TCMD
| FFBDAC_CFG_WTCTRL_TE
));
426 unsigned int wtctrl
= DACCFG_READ(dac
, FFBDAC_CFG_WTCTRL
);
428 if ((wtctrl
& FFBDAC_CFG_WTCTRL_DS
) == 0)
434 UNLOCK_HARDWARE(fmesa
);
437 static void ffb_init_wid(ffbContextPtr fmesa
, unsigned int wid
)
439 ffb_dacPtr dac
= fmesa
->ffbScreen
->dac
;
440 unsigned int wid_reg_val
, dac_db_bit
, active_dac_addr
;
441 unsigned int shadow_dac_addr
;
443 if (fmesa
->ffb_sarea
->flags
& FFB_DRI_PAC1
) {
444 shadow_dac_addr
= FFBDAC_PAC1_SPWLUT(wid
);
445 active_dac_addr
= FFBDAC_PAC1_APWLUT(wid
);
446 dac_db_bit
= FFBDAC_PAC1_WLUT_DB
;
448 shadow_dac_addr
= FFBDAC_PAC2_SPWLUT(wid
);
449 active_dac_addr
= FFBDAC_PAC2_APWLUT(wid
);
450 dac_db_bit
= FFBDAC_PAC2_WLUT_DB
;
453 wid_reg_val
= DACCFG_READ(dac
, active_dac_addr
);
454 wid_reg_val
&= ~dac_db_bit
;
456 DACCFG_WRITE(dac
, active_dac_addr
, wid_reg_val
);
458 DACCFG_WRITE(dac
, shadow_dac_addr
, wid_reg_val
);
460 /* Schedule the window transfer. */
461 DACCFG_WRITE(dac
, FFBDAC_CFG_WTCTRL
,
462 (FFBDAC_CFG_WTCTRL_TCMD
| FFBDAC_CFG_WTCTRL_TE
));
467 unsigned int wtctrl
= DACCFG_READ(dac
, FFBDAC_CFG_WTCTRL
);
469 if ((wtctrl
& FFBDAC_CFG_WTCTRL_DS
) == 0)
476 /* Force the context `c' to be the current context and associate with it
479 ffbMakeCurrent(__DRIcontextPrivate
*driContextPriv
,
480 __DRIdrawablePrivate
*driDrawPriv
,
481 __DRIdrawablePrivate
*driReadPriv
)
483 if (driContextPriv
) {
484 ffbContextPtr fmesa
= (ffbContextPtr
) driContextPriv
->driverPrivate
;
487 fmesa
->driDrawable
= driDrawPriv
;
489 _mesa_make_current2(fmesa
->glCtx
,
490 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
491 (GLframebuffer
*) driReadPriv
->driverPrivate
);
493 if (!fmesa
->glCtx
->Viewport
.Width
)
494 _mesa_set_viewport(fmesa
->glCtx
,
500 if (fmesa
->wid
== ~0) {
502 if (getenv("LIBGL_SOFTWARE_RENDERING"))
503 FALLBACK( fmesa
->glCtx
, FFB_BADATTR_SWONLY
, GL_TRUE
);
506 LOCK_HARDWARE(fmesa
);
508 fmesa
->wid
= fmesa
->ffb_sarea
->wid_table
[driDrawPriv
->index
];
509 ffb_init_wid(fmesa
, fmesa
->wid
);
512 fmesa
->state_dirty
|= FFB_STATE_ALL
;
513 fmesa
->state_fifo_ents
= fmesa
->state_all_fifo_ents
;
514 ffbSyncHardware(fmesa
);
515 UNLOCK_HARDWARE(fmesa
);
518 /* Also, at the first switch to a new context,
519 * we need to clear all the hw buffers.
521 ffbDDClear(fmesa
->glCtx
,
522 (DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
|
523 DD_DEPTH_BIT
| DD_STENCIL_BIT
),
527 _mesa_make_current(NULL
, NULL
);
533 /* Force the context `c' to be unbound from its buffer */
535 ffbUnbindContext(__DRIcontextPrivate
*driContextPriv
)
541 ffbOpenFullScreen(__DRIcontextPrivate
*driContextPriv
)
547 ffbCloseFullScreen(__DRIcontextPrivate
*driContextPriv
)
552 void ffbXMesaUpdateState(ffbContextPtr fmesa
)
554 __DRIdrawablePrivate
*dPriv
= fmesa
->driDrawable
;
555 __DRIscreenPrivate
*sPriv
= fmesa
->driScreen
;
556 int stamp
= dPriv
->lastStamp
;
558 DRI_VALIDATE_DRAWABLE_INFO(sPriv
, dPriv
);
560 if (dPriv
->lastStamp
!= stamp
) {
561 GLcontext
*ctx
= fmesa
->glCtx
;
563 ffbCalcViewport(ctx
);
564 if (ctx
->Polygon
.StippleFlag
)
565 ffbXformAreaPattern(fmesa
,
566 (const GLubyte
*)ctx
->PolygonStipple
);
571 static struct __DriverAPIRec ffbAPI
= {
588 * This is the bootstrap function for the driver.
589 * The __driCreateScreen name is the symbol that libGL.so fetches.
590 * Return: pointer to a __DRIscreenPrivate.
592 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
593 int numConfigs
, __GLXvisualConfig
*config
)
595 __DRIscreenPrivate
*psp
;
596 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &ffbAPI
);
601 #endif /* GLX_DIRECT_RENDERING */