r128_dri.c revision c582b7e3
1c582b7e3Smrg/*
2c582b7e3Smrg * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
3c582b7e3Smrg *                      Precision Insight, Inc., Cedar Park, Texas, and
4c582b7e3Smrg *                      VA Linux Systems Inc., Fremont, California.
5c582b7e3Smrg *
6c582b7e3Smrg * All Rights Reserved.
7c582b7e3Smrg *
8c582b7e3Smrg * Permission is hereby granted, free of charge, to any person obtaining
9c582b7e3Smrg * a copy of this software and associated documentation files (the
10c582b7e3Smrg * "Software"), to deal in the Software without restriction, including
11c582b7e3Smrg * without limitation on the rights to use, copy, modify, merge,
12c582b7e3Smrg * publish, distribute, sublicense, and/or sell copies of the Software,
13c582b7e3Smrg * and to permit persons to whom the Software is furnished to do so,
14c582b7e3Smrg * subject to the following conditions:
15c582b7e3Smrg *
16c582b7e3Smrg * The above copyright notice and this permission notice (including the
17c582b7e3Smrg * next paragraph) shall be included in all copies or substantial
18c582b7e3Smrg * portions of the Software.
19c582b7e3Smrg *
20c582b7e3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21c582b7e3Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22c582b7e3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23c582b7e3Smrg * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
24c582b7e3Smrg * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25c582b7e3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26c582b7e3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27c582b7e3Smrg * OTHER DEALINGS IN THE SOFTWARE.
28c582b7e3Smrg */
29c582b7e3Smrg
30c582b7e3Smrg#ifdef HAVE_CONFIG_H
31c582b7e3Smrg#include "config.h"
32c582b7e3Smrg#endif
33c582b7e3Smrg
34c582b7e3Smrg#include <string.h>
35c582b7e3Smrg#include <stdio.h>
36c582b7e3Smrg
37c582b7e3Smrg/*
38c582b7e3Smrg * Authors:
39c582b7e3Smrg *   Kevin E. Martin <martin@valinux.com>
40c582b7e3Smrg *   Rickard E. Faith <faith@valinux.com>
41c582b7e3Smrg *   Daryll Strauss <daryll@valinux.com>
42c582b7e3Smrg *   Gareth Hughes <gareth@valinux.com>
43c582b7e3Smrg *
44c582b7e3Smrg */
45c582b7e3Smrg
46c582b7e3Smrg				/* Driver data structures */
47c582b7e3Smrg#include "r128.h"
48c582b7e3Smrg#include "r128_dri.h"
49c582b7e3Smrg#include "r128_common.h"
50c582b7e3Smrg#include "r128_reg.h"
51c582b7e3Smrg#include "r128_sarea.h"
52c582b7e3Smrg#include "r128_version.h"
53c582b7e3Smrg
54c582b7e3Smrg				/* X and server generic header files */
55c582b7e3Smrg#include "xf86.h"
56c582b7e3Smrg#include "xf86PciInfo.h"
57c582b7e3Smrg#include "windowstr.h"
58c582b7e3Smrg
59c582b7e3Smrg#include "shadowfb.h"
60c582b7e3Smrg				/* GLX/DRI/DRM definitions */
61c582b7e3Smrg#define _XF86DRI_SERVER_
62c582b7e3Smrg#include "GL/glxtokens.h"
63c582b7e3Smrg#include "sarea.h"
64c582b7e3Smrg
65c582b7e3Smrgstatic size_t r128_drm_page_size;
66c582b7e3Smrg
67c582b7e3Smrgstatic void R128DRITransitionTo2d(ScreenPtr pScreen);
68c582b7e3Smrgstatic void R128DRITransitionTo3d(ScreenPtr pScreen);
69c582b7e3Smrgstatic void R128DRITransitionMultiToSingle3d(ScreenPtr pScreen);
70c582b7e3Smrgstatic void R128DRITransitionSingleToMulti3d(ScreenPtr pScreen);
71c582b7e3Smrg
72c582b7e3Smrgstatic void R128DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
73c582b7e3Smrg
74c582b7e3Smrg/* Initialize the visual configs that are supported by the hardware.
75c582b7e3Smrg   These are combined with the visual configs that the indirect
76c582b7e3Smrg   rendering core supports, and the intersection is exported to the
77c582b7e3Smrg   client. */
78c582b7e3Smrgstatic Bool R128InitVisualConfigs(ScreenPtr pScreen)
79c582b7e3Smrg{
80c582b7e3Smrg    ScrnInfoPtr       pScrn            = xf86Screens[pScreen->myNum];
81c582b7e3Smrg    R128InfoPtr       info             = R128PTR(pScrn);
82c582b7e3Smrg    int               numConfigs       = 0;
83c582b7e3Smrg    __GLXvisualConfig *pConfigs        = NULL;
84c582b7e3Smrg    R128ConfigPrivPtr pR128Configs     = NULL;
85c582b7e3Smrg    R128ConfigPrivPtr *pR128ConfigPtrs = NULL;
86c582b7e3Smrg    int               i, accum, stencil, db;
87c582b7e3Smrg
88c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
89c582b7e3Smrg    case 8:  /* 8bpp mode is not support */
90c582b7e3Smrg    case 15: /* FIXME */
91c582b7e3Smrg    case 24: /* FIXME */
92c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
93c582b7e3Smrg		   "[dri] R128DRIScreenInit failed (depth %d not supported).  "
94c582b7e3Smrg		   "Disabling DRI.\n", info->CurrentLayout.pixel_code);
95c582b7e3Smrg	return FALSE;
96c582b7e3Smrg
97c582b7e3Smrg#define R128_USE_ACCUM   1
98c582b7e3Smrg#define R128_USE_STENCIL 1
99c582b7e3Smrg#define R128_USE_DB      1
100c582b7e3Smrg
101c582b7e3Smrg    case 16:
102c582b7e3Smrg	numConfigs = 1;
103c582b7e3Smrg	if (R128_USE_ACCUM)   numConfigs *= 2;
104c582b7e3Smrg	if (R128_USE_STENCIL) numConfigs *= 2;
105c582b7e3Smrg	if (R128_USE_DB)      numConfigs *= 2;
106c582b7e3Smrg
107c582b7e3Smrg	if (!(pConfigs
108c582b7e3Smrg	      = (__GLXvisualConfig*)xcalloc(sizeof(__GLXvisualConfig),
109c582b7e3Smrg					      numConfigs))) {
110c582b7e3Smrg	    return FALSE;
111c582b7e3Smrg	}
112c582b7e3Smrg	if (!(pR128Configs
113c582b7e3Smrg	      = (R128ConfigPrivPtr)xcalloc(sizeof(R128ConfigPrivRec),
114c582b7e3Smrg					     numConfigs))) {
115c582b7e3Smrg	    xfree(pConfigs);
116c582b7e3Smrg	    return FALSE;
117c582b7e3Smrg	}
118c582b7e3Smrg	if (!(pR128ConfigPtrs
119c582b7e3Smrg	      = (R128ConfigPrivPtr*)xcalloc(sizeof(R128ConfigPrivPtr),
120c582b7e3Smrg					      numConfigs))) {
121c582b7e3Smrg	    xfree(pConfigs);
122c582b7e3Smrg	    xfree(pR128Configs);
123c582b7e3Smrg	    return FALSE;
124c582b7e3Smrg	}
125c582b7e3Smrg
126c582b7e3Smrg	i = 0;
127c582b7e3Smrg	for (db = 0; db <= R128_USE_DB; db++) {
128c582b7e3Smrg	  for (accum = 0; accum <= R128_USE_ACCUM; accum++) {
129c582b7e3Smrg	    for (stencil = 0; stencil <= R128_USE_STENCIL; stencil++) {
130c582b7e3Smrg		pR128ConfigPtrs[i] = &pR128Configs[i];
131c582b7e3Smrg
132c582b7e3Smrg		pConfigs[i].vid                = (VisualID)(-1);
133c582b7e3Smrg		pConfigs[i].class              = -1;
134c582b7e3Smrg		pConfigs[i].rgba               = TRUE;
135c582b7e3Smrg		pConfigs[i].redSize            = 5;
136c582b7e3Smrg		pConfigs[i].greenSize          = 6;
137c582b7e3Smrg		pConfigs[i].blueSize           = 5;
138c582b7e3Smrg		pConfigs[i].alphaSize          = 0;
139c582b7e3Smrg		pConfigs[i].redMask            = 0x0000F800;
140c582b7e3Smrg		pConfigs[i].greenMask          = 0x000007E0;
141c582b7e3Smrg		pConfigs[i].blueMask           = 0x0000001F;
142c582b7e3Smrg		pConfigs[i].alphaMask          = 0x00000000;
143c582b7e3Smrg		if (accum) { /* Simulated in software */
144c582b7e3Smrg		    pConfigs[i].accumRedSize   = 16;
145c582b7e3Smrg		    pConfigs[i].accumGreenSize = 16;
146c582b7e3Smrg		    pConfigs[i].accumBlueSize  = 16;
147c582b7e3Smrg		    pConfigs[i].accumAlphaSize = 0;
148c582b7e3Smrg		} else {
149c582b7e3Smrg		    pConfigs[i].accumRedSize   = 0;
150c582b7e3Smrg		    pConfigs[i].accumGreenSize = 0;
151c582b7e3Smrg		    pConfigs[i].accumBlueSize  = 0;
152c582b7e3Smrg		    pConfigs[i].accumAlphaSize = 0;
153c582b7e3Smrg		}
154c582b7e3Smrg		if (db)
155c582b7e3Smrg		    pConfigs[i].doubleBuffer       = TRUE;
156c582b7e3Smrg		else
157c582b7e3Smrg		    pConfigs[i].doubleBuffer       = FALSE;
158c582b7e3Smrg		pConfigs[i].stereo             = FALSE;
159c582b7e3Smrg		pConfigs[i].bufferSize         = 16;
160c582b7e3Smrg		pConfigs[i].depthSize          = 16;
161c582b7e3Smrg		if (stencil)
162c582b7e3Smrg		    pConfigs[i].stencilSize    = 8; /* Simulated in software */
163c582b7e3Smrg		else
164c582b7e3Smrg		    pConfigs[i].stencilSize    = 0;
165c582b7e3Smrg		pConfigs[i].auxBuffers         = 0;
166c582b7e3Smrg		pConfigs[i].level              = 0;
167c582b7e3Smrg		if (accum || stencil) {
168c582b7e3Smrg		   pConfigs[i].visualRating    = GLX_SLOW_CONFIG;
169c582b7e3Smrg		} else {
170c582b7e3Smrg		   pConfigs[i].visualRating    = GLX_NONE;
171c582b7e3Smrg		}
172c582b7e3Smrg		pConfigs[i].transparentPixel   = GLX_NONE;
173c582b7e3Smrg		pConfigs[i].transparentRed     = 0;
174c582b7e3Smrg		pConfigs[i].transparentGreen   = 0;
175c582b7e3Smrg		pConfigs[i].transparentBlue    = 0;
176c582b7e3Smrg		pConfigs[i].transparentAlpha   = 0;
177c582b7e3Smrg		pConfigs[i].transparentIndex   = 0;
178c582b7e3Smrg		i++;
179c582b7e3Smrg	    }
180c582b7e3Smrg	  }
181c582b7e3Smrg	}
182c582b7e3Smrg	break;
183c582b7e3Smrg
184c582b7e3Smrg    case 32:
185c582b7e3Smrg	numConfigs = 1;
186c582b7e3Smrg	if (R128_USE_ACCUM)   numConfigs *= 2;
187c582b7e3Smrg	if (R128_USE_STENCIL) numConfigs *= 2;
188c582b7e3Smrg	if (R128_USE_DB)      numConfigs *= 2;
189c582b7e3Smrg
190c582b7e3Smrg	if (!(pConfigs
191c582b7e3Smrg	      = (__GLXvisualConfig*)xcalloc(sizeof(__GLXvisualConfig),
192c582b7e3Smrg					      numConfigs))) {
193c582b7e3Smrg	    return FALSE;
194c582b7e3Smrg	}
195c582b7e3Smrg	if (!(pR128Configs
196c582b7e3Smrg	      = (R128ConfigPrivPtr)xcalloc(sizeof(R128ConfigPrivRec),
197c582b7e3Smrg					     numConfigs))) {
198c582b7e3Smrg	    xfree(pConfigs);
199c582b7e3Smrg	    return FALSE;
200c582b7e3Smrg	}
201c582b7e3Smrg	if (!(pR128ConfigPtrs
202c582b7e3Smrg	      = (R128ConfigPrivPtr*)xcalloc(sizeof(R128ConfigPrivPtr),
203c582b7e3Smrg					      numConfigs))) {
204c582b7e3Smrg	    xfree(pConfigs);
205c582b7e3Smrg	    xfree(pR128Configs);
206c582b7e3Smrg	    return FALSE;
207c582b7e3Smrg	}
208c582b7e3Smrg
209c582b7e3Smrg	i = 0;
210c582b7e3Smrg	for (db = 0; db <= R128_USE_DB; db++) {
211c582b7e3Smrg	  for (accum = 0; accum <= R128_USE_ACCUM; accum++) {
212c582b7e3Smrg	    for (stencil = 0; stencil <= R128_USE_STENCIL; stencil++) {
213c582b7e3Smrg		pR128ConfigPtrs[i] = &pR128Configs[i];
214c582b7e3Smrg
215c582b7e3Smrg		pConfigs[i].vid                = (VisualID)(-1);
216c582b7e3Smrg		pConfigs[i].class              = -1;
217c582b7e3Smrg		pConfigs[i].rgba               = TRUE;
218c582b7e3Smrg		pConfigs[i].redSize            = 8;
219c582b7e3Smrg		pConfigs[i].greenSize          = 8;
220c582b7e3Smrg		pConfigs[i].blueSize           = 8;
221c582b7e3Smrg		pConfigs[i].alphaSize          = 0;
222c582b7e3Smrg		pConfigs[i].redMask            = 0x00FF0000;
223c582b7e3Smrg		pConfigs[i].greenMask          = 0x0000FF00;
224c582b7e3Smrg		pConfigs[i].blueMask           = 0x000000FF;
225c582b7e3Smrg		pConfigs[i].alphaMask          = 0x00000000;
226c582b7e3Smrg		if (accum) { /* Simulated in software */
227c582b7e3Smrg		    pConfigs[i].accumRedSize   = 16;
228c582b7e3Smrg		    pConfigs[i].accumGreenSize = 16;
229c582b7e3Smrg		    pConfigs[i].accumBlueSize  = 16;
230c582b7e3Smrg		    pConfigs[i].accumAlphaSize = 0;
231c582b7e3Smrg		} else {
232c582b7e3Smrg		    pConfigs[i].accumRedSize   = 0;
233c582b7e3Smrg		    pConfigs[i].accumGreenSize = 0;
234c582b7e3Smrg		    pConfigs[i].accumBlueSize  = 0;
235c582b7e3Smrg		    pConfigs[i].accumAlphaSize = 0;
236c582b7e3Smrg		}
237c582b7e3Smrg		if (db)
238c582b7e3Smrg		    pConfigs[i].doubleBuffer       = TRUE;
239c582b7e3Smrg		else
240c582b7e3Smrg		    pConfigs[i].doubleBuffer       = FALSE;
241c582b7e3Smrg		pConfigs[i].stereo             = FALSE;
242c582b7e3Smrg		pConfigs[i].bufferSize         = 24;
243c582b7e3Smrg		if (stencil) {
244c582b7e3Smrg		    pConfigs[i].depthSize      = 24;
245c582b7e3Smrg		    pConfigs[i].stencilSize    = 8;
246c582b7e3Smrg		} else {
247c582b7e3Smrg		    pConfigs[i].depthSize      = 24;
248c582b7e3Smrg		    pConfigs[i].stencilSize    = 0;
249c582b7e3Smrg		}
250c582b7e3Smrg		pConfigs[i].auxBuffers         = 0;
251c582b7e3Smrg		pConfigs[i].level              = 0;
252c582b7e3Smrg		if (accum) {
253c582b7e3Smrg		   pConfigs[i].visualRating    = GLX_SLOW_CONFIG;
254c582b7e3Smrg		} else {
255c582b7e3Smrg		   pConfigs[i].visualRating    = GLX_NONE;
256c582b7e3Smrg		}
257c582b7e3Smrg		pConfigs[i].transparentPixel   = GLX_NONE;
258c582b7e3Smrg		pConfigs[i].transparentRed     = 0;
259c582b7e3Smrg		pConfigs[i].transparentGreen   = 0;
260c582b7e3Smrg		pConfigs[i].transparentBlue    = 0;
261c582b7e3Smrg		pConfigs[i].transparentAlpha   = 0;
262c582b7e3Smrg		pConfigs[i].transparentIndex   = 0;
263c582b7e3Smrg		i++;
264c582b7e3Smrg	    }
265c582b7e3Smrg	  }
266c582b7e3Smrg	}
267c582b7e3Smrg	break;
268c582b7e3Smrg    }
269c582b7e3Smrg
270c582b7e3Smrg    info->numVisualConfigs   = numConfigs;
271c582b7e3Smrg    info->pVisualConfigs     = pConfigs;
272c582b7e3Smrg    info->pVisualConfigsPriv = pR128Configs;
273c582b7e3Smrg    GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pR128ConfigPtrs);
274c582b7e3Smrg    return TRUE;
275c582b7e3Smrg}
276c582b7e3Smrg
277c582b7e3Smrg/* Create the Rage 128-specific context information */
278c582b7e3Smrgstatic Bool R128CreateContext(ScreenPtr pScreen, VisualPtr visual,
279c582b7e3Smrg			      drm_context_t hwContext, void *pVisualConfigPriv,
280c582b7e3Smrg			      DRIContextType contextStore)
281c582b7e3Smrg{
282c582b7e3Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
283c582b7e3Smrg    R128InfoPtr info = R128PTR(pScrn);
284c582b7e3Smrg
285c582b7e3Smrg    info->drmCtx = hwContext;
286c582b7e3Smrg    return TRUE;
287c582b7e3Smrg}
288c582b7e3Smrg
289c582b7e3Smrg/* Destroy the Rage 128-specific context information */
290c582b7e3Smrgstatic void R128DestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
291c582b7e3Smrg			       DRIContextType contextStore)
292c582b7e3Smrg{
293c582b7e3Smrg    /* Nothing yet */
294c582b7e3Smrg}
295c582b7e3Smrg
296c582b7e3Smrg/* Called when the X server is woken up to allow the last client's
297c582b7e3Smrg   context to be saved and the X server's context to be loaded.  This is
298c582b7e3Smrg   not necessary for the Rage 128 since the client detects when it's
299c582b7e3Smrg   context is not currently loaded and then load's it itself.  Since the
300c582b7e3Smrg   registers to start and stop the CCE are privileged, only the X server
301c582b7e3Smrg   can start/stop the engine. */
302c582b7e3Smrgstatic void R128EnterServer(ScreenPtr pScreen)
303c582b7e3Smrg{
304c582b7e3Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
305c582b7e3Smrg    R128InfoPtr info = R128PTR(pScrn);
306c582b7e3Smrg
307c582b7e3Smrg    if (info->accel) info->accel->NeedToSync = TRUE;
308c582b7e3Smrg}
309c582b7e3Smrg
310c582b7e3Smrg/* Called when the X server goes to sleep to allow the X server's
311c582b7e3Smrg   context to be saved and the last client's context to be loaded.  This
312c582b7e3Smrg   is not necessary for the Rage 128 since the client detects when it's
313c582b7e3Smrg   context is not currently loaded and then load's it itself.  Since the
314c582b7e3Smrg   registers to start and stop the CCE are privileged, only the X server
315c582b7e3Smrg   can start/stop the engine. */
316c582b7e3Smrgstatic void R128LeaveServer(ScreenPtr pScreen)
317c582b7e3Smrg{
318c582b7e3Smrg    ScrnInfoPtr   pScrn     = xf86Screens[pScreen->myNum];
319c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
320c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
321c582b7e3Smrg
322c582b7e3Smrg    if (!info->directRenderingEnabled) {
323c582b7e3Smrg	/* Save all hardware scissors */
324c582b7e3Smrg	info->sc_left     = INREG(R128_SC_LEFT);
325c582b7e3Smrg	info->sc_right    = INREG(R128_SC_RIGHT);
326c582b7e3Smrg	info->sc_top      = INREG(R128_SC_TOP);
327c582b7e3Smrg	info->sc_bottom   = INREG(R128_SC_BOTTOM);
328c582b7e3Smrg	info->aux_sc_cntl = INREG(R128_SC_BOTTOM);
329c582b7e3Smrg    } else if (info->CCEInUse) {
330c582b7e3Smrg	R128CCEReleaseIndirect(pScrn);
331c582b7e3Smrg
332c582b7e3Smrg	info->CCEInUse = FALSE;
333c582b7e3Smrg    }
334c582b7e3Smrg}
335c582b7e3Smrg
336c582b7e3Smrg/* Contexts can be swapped by the X server if necessary.  This callback
337c582b7e3Smrg   is currently only used to perform any functions necessary when
338c582b7e3Smrg   entering or leaving the X server, and in the future might not be
339c582b7e3Smrg   necessary. */
340c582b7e3Smrgstatic void R128DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
341c582b7e3Smrg			       DRIContextType oldContextType, void *oldContext,
342c582b7e3Smrg			       DRIContextType newContextType, void *newContext)
343c582b7e3Smrg{
344c582b7e3Smrg    if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) &&
345c582b7e3Smrg	(newContextType==DRI_2D_CONTEXT)) { /* Entering from Wakeup */
346c582b7e3Smrg	R128EnterServer(pScreen);
347c582b7e3Smrg    }
348c582b7e3Smrg    if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) &&
349c582b7e3Smrg	(newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */
350c582b7e3Smrg	R128LeaveServer(pScreen);
351c582b7e3Smrg    }
352c582b7e3Smrg}
353c582b7e3Smrg
354c582b7e3Smrg/* Initialize the state of the back and depth buffers. */
355c582b7e3Smrgstatic void R128DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 indx)
356c582b7e3Smrg{
357c582b7e3Smrg    /* FIXME: This routine needs to have acceleration turned on */
358c582b7e3Smrg    ScreenPtr   pScreen = pWin->drawable.pScreen;
359c582b7e3Smrg    ScrnInfoPtr pScrn   = xf86Screens[pScreen->myNum];
360c582b7e3Smrg    R128InfoPtr info    = R128PTR(pScrn);
361c582b7e3Smrg    BoxPtr      pbox, pboxSave;
362c582b7e3Smrg    int         nbox, nboxSave;
363c582b7e3Smrg    int         depth;
364c582b7e3Smrg
365c582b7e3Smrg    /* FIXME: Use accel when CCE 2D code is written
366c582b7e3Smrg     * EA: What is this code kept for? Radeon doesn't have it and
367c582b7e3Smrg     * has a comment: "There's no need for the 2d driver to be clearing
368c582b7e3Smrg     * buffers for the 3d client.  It knows how to do that on its own."
369c582b7e3Smrg     */
370c582b7e3Smrg    if (info->directRenderingEnabled)
371c582b7e3Smrg	return;
372c582b7e3Smrg
373c582b7e3Smrg    /* FIXME: This should be based on the __GLXvisualConfig info */
374c582b7e3Smrg    switch (pScrn->bitsPerPixel) {
375c582b7e3Smrg    case  8: depth = 0x000000ff; break;
376c582b7e3Smrg    case 16: depth = 0x0000ffff; break;
377c582b7e3Smrg    case 24: depth = 0x00ffffff; break;
378c582b7e3Smrg    case 32: depth = 0xffffffff; break;
379c582b7e3Smrg    default: depth = 0x00000000; break;
380c582b7e3Smrg    }
381c582b7e3Smrg
382c582b7e3Smrg    /* FIXME: Copy XAAPaintWindow() and use REGION_TRANSLATE() */
383c582b7e3Smrg    /* FIXME: Only initialize the back and depth buffers for contexts
384c582b7e3Smrg       that request them */
385c582b7e3Smrg
386c582b7e3Smrg    pboxSave = pbox = REGION_RECTS(prgn);
387c582b7e3Smrg    nboxSave = nbox = REGION_NUM_RECTS(prgn);
388c582b7e3Smrg
389c582b7e3Smrg    (*info->accel->SetupForSolidFill)(pScrn, 0, GXcopy, (CARD32)(-1));
390c582b7e3Smrg    for (; nbox; nbox--, pbox++) {
391c582b7e3Smrg	(*info->accel->SubsequentSolidFillRect)(pScrn,
392c582b7e3Smrg						pbox->x1 + info->fbX,
393c582b7e3Smrg						pbox->y1 + info->fbY,
394c582b7e3Smrg						pbox->x2 - pbox->x1,
395c582b7e3Smrg						pbox->y2 - pbox->y1);
396c582b7e3Smrg	(*info->accel->SubsequentSolidFillRect)(pScrn,
397c582b7e3Smrg						pbox->x1 + info->backX,
398c582b7e3Smrg						pbox->y1 + info->backY,
399c582b7e3Smrg						pbox->x2 - pbox->x1,
400c582b7e3Smrg						pbox->y2 - pbox->y1);
401c582b7e3Smrg    }
402c582b7e3Smrg
403c582b7e3Smrg    pbox = pboxSave;
404c582b7e3Smrg    nbox = nboxSave;
405c582b7e3Smrg
406c582b7e3Smrg    /* FIXME: this needs to consider depth tiling. */
407c582b7e3Smrg    (*info->accel->SetupForSolidFill)(pScrn, depth, GXcopy, (CARD32)(-1));
408c582b7e3Smrg    for (; nbox; nbox--, pbox++)
409c582b7e3Smrg	(*info->accel->SubsequentSolidFillRect)(pScrn,
410c582b7e3Smrg						pbox->x1 + info->depthX,
411c582b7e3Smrg						pbox->y1 + info->depthY,
412c582b7e3Smrg						pbox->x2 - pbox->x1,
413c582b7e3Smrg						pbox->y2 - pbox->y1);
414c582b7e3Smrg
415c582b7e3Smrg    info->accel->NeedToSync = TRUE;
416c582b7e3Smrg}
417c582b7e3Smrg
418c582b7e3Smrg/* Copy the back and depth buffers when the X server moves a window. */
419c582b7e3Smrgstatic void R128DRIMoveBuffers(WindowPtr pWin, DDXPointRec ptOldOrg,
420c582b7e3Smrg			       RegionPtr prgnSrc, CARD32 indx)
421c582b7e3Smrg{
422c582b7e3Smrg    ScreenPtr   pScreen = pWin->drawable.pScreen;
423c582b7e3Smrg    ScrnInfoPtr pScrn   = xf86Screens[pScreen->myNum];
424c582b7e3Smrg    R128InfoPtr info   = R128PTR(pScrn);
425c582b7e3Smrg
426c582b7e3Smrg    /* FIXME: This routine needs to have acceleration turned on */
427c582b7e3Smrg    /* FIXME: Copy XAACopyWindow() and use REGION_TRANSLATE() */
428c582b7e3Smrg    /* FIXME: Only initialize the back and depth buffers for contexts
429c582b7e3Smrg       that request them */
430c582b7e3Smrg
431c582b7e3Smrg    /* FIXME: Use accel when CCE 2D code is written */
432c582b7e3Smrg    if (info->directRenderingEnabled)
433c582b7e3Smrg	return;
434c582b7e3Smrg}
435c582b7e3Smrg
436c582b7e3Smrg/* Initialize the AGP state.  Request memory for use in AGP space, and
437c582b7e3Smrg   initialize the Rage 128 registers to point to that memory. */
438c582b7e3Smrgstatic Bool R128DRIAgpInit(R128InfoPtr info, ScreenPtr pScreen)
439c582b7e3Smrg{
440c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
441c582b7e3Smrg    unsigned long mode;
442c582b7e3Smrg    unsigned int  vendor, device;
443c582b7e3Smrg    int           ret;
444c582b7e3Smrg    unsigned long cntl, chunk;
445c582b7e3Smrg    int           s, l;
446c582b7e3Smrg    int           flags;
447c582b7e3Smrg    unsigned long agpBase;
448c582b7e3Smrg
449c582b7e3Smrg    if (drmAgpAcquire(info->drmFD) < 0) {
450c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_WARNING, "[agp] AGP not available\n");
451c582b7e3Smrg	return FALSE;
452c582b7e3Smrg    }
453c582b7e3Smrg
454c582b7e3Smrg				/* Modify the mode if the default mode is
455c582b7e3Smrg				   not appropriate for this particular
456c582b7e3Smrg				   combination of graphics card and AGP
457c582b7e3Smrg				   chipset. */
458c582b7e3Smrg
459c582b7e3Smrg    mode   = drmAgpGetMode(info->drmFD);        /* Default mode */
460c582b7e3Smrg    vendor = drmAgpVendorId(info->drmFD);
461c582b7e3Smrg    device = drmAgpDeviceId(info->drmFD);
462c582b7e3Smrg
463c582b7e3Smrg    mode &= ~R128_AGP_MODE_MASK;
464c582b7e3Smrg    switch (info->agpMode) {
465c582b7e3Smrg    case 4:          mode |= R128_AGP_4X_MODE;
466c582b7e3Smrg    case 2:          mode |= R128_AGP_2X_MODE;
467c582b7e3Smrg    case 1: default: mode |= R128_AGP_1X_MODE;
468c582b7e3Smrg    }
469c582b7e3Smrg
470c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
471c582b7e3Smrg	       "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
472c582b7e3Smrg	       mode, vendor, device,
473c582b7e3Smrg	       PCI_DEV_VENDOR_ID(info->PciInfo),
474c582b7e3Smrg	       PCI_DEV_DEVICE_ID(info->PciInfo));
475c582b7e3Smrg
476c582b7e3Smrg    if (drmAgpEnable(info->drmFD, mode) < 0) {
477c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n");
478c582b7e3Smrg	drmAgpRelease(info->drmFD);
479c582b7e3Smrg	return FALSE;
480c582b7e3Smrg    }
481c582b7e3Smrg
482c582b7e3Smrg    info->agpOffset = 0;
483c582b7e3Smrg
484c582b7e3Smrg    if ((ret = drmAgpAlloc(info->drmFD, info->agpSize*1024*1024, 0, NULL,
485c582b7e3Smrg			   &info->agpMemHandle)) < 0) {
486c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret);
487c582b7e3Smrg	drmAgpRelease(info->drmFD);
488c582b7e3Smrg	return FALSE;
489c582b7e3Smrg    }
490c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
491c582b7e3Smrg	       "[agp] %d kB allocated with handle 0x%08x\n",
492c582b7e3Smrg	       info->agpSize*1024, info->agpMemHandle);
493c582b7e3Smrg
494c582b7e3Smrg    if (drmAgpBind(info->drmFD, info->agpMemHandle, info->agpOffset) < 0) {
495c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not bind\n");
496c582b7e3Smrg	drmAgpFree(info->drmFD, info->agpMemHandle);
497c582b7e3Smrg	drmAgpRelease(info->drmFD);
498c582b7e3Smrg	return FALSE;
499c582b7e3Smrg    }
500c582b7e3Smrg
501c582b7e3Smrg				/* Initialize the CCE ring buffer data */
502c582b7e3Smrg    info->ringStart       = info->agpOffset;
503c582b7e3Smrg    info->ringMapSize     = info->ringSize*1024*1024 + r128_drm_page_size;
504c582b7e3Smrg    info->ringSizeLog2QW  = R128MinBits(info->ringSize*1024*1024/8) - 1;
505c582b7e3Smrg
506c582b7e3Smrg    info->ringReadOffset  = info->ringStart + info->ringMapSize;
507c582b7e3Smrg    info->ringReadMapSize = r128_drm_page_size;
508c582b7e3Smrg
509c582b7e3Smrg				/* Reserve space for vertex/indirect buffers */
510c582b7e3Smrg    info->bufStart        = info->ringReadOffset + info->ringReadMapSize;
511c582b7e3Smrg    info->bufMapSize      = info->bufSize*1024*1024;
512c582b7e3Smrg
513c582b7e3Smrg				/* Reserve the rest for AGP textures */
514c582b7e3Smrg    info->agpTexStart     = info->bufStart + info->bufMapSize;
515c582b7e3Smrg    s = (info->agpSize*1024*1024 - info->agpTexStart);
516c582b7e3Smrg    l = R128MinBits((s-1) / R128_NR_TEX_REGIONS);
517c582b7e3Smrg    if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
518c582b7e3Smrg    info->agpTexMapSize   = (s >> l) << l;
519c582b7e3Smrg    info->log2AGPTexGran  = l;
520c582b7e3Smrg
521c582b7e3Smrg    if (info->CCESecure) flags = DRM_READ_ONLY;
522c582b7e3Smrg    else                  flags = 0;
523c582b7e3Smrg
524c582b7e3Smrg    if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize,
525c582b7e3Smrg		  DRM_AGP, flags, &info->ringHandle) < 0) {
526c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
527c582b7e3Smrg		   "[agp] Could not add ring mapping\n");
528c582b7e3Smrg	return FALSE;
529c582b7e3Smrg    }
530c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
531c582b7e3Smrg	       "[agp] ring handle = 0x%08x\n", info->ringHandle);
532c582b7e3Smrg
533c582b7e3Smrg    if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize,
534c582b7e3Smrg	       &info->ring) < 0) {
535c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n");
536c582b7e3Smrg	return FALSE;
537c582b7e3Smrg    }
538c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
539c582b7e3Smrg	       "[agp] Ring mapped at 0x%08lx\n",
540c582b7e3Smrg	       (unsigned long)info->ring);
541c582b7e3Smrg
542c582b7e3Smrg    if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize,
543c582b7e3Smrg		  DRM_AGP, flags, &info->ringReadPtrHandle) < 0) {
544c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
545c582b7e3Smrg		   "[agp] Could not add ring read ptr mapping\n");
546c582b7e3Smrg	return FALSE;
547c582b7e3Smrg    }
548c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
549c582b7e3Smrg 	       "[agp] ring read ptr handle = 0x%08x\n",
550c582b7e3Smrg	       info->ringReadPtrHandle);
551c582b7e3Smrg
552c582b7e3Smrg    if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
553c582b7e3Smrg	       &info->ringReadPtr) < 0) {
554c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
555c582b7e3Smrg		   "[agp] Could not map ring read ptr\n");
556c582b7e3Smrg	return FALSE;
557c582b7e3Smrg    }
558c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
559c582b7e3Smrg	       "[agp] Ring read ptr mapped at 0x%08lx\n",
560c582b7e3Smrg	       (unsigned long)info->ringReadPtr);
561c582b7e3Smrg
562c582b7e3Smrg    if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize,
563c582b7e3Smrg		  DRM_AGP, 0, &info->bufHandle) < 0) {
564c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
565c582b7e3Smrg		   "[agp] Could not add vertex/indirect buffers mapping\n");
566c582b7e3Smrg	return FALSE;
567c582b7e3Smrg    }
568c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
569c582b7e3Smrg	       "[agp] vertex/indirect buffers handle = 0x%08x\n",
570c582b7e3Smrg	       info->bufHandle);
571c582b7e3Smrg
572c582b7e3Smrg    if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize,
573c582b7e3Smrg	       &info->buf) < 0) {
574c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
575c582b7e3Smrg		   "[agp] Could not map vertex/indirect buffers\n");
576c582b7e3Smrg	return FALSE;
577c582b7e3Smrg    }
578c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
579c582b7e3Smrg	       "[agp] Vertex/indirect buffers mapped at 0x%08lx\n",
580c582b7e3Smrg	       (unsigned long)info->buf);
581c582b7e3Smrg
582c582b7e3Smrg    if (drmAddMap(info->drmFD, info->agpTexStart, info->agpTexMapSize,
583c582b7e3Smrg		  DRM_AGP, 0, &info->agpTexHandle) < 0) {
584c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
585c582b7e3Smrg		   "[agp] Could not add AGP texture map mapping\n");
586c582b7e3Smrg	return FALSE;
587c582b7e3Smrg    }
588c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
589c582b7e3Smrg	       "[agp] AGP texture map handle = 0x%08x\n",
590c582b7e3Smrg	       info->agpTexHandle);
591c582b7e3Smrg
592c582b7e3Smrg    if (drmMap(info->drmFD, info->agpTexHandle, info->agpTexMapSize,
593c582b7e3Smrg	       &info->agpTex) < 0) {
594c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
595c582b7e3Smrg		   "[agp] Could not map AGP texture map\n");
596c582b7e3Smrg	return FALSE;
597c582b7e3Smrg    }
598c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
599c582b7e3Smrg	       "[agp] AGP Texture map mapped at 0x%08lx\n",
600c582b7e3Smrg	       (unsigned long)info->agpTex);
601c582b7e3Smrg
602c582b7e3Smrg				/* Initialize Rage 128's AGP registers */
603c582b7e3Smrg    cntl  = INREG(R128_AGP_CNTL);
604c582b7e3Smrg    cntl &= ~R128_AGP_APER_SIZE_MASK;
605c582b7e3Smrg    switch (info->agpSize) {
606c582b7e3Smrg    case 256: cntl |= R128_AGP_APER_SIZE_256MB; break;
607c582b7e3Smrg    case 128: cntl |= R128_AGP_APER_SIZE_128MB; break;
608c582b7e3Smrg    case  64: cntl |= R128_AGP_APER_SIZE_64MB;  break;
609c582b7e3Smrg    case  32: cntl |= R128_AGP_APER_SIZE_32MB;  break;
610c582b7e3Smrg    case  16: cntl |= R128_AGP_APER_SIZE_16MB;  break;
611c582b7e3Smrg    case   8: cntl |= R128_AGP_APER_SIZE_8MB;   break;
612c582b7e3Smrg    case   4: cntl |= R128_AGP_APER_SIZE_4MB;   break;
613c582b7e3Smrg    default:
614c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
615c582b7e3Smrg		   "[agp] Illegal aperture size %d kB\n",
616c582b7e3Smrg		   info->agpSize*1024);
617c582b7e3Smrg	return FALSE;
618c582b7e3Smrg    }
619c582b7e3Smrg    agpBase = drmAgpBase(info->drmFD);
620c582b7e3Smrg    OUTREG(R128_AGP_BASE, agpBase);
621c582b7e3Smrg    OUTREG(R128_AGP_CNTL, cntl);
622c582b7e3Smrg
623c582b7e3Smrg				/* Disable Rage 128's PCIGART registers */
624c582b7e3Smrg    chunk = INREG(R128_BM_CHUNK_0_VAL);
625c582b7e3Smrg    chunk &= ~(R128_BM_PTR_FORCE_TO_PCI |
626c582b7e3Smrg	       R128_BM_PM4_RD_FORCE_TO_PCI |
627c582b7e3Smrg	       R128_BM_GLOBAL_FORCE_TO_PCI);
628c582b7e3Smrg    OUTREG(R128_BM_CHUNK_0_VAL, chunk);
629c582b7e3Smrg
630c582b7e3Smrg    OUTREG(R128_PCI_GART_PAGE, 1); /* Ensure AGP GART is used (for now) */
631c582b7e3Smrg
632c582b7e3Smrg    return TRUE;
633c582b7e3Smrg}
634c582b7e3Smrg
635c582b7e3Smrgstatic Bool R128DRIPciInit(R128InfoPtr info, ScreenPtr pScreen)
636c582b7e3Smrg{
637c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
638c582b7e3Smrg    CARD32 chunk;
639c582b7e3Smrg    int ret;
640c582b7e3Smrg    int flags;
641c582b7e3Smrg
642c582b7e3Smrg    info->agpOffset = 0;
643c582b7e3Smrg
644c582b7e3Smrg    ret = drmScatterGatherAlloc(info->drmFD, info->agpSize*1024*1024,
645c582b7e3Smrg				&info->pciMemHandle);
646c582b7e3Smrg    if (ret < 0) {
647c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Out of memory (%d)\n", ret);
648c582b7e3Smrg	return FALSE;
649c582b7e3Smrg    }
650c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
651c582b7e3Smrg	       "[pci] %d kB allocated with handle 0x%08x\n",
652c582b7e3Smrg	       info->agpSize*1024, info->pciMemHandle);
653c582b7e3Smrg
654c582b7e3Smrg				/* Initialize the CCE ring buffer data */
655c582b7e3Smrg    info->ringStart       = info->agpOffset;
656c582b7e3Smrg    info->ringMapSize     = info->ringSize*1024*1024 + r128_drm_page_size;
657c582b7e3Smrg    info->ringSizeLog2QW  = R128MinBits(info->ringSize*1024*1024/8) - 1;
658c582b7e3Smrg
659c582b7e3Smrg    info->ringReadOffset  = info->ringStart + info->ringMapSize;
660c582b7e3Smrg    info->ringReadMapSize = r128_drm_page_size;
661c582b7e3Smrg
662c582b7e3Smrg				/* Reserve space for vertex/indirect buffers */
663c582b7e3Smrg    info->bufStart        = info->ringReadOffset + info->ringReadMapSize;
664c582b7e3Smrg    info->bufMapSize      = info->bufSize*1024*1024;
665c582b7e3Smrg
666c582b7e3Smrg    flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL;
667c582b7e3Smrg
668c582b7e3Smrg    if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize,
669c582b7e3Smrg		  DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) {
670c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
671c582b7e3Smrg		   "[pci] Could not add ring mapping\n");
672c582b7e3Smrg	return FALSE;
673c582b7e3Smrg    }
674c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
675c582b7e3Smrg	       "[pci] ring handle = 0x%08x\n", info->ringHandle);
676c582b7e3Smrg
677c582b7e3Smrg    if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize,
678c582b7e3Smrg	       &info->ring) < 0) {
679c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n");
680c582b7e3Smrg	return FALSE;
681c582b7e3Smrg    }
682c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
683c582b7e3Smrg	       "[pci] Ring mapped at 0x%08lx\n",
684c582b7e3Smrg	       (unsigned long)info->ring);
685c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
686c582b7e3Smrg	       "[pci] Ring contents 0x%08lx\n",
687c582b7e3Smrg	       *(unsigned long *)(pointer)info->ring);
688c582b7e3Smrg
689c582b7e3Smrg    if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize,
690c582b7e3Smrg		  DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) {
691c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
692c582b7e3Smrg		   "[pci] Could not add ring read ptr mapping\n");
693c582b7e3Smrg	return FALSE;
694c582b7e3Smrg    }
695c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
696c582b7e3Smrg	       "[pci] ring read ptr handle = 0x%08x\n",
697c582b7e3Smrg	       info->ringReadPtrHandle);
698c582b7e3Smrg
699c582b7e3Smrg    if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
700c582b7e3Smrg	       &info->ringReadPtr) < 0) {
701c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
702c582b7e3Smrg		   "[pci] Could not map ring read ptr\n");
703c582b7e3Smrg	return FALSE;
704c582b7e3Smrg    }
705c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
706c582b7e3Smrg	       "[pci] Ring read ptr mapped at 0x%08lx\n",
707c582b7e3Smrg	       (unsigned long)info->ringReadPtr);
708c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
709c582b7e3Smrg	       "[pci] Ring read ptr contents 0x%08lx\n",
710c582b7e3Smrg	       *(unsigned long *)(pointer)info->ringReadPtr);
711c582b7e3Smrg
712c582b7e3Smrg    if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize,
713c582b7e3Smrg		  DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) {
714c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
715c582b7e3Smrg		   "[pci] Could not add vertex/indirect buffers mapping\n");
716c582b7e3Smrg	return FALSE;
717c582b7e3Smrg    }
718c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
719c582b7e3Smrg	       "[pci] vertex/indirect buffers handle = 0x%08x\n",
720c582b7e3Smrg	       info->bufHandle);
721c582b7e3Smrg
722c582b7e3Smrg    if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize,
723c582b7e3Smrg	       &info->buf) < 0) {
724c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
725c582b7e3Smrg		   "[pci] Could not map vertex/indirect buffers\n");
726c582b7e3Smrg	return FALSE;
727c582b7e3Smrg    }
728c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
729c582b7e3Smrg	       "[pci] Vertex/indirect buffers mapped at 0x%08lx\n",
730c582b7e3Smrg	       (unsigned long)info->buf);
731c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
732c582b7e3Smrg	       "[pci] Vertex/indirect buffers contents 0x%08lx\n",
733c582b7e3Smrg	       *(unsigned long *)(pointer)info->buf);
734c582b7e3Smrg
735c582b7e3Smrg    switch (info->Chipset) {
736c582b7e3Smrg    case PCI_CHIP_RAGE128LE:
737c582b7e3Smrg    case PCI_CHIP_RAGE128RE:
738c582b7e3Smrg    case PCI_CHIP_RAGE128RK:
739c582b7e3Smrg    case PCI_CHIP_RAGE128PD:
740c582b7e3Smrg    case PCI_CHIP_RAGE128PP:
741c582b7e3Smrg    case PCI_CHIP_RAGE128PR:
742c582b7e3Smrg	/* This is a PCI card, do nothing */
743c582b7e3Smrg	break;
744c582b7e3Smrg
745c582b7e3Smrg    case PCI_CHIP_RAGE128LF:
746c582b7e3Smrg    case PCI_CHIP_RAGE128MF:
747c582b7e3Smrg    case PCI_CHIP_RAGE128ML:
748c582b7e3Smrg    case PCI_CHIP_RAGE128RF:
749c582b7e3Smrg    case PCI_CHIP_RAGE128RG:
750c582b7e3Smrg    case PCI_CHIP_RAGE128RL:
751c582b7e3Smrg    case PCI_CHIP_RAGE128SM:
752c582b7e3Smrg    case PCI_CHIP_RAGE128PF:
753c582b7e3Smrg    case PCI_CHIP_RAGE128TF:
754c582b7e3Smrg    case PCI_CHIP_RAGE128TL:
755c582b7e3Smrg    case PCI_CHIP_RAGE128TR:
756c582b7e3Smrg    /* FIXME: ATI documentation does not specify if the following chips are
757c582b7e3Smrg     * AGP or PCI, it just mentions their PCI IDs.  I'm assuming they're AGP
758c582b7e3Smrg     * until I get more correct information. <mharris@redhat.com>
759c582b7e3Smrg     */
760c582b7e3Smrg    case PCI_CHIP_RAGE128PA:
761c582b7e3Smrg    case PCI_CHIP_RAGE128PB:
762c582b7e3Smrg    case PCI_CHIP_RAGE128PC:
763c582b7e3Smrg    case PCI_CHIP_RAGE128PE:
764c582b7e3Smrg    case PCI_CHIP_RAGE128PG:
765c582b7e3Smrg    case PCI_CHIP_RAGE128PH:
766c582b7e3Smrg    case PCI_CHIP_RAGE128PI:
767c582b7e3Smrg    case PCI_CHIP_RAGE128PJ:
768c582b7e3Smrg    case PCI_CHIP_RAGE128PK:
769c582b7e3Smrg    case PCI_CHIP_RAGE128PL:
770c582b7e3Smrg    case PCI_CHIP_RAGE128PM:
771c582b7e3Smrg    case PCI_CHIP_RAGE128PN:
772c582b7e3Smrg    case PCI_CHIP_RAGE128PO:
773c582b7e3Smrg    case PCI_CHIP_RAGE128PQ:
774c582b7e3Smrg    case PCI_CHIP_RAGE128PS:
775c582b7e3Smrg    case PCI_CHIP_RAGE128PT:
776c582b7e3Smrg    case PCI_CHIP_RAGE128PU:
777c582b7e3Smrg    case PCI_CHIP_RAGE128PV:
778c582b7e3Smrg    case PCI_CHIP_RAGE128PW:
779c582b7e3Smrg    case PCI_CHIP_RAGE128PX:
780c582b7e3Smrg    case PCI_CHIP_RAGE128SE:
781c582b7e3Smrg    case PCI_CHIP_RAGE128SF:
782c582b7e3Smrg    case PCI_CHIP_RAGE128SG:
783c582b7e3Smrg    case PCI_CHIP_RAGE128SH:
784c582b7e3Smrg    case PCI_CHIP_RAGE128SK:
785c582b7e3Smrg    case PCI_CHIP_RAGE128SL:
786c582b7e3Smrg    case PCI_CHIP_RAGE128SN:
787c582b7e3Smrg    case PCI_CHIP_RAGE128TS:
788c582b7e3Smrg    case PCI_CHIP_RAGE128TT:
789c582b7e3Smrg    case PCI_CHIP_RAGE128TU:
790c582b7e3Smrg    default:
791c582b7e3Smrg	/* This is really an AGP card, force PCI GART mode */
792c582b7e3Smrg        chunk = INREG(R128_BM_CHUNK_0_VAL);
793c582b7e3Smrg        chunk |= (R128_BM_PTR_FORCE_TO_PCI |
794c582b7e3Smrg		  R128_BM_PM4_RD_FORCE_TO_PCI |
795c582b7e3Smrg		  R128_BM_GLOBAL_FORCE_TO_PCI);
796c582b7e3Smrg        OUTREG(R128_BM_CHUNK_0_VAL, chunk);
797c582b7e3Smrg        OUTREG(R128_PCI_GART_PAGE, 0); /* Ensure PCI GART is used */
798c582b7e3Smrg        break;
799c582b7e3Smrg    }
800c582b7e3Smrg
801c582b7e3Smrg    return TRUE;
802c582b7e3Smrg}
803c582b7e3Smrg
804c582b7e3Smrg/* Add a map for the MMIO registers that will be accessed by any
805c582b7e3Smrg   DRI-based clients. */
806c582b7e3Smrgstatic Bool R128DRIMapInit(R128InfoPtr info, ScreenPtr pScreen)
807c582b7e3Smrg{
808c582b7e3Smrg    int flags;
809c582b7e3Smrg
810c582b7e3Smrg    if (info->CCESecure) flags = DRM_READ_ONLY;
811c582b7e3Smrg    else                 flags = 0;
812c582b7e3Smrg
813c582b7e3Smrg				/* Map registers */
814c582b7e3Smrg    info->registerSize = R128_MMIOSIZE;
815c582b7e3Smrg    if (drmAddMap(info->drmFD, info->MMIOAddr, info->registerSize,
816c582b7e3Smrg		  DRM_REGISTERS, flags, &info->registerHandle) < 0) {
817c582b7e3Smrg	return FALSE;
818c582b7e3Smrg    }
819c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
820c582b7e3Smrg	       "[drm] register handle = 0x%08x\n", info->registerHandle);
821c582b7e3Smrg
822c582b7e3Smrg    return TRUE;
823c582b7e3Smrg}
824c582b7e3Smrg
825c582b7e3Smrg/* Initialize the kernel data structures. */
826c582b7e3Smrgstatic int R128DRIKernelInit(R128InfoPtr info, ScreenPtr pScreen)
827c582b7e3Smrg{
828c582b7e3Smrg    drmR128Init drmInfo;
829c582b7e3Smrg
830c582b7e3Smrg    memset( &drmInfo, 0, sizeof(drmR128Init) );
831c582b7e3Smrg
832c582b7e3Smrg    drmInfo.func                = DRM_R128_INIT_CCE;
833c582b7e3Smrg    drmInfo.sarea_priv_offset   = sizeof(XF86DRISAREARec);
834c582b7e3Smrg    drmInfo.is_pci              = info->IsPCI;
835c582b7e3Smrg    drmInfo.cce_mode            = info->CCEMode;
836c582b7e3Smrg    drmInfo.cce_secure          = info->CCESecure;
837c582b7e3Smrg    drmInfo.ring_size           = info->ringSize*1024*1024;
838c582b7e3Smrg    drmInfo.usec_timeout        = info->CCEusecTimeout;
839c582b7e3Smrg
840c582b7e3Smrg    drmInfo.fb_bpp              = info->CurrentLayout.pixel_code;
841c582b7e3Smrg    drmInfo.depth_bpp           = info->CurrentLayout.pixel_code;
842c582b7e3Smrg
843c582b7e3Smrg    drmInfo.front_offset        = info->frontOffset;
844c582b7e3Smrg    drmInfo.front_pitch         = info->frontPitch;
845c582b7e3Smrg
846c582b7e3Smrg    drmInfo.back_offset         = info->backOffset;
847c582b7e3Smrg    drmInfo.back_pitch          = info->backPitch;
848c582b7e3Smrg
849c582b7e3Smrg    drmInfo.depth_offset        = info->depthOffset;
850c582b7e3Smrg    drmInfo.depth_pitch         = info->depthPitch;
851c582b7e3Smrg    drmInfo.span_offset         = info->spanOffset;
852c582b7e3Smrg
853c582b7e3Smrg    drmInfo.fb_offset           = info->fbHandle;
854c582b7e3Smrg    drmInfo.mmio_offset         = info->registerHandle;
855c582b7e3Smrg    drmInfo.ring_offset         = info->ringHandle;
856c582b7e3Smrg    drmInfo.ring_rptr_offset    = info->ringReadPtrHandle;
857c582b7e3Smrg    drmInfo.buffers_offset      = info->bufHandle;
858c582b7e3Smrg    drmInfo.agp_textures_offset = info->agpTexHandle;
859c582b7e3Smrg
860c582b7e3Smrg    if (drmCommandWrite(info->drmFD, DRM_R128_INIT,
861c582b7e3Smrg                        &drmInfo, sizeof(drmR128Init)) < 0)
862c582b7e3Smrg        return FALSE;
863c582b7e3Smrg
864c582b7e3Smrg    return TRUE;
865c582b7e3Smrg}
866c582b7e3Smrg
867c582b7e3Smrg/* Add a map for the vertex buffers that will be accessed by any
868c582b7e3Smrg   DRI-based clients. */
869c582b7e3Smrgstatic Bool R128DRIBufInit(R128InfoPtr info, ScreenPtr pScreen)
870c582b7e3Smrg{
871c582b7e3Smrg				/* Initialize vertex buffers */
872c582b7e3Smrg    if (info->IsPCI) {
873c582b7e3Smrg	info->bufNumBufs = drmAddBufs(info->drmFD,
874c582b7e3Smrg				      info->bufMapSize / R128_BUFFER_SIZE,
875c582b7e3Smrg				      R128_BUFFER_SIZE,
876c582b7e3Smrg				      DRM_SG_BUFFER,
877c582b7e3Smrg				      info->bufStart);
878c582b7e3Smrg    } else {
879c582b7e3Smrg	info->bufNumBufs = drmAddBufs(info->drmFD,
880c582b7e3Smrg				      info->bufMapSize / R128_BUFFER_SIZE,
881c582b7e3Smrg				      R128_BUFFER_SIZE,
882c582b7e3Smrg				      DRM_AGP_BUFFER,
883c582b7e3Smrg				      info->bufStart);
884c582b7e3Smrg    }
885c582b7e3Smrg    if (info->bufNumBufs <= 0) {
886c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
887c582b7e3Smrg		   "[drm] Could not create vertex/indirect buffers list\n");
888c582b7e3Smrg	return FALSE;
889c582b7e3Smrg    }
890c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
891c582b7e3Smrg	       "[drm] Added %d %d byte vertex/indirect buffers\n",
892c582b7e3Smrg	       info->bufNumBufs, R128_BUFFER_SIZE);
893c582b7e3Smrg
894c582b7e3Smrg    if (!(info->buffers = drmMapBufs(info->drmFD))) {
895c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
896c582b7e3Smrg		   "[drm] Failed to map vertex/indirect buffers list\n");
897c582b7e3Smrg	return FALSE;
898c582b7e3Smrg    }
899c582b7e3Smrg    xf86DrvMsg(pScreen->myNum, X_INFO,
900c582b7e3Smrg	       "[drm] Mapped %d vertex/indirect buffers\n",
901c582b7e3Smrg	       info->buffers->count);
902c582b7e3Smrg
903c582b7e3Smrg    return TRUE;
904c582b7e3Smrg}
905c582b7e3Smrg
906c582b7e3Smrgstatic void R128DRIIrqInit(R128InfoPtr info, ScreenPtr pScreen)
907c582b7e3Smrg{
908c582b7e3Smrg   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
909c582b7e3Smrg
910c582b7e3Smrg   if (!info->irq) {
911c582b7e3Smrg      info->irq = drmGetInterruptFromBusID(
912c582b7e3Smrg	 info->drmFD,
913c582b7e3Smrg	 PCI_CFG_BUS(info->PciInfo),
914c582b7e3Smrg	 PCI_CFG_DEV(info->PciInfo),
915c582b7e3Smrg	 PCI_CFG_FUNC(info->PciInfo));
916c582b7e3Smrg
917c582b7e3Smrg      if((drmCtlInstHandler(info->drmFD, info->irq)) != 0) {
918c582b7e3Smrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
919c582b7e3Smrg		    "[drm] failure adding irq handler, "
920c582b7e3Smrg		    "there is a device already using that irq\n"
921c582b7e3Smrg		    "[drm] falling back to irq-free operation\n");
922c582b7e3Smrg	 info->irq = 0;
923c582b7e3Smrg      } else {
924c582b7e3Smrg          unsigned char *R128MMIO = info->MMIO;
925c582b7e3Smrg          info->gen_int_cntl = INREG( R128_GEN_INT_CNTL );
926c582b7e3Smrg      }
927c582b7e3Smrg   }
928c582b7e3Smrg
929c582b7e3Smrg   if (info->irq)
930c582b7e3Smrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
931c582b7e3Smrg		 "[drm] dma control initialized, using IRQ %d\n",
932c582b7e3Smrg		 info->irq);
933c582b7e3Smrg}
934c582b7e3Smrg
935c582b7e3Smrg/* Initialize the CCE state, and start the CCE (if used by the X server) */
936c582b7e3Smrgstatic void R128DRICCEInit(ScrnInfoPtr pScrn)
937c582b7e3Smrg{
938c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
939c582b7e3Smrg
940c582b7e3Smrg				/* Turn on bus mastering */
941c582b7e3Smrg    info->BusCntl &= ~R128_BUS_MASTER_DIS;
942c582b7e3Smrg
943c582b7e3Smrg				/* CCEMode is initialized in r128_driver.c */
944c582b7e3Smrg    switch (info->CCEMode) {
945c582b7e3Smrg    case R128_PM4_NONPM4:                 info->CCEFifoSize = 0;   break;
946c582b7e3Smrg    case R128_PM4_192PIO:                 info->CCEFifoSize = 192; break;
947c582b7e3Smrg    case R128_PM4_192BM:                  info->CCEFifoSize = 192; break;
948c582b7e3Smrg    case R128_PM4_128PIO_64INDBM:         info->CCEFifoSize = 128; break;
949c582b7e3Smrg    case R128_PM4_128BM_64INDBM:          info->CCEFifoSize = 128; break;
950c582b7e3Smrg    case R128_PM4_64PIO_128INDBM:         info->CCEFifoSize = 64;  break;
951c582b7e3Smrg    case R128_PM4_64BM_128INDBM:          info->CCEFifoSize = 64;  break;
952c582b7e3Smrg    case R128_PM4_64PIO_64VCBM_64INDBM:   info->CCEFifoSize = 64;  break;
953c582b7e3Smrg    case R128_PM4_64BM_64VCBM_64INDBM:    info->CCEFifoSize = 64;  break;
954c582b7e3Smrg    case R128_PM4_64PIO_64VCPIO_64INDPIO: info->CCEFifoSize = 64;  break;
955c582b7e3Smrg    }
956c582b7e3Smrg
957c582b7e3Smrg    if (info->directRenderingEnabled) {
958c582b7e3Smrg				/* Make sure the CCE is on for the X server */
959c582b7e3Smrg	R128CCE_START(pScrn, info);
960c582b7e3Smrg    } else {
961c582b7e3Smrg				/* Make sure the CCE is off for the X server */
962c582b7e3Smrg	R128CCE_STOP(pScrn, info);
963c582b7e3Smrg    }
964c582b7e3Smrg}
965c582b7e3Smrg
966c582b7e3Smrg/* Initialize the screen-specific data structures for the DRI and the
967c582b7e3Smrg   Rage 128.  This is the main entry point to the device-specific
968c582b7e3Smrg   initialization code.  It calls device-independent DRI functions to
969c582b7e3Smrg   create the DRI data structures and initialize the DRI state. */
970c582b7e3SmrgBool R128DRIScreenInit(ScreenPtr pScreen)
971c582b7e3Smrg{
972c582b7e3Smrg    ScrnInfoPtr   pScrn = xf86Screens[pScreen->myNum];
973c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
974c582b7e3Smrg    DRIInfoPtr    pDRIInfo;
975c582b7e3Smrg    R128DRIPtr    pR128DRI;
976c582b7e3Smrg    int           major, minor, patch;
977c582b7e3Smrg    drmVersionPtr version;
978c582b7e3Smrg
979c582b7e3Smrg    /* Check that the GLX, DRI, and DRM modules have been loaded by testing
980c582b7e3Smrg     * for known symbols in each module. */
981c582b7e3Smrg    if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) return FALSE;
982c582b7e3Smrg    if (!xf86LoaderCheckSymbol("drmAvailable"))        return FALSE;
983c582b7e3Smrg    if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
984c582b7e3Smrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
985c582b7e3Smrg		 "[dri] R128DRIScreenInit failed (libdri.a too old)\n");
986c582b7e3Smrg      return FALSE;
987c582b7e3Smrg    }
988c582b7e3Smrg
989c582b7e3Smrg    /* Check the DRI version */
990c582b7e3Smrg    DRIQueryVersion(&major, &minor, &patch);
991c582b7e3Smrg    if (major != DRIINFO_MAJOR_VERSION || minor < 0) {
992c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
993c582b7e3Smrg		"[dri] R128DRIScreenInit failed because of a version mismatch.\n"
994c582b7e3Smrg		"[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n"
995c582b7e3Smrg		"[dri] Disabling the DRI.\n",
996c582b7e3Smrg		major, minor, patch,
997c582b7e3Smrg                DRIINFO_MAJOR_VERSION, 0);
998c582b7e3Smrg	return FALSE;
999c582b7e3Smrg    }
1000c582b7e3Smrg
1001c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
1002c582b7e3Smrg    case 8:
1003c582b7e3Smrg	/* These modes are not supported (yet). */
1004c582b7e3Smrg    case 15:
1005c582b7e3Smrg    case 24:
1006c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
1007c582b7e3Smrg		   "[dri] R128DRIScreenInit failed (depth %d not supported).  "
1008c582b7e3Smrg		   "[dri] Disabling DRI.\n", info->CurrentLayout.pixel_code);
1009c582b7e3Smrg	return FALSE;
1010c582b7e3Smrg
1011c582b7e3Smrg	/* Only 16 and 32 color depths are supports currently. */
1012c582b7e3Smrg    case 16:
1013c582b7e3Smrg    case 32:
1014c582b7e3Smrg	break;
1015c582b7e3Smrg    }
1016c582b7e3Smrg
1017c582b7e3Smrg    r128_drm_page_size = getpagesize();
1018c582b7e3Smrg
1019c582b7e3Smrg    /* Create the DRI data structure, and fill it in before calling the
1020c582b7e3Smrg       DRIScreenInit(). */
1021c582b7e3Smrg    if (!(pDRIInfo = DRICreateInfoRec())) return FALSE;
1022c582b7e3Smrg
1023c582b7e3Smrg    info->pDRIInfo                       = pDRIInfo;
1024c582b7e3Smrg    pDRIInfo->drmDriverName              = R128_DRIVER_NAME;
1025c582b7e3Smrg    pDRIInfo->clientDriverName           = R128_DRIVER_NAME;
1026c582b7e3Smrg    if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
1027c582b7e3Smrg	pDRIInfo->busIdString = DRICreatePCIBusID(info->PciInfo);
1028c582b7e3Smrg    } else {
1029c582b7e3Smrg	pDRIInfo->busIdString            = xalloc(64);
1030c582b7e3Smrg	sprintf(pDRIInfo->busIdString,
1031c582b7e3Smrg		"PCI:%d:%d:%d",
1032c582b7e3Smrg		PCI_DEV_BUS(info->PciInfo),
1033c582b7e3Smrg		PCI_DEV_DEV(info->PciInfo),
1034c582b7e3Smrg		PCI_DEV_FUNC(info->PciInfo));
1035c582b7e3Smrg    }
1036c582b7e3Smrg    pDRIInfo->ddxDriverMajorVersion      = R128_VERSION_MAJOR;
1037c582b7e3Smrg    pDRIInfo->ddxDriverMinorVersion      = R128_VERSION_MINOR;
1038c582b7e3Smrg    pDRIInfo->ddxDriverPatchVersion      = R128_VERSION_PATCH;
1039c582b7e3Smrg    pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr;
1040c582b7e3Smrg    pDRIInfo->frameBufferSize            = info->FbMapSize;
1041c582b7e3Smrg    pDRIInfo->frameBufferStride          = (pScrn->displayWidth *
1042c582b7e3Smrg					    info->CurrentLayout.pixel_bytes);
1043c582b7e3Smrg    pDRIInfo->ddxDrawableTableEntry      = R128_MAX_DRAWABLES;
1044c582b7e3Smrg    pDRIInfo->maxDrawableTableEntry      = (SAREA_MAX_DRAWABLES
1045c582b7e3Smrg					    < R128_MAX_DRAWABLES
1046c582b7e3Smrg					    ? SAREA_MAX_DRAWABLES
1047c582b7e3Smrg					    : R128_MAX_DRAWABLES);
1048c582b7e3Smrg
1049c582b7e3Smrg#ifdef NOT_DONE
1050c582b7e3Smrg    /* FIXME: Need to extend DRI protocol to pass this size back to
1051c582b7e3Smrg     * client for SAREA mapping that includes a device private record
1052c582b7e3Smrg     */
1053c582b7e3Smrg    pDRIInfo->SAREASize =
1054c582b7e3Smrg	((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */
1055c582b7e3Smrg    /* + shared memory device private rec */
1056c582b7e3Smrg#else
1057c582b7e3Smrg    /* For now the mapping works by using a fixed size defined
1058c582b7e3Smrg     * in the SAREA header
1059c582b7e3Smrg     */
1060c582b7e3Smrg    if (sizeof(XF86DRISAREARec)+sizeof(R128SAREAPriv)>SAREA_MAX) {
1061c582b7e3Smrg        xf86DrvMsg(pScreen->myNum, X_ERROR,
1062c582b7e3Smrg                   "[dri] Data does not fit in SAREA.  Disabling DRI.\n");
1063c582b7e3Smrg	return FALSE;
1064c582b7e3Smrg    }
1065c582b7e3Smrg    pDRIInfo->SAREASize = SAREA_MAX;
1066c582b7e3Smrg#endif
1067c582b7e3Smrg
1068c582b7e3Smrg    if (!(pR128DRI = (R128DRIPtr)xcalloc(sizeof(R128DRIRec),1))) {
1069c582b7e3Smrg	DRIDestroyInfoRec(info->pDRIInfo);
1070c582b7e3Smrg	info->pDRIInfo = NULL;
1071c582b7e3Smrg	return FALSE;
1072c582b7e3Smrg    }
1073c582b7e3Smrg    pDRIInfo->devPrivate     = pR128DRI;
1074c582b7e3Smrg    pDRIInfo->devPrivateSize = sizeof(R128DRIRec);
1075c582b7e3Smrg    pDRIInfo->contextSize    = sizeof(R128DRIContextRec);
1076c582b7e3Smrg
1077c582b7e3Smrg    pDRIInfo->CreateContext  = R128CreateContext;
1078c582b7e3Smrg    pDRIInfo->DestroyContext = R128DestroyContext;
1079c582b7e3Smrg    pDRIInfo->SwapContext    = R128DRISwapContext;
1080c582b7e3Smrg    pDRIInfo->InitBuffers    = R128DRIInitBuffers;
1081c582b7e3Smrg    pDRIInfo->MoveBuffers    = R128DRIMoveBuffers;
1082c582b7e3Smrg    pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
1083c582b7e3Smrg    pDRIInfo->TransitionTo2d = R128DRITransitionTo2d;
1084c582b7e3Smrg    pDRIInfo->TransitionTo3d = R128DRITransitionTo3d;
1085c582b7e3Smrg    pDRIInfo->TransitionSingleToMulti3D = R128DRITransitionSingleToMulti3d;
1086c582b7e3Smrg    pDRIInfo->TransitionMultiToSingle3D = R128DRITransitionMultiToSingle3d;
1087c582b7e3Smrg
1088c582b7e3Smrg    pDRIInfo->createDummyCtx     = TRUE;
1089c582b7e3Smrg    pDRIInfo->createDummyCtxPriv = FALSE;
1090c582b7e3Smrg
1091c582b7e3Smrg    if (!DRIScreenInit(pScreen, pDRIInfo, &info->drmFD)) {
1092c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR,
1093c582b7e3Smrg                   "[dri] DRIScreenInit failed.  Disabling DRI.\n");
1094c582b7e3Smrg	xfree(pDRIInfo->devPrivate);
1095c582b7e3Smrg	pDRIInfo->devPrivate = NULL;
1096c582b7e3Smrg	DRIDestroyInfoRec(pDRIInfo);
1097c582b7e3Smrg	pDRIInfo = NULL;
1098c582b7e3Smrg	return FALSE;
1099c582b7e3Smrg    }
1100c582b7e3Smrg
1101c582b7e3Smrg    /* Check the DRM lib version.
1102c582b7e3Smrg       drmGetLibVersion was not supported in version 1.0, so check for
1103c582b7e3Smrg       symbol first to avoid possible crash or hang.
1104c582b7e3Smrg     */
1105c582b7e3Smrg    if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
1106c582b7e3Smrg        version = drmGetLibVersion(info->drmFD);
1107c582b7e3Smrg    }
1108c582b7e3Smrg    else {
1109c582b7e3Smrg        /* drmlib version 1.0.0 didn't have the drmGetLibVersion
1110c582b7e3Smrg           entry point.  Fake it by allocating a version record
1111c582b7e3Smrg           via drmGetVersion and changing it to version 1.0.0
1112c582b7e3Smrg         */
1113c582b7e3Smrg        version = drmGetVersion(info->drmFD);
1114c582b7e3Smrg        version->version_major      = 1;
1115c582b7e3Smrg        version->version_minor      = 0;
1116c582b7e3Smrg        version->version_patchlevel = 0;
1117c582b7e3Smrg    }
1118c582b7e3Smrg
1119c582b7e3Smrg    if (version) {
1120c582b7e3Smrg	if (version->version_major != 1 ||
1121c582b7e3Smrg	    version->version_minor < 1) {
1122c582b7e3Smrg            /* incompatible drm library version */
1123c582b7e3Smrg            xf86DrvMsg(pScreen->myNum, X_ERROR,
1124c582b7e3Smrg		"[dri] R128DRIScreenInit failed because of a version mismatch.\n"
1125c582b7e3Smrg		"[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n"
1126c582b7e3Smrg		"[dri] Disabling DRI.\n",
1127c582b7e3Smrg                version->version_major,
1128c582b7e3Smrg                version->version_minor,
1129c582b7e3Smrg                version->version_patchlevel);
1130c582b7e3Smrg            drmFreeVersion(version);
1131c582b7e3Smrg	    R128DRICloseScreen(pScreen);
1132c582b7e3Smrg            return FALSE;
1133c582b7e3Smrg	}
1134c582b7e3Smrg	drmFreeVersion(version);
1135c582b7e3Smrg    }
1136c582b7e3Smrg
1137c582b7e3Smrg    /* Check the r128 DRM version */
1138c582b7e3Smrg    version = drmGetVersion(info->drmFD);
1139c582b7e3Smrg    if (version) {
1140c582b7e3Smrg	if (version->version_major != 2 ||
1141c582b7e3Smrg	    version->version_minor < 2) {
1142c582b7e3Smrg	    /* incompatible drm version */
1143c582b7e3Smrg	    xf86DrvMsg(pScreen->myNum, X_ERROR,
1144c582b7e3Smrg		"[dri] R128DRIScreenInit failed because of a version mismatch.\n"
1145c582b7e3Smrg		"[dri] r128.o kernel module version is %d.%d.%d but version 2.2 or greater is needed.\n"
1146c582b7e3Smrg		"[dri] Disabling the DRI.\n",
1147c582b7e3Smrg		version->version_major,
1148c582b7e3Smrg		version->version_minor,
1149c582b7e3Smrg		version->version_patchlevel);
1150c582b7e3Smrg	    drmFreeVersion(version);
1151c582b7e3Smrg	    R128DRICloseScreen(pScreen);
1152c582b7e3Smrg	    return FALSE;
1153c582b7e3Smrg	}
1154c582b7e3Smrg	info->drmMinor = version->version_minor;
1155c582b7e3Smrg	drmFreeVersion(version);
1156c582b7e3Smrg    }
1157c582b7e3Smrg
1158c582b7e3Smrg				/* Initialize AGP */
1159c582b7e3Smrg    if (!info->IsPCI && !R128DRIAgpInit(info, pScreen)) {
1160c582b7e3Smrg	info->IsPCI = TRUE;
1161c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_WARNING,
1162c582b7e3Smrg		   "[agp] AGP failed to initialize -- falling back to PCI mode.\n");
1163c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_WARNING,
1164c582b7e3Smrg		   "[agp] Make sure you have the agpgart kernel module loaded.\n");
1165c582b7e3Smrg    }
1166c582b7e3Smrg
1167c582b7e3Smrg				/* Initialize PCIGART */
1168c582b7e3Smrg    if (info->IsPCI && !R128DRIPciInit(info, pScreen)) {
1169c582b7e3Smrg	R128DRICloseScreen(pScreen);
1170c582b7e3Smrg	return FALSE;
1171c582b7e3Smrg    }
1172c582b7e3Smrg
1173c582b7e3Smrg				/* DRIScreenInit doesn't add all the
1174c582b7e3Smrg				   common mappings.  Add additional
1175c582b7e3Smrg				   mappings here. */
1176c582b7e3Smrg    if (!R128DRIMapInit(info, pScreen)) {
1177c582b7e3Smrg	R128DRICloseScreen(pScreen);
1178c582b7e3Smrg	return FALSE;
1179c582b7e3Smrg    }
1180c582b7e3Smrg
1181c582b7e3Smrg				/* DRIScreenInit adds the frame buffer
1182c582b7e3Smrg				   map, but we need it as well */
1183c582b7e3Smrg    {
1184c582b7e3Smrg	void *scratch_ptr;
1185c582b7e3Smrg        int scratch_int;
1186c582b7e3Smrg
1187c582b7e3Smrg	DRIGetDeviceInfo(pScreen, &info->fbHandle,
1188c582b7e3Smrg                         &scratch_int, &scratch_int,
1189c582b7e3Smrg                         &scratch_int, &scratch_int,
1190c582b7e3Smrg                         &scratch_ptr);
1191c582b7e3Smrg    }
1192c582b7e3Smrg
1193c582b7e3Smrg				/* FIXME: When are these mappings unmapped? */
1194c582b7e3Smrg
1195c582b7e3Smrg    if (!R128InitVisualConfigs(pScreen)) {
1196c582b7e3Smrg	R128DRICloseScreen(pScreen);
1197c582b7e3Smrg	return FALSE;
1198c582b7e3Smrg    }
1199c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n");
1200c582b7e3Smrg
1201c582b7e3Smrg    return TRUE;
1202c582b7e3Smrg}
1203c582b7e3Smrg
1204c582b7e3Smrg/* Finish initializing the device-dependent DRI state, and call
1205c582b7e3Smrg   DRIFinishScreenInit() to complete the device-independent DRI
1206c582b7e3Smrg   initialization. */
1207c582b7e3SmrgBool R128DRIFinishScreenInit(ScreenPtr pScreen)
1208c582b7e3Smrg{
1209c582b7e3Smrg    ScrnInfoPtr      pScrn = xf86Screens[pScreen->myNum];
1210c582b7e3Smrg    R128InfoPtr      info  = R128PTR(pScrn);
1211c582b7e3Smrg    R128SAREAPrivPtr pSAREAPriv;
1212c582b7e3Smrg    R128DRIPtr       pR128DRI;
1213c582b7e3Smrg
1214c582b7e3Smrg    info->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
1215c582b7e3Smrg    /* info->pDRIInfo->driverSwapMethod = DRI_SERVER_SWAP; */
1216c582b7e3Smrg
1217c582b7e3Smrg    /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit
1218c582b7e3Smrg       because *DRIKernelInit requires that the hardware lock is held by
1219c582b7e3Smrg       the X server, and the first time the hardware lock is grabbed is
1220c582b7e3Smrg       in DRIFinishScreenInit. */
1221c582b7e3Smrg    if (!DRIFinishScreenInit(pScreen)) {
1222c582b7e3Smrg	R128DRICloseScreen(pScreen);
1223c582b7e3Smrg	return FALSE;
1224c582b7e3Smrg    }
1225c582b7e3Smrg
1226c582b7e3Smrg    /* Initialize the kernel data structures */
1227c582b7e3Smrg    if (!R128DRIKernelInit(info, pScreen)) {
1228c582b7e3Smrg	R128DRICloseScreen(pScreen);
1229c582b7e3Smrg	return FALSE;
1230c582b7e3Smrg    }
1231c582b7e3Smrg
1232c582b7e3Smrg    /* Initialize the vertex buffers list */
1233c582b7e3Smrg    if (!R128DRIBufInit(info, pScreen)) {
1234c582b7e3Smrg	R128DRICloseScreen(pScreen);
1235c582b7e3Smrg	return FALSE;
1236c582b7e3Smrg    }
1237c582b7e3Smrg
1238c582b7e3Smrg    /* Initialize IRQ */
1239c582b7e3Smrg    R128DRIIrqInit(info, pScreen);
1240c582b7e3Smrg
1241c582b7e3Smrg    /* Initialize and start the CCE if required */
1242c582b7e3Smrg    R128DRICCEInit(pScrn);
1243c582b7e3Smrg
1244c582b7e3Smrg    pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScreen);
1245c582b7e3Smrg    memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
1246c582b7e3Smrg
1247c582b7e3Smrg    pR128DRI                    = (R128DRIPtr)info->pDRIInfo->devPrivate;
1248c582b7e3Smrg
1249c582b7e3Smrg    pR128DRI->deviceID          = info->Chipset;
1250c582b7e3Smrg    pR128DRI->width             = pScrn->virtualX;
1251c582b7e3Smrg    pR128DRI->height            = pScrn->virtualY;
1252c582b7e3Smrg    pR128DRI->depth             = pScrn->depth;
1253c582b7e3Smrg    pR128DRI->bpp               = pScrn->bitsPerPixel;
1254c582b7e3Smrg
1255c582b7e3Smrg    pR128DRI->IsPCI             = info->IsPCI;
1256c582b7e3Smrg    pR128DRI->AGPMode           = info->agpMode;
1257c582b7e3Smrg
1258c582b7e3Smrg    pR128DRI->frontOffset       = info->frontOffset;
1259c582b7e3Smrg    pR128DRI->frontPitch        = info->frontPitch;
1260c582b7e3Smrg    pR128DRI->backOffset        = info->backOffset;
1261c582b7e3Smrg    pR128DRI->backPitch         = info->backPitch;
1262c582b7e3Smrg    pR128DRI->depthOffset       = info->depthOffset;
1263c582b7e3Smrg    pR128DRI->depthPitch        = info->depthPitch;
1264c582b7e3Smrg    pR128DRI->spanOffset        = info->spanOffset;
1265c582b7e3Smrg    pR128DRI->textureOffset     = info->textureOffset;
1266c582b7e3Smrg    pR128DRI->textureSize       = info->textureSize;
1267c582b7e3Smrg    pR128DRI->log2TexGran       = info->log2TexGran;
1268c582b7e3Smrg
1269c582b7e3Smrg    pR128DRI->registerHandle    = info->registerHandle;
1270c582b7e3Smrg    pR128DRI->registerSize      = info->registerSize;
1271c582b7e3Smrg
1272c582b7e3Smrg    pR128DRI->agpTexHandle      = info->agpTexHandle;
1273c582b7e3Smrg    pR128DRI->agpTexMapSize     = info->agpTexMapSize;
1274c582b7e3Smrg    pR128DRI->log2AGPTexGran    = info->log2AGPTexGran;
1275c582b7e3Smrg    pR128DRI->agpTexOffset      = info->agpTexStart;
1276c582b7e3Smrg    pR128DRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
1277c582b7e3Smrg
1278c582b7e3Smrg    /* Have shadowfb run only while there is 3d active. */
1279c582b7e3Smrg    if (info->allowPageFlip && info->drmMinor >= 5 ) {
1280c582b7e3Smrg	ShadowFBInit( pScreen, R128DRIRefreshArea );
1281c582b7e3Smrg    } else if (info->allowPageFlip) {
1282c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_WARNING,
1283c582b7e3Smrg		   "[dri] Kernel module version 2.5.0 or newer is required for pageflipping.\n");
1284c582b7e3Smrg       info->allowPageFlip = 0;
1285c582b7e3Smrg    }
1286c582b7e3Smrg
1287c582b7e3Smrg    return TRUE;
1288c582b7e3Smrg}
1289c582b7e3Smrg
1290c582b7e3Smrg/* The screen is being closed, so clean up any state and free any
1291c582b7e3Smrg   resources used by the DRI. */
1292c582b7e3Smrgvoid R128DRICloseScreen(ScreenPtr pScreen)
1293c582b7e3Smrg{
1294c582b7e3Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1295c582b7e3Smrg    R128InfoPtr info = R128PTR(pScrn);
1296c582b7e3Smrg    drmR128Init drmInfo;
1297c582b7e3Smrg
1298c582b7e3Smrg				/* Stop the CCE if it is still in use */
1299c582b7e3Smrg    if (info->directRenderingEnabled) {
1300c582b7e3Smrg	R128CCE_STOP(pScrn, info);
1301c582b7e3Smrg    }
1302c582b7e3Smrg
1303c582b7e3Smrg    if (info->irq) {
1304c582b7e3Smrg	drmCtlUninstHandler(info->drmFD);
1305c582b7e3Smrg	info->irq = 0;
1306c582b7e3Smrg	info->gen_int_cntl = 0;
1307c582b7e3Smrg    }
1308c582b7e3Smrg
1309c582b7e3Smrg				/* De-allocate vertex buffers */
1310c582b7e3Smrg    if (info->buffers) {
1311c582b7e3Smrg	drmUnmapBufs(info->buffers);
1312c582b7e3Smrg	info->buffers = NULL;
1313c582b7e3Smrg    }
1314c582b7e3Smrg
1315c582b7e3Smrg				/* De-allocate all kernel resources */
1316c582b7e3Smrg    memset(&drmInfo, 0, sizeof(drmR128Init));
1317c582b7e3Smrg    drmInfo.func = DRM_R128_CLEANUP_CCE;
1318c582b7e3Smrg    drmCommandWrite(info->drmFD, DRM_R128_INIT,
1319c582b7e3Smrg                    &drmInfo, sizeof(drmR128Init));
1320c582b7e3Smrg
1321c582b7e3Smrg				/* De-allocate all AGP resources */
1322c582b7e3Smrg    if (info->agpTex) {
1323c582b7e3Smrg	drmUnmap(info->agpTex, info->agpTexMapSize);
1324c582b7e3Smrg	info->agpTex = NULL;
1325c582b7e3Smrg    }
1326c582b7e3Smrg    if (info->buf) {
1327c582b7e3Smrg	drmUnmap(info->buf, info->bufMapSize);
1328c582b7e3Smrg	info->buf = NULL;
1329c582b7e3Smrg    }
1330c582b7e3Smrg    if (info->ringReadPtr) {
1331c582b7e3Smrg	drmUnmap(info->ringReadPtr, info->ringReadMapSize);
1332c582b7e3Smrg	info->ringReadPtr = NULL;
1333c582b7e3Smrg    }
1334c582b7e3Smrg    if (info->ring) {
1335c582b7e3Smrg	drmUnmap(info->ring, info->ringMapSize);
1336c582b7e3Smrg	info->ring = NULL;
1337c582b7e3Smrg    }
1338c582b7e3Smrg    if (info->agpMemHandle != DRM_AGP_NO_HANDLE) {
1339c582b7e3Smrg	drmAgpUnbind(info->drmFD, info->agpMemHandle);
1340c582b7e3Smrg	drmAgpFree(info->drmFD, info->agpMemHandle);
1341c582b7e3Smrg	info->agpMemHandle = DRM_AGP_NO_HANDLE;
1342c582b7e3Smrg	drmAgpRelease(info->drmFD);
1343c582b7e3Smrg    }
1344c582b7e3Smrg    if (info->pciMemHandle) {
1345c582b7e3Smrg	drmScatterGatherFree(info->drmFD, info->pciMemHandle);
1346c582b7e3Smrg	info->pciMemHandle = 0;
1347c582b7e3Smrg    }
1348c582b7e3Smrg
1349c582b7e3Smrg				/* De-allocate all DRI resources */
1350c582b7e3Smrg    DRICloseScreen(pScreen);
1351c582b7e3Smrg
1352c582b7e3Smrg				/* De-allocate all DRI data structures */
1353c582b7e3Smrg    if (info->pDRIInfo) {
1354c582b7e3Smrg	if (info->pDRIInfo->devPrivate) {
1355c582b7e3Smrg	    xfree(info->pDRIInfo->devPrivate);
1356c582b7e3Smrg	    info->pDRIInfo->devPrivate = NULL;
1357c582b7e3Smrg	}
1358c582b7e3Smrg	DRIDestroyInfoRec(info->pDRIInfo);
1359c582b7e3Smrg	info->pDRIInfo = NULL;
1360c582b7e3Smrg    }
1361c582b7e3Smrg    if (info->pVisualConfigs) {
1362c582b7e3Smrg	xfree(info->pVisualConfigs);
1363c582b7e3Smrg	info->pVisualConfigs = NULL;
1364c582b7e3Smrg    }
1365c582b7e3Smrg    if (info->pVisualConfigsPriv) {
1366c582b7e3Smrg	xfree(info->pVisualConfigsPriv);
1367c582b7e3Smrg	info->pVisualConfigsPriv = NULL;
1368c582b7e3Smrg    }
1369c582b7e3Smrg}
1370c582b7e3Smrg
1371c582b7e3Smrg/* Use callbacks from dri.c to support pageflipping mode for a single
1372c582b7e3Smrg * 3d context without need for any specific full-screen extension.
1373c582b7e3Smrg */
1374c582b7e3Smrg
1375c582b7e3Smrg/* Use the shadowfb module to maintain a list of dirty rectangles.
1376c582b7e3Smrg * These are blitted to the back buffer to keep both buffers clean
1377c582b7e3Smrg * during page-flipping when the 3d application isn't fullscreen.
1378c582b7e3Smrg *
1379c582b7e3Smrg * Unlike most use of the shadowfb code, both buffers are in video memory.
1380c582b7e3Smrg *
1381c582b7e3Smrg * An alternative to this would be to organize for all on-screen drawing
1382c582b7e3Smrg * operations to be duplicated for the two buffers.  That might be
1383c582b7e3Smrg * faster, but seems like a lot more work...
1384c582b7e3Smrg */
1385c582b7e3Smrg
1386c582b7e3Smrg
1387c582b7e3Smrgstatic void R128DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
1388c582b7e3Smrg{
1389c582b7e3Smrg    R128InfoPtr         info       = R128PTR(pScrn);
1390c582b7e3Smrg    int                 i;
1391c582b7e3Smrg    R128SAREAPrivPtr    pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
1392c582b7e3Smrg
1393c582b7e3Smrg    /* Don't want to do this when no 3d is active and pages are
1394c582b7e3Smrg     * right-way-round
1395c582b7e3Smrg     */
1396c582b7e3Smrg    if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0)
1397c582b7e3Smrg	return;
1398c582b7e3Smrg
1399c582b7e3Smrg    (*info->accel->SetupForScreenToScreenCopy)(pScrn,
1400c582b7e3Smrg					       1, 1, GXcopy,
1401c582b7e3Smrg					       (CARD32)(-1), -1);
1402c582b7e3Smrg
1403c582b7e3Smrg    for (i = 0 ; i < num ; i++, pbox++) {
1404c582b7e3Smrg	int xa = max(pbox->x1, 0), xb = min(pbox->x2, pScrn->virtualX-1);
1405c582b7e3Smrg	int ya = max(pbox->y1, 0), yb = min(pbox->y2, pScrn->virtualY-1);
1406c582b7e3Smrg
1407c582b7e3Smrg	if (xa <= xb && ya <= yb) {
1408c582b7e3Smrg	    (*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya,
1409c582b7e3Smrg							 xa + info->backX,
1410c582b7e3Smrg							 ya + info->backY,
1411c582b7e3Smrg							 xb - xa + 1,
1412c582b7e3Smrg							 yb - ya + 1);
1413c582b7e3Smrg	}
1414c582b7e3Smrg    }
1415c582b7e3Smrg}
1416c582b7e3Smrg
1417c582b7e3Smrgstatic void R128EnablePageFlip(ScreenPtr pScreen)
1418c582b7e3Smrg{
1419c582b7e3Smrg    ScrnInfoPtr         pScrn      = xf86Screens[pScreen->myNum];
1420c582b7e3Smrg    R128InfoPtr         info       = R128PTR(pScrn);
1421c582b7e3Smrg    R128SAREAPrivPtr    pSAREAPriv = DRIGetSAREAPrivate(pScreen);
1422c582b7e3Smrg
1423c582b7e3Smrg    if (info->allowPageFlip) {
1424c582b7e3Smrg	/* Duplicate the frontbuffer to the backbuffer */
1425c582b7e3Smrg	(*info->accel->SetupForScreenToScreenCopy)(pScrn,
1426c582b7e3Smrg						   1, 1, GXcopy,
1427c582b7e3Smrg						   (CARD32)(-1), -1);
1428c582b7e3Smrg
1429c582b7e3Smrg	(*info->accel->SubsequentScreenToScreenCopy)(pScrn,
1430c582b7e3Smrg						     0,
1431c582b7e3Smrg						     0,
1432c582b7e3Smrg						     info->backX,
1433c582b7e3Smrg						     info->backY,
1434c582b7e3Smrg						     pScrn->virtualX,
1435c582b7e3Smrg						     pScrn->virtualY);
1436c582b7e3Smrg
1437c582b7e3Smrg	pSAREAPriv->pfAllowPageFlip = 1;
1438c582b7e3Smrg    }
1439c582b7e3Smrg}
1440c582b7e3Smrg
1441c582b7e3Smrgstatic void R128DisablePageFlip(ScreenPtr pScreen)
1442c582b7e3Smrg{
1443c582b7e3Smrg    /* Tell the clients not to pageflip.  How?
1444c582b7e3Smrg     *   -- Field in sarea, plus bumping the window counters.
1445c582b7e3Smrg     *   -- DRM needs to cope with Front-to-Back swapbuffers.
1446c582b7e3Smrg     */
1447c582b7e3Smrg    R128SAREAPrivPtr  pSAREAPriv = DRIGetSAREAPrivate(pScreen);
1448c582b7e3Smrg
1449c582b7e3Smrg    pSAREAPriv->pfAllowPageFlip = 0;
1450c582b7e3Smrg}
1451c582b7e3Smrg
1452c582b7e3Smrgstatic void R128DRITransitionSingleToMulti3d(ScreenPtr pScreen)
1453c582b7e3Smrg{
1454c582b7e3Smrg    R128DisablePageFlip(pScreen);
1455c582b7e3Smrg}
1456c582b7e3Smrg
1457c582b7e3Smrgstatic void R128DRITransitionMultiToSingle3d(ScreenPtr pScreen)
1458c582b7e3Smrg{
1459c582b7e3Smrg    /* Let the remaining 3d app start page flipping again */
1460c582b7e3Smrg    R128EnablePageFlip(pScreen);
1461c582b7e3Smrg}
1462c582b7e3Smrg
1463c582b7e3Smrgstatic void R128DRITransitionTo3d(ScreenPtr pScreen)
1464c582b7e3Smrg{
1465c582b7e3Smrg    ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
1466c582b7e3Smrg    R128InfoPtr    info  = R128PTR(pScrn);
1467c582b7e3Smrg
1468c582b7e3Smrg    R128EnablePageFlip(pScreen);
1469c582b7e3Smrg
1470c582b7e3Smrg    info->have3DWindows = 1;
1471c582b7e3Smrg
1472c582b7e3Smrg    if (info->cursor_start)
1473c582b7e3Smrg        xf86ForceHWCursor(pScreen, TRUE);
1474c582b7e3Smrg}
1475c582b7e3Smrg
1476c582b7e3Smrgstatic void R128DRITransitionTo2d(ScreenPtr pScreen)
1477c582b7e3Smrg{
1478c582b7e3Smrg    ScrnInfoPtr         pScrn      = xf86Screens[pScreen->myNum];
1479c582b7e3Smrg    R128InfoPtr         info       = R128PTR(pScrn);
1480c582b7e3Smrg    R128SAREAPrivPtr    pSAREAPriv = DRIGetSAREAPrivate(pScreen);
1481c582b7e3Smrg
1482c582b7e3Smrg    /* Try flipping back to the front page if necessary */
1483c582b7e3Smrg    if (pSAREAPriv->pfCurrentPage == 1)
1484c582b7e3Smrg	drmCommandNone(info->drmFD, DRM_R128_FLIP);
1485c582b7e3Smrg
1486c582b7e3Smrg    /* Shut down shadowing if we've made it back to the front page */
1487c582b7e3Smrg    if (pSAREAPriv->pfCurrentPage == 0) {
1488c582b7e3Smrg	R128DisablePageFlip(pScreen);
1489c582b7e3Smrg    } else {
1490c582b7e3Smrg	xf86DrvMsg(pScreen->myNum, X_WARNING,
1491c582b7e3Smrg		   "[dri] R128DRITransitionTo2d: "
1492c582b7e3Smrg		   "kernel failed to unflip buffers.\n");
1493c582b7e3Smrg    }
1494c582b7e3Smrg
1495c582b7e3Smrg    info->have3DWindows = 0;
1496c582b7e3Smrg
1497c582b7e3Smrg    if (info->cursor_start)
1498c582b7e3Smrg        xf86ForceHWCursor(pScreen, FALSE);
1499c582b7e3Smrg}
1500