All elements of pre-DRI_NEW_INTERFACE_ONLY are removed. This allows
[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 #include "ffb_xmesa.h"
29 #include "context.h"
30 #include "framebuffer.h"
31 #include "matrix.h"
32 #include "renderbuffer.h"
33 #include "simple_list.h"
34 #include "imports.h"
35 #include "utils.h"
36
37 #include "swrast/swrast.h"
38 #include "swrast_setup/swrast_setup.h"
39 #include "tnl/tnl.h"
40 #include "tnl/t_pipeline.h"
41 #include "array_cache/acache.h"
42 #include "drivers/common/driverfuncs.h"
43
44 #include "ffb_context.h"
45 #include "ffb_dd.h"
46 #include "ffb_span.h"
47 #include "ffb_depth.h"
48 #include "ffb_stencil.h"
49 #include "ffb_clear.h"
50 #include "ffb_vb.h"
51 #include "ffb_tris.h"
52 #include "ffb_lines.h"
53 #include "ffb_points.h"
54 #include "ffb_state.h"
55 #include "ffb_tex.h"
56 #include "ffb_lock.h"
57 #include "ffb_vtxfmt.h"
58 #include "ffb_bitmap.h"
59
60 #include "drm_sarea.h"
61
62 static GLboolean
63 ffbInitDriver(__DRIscreenPrivate *sPriv)
64 {
65 ffbScreenPrivate *ffbScreen;
66 FFBDRIPtr gDRIPriv = (FFBDRIPtr) sPriv->pDevPriv;
67
68 if (getenv("LIBGL_FORCE_XSERVER"))
69 return GL_FALSE;
70
71 /* Allocate the private area. */
72 ffbScreen = (ffbScreenPrivate *) MALLOC(sizeof(ffbScreenPrivate));
73 if (!ffbScreen)
74 return GL_FALSE;
75
76 /* Map FBC registers. */
77 if (drmMap(sPriv->fd,
78 gDRIPriv->hFbcRegs,
79 gDRIPriv->sFbcRegs,
80 &gDRIPriv->mFbcRegs)) {
81 FREE(ffbScreen);
82 return GL_FALSE;
83 }
84 ffbScreen->regs = (ffb_fbcPtr) gDRIPriv->mFbcRegs;
85
86 /* Map ramdac registers. */
87 if (drmMap(sPriv->fd,
88 gDRIPriv->hDacRegs,
89 gDRIPriv->sDacRegs,
90 &gDRIPriv->mDacRegs)) {
91 drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
92 FREE(ffbScreen);
93 return GL_FALSE;
94 }
95 ffbScreen->dac = (ffb_dacPtr) gDRIPriv->mDacRegs;
96
97 /* Map "Smart" framebuffer views. */
98 if (drmMap(sPriv->fd,
99 gDRIPriv->hSfb8r,
100 gDRIPriv->sSfb8r,
101 &gDRIPriv->mSfb8r)) {
102 drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
103 drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs);
104 FREE(ffbScreen);
105 return GL_FALSE;
106 }
107 ffbScreen->sfb8r = (volatile char *) gDRIPriv->mSfb8r;
108
109 if (drmMap(sPriv->fd,
110 gDRIPriv->hSfb32,
111 gDRIPriv->sSfb32,
112 &gDRIPriv->mSfb32)) {
113 drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
114 drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs);
115 drmUnmap(gDRIPriv->mSfb8r, gDRIPriv->sSfb8r);
116 FREE(ffbScreen);
117 return GL_FALSE;
118 }
119 ffbScreen->sfb32 = (volatile char *) gDRIPriv->mSfb32;
120
121 if (drmMap(sPriv->fd,
122 gDRIPriv->hSfb64,
123 gDRIPriv->sSfb64,
124 &gDRIPriv->mSfb64)) {
125 drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
126 drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs);
127 drmUnmap(gDRIPriv->mSfb8r, gDRIPriv->sSfb8r);
128 drmUnmap(gDRIPriv->mSfb32, gDRIPriv->sSfb32);
129 FREE(ffbScreen);
130 return GL_FALSE;
131 }
132 ffbScreen->sfb64 = (volatile char *) gDRIPriv->mSfb64;
133
134 ffbScreen->fifo_cache = 0;
135 ffbScreen->rp_active = 0;
136
137 ffbScreen->sPriv = sPriv;
138 sPriv->private = (void *) ffbScreen;
139
140 ffbDDLinefuncInit();
141 ffbDDPointfuncInit();
142
143 return GL_TRUE;
144 }
145
146
147 static void
148 ffbDestroyScreen(__DRIscreenPrivate *sPriv)
149 {
150 ffbScreenPrivate *ffbScreen = sPriv->private;
151 FFBDRIPtr gDRIPriv = (FFBDRIPtr) sPriv->pDevPriv;
152
153 drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
154 drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs);
155 drmUnmap(gDRIPriv->mSfb8r, gDRIPriv->sSfb8r);
156 drmUnmap(gDRIPriv->mSfb32, gDRIPriv->sSfb32);
157 drmUnmap(gDRIPriv->mSfb64, gDRIPriv->sSfb64);
158
159 FREE(ffbScreen);
160 }
161
162 static const struct tnl_pipeline_stage *ffb_pipeline[] = {
163 &_tnl_vertex_transform_stage,
164 &_tnl_normal_transform_stage,
165 &_tnl_lighting_stage,
166 /* REMOVE: fog coord stage */
167 &_tnl_texgen_stage,
168 &_tnl_texture_transform_stage,
169 /* REMOVE: point attenuation stage */
170 &_tnl_render_stage,
171 0,
172 };
173
174 /* Create and initialize the Mesa and driver specific context data */
175 static GLboolean
176 ffbCreateContext(const __GLcontextModes *mesaVis,
177 __DRIcontextPrivate *driContextPriv,
178 void *sharedContextPrivate)
179 {
180 ffbContextPtr fmesa;
181 GLcontext *ctx, *shareCtx;
182 __DRIscreenPrivate *sPriv;
183 ffbScreenPrivate *ffbScreen;
184 char *debug;
185 struct dd_function_table functions;
186
187 /* Allocate ffb context */
188 fmesa = (ffbContextPtr) CALLOC(sizeof(ffbContextRec));
189 if (!fmesa)
190 return GL_FALSE;
191
192 _mesa_init_driver_functions(&functions);
193
194 /* Allocate Mesa context */
195 if (sharedContextPrivate)
196 shareCtx = ((ffbContextPtr) sharedContextPrivate)->glCtx;
197 else
198 shareCtx = NULL;
199 fmesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
200 &functions, fmesa);
201 if (!fmesa->glCtx) {
202 FREE(fmesa);
203 return GL_FALSE;
204 }
205 driContextPriv->driverPrivate = fmesa;
206 ctx = fmesa->glCtx;
207
208 sPriv = driContextPriv->driScreenPriv;
209 ffbScreen = (ffbScreenPrivate *) sPriv->private;
210
211 /* Dri stuff. */
212 fmesa->hHWContext = driContextPriv->hHWContext;
213 fmesa->driFd = sPriv->fd;
214 fmesa->driHwLock = &sPriv->pSAREA->lock;
215
216 fmesa->ffbScreen = ffbScreen;
217 fmesa->driScreen = sPriv;
218 fmesa->ffb_sarea = FFB_DRISHARE(sPriv->pSAREA);
219
220 /* Register and framebuffer hw pointers. */
221 fmesa->regs = ffbScreen->regs;
222 fmesa->sfb32 = ffbScreen->sfb32;
223
224 ffbDDInitContextHwState(ctx);
225
226 /* Default clear and depth colors. */
227 {
228 GLubyte r = (GLint) (ctx->Color.ClearColor[0] * 255.0F);
229 GLubyte g = (GLint) (ctx->Color.ClearColor[1] * 255.0F);
230 GLubyte b = (GLint) (ctx->Color.ClearColor[2] * 255.0F);
231
232 fmesa->clear_pixel = ((r << 0) |
233 (g << 8) |
234 (b << 16));
235 }
236 fmesa->clear_depth = Z_FROM_MESA(ctx->Depth.Clear * 4294967295.0f);
237 fmesa->clear_stencil = ctx->Stencil.Clear & 0xf;
238
239 /* No wide points. */
240 ctx->Const.MinPointSize = 1.0;
241 ctx->Const.MinPointSizeAA = 1.0;
242 ctx->Const.MaxPointSize = 1.0;
243 ctx->Const.MaxPointSizeAA = 1.0;
244
245 /* Disable wide lines as we can't antialias them correctly in
246 * hardware.
247 */
248 ctx->Const.MinLineWidth = 1.0;
249 ctx->Const.MinLineWidthAA = 1.0;
250 ctx->Const.MaxLineWidth = 1.0;
251 ctx->Const.MaxLineWidthAA = 1.0;
252 ctx->Const.LineWidthGranularity = 1.0;
253
254 /* Instead of having GCC emit these constants a zillion times
255 * everywhere in the driver, put them here.
256 */
257 fmesa->ffb_2_30_fixed_scale = __FFB_2_30_FIXED_SCALE;
258 fmesa->ffb_one_over_2_30_fixed_scale = (1.0 / __FFB_2_30_FIXED_SCALE);
259 fmesa->ffb_16_16_fixed_scale = __FFB_16_16_FIXED_SCALE;
260 fmesa->ffb_one_over_16_16_fixed_scale = (1.0 / __FFB_16_16_FIXED_SCALE);
261 fmesa->ffb_ubyte_color_scale = 255.0f;
262 fmesa->ffb_zero = 0.0f;
263
264 fmesa->debugFallbacks = GL_FALSE;
265 debug = getenv("LIBGL_DEBUG");
266 if (debug && strstr(debug, "fallbacks"))
267 fmesa->debugFallbacks = GL_TRUE;
268
269 /* Initialize the software rasterizer and helper modules. */
270 _swrast_CreateContext( ctx );
271 _ac_CreateContext( ctx );
272 _tnl_CreateContext( ctx );
273 _swsetup_CreateContext( ctx );
274
275 /* All of this need only be done once for a new context. */
276 /* XXX these should be moved right after the
277 * _mesa_init_driver_functions() call above.
278 */
279 ffbDDExtensionsInit(ctx);
280 ffbDDInitDriverFuncs(ctx);
281 ffbDDInitStateFuncs(ctx);
282 ffbDDInitRenderFuncs(ctx);
283 /*ffbDDInitTexFuncs(ctx); not needed */
284 ffbDDInitBitmapFuncs(ctx);
285 ffbInitVB(ctx);
286
287 #if 0
288 ffbInitTnlModule(ctx);
289 #endif
290
291 _tnl_destroy_pipeline(ctx);
292 _tnl_install_pipeline(ctx, ffb_pipeline);
293
294 return GL_TRUE;
295 }
296
297 static void
298 ffbDestroyContext(__DRIcontextPrivate *driContextPriv)
299 {
300 ffbContextPtr fmesa = (ffbContextPtr) driContextPriv->driverPrivate;
301
302 if (fmesa) {
303 ffbFreeVB(fmesa->glCtx);
304
305 _swsetup_DestroyContext( fmesa->glCtx );
306 _tnl_DestroyContext( fmesa->glCtx );
307 _ac_DestroyContext( fmesa->glCtx );
308 _swrast_DestroyContext( fmesa->glCtx );
309
310 /* free the Mesa context */
311 fmesa->glCtx->DriverCtx = NULL;
312 _mesa_destroy_context(fmesa->glCtx);
313
314 FREE(fmesa);
315 }
316 }
317
318 /* Create and initialize the Mesa and driver specific pixmap buffer data */
319 static GLboolean
320 ffbCreateBuffer(__DRIscreenPrivate *driScrnPriv,
321 __DRIdrawablePrivate *driDrawPriv,
322 const __GLcontextModes *mesaVis,
323 GLboolean isPixmap )
324 {
325 /* Mesa checks for pitch > 0, but ffb doesn't use pitches */
326 int bogusPitch = 1;
327 int bpp = 4; /* we've always got a 32bpp framebuffer */
328 int offset = 0; /* always at 0 for offset */
329
330 if (isPixmap) {
331 return GL_FALSE; /* not implemented */
332 } else {
333 GLboolean swStencil = (mesaVis->stencilBits > 0 &&
334 mesaVis->depthBits != 24);
335 #if 0
336 driDrawPriv->driverPrivate = (void *)
337 _mesa_create_framebuffer(mesaVis,
338 GL_FALSE, /* software depth buffer? */
339 mesaVis->stencilBits > 0,
340 mesaVis->accumRedBits > 0,
341 mesaVis->alphaBits > 0);
342 #else
343 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
344
345 {
346 driRenderbuffer *frontRb
347 = driNewRenderbuffer(GL_RGBA, bpp, offset, bogusPitch);
348 ffbSetSpanFunctions(frontRb, mesaVis);
349 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
350 }
351
352 if (mesaVis->doubleBufferMode) {
353 driRenderbuffer *backRb
354 = driNewRenderbuffer(GL_RGBA, bpp, offset, bogusPitch);
355 ffbSetSpanFunctions(backRb, mesaVis);
356 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
357 }
358
359 if (mesaVis->depthBits == 16) {
360 driRenderbuffer *depthRb
361 = driNewRenderbuffer(GL_DEPTH_COMPONENT16, bpp, offset, bogusPitch);
362 ffbSetDepthFunctions(depthRb, mesaVis);
363 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
364 }
365
366 if (mesaVis->stencilBits > 0 && !swStencil) {
367 driRenderbuffer *stencilRb
368 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT, bpp, offset,bogusPitch);
369 ffbSetStencilFunctions(stencilRb, mesaVis);
370 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
371 }
372
373 _mesa_add_soft_renderbuffers(fb,
374 GL_FALSE, /* color */
375 GL_FALSE, /* depth */
376 swStencil,
377 mesaVis->accumRedBits > 0,
378 GL_FALSE, /* alpha */
379 GL_FALSE /* aux */);
380 driDrawPriv->driverPrivate = (void *) fb;
381 #endif
382 return (driDrawPriv->driverPrivate != NULL);
383 }
384 }
385
386
387 static void
388 ffbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
389 {
390 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
391 }
392
393
394 #define USE_FAST_SWAP
395
396 static void
397 ffbSwapBuffers( __DRIdrawablePrivate *dPriv )
398 {
399 ffbContextPtr fmesa = (ffbContextPtr) dPriv->driContextPriv->driverPrivate;
400 unsigned int fbc, wid, wid_reg_val, dac_db_bit;
401 unsigned int shadow_dac_addr, active_dac_addr;
402 ffb_fbcPtr ffb;
403 ffb_dacPtr dac;
404
405 if (fmesa == NULL ||
406 fmesa->glCtx->Visual.doubleBufferMode == 0)
407 return;
408
409 /* Flush pending rendering commands */
410 _mesa_notifySwapBuffers(fmesa->glCtx);
411
412 ffb = fmesa->regs;
413 dac = fmesa->ffbScreen->dac;
414
415 fbc = fmesa->fbc;
416 wid = fmesa->wid;
417
418 /* Swap the buffer we render into and read pixels from. */
419 fmesa->back_buffer ^= 1;
420
421 /* If we are writing into both buffers, don't mess with
422 * the WB setting.
423 */
424 if ((fbc & FFB_FBC_WB_AB) != FFB_FBC_WB_AB) {
425 if ((fbc & FFB_FBC_WB_A) != 0)
426 fbc = (fbc & ~FFB_FBC_WB_A) | FFB_FBC_WB_B;
427 else
428 fbc = (fbc & ~FFB_FBC_WB_B) | FFB_FBC_WB_A;
429 }
430
431 /* But either way, we must flip the read buffer setting. */
432 if ((fbc & FFB_FBC_RB_A) != 0)
433 fbc = (fbc & ~FFB_FBC_RB_A) | FFB_FBC_RB_B;
434 else
435 fbc = (fbc & ~FFB_FBC_RB_B) | FFB_FBC_RB_A;
436
437 LOCK_HARDWARE(fmesa);
438
439 if (fmesa->fbc != fbc) {
440 FFBFifo(fmesa, 1);
441 ffb->fbc = fmesa->fbc = fbc;
442 fmesa->ffbScreen->rp_active = 1;
443 }
444
445 /* And swap the buffer displayed in the WID. */
446 if (fmesa->ffb_sarea->flags & FFB_DRI_PAC1) {
447 shadow_dac_addr = FFBDAC_PAC1_SPWLUT(wid);
448 active_dac_addr = FFBDAC_PAC1_APWLUT(wid);
449 dac_db_bit = FFBDAC_PAC1_WLUT_DB;
450 } else {
451 shadow_dac_addr = FFBDAC_PAC2_SPWLUT(wid);
452 active_dac_addr = FFBDAC_PAC2_APWLUT(wid);
453 dac_db_bit = FFBDAC_PAC2_WLUT_DB;
454 }
455
456 FFBWait(fmesa, ffb);
457
458 wid_reg_val = DACCFG_READ(dac, active_dac_addr);
459 if (fmesa->back_buffer == 0)
460 wid_reg_val |= dac_db_bit;
461 else
462 wid_reg_val &= ~dac_db_bit;
463 #ifdef USE_FAST_SWAP
464 DACCFG_WRITE(dac, active_dac_addr, wid_reg_val);
465 #else
466 DACCFG_WRITE(dac, shadow_dac_addr, wid_reg_val);
467
468 /* Schedule the window transfer. */
469 DACCFG_WRITE(dac, FFBDAC_CFG_WTCTRL,
470 (FFBDAC_CFG_WTCTRL_TCMD | FFBDAC_CFG_WTCTRL_TE));
471
472 {
473 int limit = 1000000;
474 while (limit--) {
475 unsigned int wtctrl = DACCFG_READ(dac, FFBDAC_CFG_WTCTRL);
476
477 if ((wtctrl & FFBDAC_CFG_WTCTRL_DS) == 0)
478 break;
479 }
480 }
481 #endif
482
483 UNLOCK_HARDWARE(fmesa);
484 }
485
486 static void ffb_init_wid(ffbContextPtr fmesa, unsigned int wid)
487 {
488 ffb_dacPtr dac = fmesa->ffbScreen->dac;
489 unsigned int wid_reg_val, dac_db_bit, active_dac_addr;
490 unsigned int shadow_dac_addr;
491
492 if (fmesa->ffb_sarea->flags & FFB_DRI_PAC1) {
493 shadow_dac_addr = FFBDAC_PAC1_SPWLUT(wid);
494 active_dac_addr = FFBDAC_PAC1_APWLUT(wid);
495 dac_db_bit = FFBDAC_PAC1_WLUT_DB;
496 } else {
497 shadow_dac_addr = FFBDAC_PAC2_SPWLUT(wid);
498 active_dac_addr = FFBDAC_PAC2_APWLUT(wid);
499 dac_db_bit = FFBDAC_PAC2_WLUT_DB;
500 }
501
502 wid_reg_val = DACCFG_READ(dac, active_dac_addr);
503 wid_reg_val &= ~dac_db_bit;
504 #ifdef USE_FAST_SWAP
505 DACCFG_WRITE(dac, active_dac_addr, wid_reg_val);
506 #else
507 DACCFG_WRITE(dac, shadow_dac_addr, wid_reg_val);
508
509 /* Schedule the window transfer. */
510 DACCFG_WRITE(dac, FFBDAC_CFG_WTCTRL,
511 (FFBDAC_CFG_WTCTRL_TCMD | FFBDAC_CFG_WTCTRL_TE));
512
513 {
514 int limit = 1000000;
515 while (limit--) {
516 unsigned int wtctrl = DACCFG_READ(dac, FFBDAC_CFG_WTCTRL);
517
518 if ((wtctrl & FFBDAC_CFG_WTCTRL_DS) == 0)
519 break;
520 }
521 }
522 #endif
523 }
524
525 /* Force the context `c' to be the current context and associate with it
526 buffer `b' */
527 static GLboolean
528 ffbMakeCurrent(__DRIcontextPrivate *driContextPriv,
529 __DRIdrawablePrivate *driDrawPriv,
530 __DRIdrawablePrivate *driReadPriv)
531 {
532 if (driContextPriv) {
533 ffbContextPtr fmesa = (ffbContextPtr) driContextPriv->driverPrivate;
534 int first_time;
535
536 fmesa->driDrawable = driDrawPriv;
537
538 _mesa_make_current(fmesa->glCtx,
539 (GLframebuffer *) driDrawPriv->driverPrivate,
540 (GLframebuffer *) driReadPriv->driverPrivate);
541
542 first_time = 0;
543 if (fmesa->wid == ~0) {
544 first_time = 1;
545 if (getenv("LIBGL_SOFTWARE_RENDERING"))
546 FALLBACK( fmesa->glCtx, FFB_BADATTR_SWONLY, GL_TRUE );
547 }
548
549 LOCK_HARDWARE(fmesa);
550 if (first_time) {
551 fmesa->wid = fmesa->ffb_sarea->wid_table[driDrawPriv->index];
552 ffb_init_wid(fmesa, fmesa->wid);
553 }
554
555 fmesa->state_dirty |= FFB_STATE_ALL;
556 fmesa->state_fifo_ents = fmesa->state_all_fifo_ents;
557 ffbSyncHardware(fmesa);
558 UNLOCK_HARDWARE(fmesa);
559
560 if (first_time) {
561 /* Also, at the first switch to a new context,
562 * we need to clear all the hw buffers.
563 */
564 ffbDDClear(fmesa->glCtx,
565 (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT |
566 BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL),
567 1, 0, 0, 0, 0);
568 }
569 } else {
570 _mesa_make_current(NULL, NULL, NULL);
571 }
572
573 return GL_TRUE;
574 }
575
576 /* Force the context `c' to be unbound from its buffer */
577 static GLboolean
578 ffbUnbindContext(__DRIcontextPrivate *driContextPriv)
579 {
580 return GL_TRUE;
581 }
582
583 void ffbXMesaUpdateState(ffbContextPtr fmesa)
584 {
585 __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
586 __DRIscreenPrivate *sPriv = fmesa->driScreen;
587 int stamp = dPriv->lastStamp;
588
589 DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
590
591 if (dPriv->lastStamp != stamp) {
592 GLcontext *ctx = fmesa->glCtx;
593
594 ffbCalcViewport(ctx);
595 if (ctx->Polygon.StippleFlag)
596 ffbXformAreaPattern(fmesa,
597 (const GLubyte *)ctx->PolygonStipple);
598 }
599 }
600
601 static const struct __DriverAPIRec ffbAPI = {
602 .InitDriver = ffbInitDriver,
603 .DestroyScreen = ffbDestroyScreen,
604 .CreateContext = ffbCreateContext,
605 .DestroyContext = ffbDestroyContext,
606 .CreateBuffer = ffbCreateBuffer,
607 .DestroyBuffer = ffbDestroyBuffer,
608 .SwapBuffers = ffbSwapBuffers,
609 .MakeCurrent = ffbMakeCurrent,
610 .UnbindContext = ffbUnbindContext,
611 .GetSwapInfo = NULL,
612 .GetMSC = NULL,
613 .WaitForMSC = NULL,
614 .WaitForSBC = NULL,
615 .SwapBuffersMSC = NULL
616 };
617
618
619 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
620
621 static __GLcontextModes *
622 ffbFillInModes( unsigned pixel_bits, unsigned depth_bits,
623 unsigned stencil_bits, GLboolean have_back_buffer )
624 {
625 __GLcontextModes * modes;
626 __GLcontextModes * m;
627 unsigned num_modes;
628 unsigned depth_buffer_factor;
629 unsigned back_buffer_factor;
630 GLenum fb_format;
631 GLenum fb_type;
632
633 /* GLX_SWAP_COPY_OML is only supported because the FFB driver doesn't
634 * support pageflipping at all.
635 */
636 static const GLenum back_buffer_modes[] = {
637 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
638 };
639
640 u_int8_t depth_bits_array[3];
641 u_int8_t stencil_bits_array[3];
642
643
644 depth_bits_array[0] = 0;
645 depth_bits_array[1] = depth_bits;
646 depth_bits_array[2] = depth_bits;
647
648 /* Just like with the accumulation buffer, always provide some modes
649 * with a stencil buffer. It will be a sw fallback, but some apps won't
650 * care about that.
651 */
652 stencil_bits_array[0] = 0;
653 stencil_bits_array[1] = 0;
654 stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
655
656 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
657 back_buffer_factor = (have_back_buffer) ? 3 : 1;
658
659 num_modes = depth_buffer_factor * back_buffer_factor * 4;
660
661 if ( pixel_bits == 16 ) {
662 fb_format = GL_RGB;
663 fb_type = GL_UNSIGNED_SHORT_5_6_5;
664 }
665 else {
666 fb_format = GL_BGRA;
667 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
668 }
669
670 modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
671 m = modes;
672 if ( ! driFillInModes( & m, fb_format, fb_type,
673 depth_bits_array, stencil_bits_array, depth_buffer_factor,
674 back_buffer_modes, back_buffer_factor,
675 GLX_TRUE_COLOR ) ) {
676 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
677 __func__, __LINE__ );
678 return NULL;
679 }
680 if ( ! driFillInModes( & m, fb_format, fb_type,
681 depth_bits_array, stencil_bits_array, depth_buffer_factor,
682 back_buffer_modes, back_buffer_factor,
683 GLX_DIRECT_COLOR ) ) {
684 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
685 __func__, __LINE__ );
686 return NULL;
687 }
688
689
690 /* Mark the visual as slow if there are "fake" stencil bits.
691 */
692 for ( m = modes ; m != NULL ; m = m->next ) {
693 if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
694 m->visualRating = GLX_SLOW_CONFIG;
695 }
696 }
697
698 return modes;
699 }
700
701
702 /**
703 * This is the bootstrap function for the driver. libGL supplies all of the
704 * requisite information about the system, and the driver initializes itself.
705 * This routine also fills in the linked list pointed to by \c driver_modes
706 * with the \c __GLcontextModes that the driver can support for windows or
707 * pbuffers.
708 *
709 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
710 * failure.
711 */
712 PUBLIC
713 void * __driCreateNewScreen_20050722( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
714 const __GLcontextModes * modes,
715 const __DRIversion * ddx_version,
716 const __DRIversion * dri_version,
717 const __DRIversion * drm_version,
718 const __DRIframebuffer * frame_buffer,
719 drmAddress pSAREA, int fd,
720 int internal_api_version,
721 __GLcontextModes ** driver_modes )
722
723 {
724 __DRIscreenPrivate *psp;
725 static const __DRIversion ddx_expected = { 0, 0, 1 };
726 static const __DRIversion dri_expected = { 4, 0, 0 };
727 static const __DRIversion drm_expected = { 0, 0, 1 };
728
729 if ( ! driCheckDriDdxDrmVersions2( "ffb",
730 dri_version, & dri_expected,
731 ddx_version, & ddx_expected,
732 drm_version, & drm_expected ) ) {
733 return NULL;
734 }
735
736 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
737 ddx_version, dri_version, drm_version,
738 frame_buffer, pSAREA, fd,
739 internal_api_version, &ffbAPI);
740 if ( psp != NULL ) {
741 create_context_modes = (PFNGLXCREATECONTEXTMODES)
742 glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
743 if ( create_context_modes != NULL ) {
744 *driver_modes = ffbFillInModes( 32, 16, 0, GL_TRUE );
745 }
746 }
747
748 return (void *) psp;
749 }