radeon_exa.c revision ad43ddac
1/*
2 * Copyright 2005 Eric Anholt
3 * Copyright 2005 Benjamin Herrenschmidt
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Authors:
26 *    Eric Anholt <anholt@FreeBSD.org>
27 *    Zack Rusin <zrusin@trolltech.com>
28 *    Benjamin Herrenschmidt <benh@kernel.crashing.org>
29 *
30 */
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#include "radeon.h"
37#include "radeon_reg.h"
38#include "r600_reg.h"
39#ifdef XF86DRI
40#include "radeon_drm.h"
41#endif
42#include "radeon_macros.h"
43#include "radeon_probe.h"
44#include "radeon_version.h"
45
46#include "xf86.h"
47
48
49/***********************************************************************/
50#define RINFO_FROM_SCREEN(pScr) ScrnInfoPtr pScrn =  xf86Screens[pScr->myNum]; \
51    RADEONInfoPtr info   = RADEONPTR(pScrn)
52
53#define RADEON_TRACE_FALL 0
54#define RADEON_TRACE_DRAW 0
55
56#if RADEON_TRACE_FALL
57#define RADEON_FALLBACK(x)     		\
58do {					\
59	ErrorF("%s: ", __FUNCTION__);	\
60	ErrorF x;			\
61	return FALSE;			\
62} while (0)
63#else
64#define RADEON_FALLBACK(x) return FALSE
65#endif
66
67#if RADEON_TRACE_DRAW
68#define TRACE do { ErrorF("TRACE: %s\n", __FUNCTION__); } while(0)
69#else
70#define TRACE
71#endif
72
73static struct {
74    int rop;
75    int pattern;
76} RADEON_ROP[] = {
77    { RADEON_ROP3_ZERO, RADEON_ROP3_ZERO }, /* GXclear        */
78    { RADEON_ROP3_DSa,  RADEON_ROP3_DPa  }, /* Gxand          */
79    { RADEON_ROP3_SDna, RADEON_ROP3_PDna }, /* GXandReverse   */
80    { RADEON_ROP3_S,    RADEON_ROP3_P    }, /* GXcopy         */
81    { RADEON_ROP3_DSna, RADEON_ROP3_DPna }, /* GXandInverted  */
82    { RADEON_ROP3_D,    RADEON_ROP3_D    }, /* GXnoop         */
83    { RADEON_ROP3_DSx,  RADEON_ROP3_DPx  }, /* GXxor          */
84    { RADEON_ROP3_DSo,  RADEON_ROP3_DPo  }, /* GXor           */
85    { RADEON_ROP3_DSon, RADEON_ROP3_DPon }, /* GXnor          */
86    { RADEON_ROP3_DSxn, RADEON_ROP3_PDxn }, /* GXequiv        */
87    { RADEON_ROP3_Dn,   RADEON_ROP3_Dn   }, /* GXinvert       */
88    { RADEON_ROP3_SDno, RADEON_ROP3_PDno }, /* GXorReverse    */
89    { RADEON_ROP3_Sn,   RADEON_ROP3_Pn   }, /* GXcopyInverted */
90    { RADEON_ROP3_DSno, RADEON_ROP3_DPno }, /* GXorInverted   */
91    { RADEON_ROP3_DSan, RADEON_ROP3_DPan }, /* GXnand         */
92    { RADEON_ROP3_ONE,  RADEON_ROP3_ONE  }  /* GXset          */
93};
94
95/* Compute log base 2 of val. */
96static __inline__ int
97RADEONLog2(int val)
98{
99	int bits;
100#if (defined __i386__ || defined __x86_64__) && (defined __GNUC__)
101	__asm volatile("bsrl	%1, %0"
102		: "=r" (bits)
103		: "c" (val)
104	);
105	return bits;
106#else
107	for (bits = 0; val != 0; val >>= 1, ++bits)
108		;
109	return bits - 1;
110#endif
111}
112
113static __inline__ uint32_t F_TO_DW(float val)
114{
115    union {
116	float f;
117	uint32_t l;
118    } tmp;
119    tmp.f = val;
120    return tmp.l;
121}
122
123
124#ifdef XF86DRM_MODE
125
126static inline void radeon_add_pixmap(struct radeon_cs *cs, PixmapPtr pPix, int read_domains, int write_domain)
127{
128    struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix);
129
130    radeon_cs_space_add_persistent_bo(cs, driver_priv->bo, read_domains, write_domain);
131}
132
133#endif /* XF86DRM_MODE */
134
135
136/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
137 * require src and dest datatypes to be equal.
138 */
139Bool RADEONGetDatatypeBpp(int bpp, uint32_t *type)
140{
141	switch (bpp) {
142	case 8:
143		*type = ATI_DATATYPE_CI8;
144		return TRUE;
145	case 16:
146		*type = ATI_DATATYPE_RGB565;
147		return TRUE;
148	case 24:
149		*type = ATI_DATATYPE_CI8;
150		return TRUE;
151	case 32:
152		*type = ATI_DATATYPE_ARGB8888;
153		return TRUE;
154	default:
155		RADEON_FALLBACK(("Unsupported bpp: %d\n", bpp));
156		return FALSE;
157	}
158}
159
160static Bool RADEONPixmapIsColortiled(PixmapPtr pPix)
161{
162    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
163
164    /* This doesn't account for the back buffer, which we may want to wrap in
165     * a pixmap at some point for the purposes of DRI buffer moves.
166     */
167    if (info->tilingEnabled && exaGetPixmapOffset(pPix) == 0)
168	return TRUE;
169    else
170	return FALSE;
171}
172
173static Bool RADEONGetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset,
174				 unsigned int offset, unsigned int pitch)
175{
176	RINFO_FROM_SCREEN(pPix->drawable.pScreen);
177
178	if (pitch > 16320 || pitch % info->accel_state->exa->pixmapPitchAlign != 0)
179		RADEON_FALLBACK(("Bad pitch 0x%08x\n", pitch));
180
181	if (offset % info->accel_state->exa->pixmapOffsetAlign != 0)
182		RADEON_FALLBACK(("Bad offset 0x%08x\n", offset));
183
184	pitch = pitch >> 6;
185	*pitch_offset = (pitch << 22) | (offset >> 10);
186
187	/* If it's the front buffer, we've got to note that it's tiled? */
188	if (RADEONPixmapIsColortiled(pPix))
189		*pitch_offset |= RADEON_DST_TILE_MACRO;
190	return TRUE;
191}
192
193Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
194{
195	uint32_t pitch, offset;
196	int bpp;
197
198	bpp = pPix->drawable.bitsPerPixel;
199	if (bpp == 24)
200		bpp = 8;
201
202	offset = radeonGetPixmapOffset(pPix);
203	pitch = exaGetPixmapPitch(pPix);
204
205	return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
206}
207
208#if X_BYTE_ORDER == X_BIG_ENDIAN
209
210static unsigned long swapper_surfaces[6];
211
212static Bool RADEONPrepareAccess_BE(PixmapPtr pPix, int index)
213{
214    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
215    unsigned char *RADEONMMIO = info->MMIO;
216    uint32_t offset = exaGetPixmapOffset(pPix);
217    int bpp, soff;
218    uint32_t size, flags;
219
220    /* Front buffer is always set with proper swappers */
221    if (offset == 0)
222        return TRUE;
223
224    /* If same bpp as front buffer, just do nothing as the main
225     * swappers will apply
226     */
227    bpp = pPix->drawable.bitsPerPixel;
228    if (bpp == pScrn->bitsPerPixel)
229        return TRUE;
230
231    /* We need to setup a separate swapper, let's request a
232     * surface. We need to align the size first
233     */
234    size = exaGetPixmapSize(pPix);
235    size = RADEON_ALIGN(size, RADEON_GPU_PAGE_SIZE);
236
237    /* Set surface to tiling disabled with appropriate swapper */
238    switch (bpp) {
239    case 16:
240        flags = RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP;
241	break;
242    case 32:
243        flags = RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP;
244	break;
245    default:
246        flags = 0;
247    }
248#if defined(XF86DRI)
249    if (info->directRenderingEnabled && info->allowColorTiling) {
250	struct drm_radeon_surface_alloc drmsurfalloc;
251	int rc;
252
253        drmsurfalloc.address = offset;
254        drmsurfalloc.size = size;
255	drmsurfalloc.flags = flags | 1; /* bogus pitch to please DRM */
256
257        rc = drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_ALLOC,
258			     &drmsurfalloc, sizeof(drmsurfalloc));
259	if (rc < 0) {
260	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
261		       "drm: could not allocate surface for access"
262		       " swapper, err: %d!\n", rc);
263	    return FALSE;
264	}
265	swapper_surfaces[index] = offset;
266
267	return TRUE;
268    }
269#endif
270    soff = (index + 1) * 0x10;
271    OUTREG(RADEON_SURFACE0_INFO + soff, flags);
272    OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset);
273    OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1);
274    swapper_surfaces[index] = offset;
275    return TRUE;
276}
277
278static void RADEONFinishAccess_BE(PixmapPtr pPix, int index)
279{
280    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
281    unsigned char *RADEONMMIO = info->MMIO;
282    uint32_t offset = exaGetPixmapOffset(pPix);
283    int soff;
284
285    /* Front buffer is always set with proper swappers */
286    if (offset == 0)
287        return;
288
289    if (swapper_surfaces[index] == 0)
290        return;
291#if defined(XF86DRI)
292    if (info->directRenderingEnabled && info->allowColorTiling) {
293	struct drm_radeon_surface_free drmsurffree;
294
295	drmsurffree.address = offset;
296	drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_FREE,
297			&drmsurffree, sizeof(drmsurffree));
298	swapper_surfaces[index] = 0;
299	return;
300    }
301#endif
302    soff = (index + 1) * 0x10;
303    OUTREG(RADEON_SURFACE0_INFO + soff, 0);
304    OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, 0);
305    OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, 0);
306    swapper_surfaces[index] = 0;
307}
308
309#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
310
311#ifdef XF86DRM_MODE
312Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
313{
314    ScreenPtr pScreen = pPix->drawable.pScreen;
315    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
316    RADEONInfoPtr info = RADEONPTR(pScrn);
317    struct radeon_exa_pixmap_priv *driver_priv;
318    int ret;
319
320#if X_BYTE_ORDER == X_BIG_ENDIAN
321    /* May need to handle byte swapping in DownloadFrom/UploadToScreen */
322    if (pPix->drawable.bitsPerPixel > 8 &&
323	pPix != pScreen->GetScreenPixmap(pScreen))
324	return FALSE;
325#endif
326
327    driver_priv = exaGetPixmapDriverPrivate(pPix);
328    if (!driver_priv)
329      return FALSE;
330
331    /* if we have more refs than just the BO then flush */
332    if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs))
333        radeon_cs_flush_indirect(pScrn);
334
335    /* flush IB */
336    ret = radeon_bo_map(driver_priv->bo, 1);
337    if (ret) {
338      FatalError("failed to map pixmap %d\n", ret);
339      return FALSE;
340    }
341    driver_priv->bo_mapped = TRUE;
342
343    pPix->devPrivate.ptr = driver_priv->bo->ptr;
344
345    return TRUE;
346}
347
348void RADEONFinishAccess_CS(PixmapPtr pPix, int index)
349{
350    struct radeon_exa_pixmap_priv *driver_priv;
351
352    driver_priv = exaGetPixmapDriverPrivate(pPix);
353    if (!driver_priv || !driver_priv->bo_mapped)
354        return;
355
356    radeon_bo_unmap(driver_priv->bo);
357    pPix->devPrivate.ptr = NULL;
358}
359
360
361void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
362{
363    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
364    RADEONInfoPtr info = RADEONPTR(pScrn);
365    struct radeon_exa_pixmap_priv *new_priv;
366
367#ifdef EXA_MIXED_PIXMAPS
368    if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) {
369        if (size != 0 && !info->exa_force_create &&
370	    info->exa_pixmaps == FALSE)
371            return NULL;
372    }
373#endif
374
375    new_priv = xcalloc(1, sizeof(struct radeon_exa_pixmap_priv));
376    if (!new_priv)
377	return NULL;
378
379    if (size == 0)
380	return new_priv;
381
382    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, align,
383				  RADEON_GEM_DOMAIN_VRAM, 0);
384    if (!new_priv->bo) {
385	xfree(new_priv);
386	ErrorF("Failed to alloc memory\n");
387	return NULL;
388    }
389
390    return new_priv;
391
392}
393
394void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
395			     int depth, int usage_hint, int bitsPerPixel,
396			     int *new_pitch)
397{
398    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
399    RADEONInfoPtr info = RADEONPTR(pScrn);
400    struct radeon_exa_pixmap_priv *new_priv;
401    int padded_width;
402    uint32_t size;
403    uint32_t tiling = 0;
404    int pixmap_align;
405
406#ifdef EXA_MIXED_PIXMAPS
407    if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) {
408	if (width != 0 && height != 0 && !info->exa_force_create &&
409	    info->exa_pixmaps == FALSE)
410            return NULL;
411    }
412#endif
413
414    if (usage_hint) {
415	if (info->allowColorTiling) {
416    	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO)
417 	   	tiling |= RADEON_TILING_MACRO;
418    	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO)
419                tiling |= RADEON_TILING_MICRO;
420	}
421    }
422
423    if (tiling) {
424	height = RADEON_ALIGN(height, 16);
425	pixmap_align = 256;
426    } else
427	pixmap_align = 64;
428
429    padded_width = ((width * bitsPerPixel + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
430    padded_width = RADEON_ALIGN(padded_width, pixmap_align);
431    size = height * padded_width;
432
433    new_priv = xcalloc(1, sizeof(struct radeon_exa_pixmap_priv));
434    if (!new_priv)
435	return NULL;
436
437    if (size == 0)
438	return new_priv;
439
440    *new_pitch = padded_width;
441
442    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, 0,
443				  RADEON_GEM_DOMAIN_VRAM, 0);
444    if (!new_priv->bo) {
445	xfree(new_priv);
446	ErrorF("Failed to alloc memory\n");
447	return NULL;
448    }
449
450    if (tiling)
451	radeon_bo_set_tiling(new_priv->bo, tiling, *new_pitch);
452
453    return new_priv;
454}
455
456void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
457{
458    struct radeon_exa_pixmap_priv *driver_priv = driverPriv;
459
460    if (!driverPriv)
461      return;
462
463    if (driver_priv->bo)
464	radeon_bo_unref(driver_priv->bo);
465    xfree(driverPriv);
466}
467
468struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
469{
470    struct radeon_exa_pixmap_priv *driver_priv;
471    driver_priv = exaGetPixmapDriverPrivate(pPix);
472    return driver_priv->bo;
473}
474
475void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
476{
477    struct radeon_exa_pixmap_priv *driver_priv;
478
479    driver_priv = exaGetPixmapDriverPrivate(pPix);
480    if (driver_priv) {
481	if (driver_priv->bo)
482	    radeon_bo_unref(driver_priv->bo);
483
484	radeon_bo_ref(bo);
485	driver_priv->bo = bo;
486    }
487}
488
489Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix)
490{
491    struct radeon_exa_pixmap_priv *driver_priv;
492
493    driver_priv = exaGetPixmapDriverPrivate(pPix);
494
495    if (!driver_priv)
496       return FALSE;
497    if (driver_priv->bo)
498       return TRUE;
499    return FALSE;
500}
501#endif
502
503#define ENTER_DRAW(x) TRACE
504#define LEAVE_DRAW(x) TRACE
505/***********************************************************************/
506
507#define ACCEL_MMIO
508#define ACCEL_PREAMBLE()	unsigned char *RADEONMMIO = info->MMIO
509#define BEGIN_ACCEL(n)		RADEONWaitForFifo(pScrn, (n))
510#define OUT_ACCEL_REG(reg, val)	OUTREG(reg, val)
511#define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val))
512#define OUT_RELOC(x, read, write)            do {} while(0)
513#define FINISH_ACCEL()
514
515#ifdef RENDER
516#include "radeon_exa_render.c"
517#endif
518#include "radeon_exa_funcs.c"
519
520#undef ACCEL_MMIO
521#undef ACCEL_PREAMBLE
522#undef BEGIN_ACCEL
523#undef OUT_ACCEL_REG
524#undef OUT_ACCEL_REG_F
525#undef FINISH_ACCEL
526#undef OUT_RELOC
527
528#ifdef XF86DRI
529
530#define ACCEL_CP
531#define ACCEL_PREAMBLE()						\
532    RING_LOCALS;							\
533    RADEONCP_REFRESH(pScrn, info)
534#define BEGIN_ACCEL(n)		BEGIN_RING(2*(n))
535#define OUT_ACCEL_REG(reg, val)	OUT_RING_REG(reg, val)
536#define FINISH_ACCEL()		ADVANCE_RING()
537#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write)
538
539#define OUT_RING_F(x) OUT_RING(F_TO_DW(x))
540
541#ifdef RENDER
542#include "radeon_exa_render.c"
543#endif
544#include "radeon_exa_funcs.c"
545
546#undef ACCEL_CP
547#undef ACCEL_PREAMBLE
548#undef BEGIN_ACCEL
549#undef OUT_ACCEL_REG
550#undef FINISH_ACCEL
551#undef OUT_RING_F
552
553#endif /* XF86DRI */
554
555/*
556 * Once screen->off_screen_base is set, this function
557 * allocates the remaining memory appropriately
558 */
559Bool RADEONSetupMemEXA (ScreenPtr pScreen)
560{
561    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
562    RADEONInfoPtr info = RADEONPTR(pScrn);
563    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
564    int cpp = info->CurrentLayout.pixel_bytes;
565    int screen_size;
566    int byteStride = pScrn->displayWidth * cpp;
567
568    if (info->accel_state->exa != NULL) {
569	xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n");
570	return FALSE;
571    }
572    info->accel_state->exa = exaDriverAlloc();
573    if (info->accel_state->exa == NULL)
574	return FALSE;
575
576    /* Need to adjust screen size for 16 line tiles, and then make it align to.
577     * the buffer alignment requirement.
578     */
579    if (info->allowColorTiling)
580	screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride;
581    else
582	screen_size = pScrn->virtualY * byteStride;
583
584    info->accel_state->exa->memoryBase = info->FB;
585    info->accel_state->exa->memorySize = info->FbMapSize - info->FbSecureSize;
586    info->accel_state->exa->offScreenBase = screen_size;
587
588    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n",
589	       info->accel_state->exa->memorySize / 1024);
590
591    /* Reserve static area for hardware cursor */
592    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
593        int cursor_size = 64 * 4 * 64;
594        int align = IS_AVIVO_VARIANT ? 4096 : 256;
595        int c;
596
597        for (c = 0; c < xf86_config->num_crtc; c++) {
598            xf86CrtcPtr crtc = xf86_config->crtc[c];
599            RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
600
601            radeon_crtc->cursor_offset =
602                RADEON_ALIGN(info->accel_state->exa->offScreenBase, align);
603            info->accel_state->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size;
604
605            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
606                       "Will use %d kb for hardware cursor %d at offset 0x%08x\n",
607                       (cursor_size * xf86_config->num_crtc) / 1024,
608                       c,
609                       (unsigned int)radeon_crtc->cursor_offset);
610        }
611    }
612
613#if defined(XF86DRI)
614    if (info->directRenderingEnabled) {
615	int depthCpp = (info->dri->depthBits - 8) / 4, l, next, depth_size;
616
617	info->dri->frontOffset = 0;
618	info->dri->frontPitch = pScrn->displayWidth;
619
620        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
621	       "Will use %d kb for front buffer at offset 0x%08x\n",
622	       screen_size / 1024, info->dri->frontOffset);
623	RADEONDRIAllocatePCIGARTTable(pScreen);
624
625	if (info->cardType==CARD_PCIE)
626	  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
627		     "Will use %d kb for PCI GART at offset 0x%08x\n",
628		     info->dri->pciGartSize / 1024,
629		     (int)info->dri->pciGartOffset);
630
631	/* Reserve a static area for the back buffer the same size as the
632	 * visible screen.  XXX: This would be better initialized in ati_dri.c
633	 * when GLX is set up, but the offscreen memory manager's allocations
634	 * don't last through VT switches, while the kernel's understanding of
635	 * offscreen locations does.
636	 */
637	info->dri->backPitch = pScrn->displayWidth;
638	next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE);
639	if (!info->dri->noBackBuffer &&
640	    next + screen_size <= info->accel_state->exa->memorySize)
641	{
642	    info->dri->backOffset = next;
643	    info->accel_state->exa->offScreenBase = next + screen_size;
644	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
645		       "Will use %d kb for back buffer at offset 0x%08x\n",
646		       screen_size / 1024, info->dri->backOffset);
647	}
648
649	/* Reserve the static depth buffer, and adjust pitch and height to
650	 * handle tiling.
651	 */
652	info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32);
653	depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp;
654	next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE);
655	if (next + depth_size <= info->accel_state->exa->memorySize)
656	{
657	    info->dri->depthOffset = next;
658	    info->accel_state->exa->offScreenBase = next + depth_size;
659	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
660		       "Will use %d kb for depth buffer at offset 0x%08x\n",
661		       depth_size / 1024, info->dri->depthOffset);
662	}
663
664	info->dri->textureSize *= (info->accel_state->exa->memorySize -
665				   info->accel_state->exa->offScreenBase) / 100;
666
667	l = RADEONLog2(info->dri->textureSize / RADEON_NR_TEX_REGIONS);
668	if (l < RADEON_LOG_TEX_GRANULARITY)
669	    l = RADEON_LOG_TEX_GRANULARITY;
670	info->dri->textureSize = (info->dri->textureSize >> l) << l;
671	if (info->dri->textureSize >= 512 * 1024) {
672	    info->dri->textureOffset = info->accel_state->exa->offScreenBase;
673	    info->accel_state->exa->offScreenBase += info->dri->textureSize;
674	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
675		       "Will use %d kb for textures at offset 0x%08x\n",
676		       info->dri->textureSize / 1024, info->dri->textureOffset);
677	} else {
678	    /* Minimum texture size is for 2 256x256x32bpp textures */
679	    info->dri->textureSize = 0;
680	}
681    } else
682#endif /* XF86DRI */
683    	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
684		       "Will use %d kb for front buffer at offset 0x%08x\n",
685		       screen_size / 1024, 0);
686
687    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
688	       "Will use %ld kb for X Server offscreen at offset 0x%08lx\n",
689	       (info->accel_state->exa->memorySize - info->accel_state->exa->offScreenBase) /
690	       1024, info->accel_state->exa->offScreenBase);
691
692    return TRUE;
693}
694
695#ifdef XF86DRI
696
697#ifndef ExaOffscreenMarkUsed
698extern void ExaOffscreenMarkUsed(PixmapPtr);
699#endif
700
701unsigned long long
702RADEONTexOffsetStart(PixmapPtr pPix)
703{
704    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
705    unsigned long long offset;
706
707    if (exaGetPixmapDriverPrivate(pPix))
708	return -1;
709
710    exaMoveInPixmap(pPix);
711    ExaOffscreenMarkUsed(pPix);
712
713    offset = exaGetPixmapOffset(pPix);
714
715    if (offset > info->FbMapSize)
716	return ~0ULL;
717    else
718	return info->fbLocation + offset;
719}
720#endif
721