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