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