radeon_exa.c revision 0974d292
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#include "radeon_exa_shared.h"
46
47#include "xf86.h"
48
49
50/***********************************************************************/
51#define RINFO_FROM_SCREEN(pScr) ScrnInfoPtr pScrn =  xf86Screens[pScr->myNum]; \
52    RADEONInfoPtr info   = RADEONPTR(pScrn)
53
54static struct {
55    int rop;
56    int pattern;
57} RADEON_ROP[] = {
58    { RADEON_ROP3_ZERO, RADEON_ROP3_ZERO }, /* GXclear        */
59    { RADEON_ROP3_DSa,  RADEON_ROP3_DPa  }, /* Gxand          */
60    { RADEON_ROP3_SDna, RADEON_ROP3_PDna }, /* GXandReverse   */
61    { RADEON_ROP3_S,    RADEON_ROP3_P    }, /* GXcopy         */
62    { RADEON_ROP3_DSna, RADEON_ROP3_DPna }, /* GXandInverted  */
63    { RADEON_ROP3_D,    RADEON_ROP3_D    }, /* GXnoop         */
64    { RADEON_ROP3_DSx,  RADEON_ROP3_DPx  }, /* GXxor          */
65    { RADEON_ROP3_DSo,  RADEON_ROP3_DPo  }, /* GXor           */
66    { RADEON_ROP3_DSon, RADEON_ROP3_DPon }, /* GXnor          */
67    { RADEON_ROP3_DSxn, RADEON_ROP3_PDxn }, /* GXequiv        */
68    { RADEON_ROP3_Dn,   RADEON_ROP3_Dn   }, /* GXinvert       */
69    { RADEON_ROP3_SDno, RADEON_ROP3_PDno }, /* GXorReverse    */
70    { RADEON_ROP3_Sn,   RADEON_ROP3_Pn   }, /* GXcopyInverted */
71    { RADEON_ROP3_DSno, RADEON_ROP3_DPno }, /* GXorInverted   */
72    { RADEON_ROP3_DSan, RADEON_ROP3_DPan }, /* GXnand         */
73    { RADEON_ROP3_ONE,  RADEON_ROP3_ONE  }  /* GXset          */
74};
75
76/* Compute log base 2 of val. */
77static __inline__ int
78RADEONLog2(int val)
79{
80	int bits;
81#if (defined __i386__ || defined __x86_64__) && (defined __GNUC__)
82	__asm volatile("bsrl	%1, %0"
83		: "=r" (bits)
84		: "c" (val)
85	);
86	return bits;
87#else
88	for (bits = 0; val != 0; val >>= 1, ++bits)
89		;
90	return bits - 1;
91#endif
92}
93
94static __inline__ uint32_t F_TO_DW(float val)
95{
96    union {
97	float f;
98	uint32_t l;
99    } tmp;
100    tmp.f = val;
101    return tmp.l;
102}
103
104
105/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
106 * require src and dest datatypes to be equal.
107 */
108Bool RADEONGetDatatypeBpp(int bpp, uint32_t *type)
109{
110	switch (bpp) {
111	case 8:
112		*type = ATI_DATATYPE_CI8;
113		return TRUE;
114	case 16:
115		*type = ATI_DATATYPE_RGB565;
116		return TRUE;
117	case 24:
118		*type = ATI_DATATYPE_CI8;
119		return TRUE;
120	case 32:
121		*type = ATI_DATATYPE_ARGB8888;
122		return TRUE;
123	default:
124		RADEON_FALLBACK(("Unsupported bpp: %d\n", bpp));
125		return FALSE;
126	}
127}
128
129static Bool RADEONPixmapIsColortiled(PixmapPtr pPix)
130{
131    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
132
133    /* This doesn't account for the back buffer, which we may want to wrap in
134     * a pixmap at some point for the purposes of DRI buffer moves.
135     */
136    if (info->tilingEnabled && exaGetPixmapOffset(pPix) == 0)
137	return TRUE;
138    else
139	return FALSE;
140}
141
142static Bool RADEONGetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset,
143				 unsigned int offset, unsigned int pitch)
144{
145	RINFO_FROM_SCREEN(pPix->drawable.pScreen);
146
147	if (pitch > 16320 || pitch % info->accel_state->exa->pixmapPitchAlign != 0)
148		RADEON_FALLBACK(("Bad pitch 0x%08x\n", pitch));
149
150	if (offset % info->accel_state->exa->pixmapOffsetAlign != 0)
151		RADEON_FALLBACK(("Bad offset 0x%08x\n", offset));
152
153	pitch = pitch >> 6;
154	*pitch_offset = (pitch << 22) | (offset >> 10);
155
156	/* If it's the front buffer, we've got to note that it's tiled? */
157	if (RADEONPixmapIsColortiled(pPix))
158		*pitch_offset |= RADEON_DST_TILE_MACRO;
159	return TRUE;
160}
161
162Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
163{
164	uint32_t pitch, offset;
165	int bpp;
166
167	bpp = pPix->drawable.bitsPerPixel;
168	if (bpp == 24)
169		bpp = 8;
170
171	offset = radeonGetPixmapOffset(pPix);
172	pitch = exaGetPixmapPitch(pPix);
173
174	return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
175}
176
177#if X_BYTE_ORDER == X_BIG_ENDIAN
178
179static unsigned long swapper_surfaces[6];
180
181static Bool RADEONPrepareAccess_BE(PixmapPtr pPix, int index)
182{
183    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
184    unsigned char *RADEONMMIO = info->MMIO;
185    uint32_t offset = exaGetPixmapOffset(pPix);
186    int bpp, soff;
187    uint32_t size, flags;
188
189    /* Front buffer is always set with proper swappers */
190    if (offset == 0)
191        return TRUE;
192
193    /* If same bpp as front buffer, just do nothing as the main
194     * swappers will apply
195     */
196    bpp = pPix->drawable.bitsPerPixel;
197    if (bpp == pScrn->bitsPerPixel)
198        return TRUE;
199
200    /* We need to setup a separate swapper, let's request a
201     * surface. We need to align the size first
202     */
203    size = exaGetPixmapSize(pPix);
204    size = RADEON_ALIGN(size, RADEON_GPU_PAGE_SIZE);
205
206    /* Set surface to tiling disabled with appropriate swapper */
207    switch (bpp) {
208    case 16:
209        flags = RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP;
210	break;
211    case 32:
212        flags = RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP;
213	break;
214    default:
215        flags = 0;
216    }
217#if defined(XF86DRI)
218    if (info->directRenderingEnabled && info->allowColorTiling) {
219	struct drm_radeon_surface_alloc drmsurfalloc;
220	int rc;
221
222        drmsurfalloc.address = offset;
223        drmsurfalloc.size = size;
224	drmsurfalloc.flags = flags | 1; /* bogus pitch to please DRM */
225
226        rc = drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_ALLOC,
227			     &drmsurfalloc, sizeof(drmsurfalloc));
228	if (rc < 0) {
229	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
230		       "drm: could not allocate surface for access"
231		       " swapper, err: %d!\n", rc);
232	    return FALSE;
233	}
234	swapper_surfaces[index] = offset;
235
236	return TRUE;
237    }
238#endif
239    soff = (index + 1) * 0x10;
240    OUTREG(RADEON_SURFACE0_INFO + soff, flags);
241    OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset);
242    OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1);
243    swapper_surfaces[index] = offset;
244    return TRUE;
245}
246
247static void RADEONFinishAccess_BE(PixmapPtr pPix, int index)
248{
249    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
250    unsigned char *RADEONMMIO = info->MMIO;
251    uint32_t offset = exaGetPixmapOffset(pPix);
252    int soff;
253
254    /* Front buffer is always set with proper swappers */
255    if (offset == 0)
256        return;
257
258    if (swapper_surfaces[index] == 0)
259        return;
260#if defined(XF86DRI)
261    if (info->directRenderingEnabled && info->allowColorTiling) {
262	struct drm_radeon_surface_free drmsurffree;
263
264	drmsurffree.address = offset;
265	drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_FREE,
266			&drmsurffree, sizeof(drmsurffree));
267	swapper_surfaces[index] = 0;
268	return;
269    }
270#endif
271    soff = (index + 1) * 0x10;
272    OUTREG(RADEON_SURFACE0_INFO + soff, 0);
273    OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, 0);
274    OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, 0);
275    swapper_surfaces[index] = 0;
276}
277
278#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
279
280#ifdef XF86DRM_MODE
281Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
282{
283    ScreenPtr pScreen = pPix->drawable.pScreen;
284    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
285    RADEONInfoPtr info = RADEONPTR(pScrn);
286    struct radeon_exa_pixmap_priv *driver_priv;
287    uint32_t possible_domains = ~0U;
288    uint32_t current_domain = 0;
289#ifdef EXA_MIXED_PIXMAPS
290    Bool can_fail = !(pPix->drawable.bitsPerPixel < 8) &&
291	pPix != pScreen->GetScreenPixmap(pScreen) &&
292        (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS);
293#else
294    Bool can_fail = FALSE;
295#endif
296    Bool flush = FALSE;
297    int ret;
298
299#if X_BYTE_ORDER == X_BIG_ENDIAN
300    /* May need to handle byte swapping in DownloadFrom/UploadToScreen */
301    if (can_fail && pPix->drawable.bitsPerPixel > 8)
302	return FALSE;
303#endif
304
305    driver_priv = exaGetPixmapDriverPrivate(pPix);
306    if (!driver_priv)
307      return FALSE;
308
309    /* if we have more refs than just the BO then flush */
310    if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) {
311	flush = TRUE;
312
313	if (can_fail) {
314	    possible_domains = radeon_bo_get_src_domain(driver_priv->bo);
315	    if (possible_domains == RADEON_GEM_DOMAIN_VRAM)
316		return FALSE; /* use DownloadFromScreen */
317	}
318    }
319
320    /* if the BO might end up in VRAM, prefer DownloadFromScreen */
321    if (can_fail && (possible_domains & RADEON_GEM_DOMAIN_VRAM)) {
322	radeon_bo_is_busy(driver_priv->bo, &current_domain);
323
324	if (current_domain & possible_domains) {
325	    if (current_domain == RADEON_GEM_DOMAIN_VRAM)
326		return FALSE;
327	} else if (possible_domains & RADEON_GEM_DOMAIN_VRAM)
328	    return FALSE;
329    }
330
331    if (flush)
332        radeon_cs_flush_indirect(pScrn);
333
334    /* flush IB */
335    ret = radeon_bo_map(driver_priv->bo, 1);
336    if (ret) {
337      FatalError("failed to map pixmap %d\n", ret);
338      return FALSE;
339    }
340    driver_priv->bo_mapped = TRUE;
341
342    pPix->devPrivate.ptr = driver_priv->bo->ptr;
343
344    return TRUE;
345}
346
347void RADEONFinishAccess_CS(PixmapPtr pPix, int index)
348{
349    struct radeon_exa_pixmap_priv *driver_priv;
350
351    driver_priv = exaGetPixmapDriverPrivate(pPix);
352    if (!driver_priv || !driver_priv->bo_mapped)
353        return;
354
355    radeon_bo_unmap(driver_priv->bo);
356    driver_priv->bo_mapped = FALSE;
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 = calloc(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	free(new_priv);
386	ErrorF("Failed to alloc memory\n");
387	return NULL;
388    }
389
390    return new_priv;
391
392}
393
394static const unsigned MicroBlockTable[5][3][2] = {
395    /*linear  tiled   square-tiled */
396    {{32, 1}, {8, 4}, {0, 0}}, /*   8 bits per pixel */
397    {{16, 1}, {8, 2}, {4, 4}}, /*  16 bits per pixel */
398    {{ 8, 1}, {4, 2}, {0, 0}}, /*  32 bits per pixel */
399    {{ 4, 1}, {0, 0}, {2, 2}}, /*  64 bits per pixel */
400    {{ 2, 1}, {0, 0}, {0, 0}}  /* 128 bits per pixel */
401};
402
403/* Return true if macrotiling can be enabled */
404static Bool RADEONMacroSwitch(int width, int height, int bpp,
405                              uint32_t flags, Bool rv350_mode)
406{
407    unsigned tilew, tileh, microtiled, logbpp;
408
409    logbpp = RADEONLog2(bpp / 8);
410    if (logbpp > 4)
411        return 0;
412
413    microtiled = !!(flags & RADEON_TILING_MICRO);
414    tilew = MicroBlockTable[logbpp][microtiled][0] * 8;
415    tileh = MicroBlockTable[logbpp][microtiled][1] * 8;
416
417    /* See TX_FILTER1_n.MACRO_SWITCH. */
418    if (rv350_mode) {
419        return width >= tilew && height >= tileh;
420    } else {
421        return width > tilew && height > tileh;
422    }
423}
424
425void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
426			     int depth, int usage_hint, int bitsPerPixel,
427			     int *new_pitch)
428{
429    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
430    RADEONInfoPtr info = RADEONPTR(pScrn);
431    struct radeon_exa_pixmap_priv *new_priv;
432    int padded_width;
433    uint32_t size;
434    uint32_t tiling = 0;
435    int pixmap_align;
436
437#ifdef EXA_MIXED_PIXMAPS
438    if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) {
439	if (width != 0 && height != 0 && !info->exa_force_create &&
440	    info->exa_pixmaps == FALSE)
441            return NULL;
442    }
443#endif
444
445    if (usage_hint) {
446	if (info->allowColorTiling) {
447    	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO)
448 	   	tiling |= RADEON_TILING_MACRO;
449    	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO)
450                tiling |= RADEON_TILING_MICRO;
451	}
452    }
453
454    /* Small pixmaps must not be macrotiled on R300, hw cannot sample them
455     * correctly because samplers automatically switch to macrolinear. */
456    if (info->ChipFamily >= CHIP_FAMILY_R300 &&
457        info->ChipFamily <= CHIP_FAMILY_RS740 &&
458        (tiling & RADEON_TILING_MACRO) &&
459        !RADEONMacroSwitch(width, height, bitsPerPixel, tiling,
460                           info->ChipFamily >= CHIP_FAMILY_RV350)) {
461        tiling &= ~RADEON_TILING_MACRO;
462    }
463
464    if (info->ChipFamily >= CHIP_FAMILY_R600) {
465	int bpe = bitsPerPixel / 8;
466
467	if (tiling & RADEON_TILING_MACRO) {
468	    height = RADEON_ALIGN(height, info->num_banks * 8);
469	    pixmap_align = MAX(info->num_banks,
470			       (((info->group_bytes / 8) / bpe) * info->num_banks)) * 8 * bpe;
471	} else if (tiling & RADEON_TILING_MICRO) {
472	    height = RADEON_ALIGN(height, 8);
473	    pixmap_align = MAX(8, (info->group_bytes / (8 * bpe))) * bpe;
474	} else {
475	    height = RADEON_ALIGN(height, 8);
476	    pixmap_align = 256; /* 8 * bpe */
477	}
478    } else {
479	if (tiling) {
480	    height = RADEON_ALIGN(height, 16);
481	    pixmap_align = 256;
482	} else
483	    pixmap_align = 64;
484    }
485
486    padded_width = ((width * bitsPerPixel + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
487    padded_width = RADEON_ALIGN(padded_width, pixmap_align);
488    size = height * padded_width;
489
490    new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv));
491    if (!new_priv)
492	return NULL;
493
494    if (size == 0)
495	return new_priv;
496
497    *new_pitch = padded_width;
498
499    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, 0,
500				  RADEON_GEM_DOMAIN_VRAM, 0);
501    if (!new_priv->bo) {
502	free(new_priv);
503	ErrorF("Failed to alloc memory\n");
504	return NULL;
505    }
506
507    if (tiling)
508	radeon_bo_set_tiling(new_priv->bo, tiling, *new_pitch);
509
510    return new_priv;
511}
512
513void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
514{
515    struct radeon_exa_pixmap_priv *driver_priv = driverPriv;
516
517    if (!driverPriv)
518      return;
519
520    if (driver_priv->bo)
521	radeon_bo_unref(driver_priv->bo);
522    free(driverPriv);
523}
524
525struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
526{
527    struct radeon_exa_pixmap_priv *driver_priv;
528    driver_priv = exaGetPixmapDriverPrivate(pPix);
529    return driver_priv->bo;
530}
531
532void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
533{
534    struct radeon_exa_pixmap_priv *driver_priv;
535
536    driver_priv = exaGetPixmapDriverPrivate(pPix);
537    if (driver_priv) {
538	if (driver_priv->bo)
539	    radeon_bo_unref(driver_priv->bo);
540
541	radeon_bo_ref(bo);
542	driver_priv->bo = bo;
543    }
544}
545
546Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix)
547{
548    struct radeon_exa_pixmap_priv *driver_priv;
549
550    driver_priv = exaGetPixmapDriverPrivate(pPix);
551
552    if (!driver_priv)
553       return FALSE;
554    if (driver_priv->bo)
555       return TRUE;
556    return FALSE;
557}
558#endif
559
560#define ENTER_DRAW(x) TRACE
561#define LEAVE_DRAW(x) TRACE
562/***********************************************************************/
563
564#define ACCEL_MMIO
565#define ACCEL_PREAMBLE()	unsigned char *RADEONMMIO = info->MMIO
566#define BEGIN_ACCEL(n)		RADEONWaitForFifo(pScrn, (n))
567#define OUT_ACCEL_REG(reg, val)	OUTREG(reg, val)
568#define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val))
569#define OUT_RELOC(x, read, write)            do {} while(0)
570#define FINISH_ACCEL()
571
572#ifdef RENDER
573#include "radeon_exa_render.c"
574#endif
575#include "radeon_exa_funcs.c"
576
577#undef ACCEL_MMIO
578#undef ACCEL_PREAMBLE
579#undef BEGIN_ACCEL
580#undef OUT_ACCEL_REG
581#undef OUT_ACCEL_REG_F
582#undef FINISH_ACCEL
583#undef OUT_RELOC
584
585#ifdef XF86DRI
586
587#define ACCEL_CP
588#define ACCEL_PREAMBLE()						\
589    RING_LOCALS;							\
590    RADEONCP_REFRESH(pScrn, info)
591#define BEGIN_ACCEL(n)		BEGIN_RING(2*(n))
592#define OUT_ACCEL_REG(reg, val)	OUT_RING_REG(reg, val)
593#define FINISH_ACCEL()		ADVANCE_RING()
594#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write)
595
596#define OUT_RING_F(x) OUT_RING(F_TO_DW(x))
597
598#ifdef RENDER
599#include "radeon_exa_render.c"
600#endif
601#include "radeon_exa_funcs.c"
602
603#undef ACCEL_CP
604#undef ACCEL_PREAMBLE
605#undef BEGIN_ACCEL
606#undef OUT_ACCEL_REG
607#undef FINISH_ACCEL
608#undef OUT_RING_F
609
610#endif /* XF86DRI */
611
612/*
613 * Once screen->off_screen_base is set, this function
614 * allocates the remaining memory appropriately
615 */
616Bool RADEONSetupMemEXA (ScreenPtr pScreen)
617{
618    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
619    RADEONInfoPtr info = RADEONPTR(pScrn);
620    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
621    int cpp = info->CurrentLayout.pixel_bytes;
622    int screen_size;
623    int byteStride = pScrn->displayWidth * cpp;
624
625    if (info->accel_state->exa != NULL) {
626	xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n");
627	return FALSE;
628    }
629    info->accel_state->exa = exaDriverAlloc();
630    if (info->accel_state->exa == NULL)
631	return FALSE;
632
633    /* Need to adjust screen size for 16 line tiles, and then make it align to.
634     * the buffer alignment requirement.
635     */
636    if (info->allowColorTiling)
637	screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride;
638    else
639	screen_size = pScrn->virtualY * byteStride;
640
641    info->accel_state->exa->memoryBase = info->FB;
642    info->accel_state->exa->memorySize = info->FbMapSize - info->FbSecureSize;
643    info->accel_state->exa->offScreenBase = screen_size;
644
645    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n",
646	       info->accel_state->exa->memorySize / 1024);
647
648    /* Reserve static area for hardware cursor */
649    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
650        int cursor_size = 64 * 4 * 64;
651        int align = IS_AVIVO_VARIANT ? 4096 : 256;
652        int c;
653
654        for (c = 0; c < xf86_config->num_crtc; c++) {
655            xf86CrtcPtr crtc = xf86_config->crtc[c];
656            RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
657
658            radeon_crtc->cursor_offset =
659                RADEON_ALIGN(info->accel_state->exa->offScreenBase, align);
660            info->accel_state->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size;
661
662            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
663                       "Will use %d kb for hardware cursor %d at offset 0x%08x\n",
664                       (cursor_size * xf86_config->num_crtc) / 1024,
665                       c,
666                       (unsigned int)radeon_crtc->cursor_offset);
667        }
668    }
669
670#if defined(XF86DRI)
671    if (info->directRenderingEnabled) {
672	int depthCpp = (info->dri->depthBits - 8) / 4, l, next, depth_size;
673
674	info->dri->frontOffset = 0;
675	info->dri->frontPitch = pScrn->displayWidth;
676
677        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
678	       "Will use %d kb for front buffer at offset 0x%08x\n",
679	       screen_size / 1024, info->dri->frontOffset);
680	RADEONDRIAllocatePCIGARTTable(pScreen);
681
682	if (info->cardType==CARD_PCIE)
683	  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
684		     "Will use %d kb for PCI GART at offset 0x%08x\n",
685		     info->dri->pciGartSize / 1024,
686		     (int)info->dri->pciGartOffset);
687
688	/* Reserve a static area for the back buffer the same size as the
689	 * visible screen.  XXX: This would be better initialized in ati_dri.c
690	 * when GLX is set up, but the offscreen memory manager's allocations
691	 * don't last through VT switches, while the kernel's understanding of
692	 * offscreen locations does.
693	 */
694	info->dri->backPitch = pScrn->displayWidth;
695	next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE);
696	if (!info->dri->noBackBuffer &&
697	    next + screen_size <= info->accel_state->exa->memorySize)
698	{
699	    info->dri->backOffset = next;
700	    info->accel_state->exa->offScreenBase = next + screen_size;
701	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
702		       "Will use %d kb for back buffer at offset 0x%08x\n",
703		       screen_size / 1024, info->dri->backOffset);
704	}
705
706	/* Reserve the static depth buffer, and adjust pitch and height to
707	 * handle tiling.
708	 */
709	info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32);
710	depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp;
711	next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE);
712	if (next + depth_size <= info->accel_state->exa->memorySize)
713	{
714	    info->dri->depthOffset = next;
715	    info->accel_state->exa->offScreenBase = next + depth_size;
716	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
717		       "Will use %d kb for depth buffer at offset 0x%08x\n",
718		       depth_size / 1024, info->dri->depthOffset);
719	}
720
721	info->dri->textureSize *= (info->accel_state->exa->memorySize -
722				   info->accel_state->exa->offScreenBase) / 100;
723
724	l = RADEONLog2(info->dri->textureSize / RADEON_NR_TEX_REGIONS);
725	if (l < RADEON_LOG_TEX_GRANULARITY)
726	    l = RADEON_LOG_TEX_GRANULARITY;
727	info->dri->textureSize = (info->dri->textureSize >> l) << l;
728	if (info->dri->textureSize >= 512 * 1024) {
729	    info->dri->textureOffset = info->accel_state->exa->offScreenBase;
730	    info->accel_state->exa->offScreenBase += info->dri->textureSize;
731	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
732		       "Will use %d kb for textures at offset 0x%08x\n",
733		       info->dri->textureSize / 1024, info->dri->textureOffset);
734	} else {
735	    /* Minimum texture size is for 2 256x256x32bpp textures */
736	    info->dri->textureSize = 0;
737	}
738    } else
739#endif /* XF86DRI */
740    	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
741		       "Will use %d kb for front buffer at offset 0x%08x\n",
742		       screen_size / 1024, 0);
743
744    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
745	       "Will use %ld kb for X Server offscreen at offset 0x%08lx\n",
746	       (info->accel_state->exa->memorySize - info->accel_state->exa->offScreenBase) /
747	       1024, info->accel_state->exa->offScreenBase);
748
749    return TRUE;
750}
751
752#ifdef XF86DRI
753
754#ifndef ExaOffscreenMarkUsed
755extern void ExaOffscreenMarkUsed(PixmapPtr);
756#endif
757
758unsigned long long
759RADEONTexOffsetStart(PixmapPtr pPix)
760{
761    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
762    unsigned long long offset;
763
764    if (exaGetPixmapDriverPrivate(pPix))
765	return -1;
766
767    exaMoveInPixmap(pPix);
768    ExaOffscreenMarkUsed(pPix);
769
770    offset = exaGetPixmapOffset(pPix);
771
772    if (offset > info->FbMapSize)
773	return ~0ULL;
774    else
775	return info->fbLocation + offset;
776}
777#endif
778