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