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 #include "ffb_xmesa.h"
29 #include "main/context.h"
30 #include "main/framebuffer.h"
31 #include "main/renderbuffer.h"
32 #include "main/simple_list.h"
33 #include "main/imports.h"
36 #include "swrast/swrast.h"
37 #include "swrast_setup/swrast_setup.h"
39 #include "tnl/t_pipeline.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"
55 #include "ffb_vtxfmt.h"
56 #include "ffb_bitmap.h"
58 #include "drm_sarea.h"
60 #include "drirenderbuffer.h"
63 ffbInitDriver(__DRIscreen
*sPriv
)
65 ffbScreenPrivate
*ffbScreen
;
66 FFBDRIPtr gDRIPriv
= (FFBDRIPtr
) sPriv
->pDevPriv
;
69 if (getenv("LIBGL_FORCE_XSERVER"))
73 if (sPriv
->devPrivSize
!= sizeof(FFBDRIRec
)) {
74 fprintf(stderr
,"\nERROR! sizeof(FFBDRIRec) does not match passed size from device driver\n");
78 /* Allocate the private area. */
79 ffbScreen
= (ffbScreenPrivate
*) MALLOC(sizeof(ffbScreenPrivate
));
83 /* Map FBC registers. */
91 ffbScreen
->regs
= (ffb_fbcPtr
) map
;
93 /* Map ramdac registers. */
98 drmUnmap((drmAddress
)ffbScreen
->regs
, gDRIPriv
->sFbcRegs
);
102 ffbScreen
->dac
= (ffb_dacPtr
) map
;
104 /* Map "Smart" framebuffer views. */
105 if (drmMap(sPriv
->fd
,
109 drmUnmap((drmAddress
)ffbScreen
->regs
, gDRIPriv
->sFbcRegs
);
110 drmUnmap((drmAddress
)ffbScreen
->dac
, gDRIPriv
->sDacRegs
);
114 ffbScreen
->sfb8r
= (volatile char *) map
;
116 if (drmMap(sPriv
->fd
,
120 drmUnmap((drmAddress
)ffbScreen
->regs
, gDRIPriv
->sFbcRegs
);
121 drmUnmap((drmAddress
)ffbScreen
->dac
, gDRIPriv
->sDacRegs
);
122 drmUnmap((drmAddress
)ffbScreen
->sfb8r
, gDRIPriv
->sSfb8r
);
126 ffbScreen
->sfb32
= (volatile char *) map
;
128 if (drmMap(sPriv
->fd
,
132 drmUnmap((drmAddress
)ffbScreen
->regs
, gDRIPriv
->sFbcRegs
);
133 drmUnmap((drmAddress
)ffbScreen
->dac
, gDRIPriv
->sDacRegs
);
134 drmUnmap((drmAddress
)ffbScreen
->sfb8r
, gDRIPriv
->sSfb8r
);
135 drmUnmap((drmAddress
)ffbScreen
->sfb32
, gDRIPriv
->sSfb32
);
139 ffbScreen
->sfb64
= (volatile char *) map
;
141 ffbScreen
->fifo_cache
= 0;
142 ffbScreen
->rp_active
= 0;
144 ffbScreen
->sPriv
= sPriv
;
145 sPriv
->private = (void *) ffbScreen
;
148 ffbDDPointfuncInit();
155 ffbDestroyScreen(__DRIscreen
*sPriv
)
157 ffbScreenPrivate
*ffbScreen
= sPriv
->private;
158 FFBDRIPtr gDRIPriv
= (FFBDRIPtr
) sPriv
->pDevPriv
;
160 drmUnmap((drmAddress
)ffbScreen
->regs
, gDRIPriv
->sFbcRegs
);
161 drmUnmap((drmAddress
)ffbScreen
->dac
, gDRIPriv
->sDacRegs
);
162 drmUnmap((drmAddress
)ffbScreen
->sfb8r
, gDRIPriv
->sSfb8r
);
163 drmUnmap((drmAddress
)ffbScreen
->sfb32
, gDRIPriv
->sSfb32
);
164 drmUnmap((drmAddress
)ffbScreen
->sfb64
, gDRIPriv
->sSfb64
);
169 static const struct tnl_pipeline_stage
*ffb_pipeline
[] = {
170 &_tnl_vertex_transform_stage
,
171 &_tnl_normal_transform_stage
,
172 &_tnl_lighting_stage
,
173 /* REMOVE: fog coord stage */
175 &_tnl_texture_transform_stage
,
176 /* REMOVE: point attenuation stage */
181 /* Create and initialize the Mesa and driver specific context data */
183 ffbCreateContext(const __GLcontextModes
*mesaVis
,
184 __DRIcontext
*driContextPriv
,
185 void *sharedContextPrivate
)
188 GLcontext
*ctx
, *shareCtx
;
190 ffbScreenPrivate
*ffbScreen
;
192 struct dd_function_table functions
;
194 /* Allocate ffb context */
195 fmesa
= (ffbContextPtr
) CALLOC(sizeof(ffbContextRec
));
199 _mesa_init_driver_functions(&functions
);
201 /* Allocate Mesa context */
202 if (sharedContextPrivate
)
203 shareCtx
= ((ffbContextPtr
) sharedContextPrivate
)->glCtx
;
206 fmesa
->glCtx
= _mesa_create_context(mesaVis
, shareCtx
,
212 driContextPriv
->driverPrivate
= fmesa
;
215 sPriv
= driContextPriv
->driScreenPriv
;
216 ffbScreen
= (ffbScreenPrivate
*) sPriv
->private;
219 fmesa
->hHWContext
= driContextPriv
->hHWContext
;
220 fmesa
->driFd
= sPriv
->fd
;
221 fmesa
->driHwLock
= &sPriv
->pSAREA
->lock
;
223 fmesa
->ffbScreen
= ffbScreen
;
224 fmesa
->driScreen
= sPriv
;
225 fmesa
->ffb_sarea
= FFB_DRISHARE(sPriv
->pSAREA
);
227 /* Register and framebuffer pointers. */
228 fmesa
->regs
= ffbScreen
->regs
;
229 fmesa
->sfb32
= ffbScreen
->sfb32
;
231 ffbDDInitContextHwState(ctx
);
233 /* Default clear and depth colors. */
235 GLubyte r
= (GLint
) (ctx
->Color
.ClearColor
[0] * 255.0F
);
236 GLubyte g
= (GLint
) (ctx
->Color
.ClearColor
[1] * 255.0F
);
237 GLubyte b
= (GLint
) (ctx
->Color
.ClearColor
[2] * 255.0F
);
239 fmesa
->clear_pixel
= ((r
<< 0) |
243 fmesa
->clear_depth
= Z_FROM_MESA(ctx
->Depth
.Clear
* 4294967295.0f
);
244 fmesa
->clear_stencil
= ctx
->Stencil
.Clear
& 0xf;
246 /* No wide points. */
247 ctx
->Const
.MinPointSize
= 1.0;
248 ctx
->Const
.MinPointSizeAA
= 1.0;
249 ctx
->Const
.MaxPointSize
= 1.0;
250 ctx
->Const
.MaxPointSizeAA
= 1.0;
252 /* Disable wide lines as we can't antialias them correctly in
255 ctx
->Const
.MinLineWidth
= 1.0;
256 ctx
->Const
.MinLineWidthAA
= 1.0;
257 ctx
->Const
.MaxLineWidth
= 1.0;
258 ctx
->Const
.MaxLineWidthAA
= 1.0;
259 ctx
->Const
.LineWidthGranularity
= 1.0;
261 ctx
->Const
.MaxDrawBuffers
= 1;
263 /* Instead of having GCC emit these constants a zillion times
264 * everywhere in the driver, put them here.
266 fmesa
->ffb_2_30_fixed_scale
= __FFB_2_30_FIXED_SCALE
;
267 fmesa
->ffb_one_over_2_30_fixed_scale
= (1.0 / __FFB_2_30_FIXED_SCALE
);
268 fmesa
->ffb_16_16_fixed_scale
= __FFB_16_16_FIXED_SCALE
;
269 fmesa
->ffb_one_over_16_16_fixed_scale
= (1.0 / __FFB_16_16_FIXED_SCALE
);
270 fmesa
->ffb_ubyte_color_scale
= 255.0f
;
271 fmesa
->ffb_zero
= 0.0f
;
273 fmesa
->debugFallbacks
= GL_FALSE
;
274 debug
= getenv("LIBGL_DEBUG");
275 if (debug
&& strstr(debug
, "fallbacks"))
276 fmesa
->debugFallbacks
= GL_TRUE
;
278 /* Initialize the software rasterizer and helper modules. */
279 _swrast_CreateContext( ctx
);
280 _vbo_CreateContext( ctx
);
281 _tnl_CreateContext( ctx
);
282 _swsetup_CreateContext( ctx
);
284 /* All of this need only be done once for a new context. */
285 /* XXX these should be moved right after the
286 * _mesa_init_driver_functions() call above.
288 ffbDDExtensionsInit(ctx
);
289 ffbDDInitDriverFuncs(ctx
);
290 ffbDDInitStateFuncs(ctx
);
291 ffbDDInitRenderFuncs(ctx
);
292 /*ffbDDInitTexFuncs(ctx); not needed */
293 ffbDDInitBitmapFuncs(ctx
);
297 ffbInitTnlModule(ctx
);
300 _tnl_destroy_pipeline(ctx
);
301 _tnl_install_pipeline(ctx
, ffb_pipeline
);
307 ffbDestroyContext(__DRIcontext
*driContextPriv
)
309 ffbContextPtr fmesa
= (ffbContextPtr
) driContextPriv
->driverPrivate
;
312 ffbFreeVB(fmesa
->glCtx
);
314 _swsetup_DestroyContext( fmesa
->glCtx
);
315 _tnl_DestroyContext( fmesa
->glCtx
);
316 _vbo_DestroyContext( fmesa
->glCtx
);
317 _swrast_DestroyContext( fmesa
->glCtx
);
319 /* free the Mesa context */
320 fmesa
->glCtx
->DriverCtx
= NULL
;
321 _mesa_destroy_context(fmesa
->glCtx
);
327 /* Create and initialize the Mesa and driver specific pixmap buffer data */
329 ffbCreateBuffer(__DRIscreen
*driScrnPriv
,
330 __DRIdrawable
*driDrawPriv
,
331 const __GLcontextModes
*mesaVis
,
334 /* Mesa checks for pitch > 0, but ffb doesn't use pitches */
336 int bpp
= 4; /* we've always got a 32bpp framebuffer */
337 int offset
= 0; /* always at 0 for offset */
340 return GL_FALSE
; /* not implemented */
342 GLboolean swStencil
= (mesaVis
->stencilBits
> 0 &&
343 mesaVis
->depthBits
!= 24);
344 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
347 driRenderbuffer
*frontRb
348 = driNewRenderbuffer(MESA_FORMAT_ARGB8888
, NULL
, bpp
, offset
, bogusPitch
,
350 ffbSetSpanFunctions(frontRb
, mesaVis
);
351 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
354 if (mesaVis
->doubleBufferMode
) {
355 driRenderbuffer
*backRb
356 = driNewRenderbuffer(MESA_FORMAT_ARGB8888
, NULL
, bpp
, offset
, bogusPitch
,
358 ffbSetSpanFunctions(backRb
, mesaVis
);
359 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
362 if (mesaVis
->depthBits
== 16) {
363 driRenderbuffer
*depthRb
364 = driNewRenderbuffer(MESA_FORMAT_Z16
, NULL
, bpp
, offset
,
365 bogusPitch
, driDrawPriv
);
366 ffbSetDepthFunctions(depthRb
, mesaVis
);
367 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
370 if (mesaVis
->stencilBits
> 0 && !swStencil
) {
371 driRenderbuffer
*stencilRb
372 = driNewRenderbuffer(MESA_FORMAT_S8
, NULL
, bpp
, offset
,
373 bogusPitch
, driDrawPriv
);
374 ffbSetStencilFunctions(stencilRb
, mesaVis
);
375 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
378 _mesa_add_soft_renderbuffers(fb
,
379 GL_FALSE
, /* color */
380 GL_FALSE
, /* depth */
382 mesaVis
->accumRedBits
> 0,
383 GL_FALSE
, /* alpha */
385 driDrawPriv
->driverPrivate
= (void *) fb
;
387 return (driDrawPriv
->driverPrivate
!= NULL
);
393 ffbDestroyBuffer(__DRIdrawable
*driDrawPriv
)
395 _mesa_reference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)), NULL
);
399 #define USE_FAST_SWAP
402 ffbSwapBuffers( __DRIdrawable
*dPriv
)
404 ffbContextPtr fmesa
= (ffbContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
405 unsigned int fbc
, wid
, wid_reg_val
, dac_db_bit
;
406 unsigned int shadow_dac_addr
, active_dac_addr
;
411 fmesa
->glCtx
->Visual
.doubleBufferMode
== 0)
414 /* Flush pending rendering commands */
415 _mesa_notifySwapBuffers(fmesa
->glCtx
);
418 dac
= fmesa
->ffbScreen
->dac
;
423 /* Swap the buffer we render into and read pixels from. */
424 fmesa
->back_buffer
^= 1;
426 /* If we are writing into both buffers, don't mess with
429 if ((fbc
& FFB_FBC_WB_AB
) != FFB_FBC_WB_AB
) {
430 if ((fbc
& FFB_FBC_WB_A
) != 0)
431 fbc
= (fbc
& ~FFB_FBC_WB_A
) | FFB_FBC_WB_B
;
433 fbc
= (fbc
& ~FFB_FBC_WB_B
) | FFB_FBC_WB_A
;
436 /* But either way, we must flip the read buffer setting. */
437 if ((fbc
& FFB_FBC_RB_A
) != 0)
438 fbc
= (fbc
& ~FFB_FBC_RB_A
) | FFB_FBC_RB_B
;
440 fbc
= (fbc
& ~FFB_FBC_RB_B
) | FFB_FBC_RB_A
;
442 LOCK_HARDWARE(fmesa
);
444 if (fmesa
->fbc
!= fbc
) {
446 ffb
->fbc
= fmesa
->fbc
= fbc
;
447 fmesa
->ffbScreen
->rp_active
= 1;
450 /* And swap the buffer displayed in the WID. */
451 if (fmesa
->ffb_sarea
->flags
& FFB_DRI_PAC1
) {
452 shadow_dac_addr
= FFBDAC_PAC1_SPWLUT(wid
);
453 active_dac_addr
= FFBDAC_PAC1_APWLUT(wid
);
454 dac_db_bit
= FFBDAC_PAC1_WLUT_DB
;
456 shadow_dac_addr
= FFBDAC_PAC2_SPWLUT(wid
);
457 active_dac_addr
= FFBDAC_PAC2_APWLUT(wid
);
458 dac_db_bit
= FFBDAC_PAC2_WLUT_DB
;
463 wid_reg_val
= DACCFG_READ(dac
, active_dac_addr
);
464 if (fmesa
->back_buffer
== 0)
465 wid_reg_val
|= dac_db_bit
;
467 wid_reg_val
&= ~dac_db_bit
;
469 DACCFG_WRITE(dac
, active_dac_addr
, wid_reg_val
);
471 DACCFG_WRITE(dac
, shadow_dac_addr
, wid_reg_val
);
473 /* Schedule the window transfer. */
474 DACCFG_WRITE(dac
, FFBDAC_CFG_WTCTRL
,
475 (FFBDAC_CFG_WTCTRL_TCMD
| FFBDAC_CFG_WTCTRL_TE
));
480 unsigned int wtctrl
= DACCFG_READ(dac
, FFBDAC_CFG_WTCTRL
);
482 if ((wtctrl
& FFBDAC_CFG_WTCTRL_DS
) == 0)
488 UNLOCK_HARDWARE(fmesa
);
491 static void ffb_init_wid(ffbContextPtr fmesa
, unsigned int wid
)
493 ffb_dacPtr dac
= fmesa
->ffbScreen
->dac
;
494 unsigned int wid_reg_val
, dac_db_bit
, active_dac_addr
;
495 unsigned int shadow_dac_addr
;
497 if (fmesa
->ffb_sarea
->flags
& FFB_DRI_PAC1
) {
498 shadow_dac_addr
= FFBDAC_PAC1_SPWLUT(wid
);
499 active_dac_addr
= FFBDAC_PAC1_APWLUT(wid
);
500 dac_db_bit
= FFBDAC_PAC1_WLUT_DB
;
502 shadow_dac_addr
= FFBDAC_PAC2_SPWLUT(wid
);
503 active_dac_addr
= FFBDAC_PAC2_APWLUT(wid
);
504 dac_db_bit
= FFBDAC_PAC2_WLUT_DB
;
507 wid_reg_val
= DACCFG_READ(dac
, active_dac_addr
);
508 wid_reg_val
&= ~dac_db_bit
;
510 DACCFG_WRITE(dac
, active_dac_addr
, wid_reg_val
);
512 DACCFG_WRITE(dac
, shadow_dac_addr
, wid_reg_val
);
514 /* Schedule the window transfer. */
515 DACCFG_WRITE(dac
, FFBDAC_CFG_WTCTRL
,
516 (FFBDAC_CFG_WTCTRL_TCMD
| FFBDAC_CFG_WTCTRL_TE
));
521 unsigned int wtctrl
= DACCFG_READ(dac
, FFBDAC_CFG_WTCTRL
);
523 if ((wtctrl
& FFBDAC_CFG_WTCTRL_DS
) == 0)
530 /* Force the context `c' to be the current context and associate with it
533 ffbMakeCurrent(__DRIcontext
*driContextPriv
,
534 __DRIdrawable
*driDrawPriv
,
535 __DRIdrawable
*driReadPriv
)
537 if (driContextPriv
) {
538 ffbContextPtr fmesa
= (ffbContextPtr
) driContextPriv
->driverPrivate
;
541 fmesa
->driDrawable
= driDrawPriv
;
543 _mesa_make_current(fmesa
->glCtx
,
544 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
545 (GLframebuffer
*) driReadPriv
->driverPrivate
);
548 if (fmesa
->wid
== ~0) {
550 if (getenv("LIBGL_SOFTWARE_RENDERING"))
551 FALLBACK( fmesa
->glCtx
, FFB_BADATTR_SWONLY
, GL_TRUE
);
554 LOCK_HARDWARE(fmesa
);
556 fmesa
->wid
= fmesa
->ffb_sarea
->wid_table
[driDrawPriv
->index
];
557 ffb_init_wid(fmesa
, fmesa
->wid
);
560 fmesa
->state_dirty
|= FFB_STATE_ALL
;
561 fmesa
->state_fifo_ents
= fmesa
->state_all_fifo_ents
;
562 ffbSyncHardware(fmesa
);
563 UNLOCK_HARDWARE(fmesa
);
566 /* Also, at the first switch to a new context,
567 * we need to clear all the hw buffers.
569 ffbDDClear(fmesa
->glCtx
,
570 (BUFFER_BIT_FRONT_LEFT
| BUFFER_BIT_BACK_LEFT
|
571 BUFFER_BIT_DEPTH
| BUFFER_BIT_STENCIL
));
574 _mesa_make_current(NULL
, NULL
, NULL
);
580 /* Force the context `c' to be unbound from its buffer */
582 ffbUnbindContext(__DRIcontext
*driContextPriv
)
587 void ffbXMesaUpdateState(ffbContextPtr fmesa
)
589 __DRIdrawable
*dPriv
= fmesa
->driDrawable
;
590 __DRIscreen
*sPriv
= fmesa
->driScreen
;
591 int stamp
= dPriv
->lastStamp
;
593 DRI_VALIDATE_DRAWABLE_INFO(sPriv
, dPriv
);
595 if (dPriv
->lastStamp
!= stamp
) {
596 GLcontext
*ctx
= fmesa
->glCtx
;
598 ffbCalcViewport(ctx
);
599 driUpdateFramebufferSize(ctx
, dPriv
);
600 if (ctx
->Polygon
.StippleFlag
) {
601 ffbXformAreaPattern(fmesa
,
602 (const GLubyte
*)ctx
->PolygonStipple
);
607 static const __DRIconfig
**
608 ffbFillInModes( __DRIscreen
*psp
,
609 unsigned pixel_bits
, unsigned depth_bits
,
610 unsigned stencil_bits
, GLboolean have_back_buffer
)
612 __DRIconfig
**configs
;
614 unsigned depth_buffer_factor
;
615 unsigned back_buffer_factor
;
620 /* GLX_SWAP_COPY_OML is only supported because the FFB driver doesn't
621 * support pageflipping at all.
623 static const GLenum back_buffer_modes
[] = {
624 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
, GLX_SWAP_COPY_OML
627 uint8_t depth_bits_array
[3];
628 uint8_t stencil_bits_array
[3];
629 uint8_t msaa_samples_array
[1];
631 depth_bits_array
[0] = 0;
632 depth_bits_array
[1] = depth_bits
;
633 depth_bits_array
[2] = depth_bits
;
635 /* Just like with the accumulation buffer, always provide some modes
636 * with a stencil buffer. It will be a sw fallback, but some apps won't
639 stencil_bits_array
[0] = 0;
640 stencil_bits_array
[1] = 0;
641 stencil_bits_array
[2] = (stencil_bits
== 0) ? 8 : stencil_bits
;
643 msaa_samples_array
[0] = 0;
645 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 3 : 1;
646 back_buffer_factor
= (have_back_buffer
) ? 3 : 1;
648 if ( pixel_bits
== 16 ) {
650 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
654 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
657 configs
= driCreateConfigs(fb_format
, fb_type
,
658 depth_bits_array
, stencil_bits_array
,
659 depth_buffer_factor
, back_buffer_modes
,
661 msaa_samples_array
, 1);
662 if (configs
== NULL
) {
663 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n", __func__
,
668 /* Mark the visual as slow if there are "fake" stencil bits.
670 for (i
= 0; configs
[i
]; i
++) {
671 m
= &configs
[i
]->modes
;
672 if ((m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
)) {
673 m
->visualRating
= GLX_SLOW_CONFIG
;
677 return (const __DRIconfig
**) configs
;
682 * This is the driver specific part of the createNewScreen entry point.
684 * \todo maybe fold this into intelInitDriver
686 * \return the __GLcontextModes supported by this driver
688 static const __DRIconfig
**
689 ffbInitScreen(__DRIscreen
*psp
)
691 static const __DRIversion ddx_expected
= { 0, 1, 1 };
692 static const __DRIversion dri_expected
= { 4, 0, 0 };
693 static const __DRIversion drm_expected
= { 0, 0, 1 };
695 if ( ! driCheckDriDdxDrmVersions2( "ffb",
696 &psp
->dri_version
, & dri_expected
,
697 &psp
->ddx_version
, & ddx_expected
,
698 &psp
->drm_version
, & drm_expected
) )
701 if (!ffbInitDriver(psp
))
704 return ffbFillInModes( psp
, 32, 16, 0, GL_TRUE
);
707 const struct __DriverAPIRec driDriverAPI
= {
708 .InitScreen
= ffbInitScreen
,
709 .DestroyScreen
= ffbDestroyScreen
,
710 .CreateContext
= ffbCreateContext
,
711 .DestroyContext
= ffbDestroyContext
,
712 .CreateBuffer
= ffbCreateBuffer
,
713 .DestroyBuffer
= ffbDestroyBuffer
,
714 .SwapBuffers
= ffbSwapBuffers
,
715 .MakeCurrent
= ffbMakeCurrent
,
716 .UnbindContext
= ffbUnbindContext
,
718 .GetDrawableMSC
= NULL
,
721 .SwapBuffersMSC
= NULL
724 /* This is the table of extensions that the loader will dlsym() for. */
725 PUBLIC
const __DRIextension
*__driDriverExtensions
[] = {
726 &driCoreExtension
.base
,
727 &driLegacyExtension
.base
,