Undo some bits from last check-in related to the ctx->Driver.NewTextureObject
[mesa.git] / src / mesa / drivers / dri / ffb / ffb_xmesa.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_xmesa.c,v 1.4 2002/02/22 21:32:59 dawes Exp $
2 *
3 * GLX Hardware Device Driver for Sun Creator/Creator3D
4 * Copyright (C) 2000, 2001 David S. Miller
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
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.
23 *
24 *
25 * David S. Miller <davem@redhat.com>
26 */
27
28 #ifdef GLX_DIRECT_RENDERING
29
30 #include "ffb_xmesa.h"
31 #include "context.h"
32 #include "matrix.h"
33 #include "simple_list.h"
34 #include "imports.h"
35
36 #include "swrast/swrast.h"
37 #include "swrast_setup/swrast_setup.h"
38 #include "tnl/tnl.h"
39 #include "tnl/t_pipeline.h"
40 #include "array_cache/acache.h"
41 #include "drivers/common/driverfuncs.h"
42
43 #include "ffb_context.h"
44 #include "ffb_dd.h"
45 #include "ffb_span.h"
46 #include "ffb_depth.h"
47 #include "ffb_stencil.h"
48 #include "ffb_clear.h"
49 #include "ffb_vb.h"
50 #include "ffb_tris.h"
51 #include "ffb_lines.h"
52 #include "ffb_points.h"
53 #include "ffb_state.h"
54 #include "ffb_tex.h"
55 #include "ffb_lock.h"
56 #include "ffb_vtxfmt.h"
57 #include "ffb_bitmap.h"
58
59 static GLboolean
60 ffbInitDriver(__DRIscreenPrivate *sPriv)
61 {
62 ffbScreenPrivate *ffbScreen;
63 FFBDRIPtr gDRIPriv = (FFBDRIPtr) sPriv->pDevPriv;
64
65 if (getenv("LIBGL_FORCE_XSERVER"))
66 return GL_FALSE;
67
68 /* Allocate the private area. */
69 ffbScreen = (ffbScreenPrivate *) Xmalloc(sizeof(ffbScreenPrivate));
70 if (!ffbScreen)
71 return GL_FALSE;
72
73 /* Map FBC registers. */
74 if (drmMap(sPriv->fd,
75 gDRIPriv->hFbcRegs,
76 gDRIPriv->sFbcRegs,
77 &gDRIPriv->mFbcRegs)) {
78 Xfree(ffbScreen);
79 return GL_FALSE;
80 }
81 ffbScreen->regs = (ffb_fbcPtr) gDRIPriv->mFbcRegs;
82
83 /* Map ramdac registers. */
84 if (drmMap(sPriv->fd,
85 gDRIPriv->hDacRegs,
86 gDRIPriv->sDacRegs,
87 &gDRIPriv->mDacRegs)) {
88 drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
89 Xfree(ffbScreen);
90 return GL_FALSE;
91 }
92 ffbScreen->dac = (ffb_dacPtr) gDRIPriv->mDacRegs;
93
94 /* Map "Smart" framebuffer views. */
95 if (drmMap(sPriv->fd,
96 gDRIPriv->hSfb8r,
97 gDRIPriv->sSfb8r,
98 &gDRIPriv->mSfb8r)) {
99 drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
100 drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs);
101 Xfree(ffbScreen);
102 return GL_FALSE;
103 }
104 ffbScreen->sfb8r = (volatile char *) gDRIPriv->mSfb8r;
105
106 if (drmMap(sPriv->fd,
107 gDRIPriv->hSfb32,
108 gDRIPriv->sSfb32,
109 &gDRIPriv->mSfb32)) {
110 drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
111 drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs);
112 drmUnmap(gDRIPriv->mSfb8r, gDRIPriv->sSfb8r);
113 Xfree(ffbScreen);
114 return GL_FALSE;
115 }
116 ffbScreen->sfb32 = (volatile char *) gDRIPriv->mSfb32;
117
118 if (drmMap(sPriv->fd,
119 gDRIPriv->hSfb64,
120 gDRIPriv->sSfb64,
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);
126 Xfree(ffbScreen);
127 return GL_FALSE;
128 }
129 ffbScreen->sfb64 = (volatile char *) gDRIPriv->mSfb64;
130
131 ffbScreen->fifo_cache = 0;
132 ffbScreen->rp_active = 0;
133
134 ffbScreen->sPriv = sPriv;
135 sPriv->private = (void *) ffbScreen;
136
137 ffbDDLinefuncInit();
138 ffbDDPointfuncInit();
139
140 return GL_TRUE;
141 }
142
143
144 static void
145 ffbDestroyScreen(__DRIscreenPrivate *sPriv)
146 {
147 ffbScreenPrivate *ffbScreen = sPriv->private;
148 FFBDRIPtr gDRIPriv = (FFBDRIPtr) sPriv->pDevPriv;
149
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);
155
156 Xfree(ffbScreen);
157 }
158
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 */
164 &_tnl_texgen_stage,
165 &_tnl_texture_transform_stage,
166 /* REMOVE: point attenuation stage */
167 &_tnl_render_stage,
168 0,
169 };
170
171 /* Create and initialize the Mesa and driver specific context data */
172 static GLboolean
173 ffbCreateContext(const __GLcontextModes *mesaVis,
174 __DRIcontextPrivate *driContextPriv,
175 void *sharedContextPrivate)
176 {
177 ffbContextPtr fmesa;
178 GLcontext *ctx, *shareCtx;
179 __DRIscreenPrivate *sPriv;
180 ffbScreenPrivate *ffbScreen;
181 char *debug;
182 struct dd_function_table functions;
183
184 /* Allocate ffb context */
185 fmesa = (ffbContextPtr) CALLOC(sizeof(ffbContextRec));
186 if (!fmesa)
187 return GL_FALSE;
188
189 _mesa_init_driver_functions(&functions);
190
191 /* Allocate Mesa context */
192 if (sharedContextPrivate)
193 shareCtx = ((ffbContextPtr) sharedContextPrivate)->glCtx;
194 else
195 shareCtx = NULL;
196 fmesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
197 &functions, fmesa);
198 if (!fmesa->glCtx) {
199 FREE(fmesa);
200 return GL_FALSE;
201 }
202 driContextPriv->driverPrivate = fmesa;
203 ctx = fmesa->glCtx;
204
205 sPriv = driContextPriv->driScreenPriv;
206 ffbScreen = (ffbScreenPrivate *) sPriv->private;
207
208 /* Dri stuff. */
209 fmesa->hHWContext = driContextPriv->hHWContext;
210 fmesa->driFd = sPriv->fd;
211 fmesa->driHwLock = &sPriv->pSAREA->lock;
212
213 fmesa->ffbScreen = ffbScreen;
214 fmesa->driScreen = sPriv;
215 fmesa->ffb_sarea = FFB_DRISHARE(sPriv->pSAREA);
216
217 /* Register and framebuffer hw pointers. */
218 fmesa->regs = ffbScreen->regs;
219 fmesa->sfb32 = ffbScreen->sfb32;
220
221 ffbDDInitContextHwState(ctx);
222
223 /* Default clear and depth colors. */
224 {
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);
228
229 fmesa->clear_pixel = ((r << 0) |
230 (g << 8) |
231 (b << 16));
232 }
233 fmesa->clear_depth = Z_FROM_MESA(ctx->Depth.Clear * 4294967295.0f);
234 fmesa->clear_stencil = ctx->Stencil.Clear & 0xf;
235
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;
241
242 /* Disable wide lines as we can't antialias them correctly in
243 * hardware.
244 */
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;
250
251 /* Instead of having GCC emit these constants a zillion times
252 * everywhere in the driver, put them here.
253 */
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;
260
261 fmesa->debugFallbacks = GL_FALSE;
262 debug = getenv("LIBGL_DEBUG");
263 if (debug && strstr(debug, "fallbacks"))
264 fmesa->debugFallbacks = GL_TRUE;
265
266 /* Initialize the software rasterizer and helper modules. */
267 _swrast_CreateContext( ctx );
268 _ac_CreateContext( ctx );
269 _tnl_CreateContext( ctx );
270 _swsetup_CreateContext( ctx );
271
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.
275 */
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);
285 ffbInitVB(ctx);
286
287 ffbInitTnlModule(ctx);
288
289 _tnl_destroy_pipeline(ctx);
290 _tnl_install_pipeline(ctx, ffb_pipeline);
291
292 return GL_TRUE;
293 }
294
295 static void
296 ffbDestroyContext(__DRIcontextPrivate *driContextPriv)
297 {
298 ffbContextPtr fmesa = (ffbContextPtr) driContextPriv->driverPrivate;
299
300 if (fmesa) {
301 ffbFreeVB(fmesa->glCtx);
302
303 _swsetup_DestroyContext( fmesa->glCtx );
304 _tnl_DestroyContext( fmesa->glCtx );
305 _ac_DestroyContext( fmesa->glCtx );
306 _swrast_DestroyContext( fmesa->glCtx );
307
308 /* free the Mesa context */
309 fmesa->glCtx->DriverCtx = NULL;
310 _mesa_destroy_context(fmesa->glCtx);
311
312 FREE(fmesa);
313 }
314 }
315
316 /* Create and initialize the Mesa and driver specific pixmap buffer data */
317 static GLboolean
318 ffbCreateBuffer(__DRIscreenPrivate *driScrnPriv,
319 __DRIdrawablePrivate *driDrawPriv,
320 const __GLcontextModes *mesaVis,
321 GLboolean isPixmap )
322 {
323 if (isPixmap) {
324 return GL_FALSE; /* not implemented */
325 }
326 else {
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);
334 }
335 }
336
337
338 static void
339 ffbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
340 {
341 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
342 }
343
344
345 #define USE_FAST_SWAP
346
347 static void
348 ffbSwapBuffers( __DRIdrawablePrivate *dPriv )
349 {
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;
353 ffb_fbcPtr ffb;
354 ffb_dacPtr dac;
355
356 if (fmesa == NULL ||
357 fmesa->glCtx->Visual.doubleBufferMode == 0)
358 return;
359
360 /* Flush pending rendering commands */
361 _mesa_notifySwapBuffers(fmesa->glCtx);
362
363 ffb = fmesa->regs;
364 dac = fmesa->ffbScreen->dac;
365
366 fbc = fmesa->fbc;
367 wid = fmesa->wid;
368
369 /* Swap the buffer we render into and read pixels from. */
370 fmesa->back_buffer ^= 1;
371
372 /* If we are writing into both buffers, don't mess with
373 * the WB setting.
374 */
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;
378 else
379 fbc = (fbc & ~FFB_FBC_WB_B) | FFB_FBC_WB_A;
380 }
381
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;
385 else
386 fbc = (fbc & ~FFB_FBC_RB_B) | FFB_FBC_RB_A;
387
388 LOCK_HARDWARE(fmesa);
389
390 if (fmesa->fbc != fbc) {
391 FFBFifo(fmesa, 1);
392 ffb->fbc = fmesa->fbc = fbc;
393 fmesa->ffbScreen->rp_active = 1;
394 }
395
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;
401 } else {
402 shadow_dac_addr = FFBDAC_PAC2_SPWLUT(wid);
403 active_dac_addr = FFBDAC_PAC2_APWLUT(wid);
404 dac_db_bit = FFBDAC_PAC2_WLUT_DB;
405 }
406
407 FFBWait(fmesa, ffb);
408
409 wid_reg_val = DACCFG_READ(dac, active_dac_addr);
410 if (fmesa->back_buffer == 0)
411 wid_reg_val |= dac_db_bit;
412 else
413 wid_reg_val &= ~dac_db_bit;
414 #ifdef USE_FAST_SWAP
415 DACCFG_WRITE(dac, active_dac_addr, wid_reg_val);
416 #else
417 DACCFG_WRITE(dac, shadow_dac_addr, wid_reg_val);
418
419 /* Schedule the window transfer. */
420 DACCFG_WRITE(dac, FFBDAC_CFG_WTCTRL,
421 (FFBDAC_CFG_WTCTRL_TCMD | FFBDAC_CFG_WTCTRL_TE));
422
423 {
424 int limit = 1000000;
425 while (limit--) {
426 unsigned int wtctrl = DACCFG_READ(dac, FFBDAC_CFG_WTCTRL);
427
428 if ((wtctrl & FFBDAC_CFG_WTCTRL_DS) == 0)
429 break;
430 }
431 }
432 #endif
433
434 UNLOCK_HARDWARE(fmesa);
435 }
436
437 static void ffb_init_wid(ffbContextPtr fmesa, unsigned int wid)
438 {
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;
442
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;
447 } else {
448 shadow_dac_addr = FFBDAC_PAC2_SPWLUT(wid);
449 active_dac_addr = FFBDAC_PAC2_APWLUT(wid);
450 dac_db_bit = FFBDAC_PAC2_WLUT_DB;
451 }
452
453 wid_reg_val = DACCFG_READ(dac, active_dac_addr);
454 wid_reg_val &= ~dac_db_bit;
455 #ifdef USE_FAST_SWAP
456 DACCFG_WRITE(dac, active_dac_addr, wid_reg_val);
457 #else
458 DACCFG_WRITE(dac, shadow_dac_addr, wid_reg_val);
459
460 /* Schedule the window transfer. */
461 DACCFG_WRITE(dac, FFBDAC_CFG_WTCTRL,
462 (FFBDAC_CFG_WTCTRL_TCMD | FFBDAC_CFG_WTCTRL_TE));
463
464 {
465 int limit = 1000000;
466 while (limit--) {
467 unsigned int wtctrl = DACCFG_READ(dac, FFBDAC_CFG_WTCTRL);
468
469 if ((wtctrl & FFBDAC_CFG_WTCTRL_DS) == 0)
470 break;
471 }
472 }
473 #endif
474 }
475
476 /* Force the context `c' to be the current context and associate with it
477 buffer `b' */
478 static GLboolean
479 ffbMakeCurrent(__DRIcontextPrivate *driContextPriv,
480 __DRIdrawablePrivate *driDrawPriv,
481 __DRIdrawablePrivate *driReadPriv)
482 {
483 if (driContextPriv) {
484 ffbContextPtr fmesa = (ffbContextPtr) driContextPriv->driverPrivate;
485 int first_time;
486
487 fmesa->driDrawable = driDrawPriv;
488
489 _mesa_make_current2(fmesa->glCtx,
490 (GLframebuffer *) driDrawPriv->driverPrivate,
491 (GLframebuffer *) driReadPriv->driverPrivate);
492
493 if (!fmesa->glCtx->Viewport.Width)
494 _mesa_set_viewport(fmesa->glCtx,
495 0, 0,
496 driDrawPriv->w,
497 driDrawPriv->h);
498
499 first_time = 0;
500 if (fmesa->wid == ~0) {
501 first_time = 1;
502 if (getenv("LIBGL_SOFTWARE_RENDERING"))
503 FALLBACK( fmesa->glCtx, FFB_BADATTR_SWONLY, GL_TRUE );
504 }
505
506 LOCK_HARDWARE(fmesa);
507 if (first_time) {
508 fmesa->wid = fmesa->ffb_sarea->wid_table[driDrawPriv->index];
509 ffb_init_wid(fmesa, fmesa->wid);
510 }
511
512 fmesa->state_dirty |= FFB_STATE_ALL;
513 fmesa->state_fifo_ents = fmesa->state_all_fifo_ents;
514 ffbSyncHardware(fmesa);
515 UNLOCK_HARDWARE(fmesa);
516
517 if (first_time) {
518 /* Also, at the first switch to a new context,
519 * we need to clear all the hw buffers.
520 */
521 ffbDDClear(fmesa->glCtx,
522 (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT |
523 DD_DEPTH_BIT | DD_STENCIL_BIT),
524 1, 0, 0, 0, 0);
525 }
526 } else {
527 _mesa_make_current(NULL, NULL);
528 }
529
530 return GL_TRUE;
531 }
532
533 /* Force the context `c' to be unbound from its buffer */
534 static GLboolean
535 ffbUnbindContext(__DRIcontextPrivate *driContextPriv)
536 {
537 return GL_TRUE;
538 }
539
540 static GLboolean
541 ffbOpenFullScreen(__DRIcontextPrivate *driContextPriv)
542 {
543 return GL_TRUE;
544 }
545
546 static GLboolean
547 ffbCloseFullScreen(__DRIcontextPrivate *driContextPriv)
548 {
549 return GL_TRUE;
550 }
551
552 void ffbXMesaUpdateState(ffbContextPtr fmesa)
553 {
554 __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
555 __DRIscreenPrivate *sPriv = fmesa->driScreen;
556 int stamp = dPriv->lastStamp;
557
558 DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
559
560 if (dPriv->lastStamp != stamp) {
561 GLcontext *ctx = fmesa->glCtx;
562
563 ffbCalcViewport(ctx);
564 if (ctx->Polygon.StippleFlag)
565 ffbXformAreaPattern(fmesa,
566 (const GLubyte *)ctx->PolygonStipple);
567 }
568 }
569
570
571 static struct __DriverAPIRec ffbAPI = {
572 ffbInitDriver,
573 ffbDestroyScreen,
574 ffbCreateContext,
575 ffbDestroyContext,
576 ffbCreateBuffer,
577 ffbDestroyBuffer,
578 ffbSwapBuffers,
579 ffbMakeCurrent,
580 ffbUnbindContext,
581 ffbOpenFullScreen,
582 ffbCloseFullScreen
583 };
584
585
586
587 /*
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.
591 */
592 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
593 int numConfigs, __GLXvisualConfig *config)
594 {
595 __DRIscreenPrivate *psp;
596 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &ffbAPI);
597 return (void *) psp;
598 }
599
600
601 #endif /* GLX_DIRECT_RENDERING */