~ubuntu-branches/ubuntu/quantal/mesa-glw/quantal

« back to all changes in this revision

Viewing changes to src/mesa/drivers/dri/ffb/ffb_xmesa.c

  • Committer: Bazaar Package Importer
  • Author(s): Morten Kjeldgaard
  • Date: 2008-05-06 16:19:15 UTC
  • Revision ID: james.westby@ubuntu.com-20080506161915-uynz7nftmfixu6bq
Tags: upstream-7.0.3
ImportĀ upstreamĀ versionĀ 7.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "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 hw 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
        /* 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(__DRIcontextPrivate *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(__DRIscreenPrivate *driScrnPriv,
 
330
                __DRIdrawablePrivate *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(GL_RGBA, 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(GL_RGBA, 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(GL_DEPTH_COMPONENT16, 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(GL_STENCIL_INDEX8_EXT, 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(__DRIdrawablePrivate *driDrawPriv)
 
394
{
 
395
   _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
 
396
}
 
397
 
 
398
 
 
399
#define USE_FAST_SWAP
 
400
 
 
401
static void
 
402
ffbSwapBuffers( __DRIdrawablePrivate *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(__DRIcontextPrivate *driContextPriv,
 
534
               __DRIdrawablePrivate *driDrawPriv,
 
535
               __DRIdrawablePrivate *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(__DRIcontextPrivate *driContextPriv)
 
583
{
 
584
        return GL_TRUE;
 
585
}
 
586
 
 
587
void ffbXMesaUpdateState(ffbContextPtr fmesa)
 
588
{
 
589
        __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
 
590
        __DRIscreenPrivate *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 struct __DriverAPIRec ffbAPI = {
 
608
   .InitDriver      = ffbInitDriver,
 
609
   .DestroyScreen   = ffbDestroyScreen,
 
610
   .CreateContext   = ffbCreateContext,
 
611
   .DestroyContext  = ffbDestroyContext,
 
612
   .CreateBuffer    = ffbCreateBuffer,
 
613
   .DestroyBuffer   = ffbDestroyBuffer,
 
614
   .SwapBuffers     = ffbSwapBuffers,
 
615
   .MakeCurrent     = ffbMakeCurrent,
 
616
   .UnbindContext   = ffbUnbindContext,
 
617
   .GetSwapInfo     = NULL,
 
618
   .GetMSC          = NULL,
 
619
   .WaitForMSC      = NULL,
 
620
   .WaitForSBC      = NULL,
 
621
   .SwapBuffersMSC  = NULL
 
622
};
 
623
 
 
624
 
 
625
static __GLcontextModes *
 
626
ffbFillInModes( unsigned pixel_bits, unsigned depth_bits,
 
627
                 unsigned stencil_bits, GLboolean have_back_buffer )
 
628
{
 
629
   __GLcontextModes * modes;
 
630
   __GLcontextModes * m;
 
631
   unsigned num_modes;
 
632
   unsigned depth_buffer_factor;
 
633
   unsigned back_buffer_factor;
 
634
   GLenum fb_format;
 
635
   GLenum fb_type;
 
636
 
 
637
   /* GLX_SWAP_COPY_OML is only supported because the FFB driver doesn't
 
638
    * support pageflipping at all.
 
639
    */
 
640
   static const GLenum back_buffer_modes[] = {
 
641
      GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
 
642
   };
 
643
 
 
644
   u_int8_t depth_bits_array[3];
 
645
   u_int8_t stencil_bits_array[3];
 
646
 
 
647
 
 
648
   depth_bits_array[0] = 0;
 
649
   depth_bits_array[1] = depth_bits;
 
650
   depth_bits_array[2] = depth_bits;
 
651
 
 
652
   /* Just like with the accumulation buffer, always provide some modes
 
653
    * with a stencil buffer.  It will be a sw fallback, but some apps won't
 
654
    * care about that.
 
655
    */
 
656
   stencil_bits_array[0] = 0;
 
657
   stencil_bits_array[1] = 0;
 
658
   stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
 
659
 
 
660
   depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
 
661
   back_buffer_factor  = (have_back_buffer) ? 3 : 1;
 
662
 
 
663
   num_modes = depth_buffer_factor * back_buffer_factor * 4;
 
664
 
 
665
    if ( pixel_bits == 16 ) {
 
666
        fb_format = GL_RGB;
 
667
        fb_type = GL_UNSIGNED_SHORT_5_6_5;
 
668
    }
 
669
    else {
 
670
        fb_format = GL_BGRA;
 
671
        fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
 
672
    }
 
673
 
 
674
   modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) );
 
675
   m = modes;
 
676
   if ( ! driFillInModes( & m, fb_format, fb_type,
 
677
                          depth_bits_array, stencil_bits_array, depth_buffer_factor,
 
678
                          back_buffer_modes, back_buffer_factor,
 
679
                          GLX_TRUE_COLOR ) ) {
 
680
        fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
 
681
                 __func__, __LINE__ );
 
682
        return NULL;
 
683
   }
 
684
   if ( ! driFillInModes( & m, fb_format, fb_type,
 
685
                          depth_bits_array, stencil_bits_array, depth_buffer_factor,
 
686
                          back_buffer_modes, back_buffer_factor,
 
687
                          GLX_DIRECT_COLOR ) ) {
 
688
        fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
 
689
                 __func__, __LINE__ );
 
690
        return NULL;
 
691
   }
 
692
 
 
693
 
 
694
   /* Mark the visual as slow if there are "fake" stencil bits.
 
695
    */
 
696
   for ( m = modes ; m != NULL ; m = m->next ) {
 
697
      if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
 
698
         m->visualRating = GLX_SLOW_CONFIG;
 
699
      }
 
700
   }
 
701
 
 
702
   return modes;
 
703
}
 
704
 
 
705
 
 
706
/**
 
707
 * This is the bootstrap function for the driver.  libGL supplies all of the
 
708
 * requisite information about the system, and the driver initializes itself.
 
709
 * This routine also fills in the linked list pointed to by \c driver_modes
 
710
 * with the \c __GLcontextModes that the driver can support for windows or
 
711
 * pbuffers.
 
712
 * 
 
713
 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on 
 
714
 *         failure.
 
715
 */
 
716
PUBLIC
 
717
void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
 
718
                             const __GLcontextModes * modes,
 
719
                             const __DRIversion * ddx_version,
 
720
                             const __DRIversion * dri_version,
 
721
                             const __DRIversion * drm_version,
 
722
                             const __DRIframebuffer * frame_buffer,
 
723
                             drmAddress pSAREA, int fd, 
 
724
                             int internal_api_version,
 
725
                             const __DRIinterfaceMethods * interface,
 
726
                             __GLcontextModes ** driver_modes )
 
727
                             
 
728
{
 
729
   __DRIscreenPrivate *psp;
 
730
   static const __DRIversion ddx_expected = { 0, 1, 1 };
 
731
   static const __DRIversion dri_expected = { 4, 0, 0 };
 
732
   static const __DRIversion drm_expected = { 0, 0, 1 };
 
733
 
 
734
   dri_interface = interface;
 
735
 
 
736
   if ( ! driCheckDriDdxDrmVersions2( "ffb",
 
737
                                      dri_version, & dri_expected,
 
738
                                      ddx_version, & ddx_expected,
 
739
                                      drm_version, & drm_expected ) ) {
 
740
      return NULL;
 
741
   }
 
742
 
 
743
   psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
 
744
                                  ddx_version, dri_version, drm_version,
 
745
                                  frame_buffer, pSAREA, fd,
 
746
                                  internal_api_version, &ffbAPI);
 
747
   if ( psp != NULL ) {
 
748
      *driver_modes = ffbFillInModes( 32, 16, 0, GL_TRUE );
 
749
   }
 
750
 
 
751
   return (void *) psp;
 
752
}