1209ff23fSmrg/*
2209ff23fSmrg * Copyright 2005 Eric Anholt
3209ff23fSmrg * Copyright 2005 Benjamin Herrenschmidt
4209ff23fSmrg * All Rights Reserved.
5209ff23fSmrg *
6209ff23fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
7209ff23fSmrg * copy of this software and associated documentation files (the "Software"),
8209ff23fSmrg * to deal in the Software without restriction, including without limitation
9209ff23fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10209ff23fSmrg * and/or sell copies of the Software, and to permit persons to whom the
11209ff23fSmrg * Software is furnished to do so, subject to the following conditions:
12209ff23fSmrg *
13209ff23fSmrg * The above copyright notice and this permission notice (including the next
14209ff23fSmrg * paragraph) shall be included in all copies or substantial portions of the
15209ff23fSmrg * Software.
16209ff23fSmrg *
17209ff23fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18209ff23fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19209ff23fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20209ff23fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21209ff23fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22209ff23fSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23209ff23fSmrg * SOFTWARE.
24209ff23fSmrg *
25209ff23fSmrg * Authors:
26209ff23fSmrg *    Eric Anholt <anholt@FreeBSD.org>
27209ff23fSmrg *    Zack Rusin <zrusin@trolltech.com>
28209ff23fSmrg *    Benjamin Herrenschmidt <benh@kernel.crashing.org>
29209ff23fSmrg *
30209ff23fSmrg */
31209ff23fSmrg
32209ff23fSmrg#ifdef HAVE_CONFIG_H
33209ff23fSmrg#include "config.h"
34209ff23fSmrg#endif
35209ff23fSmrg
36209ff23fSmrg#include "radeon.h"
37209ff23fSmrg#include "radeon_reg.h"
38b7e1c893Smrg#include "r600_reg.h"
39209ff23fSmrg#ifdef XF86DRI
40b7e1c893Smrg#include "radeon_drm.h"
41209ff23fSmrg#endif
42209ff23fSmrg#include "radeon_macros.h"
43209ff23fSmrg#include "radeon_probe.h"
44209ff23fSmrg#include "radeon_version.h"
450974d292Smrg#include "radeon_exa_shared.h"
46209ff23fSmrg
47209ff23fSmrg#include "xf86.h"
48209ff23fSmrg
49209ff23fSmrg
50209ff23fSmrg/***********************************************************************/
5168105dcbSveego#define RINFO_FROM_SCREEN(pScr) ScrnInfoPtr pScrn =  xf86ScreenToScrn(pScr); \
52209ff23fSmrg    RADEONInfoPtr info   = RADEONPTR(pScrn)
53209ff23fSmrg
54209ff23fSmrgstatic struct {
55209ff23fSmrg    int rop;
56209ff23fSmrg    int pattern;
57209ff23fSmrg} RADEON_ROP[] = {
58209ff23fSmrg    { RADEON_ROP3_ZERO, RADEON_ROP3_ZERO }, /* GXclear        */
59209ff23fSmrg    { RADEON_ROP3_DSa,  RADEON_ROP3_DPa  }, /* Gxand          */
60209ff23fSmrg    { RADEON_ROP3_SDna, RADEON_ROP3_PDna }, /* GXandReverse   */
61209ff23fSmrg    { RADEON_ROP3_S,    RADEON_ROP3_P    }, /* GXcopy         */
62209ff23fSmrg    { RADEON_ROP3_DSna, RADEON_ROP3_DPna }, /* GXandInverted  */
63209ff23fSmrg    { RADEON_ROP3_D,    RADEON_ROP3_D    }, /* GXnoop         */
64209ff23fSmrg    { RADEON_ROP3_DSx,  RADEON_ROP3_DPx  }, /* GXxor          */
65209ff23fSmrg    { RADEON_ROP3_DSo,  RADEON_ROP3_DPo  }, /* GXor           */
66209ff23fSmrg    { RADEON_ROP3_DSon, RADEON_ROP3_DPon }, /* GXnor          */
67209ff23fSmrg    { RADEON_ROP3_DSxn, RADEON_ROP3_PDxn }, /* GXequiv        */
68209ff23fSmrg    { RADEON_ROP3_Dn,   RADEON_ROP3_Dn   }, /* GXinvert       */
69209ff23fSmrg    { RADEON_ROP3_SDno, RADEON_ROP3_PDno }, /* GXorReverse    */
70209ff23fSmrg    { RADEON_ROP3_Sn,   RADEON_ROP3_Pn   }, /* GXcopyInverted */
71209ff23fSmrg    { RADEON_ROP3_DSno, RADEON_ROP3_DPno }, /* GXorInverted   */
72209ff23fSmrg    { RADEON_ROP3_DSan, RADEON_ROP3_DPan }, /* GXnand         */
73209ff23fSmrg    { RADEON_ROP3_ONE,  RADEON_ROP3_ONE  }  /* GXset          */
74209ff23fSmrg};
75209ff23fSmrg
76209ff23fSmrg/* Compute log base 2 of val. */
77209ff23fSmrgstatic __inline__ int
78209ff23fSmrgRADEONLog2(int val)
79209ff23fSmrg{
80209ff23fSmrg	int bits;
81209ff23fSmrg#if (defined __i386__ || defined __x86_64__) && (defined __GNUC__)
82209ff23fSmrg	__asm volatile("bsrl	%1, %0"
83209ff23fSmrg		: "=r" (bits)
84209ff23fSmrg		: "c" (val)
85209ff23fSmrg	);
86209ff23fSmrg	return bits;
87209ff23fSmrg#else
88209ff23fSmrg	for (bits = 0; val != 0; val >>= 1, ++bits)
89209ff23fSmrg		;
90209ff23fSmrg	return bits - 1;
91209ff23fSmrg#endif
92209ff23fSmrg}
93209ff23fSmrg
94209ff23fSmrgstatic __inline__ uint32_t F_TO_DW(float val)
95209ff23fSmrg{
96209ff23fSmrg    union {
97209ff23fSmrg	float f;
98209ff23fSmrg	uint32_t l;
99209ff23fSmrg    } tmp;
100209ff23fSmrg    tmp.f = val;
101209ff23fSmrg    return tmp.l;
102209ff23fSmrg}
103209ff23fSmrg
104ad43ddacSmrg
105209ff23fSmrg/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
106209ff23fSmrg * require src and dest datatypes to be equal.
107209ff23fSmrg */
108209ff23fSmrgBool RADEONGetDatatypeBpp(int bpp, uint32_t *type)
109209ff23fSmrg{
110209ff23fSmrg	switch (bpp) {
111209ff23fSmrg	case 8:
112209ff23fSmrg		*type = ATI_DATATYPE_CI8;
113209ff23fSmrg		return TRUE;
114209ff23fSmrg	case 16:
115209ff23fSmrg		*type = ATI_DATATYPE_RGB565;
116209ff23fSmrg		return TRUE;
117209ff23fSmrg	case 24:
118209ff23fSmrg		*type = ATI_DATATYPE_CI8;
119209ff23fSmrg		return TRUE;
120209ff23fSmrg	case 32:
121209ff23fSmrg		*type = ATI_DATATYPE_ARGB8888;
122209ff23fSmrg		return TRUE;
123209ff23fSmrg	default:
124209ff23fSmrg		RADEON_FALLBACK(("Unsupported bpp: %d\n", bpp));
125209ff23fSmrg		return FALSE;
126209ff23fSmrg	}
127209ff23fSmrg}
128209ff23fSmrg
129209ff23fSmrgstatic Bool RADEONPixmapIsColortiled(PixmapPtr pPix)
130209ff23fSmrg{
131209ff23fSmrg    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
132209ff23fSmrg
133c4ae5be6Smrg#ifdef XF86DRM_MODE
134c4ae5be6Smrg    if (info->cs) {
135c4ae5be6Smrg	/* Taken care of by the kernel relocation handling */
136c4ae5be6Smrg	return FALSE;
137c4ae5be6Smrg    }
138c4ae5be6Smrg#endif
139c4ae5be6Smrg
140209ff23fSmrg    /* This doesn't account for the back buffer, which we may want to wrap in
141209ff23fSmrg     * a pixmap at some point for the purposes of DRI buffer moves.
142209ff23fSmrg     */
143209ff23fSmrg    if (info->tilingEnabled && exaGetPixmapOffset(pPix) == 0)
144209ff23fSmrg	return TRUE;
145209ff23fSmrg    else
146209ff23fSmrg	return FALSE;
147209ff23fSmrg}
148209ff23fSmrg
149209ff23fSmrgstatic Bool RADEONGetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset,
150209ff23fSmrg				 unsigned int offset, unsigned int pitch)
151209ff23fSmrg{
152209ff23fSmrg	RINFO_FROM_SCREEN(pPix->drawable.pScreen);
153209ff23fSmrg
154b7e1c893Smrg	if (pitch > 16320 || pitch % info->accel_state->exa->pixmapPitchAlign != 0)
155209ff23fSmrg		RADEON_FALLBACK(("Bad pitch 0x%08x\n", pitch));
156209ff23fSmrg
157b7e1c893Smrg	if (offset % info->accel_state->exa->pixmapOffsetAlign != 0)
158209ff23fSmrg		RADEON_FALLBACK(("Bad offset 0x%08x\n", offset));
159209ff23fSmrg
160209ff23fSmrg	pitch = pitch >> 6;
161209ff23fSmrg	*pitch_offset = (pitch << 22) | (offset >> 10);
162209ff23fSmrg
163209ff23fSmrg	/* If it's the front buffer, we've got to note that it's tiled? */
164209ff23fSmrg	if (RADEONPixmapIsColortiled(pPix))
165209ff23fSmrg		*pitch_offset |= RADEON_DST_TILE_MACRO;
166209ff23fSmrg	return TRUE;
167209ff23fSmrg}
168209ff23fSmrg
169209ff23fSmrgBool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
170209ff23fSmrg{
171209ff23fSmrg	uint32_t pitch, offset;
172209ff23fSmrg	int bpp;
173209ff23fSmrg
174209ff23fSmrg	bpp = pPix->drawable.bitsPerPixel;
175209ff23fSmrg	if (bpp == 24)
176209ff23fSmrg		bpp = 8;
177209ff23fSmrg
178ad43ddacSmrg	offset = radeonGetPixmapOffset(pPix);
179209ff23fSmrg	pitch = exaGetPixmapPitch(pPix);
180209ff23fSmrg
181209ff23fSmrg	return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
182209ff23fSmrg}
183209ff23fSmrg
184921a55d8Smrg/**
185921a55d8Smrg * Returns whether the provided transform is affine.
186921a55d8Smrg *
187921a55d8Smrg * transform may be null.
188921a55d8Smrg */
189b13dfe66SmrgBool radeon_transform_is_affine_or_scaled(PictTransformPtr t)
190921a55d8Smrg{
191921a55d8Smrg	if (t == NULL)
192921a55d8Smrg		return TRUE;
193b13dfe66Smrg	/* the shaders don't handle scaling either */
194b13dfe66Smrg	return t->matrix[2][0] == 0 && t->matrix[2][1] == 0 && t->matrix[2][2] == IntToxFixed(1);
195921a55d8Smrg}
196921a55d8Smrg
197209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
198209ff23fSmrg
199b7e1c893Smrgstatic unsigned long swapper_surfaces[6];
200209ff23fSmrg
201ad43ddacSmrgstatic Bool RADEONPrepareAccess_BE(PixmapPtr pPix, int index)
202209ff23fSmrg{
203209ff23fSmrg    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
204209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
205209ff23fSmrg    uint32_t offset = exaGetPixmapOffset(pPix);
206209ff23fSmrg    int bpp, soff;
207209ff23fSmrg    uint32_t size, flags;
208209ff23fSmrg
209209ff23fSmrg    /* Front buffer is always set with proper swappers */
210209ff23fSmrg    if (offset == 0)
211209ff23fSmrg        return TRUE;
212209ff23fSmrg
213209ff23fSmrg    /* If same bpp as front buffer, just do nothing as the main
214209ff23fSmrg     * swappers will apply
215209ff23fSmrg     */
216209ff23fSmrg    bpp = pPix->drawable.bitsPerPixel;
217209ff23fSmrg    if (bpp == pScrn->bitsPerPixel)
218209ff23fSmrg        return TRUE;
219209ff23fSmrg
220209ff23fSmrg    /* We need to setup a separate swapper, let's request a
221209ff23fSmrg     * surface. We need to align the size first
222209ff23fSmrg     */
223209ff23fSmrg    size = exaGetPixmapSize(pPix);
224ad43ddacSmrg    size = RADEON_ALIGN(size, RADEON_GPU_PAGE_SIZE);
225209ff23fSmrg
226209ff23fSmrg    /* Set surface to tiling disabled with appropriate swapper */
227209ff23fSmrg    switch (bpp) {
228209ff23fSmrg    case 16:
229209ff23fSmrg        flags = RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP;
230209ff23fSmrg	break;
231209ff23fSmrg    case 32:
232209ff23fSmrg        flags = RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP;
233209ff23fSmrg	break;
234209ff23fSmrg    default:
235209ff23fSmrg        flags = 0;
236209ff23fSmrg    }
237209ff23fSmrg#if defined(XF86DRI)
238209ff23fSmrg    if (info->directRenderingEnabled && info->allowColorTiling) {
239b7e1c893Smrg	struct drm_radeon_surface_alloc drmsurfalloc;
240209ff23fSmrg	int rc;
241209ff23fSmrg
242209ff23fSmrg        drmsurfalloc.address = offset;
243209ff23fSmrg        drmsurfalloc.size = size;
244209ff23fSmrg	drmsurfalloc.flags = flags | 1; /* bogus pitch to please DRM */
245209ff23fSmrg
246b7e1c893Smrg        rc = drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_ALLOC,
247209ff23fSmrg			     &drmsurfalloc, sizeof(drmsurfalloc));
248209ff23fSmrg	if (rc < 0) {
249209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
250209ff23fSmrg		       "drm: could not allocate surface for access"
251209ff23fSmrg		       " swapper, err: %d!\n", rc);
252209ff23fSmrg	    return FALSE;
253209ff23fSmrg	}
254209ff23fSmrg	swapper_surfaces[index] = offset;
255209ff23fSmrg
256209ff23fSmrg	return TRUE;
257209ff23fSmrg    }
258209ff23fSmrg#endif
259209ff23fSmrg    soff = (index + 1) * 0x10;
260209ff23fSmrg    OUTREG(RADEON_SURFACE0_INFO + soff, flags);
261209ff23fSmrg    OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset);
262209ff23fSmrg    OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1);
263209ff23fSmrg    swapper_surfaces[index] = offset;
264209ff23fSmrg    return TRUE;
265209ff23fSmrg}
266209ff23fSmrg
267ad43ddacSmrgstatic void RADEONFinishAccess_BE(PixmapPtr pPix, int index)
268209ff23fSmrg{
269209ff23fSmrg    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
270209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
271209ff23fSmrg    uint32_t offset = exaGetPixmapOffset(pPix);
272209ff23fSmrg    int soff;
273209ff23fSmrg
274209ff23fSmrg    /* Front buffer is always set with proper swappers */
275209ff23fSmrg    if (offset == 0)
276209ff23fSmrg        return;
277209ff23fSmrg
278209ff23fSmrg    if (swapper_surfaces[index] == 0)
279209ff23fSmrg        return;
280209ff23fSmrg#if defined(XF86DRI)
281209ff23fSmrg    if (info->directRenderingEnabled && info->allowColorTiling) {
282b7e1c893Smrg	struct drm_radeon_surface_free drmsurffree;
283209ff23fSmrg
284209ff23fSmrg	drmsurffree.address = offset;
285b7e1c893Smrg	drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_FREE,
286209ff23fSmrg			&drmsurffree, sizeof(drmsurffree));
287209ff23fSmrg	swapper_surfaces[index] = 0;
288209ff23fSmrg	return;
289209ff23fSmrg    }
290209ff23fSmrg#endif
291209ff23fSmrg    soff = (index + 1) * 0x10;
292209ff23fSmrg    OUTREG(RADEON_SURFACE0_INFO + soff, 0);
293209ff23fSmrg    OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, 0);
294209ff23fSmrg    OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, 0);
295209ff23fSmrg    swapper_surfaces[index] = 0;
296209ff23fSmrg}
297209ff23fSmrg
298209ff23fSmrg#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
299209ff23fSmrg
300ad43ddacSmrg#ifdef XF86DRM_MODE
301ad43ddacSmrgBool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
302ad43ddacSmrg{
303ad43ddacSmrg    ScreenPtr pScreen = pPix->drawable.pScreen;
30468105dcbSveego    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
305ad43ddacSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
306ad43ddacSmrg    struct radeon_exa_pixmap_priv *driver_priv;
3070974d292Smrg    uint32_t possible_domains = ~0U;
3080974d292Smrg    uint32_t current_domain = 0;
3090974d292Smrg#ifdef EXA_MIXED_PIXMAPS
3100974d292Smrg    Bool can_fail = !(pPix->drawable.bitsPerPixel < 8) &&
3110974d292Smrg	pPix != pScreen->GetScreenPixmap(pScreen) &&
3120974d292Smrg        (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS);
3130974d292Smrg#else
3140974d292Smrg    Bool can_fail = FALSE;
3150974d292Smrg#endif
3160974d292Smrg    Bool flush = FALSE;
317ad43ddacSmrg    int ret;
318ad43ddacSmrg
319ad43ddacSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
320ad43ddacSmrg    /* May need to handle byte swapping in DownloadFrom/UploadToScreen */
3210974d292Smrg    if (can_fail && pPix->drawable.bitsPerPixel > 8)
322ad43ddacSmrg	return FALSE;
323ad43ddacSmrg#endif
324ad43ddacSmrg
325ad43ddacSmrg    driver_priv = exaGetPixmapDriverPrivate(pPix);
326ad43ddacSmrg    if (!driver_priv)
327ad43ddacSmrg      return FALSE;
328ad43ddacSmrg
329921a55d8Smrg    /* untile in DFS/UTS */
330c4ae5be6Smrg    if (driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))
331921a55d8Smrg	return FALSE;
332921a55d8Smrg
333ad43ddacSmrg    /* if we have more refs than just the BO then flush */
3340974d292Smrg    if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) {
3350974d292Smrg	flush = TRUE;
3360974d292Smrg
3370974d292Smrg	if (can_fail) {
3380974d292Smrg	    possible_domains = radeon_bo_get_src_domain(driver_priv->bo);
3390974d292Smrg	    if (possible_domains == RADEON_GEM_DOMAIN_VRAM)
3400974d292Smrg		return FALSE; /* use DownloadFromScreen */
3410974d292Smrg	}
3420974d292Smrg    }
3430974d292Smrg
3440974d292Smrg    /* if the BO might end up in VRAM, prefer DownloadFromScreen */
3450974d292Smrg    if (can_fail && (possible_domains & RADEON_GEM_DOMAIN_VRAM)) {
3460974d292Smrg	radeon_bo_is_busy(driver_priv->bo, &current_domain);
3470974d292Smrg
3480974d292Smrg	if (current_domain & possible_domains) {
3490974d292Smrg	    if (current_domain == RADEON_GEM_DOMAIN_VRAM)
3500974d292Smrg		return FALSE;
3510974d292Smrg	} else if (possible_domains & RADEON_GEM_DOMAIN_VRAM)
3520974d292Smrg	    return FALSE;
3530974d292Smrg    }
3540974d292Smrg
3550974d292Smrg    if (flush)
356ad43ddacSmrg        radeon_cs_flush_indirect(pScrn);
357ad43ddacSmrg
358ad43ddacSmrg    /* flush IB */
359ad43ddacSmrg    ret = radeon_bo_map(driver_priv->bo, 1);
360ad43ddacSmrg    if (ret) {
361ad43ddacSmrg      FatalError("failed to map pixmap %d\n", ret);
362ad43ddacSmrg      return FALSE;
363ad43ddacSmrg    }
364ad43ddacSmrg    driver_priv->bo_mapped = TRUE;
365ad43ddacSmrg
366ad43ddacSmrg    pPix->devPrivate.ptr = driver_priv->bo->ptr;
367ad43ddacSmrg
368ad43ddacSmrg    return TRUE;
369ad43ddacSmrg}
370ad43ddacSmrg
371ad43ddacSmrgvoid RADEONFinishAccess_CS(PixmapPtr pPix, int index)
372ad43ddacSmrg{
373ad43ddacSmrg    struct radeon_exa_pixmap_priv *driver_priv;
374ad43ddacSmrg
375ad43ddacSmrg    driver_priv = exaGetPixmapDriverPrivate(pPix);
376ad43ddacSmrg    if (!driver_priv || !driver_priv->bo_mapped)
377ad43ddacSmrg        return;
378ad43ddacSmrg
379ad43ddacSmrg    radeon_bo_unmap(driver_priv->bo);
3800974d292Smrg    driver_priv->bo_mapped = FALSE;
381ad43ddacSmrg    pPix->devPrivate.ptr = NULL;
382ad43ddacSmrg}
383ad43ddacSmrg
384ad43ddacSmrg
385ad43ddacSmrgvoid *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
386ad43ddacSmrg{
38768105dcbSveego    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
388ad43ddacSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
389ad43ddacSmrg    struct radeon_exa_pixmap_priv *new_priv;
390ad43ddacSmrg
391ad43ddacSmrg#ifdef EXA_MIXED_PIXMAPS
392ad43ddacSmrg    if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) {
393ad43ddacSmrg        if (size != 0 && !info->exa_force_create &&
394ad43ddacSmrg	    info->exa_pixmaps == FALSE)
395ad43ddacSmrg            return NULL;
396ad43ddacSmrg    }
397ad43ddacSmrg#endif
398ad43ddacSmrg
3992f39173dSmrg    new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv));
400ad43ddacSmrg    if (!new_priv)
401ad43ddacSmrg	return NULL;
402ad43ddacSmrg
403ad43ddacSmrg    if (size == 0)
404ad43ddacSmrg	return new_priv;
405ad43ddacSmrg
406ad43ddacSmrg    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, align,
407ad43ddacSmrg				  RADEON_GEM_DOMAIN_VRAM, 0);
408ad43ddacSmrg    if (!new_priv->bo) {
4092f39173dSmrg	free(new_priv);
410ad43ddacSmrg	ErrorF("Failed to alloc memory\n");
411ad43ddacSmrg	return NULL;
412ad43ddacSmrg    }
413ad43ddacSmrg
414ad43ddacSmrg    return new_priv;
415ad43ddacSmrg
416ad43ddacSmrg}
417ad43ddacSmrg
4182f39173dSmrgstatic const unsigned MicroBlockTable[5][3][2] = {
4192f39173dSmrg    /*linear  tiled   square-tiled */
4202f39173dSmrg    {{32, 1}, {8, 4}, {0, 0}}, /*   8 bits per pixel */
4212f39173dSmrg    {{16, 1}, {8, 2}, {4, 4}}, /*  16 bits per pixel */
4222f39173dSmrg    {{ 8, 1}, {4, 2}, {0, 0}}, /*  32 bits per pixel */
4232f39173dSmrg    {{ 4, 1}, {0, 0}, {2, 2}}, /*  64 bits per pixel */
4242f39173dSmrg    {{ 2, 1}, {0, 0}, {0, 0}}  /* 128 bits per pixel */
4252f39173dSmrg};
4262f39173dSmrg
4272f39173dSmrg/* Return true if macrotiling can be enabled */
4282f39173dSmrgstatic Bool RADEONMacroSwitch(int width, int height, int bpp,
4292f39173dSmrg                              uint32_t flags, Bool rv350_mode)
4302f39173dSmrg{
4312f39173dSmrg    unsigned tilew, tileh, microtiled, logbpp;
4322f39173dSmrg
4332f39173dSmrg    logbpp = RADEONLog2(bpp / 8);
4342f39173dSmrg    if (logbpp > 4)
4352f39173dSmrg        return 0;
4362f39173dSmrg
4372f39173dSmrg    microtiled = !!(flags & RADEON_TILING_MICRO);
4382f39173dSmrg    tilew = MicroBlockTable[logbpp][microtiled][0] * 8;
4392f39173dSmrg    tileh = MicroBlockTable[logbpp][microtiled][1] * 8;
4402f39173dSmrg
4412f39173dSmrg    /* See TX_FILTER1_n.MACRO_SWITCH. */
4422f39173dSmrg    if (rv350_mode) {
4432f39173dSmrg        return width >= tilew && height >= tileh;
4442f39173dSmrg    } else {
4452f39173dSmrg        return width > tilew && height > tileh;
4462f39173dSmrg    }
4472f39173dSmrg}
4482f39173dSmrg
449ad43ddacSmrgvoid *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
450ad43ddacSmrg			     int depth, int usage_hint, int bitsPerPixel,
451ad43ddacSmrg			     int *new_pitch)
452ad43ddacSmrg{
45368105dcbSveego    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
454ad43ddacSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
455ad43ddacSmrg    struct radeon_exa_pixmap_priv *new_priv;
456921a55d8Smrg    int pitch, base_align;
45740732134Srjs    uint32_t size, heighta;
458ad43ddacSmrg    uint32_t tiling = 0;
459921a55d8Smrg    int cpp = bitsPerPixel / 8;
46040732134Srjs#ifdef XF86DRM_MODE
46140732134Srjs    struct radeon_surface surface;
46240732134Srjs#endif
463ad43ddacSmrg
464ad43ddacSmrg#ifdef EXA_MIXED_PIXMAPS
465ad43ddacSmrg    if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) {
466ad43ddacSmrg	if (width != 0 && height != 0 && !info->exa_force_create &&
467ad43ddacSmrg	    info->exa_pixmaps == FALSE)
468ad43ddacSmrg            return NULL;
469ad43ddacSmrg    }
470ad43ddacSmrg#endif
471ad43ddacSmrg
472ad43ddacSmrg    if (usage_hint) {
473ad43ddacSmrg	if (info->allowColorTiling) {
474ad43ddacSmrg    	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO)
475ad43ddacSmrg 	   	tiling |= RADEON_TILING_MACRO;
476ad43ddacSmrg    	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO)
477ad43ddacSmrg                tiling |= RADEON_TILING_MICRO;
478ad43ddacSmrg	}
47940732134Srjs	if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH)
48040732134Srjs 	   	tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO;
48140732134Srjs
482ad43ddacSmrg    }
483ad43ddacSmrg
4842f39173dSmrg    /* Small pixmaps must not be macrotiled on R300, hw cannot sample them
4852f39173dSmrg     * correctly because samplers automatically switch to macrolinear. */
4862f39173dSmrg    if (info->ChipFamily >= CHIP_FAMILY_R300 &&
4872f39173dSmrg        info->ChipFamily <= CHIP_FAMILY_RS740 &&
4882f39173dSmrg        (tiling & RADEON_TILING_MACRO) &&
4892f39173dSmrg        !RADEONMacroSwitch(width, height, bitsPerPixel, tiling,
4902f39173dSmrg                           info->ChipFamily >= CHIP_FAMILY_RV350)) {
4912f39173dSmrg        tiling &= ~RADEON_TILING_MACRO;
4922f39173dSmrg    }
4932f39173dSmrg
49440732134Srjs    heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling));
495921a55d8Smrg    pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp;
496921a55d8Smrg    base_align = drmmode_get_base_align(pScrn, cpp, tiling);
49740732134Srjs    size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE);
49840732134Srjs    memset(&surface, 0, sizeof(struct radeon_surface));
49940732134Srjs
50040732134Srjs#ifdef XF86DRM_MODE
501c73da4dbSmrg    if (info->cs && info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
50240732134Srjs		if (width) {
50340732134Srjs			surface.npix_x = width;
50440732134Srjs			/* need to align height to 8 for old kernel */
50540732134Srjs			surface.npix_y = RADEON_ALIGN(height, 8);
50640732134Srjs			surface.npix_z = 1;
50740732134Srjs			surface.blk_w = 1;
50840732134Srjs			surface.blk_h = 1;
50940732134Srjs			surface.blk_d = 1;
51040732134Srjs			surface.array_size = 1;
51140732134Srjs			surface.last_level = 0;
51240732134Srjs			surface.bpe = cpp;
51340732134Srjs			surface.nsamples = 1;
51468105dcbSveego			if (height < 64) {
51568105dcbSveego				/* disable 2d tiling for small surface to work around
51668105dcbSveego				 * the fact that ddx align height to 8 pixel for old
51768105dcbSveego				 * obscure reason i can't remember
51868105dcbSveego				 */
51968105dcbSveego				tiling &= ~RADEON_TILING_MACRO;
52068105dcbSveego			}
52140732134Srjs			surface.flags = RADEON_SURF_SCANOUT;
52240732134Srjs			surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
52340732134Srjs			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
52440732134Srjs			if ((tiling & RADEON_TILING_MICRO)) {
52540732134Srjs				surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
52640732134Srjs				surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
52740732134Srjs			}
52840732134Srjs			if ((tiling & RADEON_TILING_MACRO)) {
52940732134Srjs				surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
53040732134Srjs				surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
53140732134Srjs			}
53240732134Srjs			if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) {
53340732134Srjs				surface.flags |= RADEON_SURF_ZBUFFER;
53440732134Srjs				surface.flags |= RADEON_SURF_SBUFFER;
53540732134Srjs			}
53640732134Srjs			if (radeon_surface_best(info->surf_man, &surface)) {
53740732134Srjs				return NULL;
53840732134Srjs			}
53940732134Srjs			if (radeon_surface_init(info->surf_man, &surface)) {
54040732134Srjs				return NULL;
54140732134Srjs			}
54240732134Srjs			size = surface.bo_size;
54340732134Srjs			base_align = surface.bo_alignment;
54440732134Srjs			pitch = surface.level[0].pitch_bytes;
54540732134Srjs			tiling = 0;
54640732134Srjs			switch (surface.level[0].mode) {
54740732134Srjs			case RADEON_SURF_MODE_2D:
54840732134Srjs				tiling |= RADEON_TILING_MACRO;
54940732134Srjs				tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
55040732134Srjs				tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
55140732134Srjs				tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
55240732134Srjs				tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
55340732134Srjs				tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT;
55440732134Srjs				break;
55540732134Srjs			case RADEON_SURF_MODE_1D:
55640732134Srjs				tiling |= RADEON_TILING_MICRO;
55740732134Srjs				break;
55840732134Srjs			default:
55940732134Srjs				break;
56040732134Srjs			}
56140732134Srjs		}
56240732134Srjs	}
56340732134Srjs#endif
564ad43ddacSmrg
5652f39173dSmrg    new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv));
56640732134Srjs    if (!new_priv) {
567ad43ddacSmrg	return NULL;
56840732134Srjs    }
569ad43ddacSmrg
57040732134Srjs    if (size == 0) {
571ad43ddacSmrg	return new_priv;
57240732134Srjs    }
573ad43ddacSmrg
574921a55d8Smrg    *new_pitch = pitch;
575ad43ddacSmrg
576921a55d8Smrg    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, base_align,
577ad43ddacSmrg				  RADEON_GEM_DOMAIN_VRAM, 0);
578ad43ddacSmrg    if (!new_priv->bo) {
5792f39173dSmrg	free(new_priv);
580ad43ddacSmrg	ErrorF("Failed to alloc memory\n");
581ad43ddacSmrg	return NULL;
582ad43ddacSmrg    }
583ad43ddacSmrg
584c4ae5be6Smrg    if (tiling && !radeon_bo_set_tiling(new_priv->bo, tiling, *new_pitch))
585c4ae5be6Smrg	new_priv->tiling_flags = tiling;
586ad43ddacSmrg
58740732134Srjs    new_priv->surface = surface;
588ad43ddacSmrg    return new_priv;
589ad43ddacSmrg}
590ad43ddacSmrg
591ad43ddacSmrgvoid RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
592ad43ddacSmrg{
593ad43ddacSmrg    struct radeon_exa_pixmap_priv *driver_priv = driverPriv;
594ad43ddacSmrg
595ad43ddacSmrg    if (!driverPriv)
596ad43ddacSmrg      return;
597ad43ddacSmrg
598ad43ddacSmrg    if (driver_priv->bo)
599ad43ddacSmrg	radeon_bo_unref(driver_priv->bo);
6002f39173dSmrg    free(driverPriv);
601ad43ddacSmrg}
602ad43ddacSmrg
603ad43ddacSmrgstruct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
604ad43ddacSmrg{
605ad43ddacSmrg    struct radeon_exa_pixmap_priv *driver_priv;
606ad43ddacSmrg    driver_priv = exaGetPixmapDriverPrivate(pPix);
607ad43ddacSmrg    return driver_priv->bo;
608ad43ddacSmrg}
609ad43ddacSmrg
61040732134Srjs#if defined(XF86DRM_MODE)
61140732134Srjsstruct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix)
61240732134Srjs{
61340732134Srjs    struct radeon_exa_pixmap_priv *driver_priv;
61440732134Srjs    driver_priv = exaGetPixmapDriverPrivate(pPix);
61540732134Srjs    return &driver_priv->surface;
61640732134Srjs}
61740732134Srjs#endif
61840732134Srjs
619c4ae5be6Smrguint32_t radeon_get_pixmap_tiling(PixmapPtr pPix)
620c4ae5be6Smrg{
621c4ae5be6Smrg    struct radeon_exa_pixmap_priv *driver_priv;
622c4ae5be6Smrg    driver_priv = exaGetPixmapDriverPrivate(pPix);
623c4ae5be6Smrg    return driver_priv->tiling_flags;
624c4ae5be6Smrg}
625c4ae5be6Smrg
626ad43ddacSmrgvoid radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
627ad43ddacSmrg{
628ad43ddacSmrg    struct radeon_exa_pixmap_priv *driver_priv;
629ad43ddacSmrg
630ad43ddacSmrg    driver_priv = exaGetPixmapDriverPrivate(pPix);
631ad43ddacSmrg    if (driver_priv) {
632c4ae5be6Smrg	uint32_t pitch;
633c4ae5be6Smrg
634ad43ddacSmrg	if (driver_priv->bo)
635ad43ddacSmrg	    radeon_bo_unref(driver_priv->bo);
636ad43ddacSmrg
637ad43ddacSmrg	radeon_bo_ref(bo);
638ad43ddacSmrg	driver_priv->bo = bo;
639c4ae5be6Smrg
640c4ae5be6Smrg	radeon_bo_get_tiling(bo, &driver_priv->tiling_flags, &pitch);
641ad43ddacSmrg    }
642ad43ddacSmrg}
643ad43ddacSmrg
644ad43ddacSmrgBool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix)
645ad43ddacSmrg{
646ad43ddacSmrg    struct radeon_exa_pixmap_priv *driver_priv;
647ad43ddacSmrg
648ad43ddacSmrg    driver_priv = exaGetPixmapDriverPrivate(pPix);
649ad43ddacSmrg
650ad43ddacSmrg    if (!driver_priv)
651ad43ddacSmrg       return FALSE;
652ad43ddacSmrg    if (driver_priv->bo)
653ad43ddacSmrg       return TRUE;
654ad43ddacSmrg    return FALSE;
655ad43ddacSmrg}
656ad43ddacSmrg#endif
657ad43ddacSmrg
658209ff23fSmrg#define ENTER_DRAW(x) TRACE
659209ff23fSmrg#define LEAVE_DRAW(x) TRACE
660209ff23fSmrg/***********************************************************************/
661209ff23fSmrg
662209ff23fSmrg#define ACCEL_MMIO
663209ff23fSmrg#define ACCEL_PREAMBLE()	unsigned char *RADEONMMIO = info->MMIO
664209ff23fSmrg#define BEGIN_ACCEL(n)		RADEONWaitForFifo(pScrn, (n))
665209ff23fSmrg#define OUT_ACCEL_REG(reg, val)	OUTREG(reg, val)
666209ff23fSmrg#define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val))
667ad43ddacSmrg#define OUT_RELOC(x, read, write)            do {} while(0)
668209ff23fSmrg#define FINISH_ACCEL()
669209ff23fSmrg
670209ff23fSmrg#ifdef RENDER
671209ff23fSmrg#include "radeon_exa_render.c"
672209ff23fSmrg#endif
673209ff23fSmrg#include "radeon_exa_funcs.c"
674209ff23fSmrg
675209ff23fSmrg#undef ACCEL_MMIO
676209ff23fSmrg#undef ACCEL_PREAMBLE
677209ff23fSmrg#undef BEGIN_ACCEL
678209ff23fSmrg#undef OUT_ACCEL_REG
679b7e1c893Smrg#undef OUT_ACCEL_REG_F
680209ff23fSmrg#undef FINISH_ACCEL
681ad43ddacSmrg#undef OUT_RELOC
682209ff23fSmrg
683209ff23fSmrg#ifdef XF86DRI
684209ff23fSmrg
685209ff23fSmrg#define ACCEL_CP
686209ff23fSmrg#define ACCEL_PREAMBLE()						\
687209ff23fSmrg    RING_LOCALS;							\
688209ff23fSmrg    RADEONCP_REFRESH(pScrn, info)
689209ff23fSmrg#define BEGIN_ACCEL(n)		BEGIN_RING(2*(n))
690209ff23fSmrg#define OUT_ACCEL_REG(reg, val)	OUT_RING_REG(reg, val)
691209ff23fSmrg#define FINISH_ACCEL()		ADVANCE_RING()
692ad43ddacSmrg#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write)
693209ff23fSmrg
694209ff23fSmrg#define OUT_RING_F(x) OUT_RING(F_TO_DW(x))
695209ff23fSmrg
696209ff23fSmrg#ifdef RENDER
697209ff23fSmrg#include "radeon_exa_render.c"
698209ff23fSmrg#endif
699209ff23fSmrg#include "radeon_exa_funcs.c"
700209ff23fSmrg
701b7e1c893Smrg#undef ACCEL_CP
702b7e1c893Smrg#undef ACCEL_PREAMBLE
703b7e1c893Smrg#undef BEGIN_ACCEL
704b7e1c893Smrg#undef OUT_ACCEL_REG
705b7e1c893Smrg#undef FINISH_ACCEL
706b7e1c893Smrg#undef OUT_RING_F
707b7e1c893Smrg
708209ff23fSmrg#endif /* XF86DRI */
709209ff23fSmrg
710209ff23fSmrg/*
711209ff23fSmrg * Once screen->off_screen_base is set, this function
712209ff23fSmrg * allocates the remaining memory appropriately
713209ff23fSmrg */
714209ff23fSmrgBool RADEONSetupMemEXA (ScreenPtr pScreen)
715209ff23fSmrg{
71668105dcbSveego    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
717209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
718209ff23fSmrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
719209ff23fSmrg    int cpp = info->CurrentLayout.pixel_bytes;
720209ff23fSmrg    int screen_size;
721209ff23fSmrg    int byteStride = pScrn->displayWidth * cpp;
722209ff23fSmrg
723b7e1c893Smrg    if (info->accel_state->exa != NULL) {
724209ff23fSmrg	xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n");
725209ff23fSmrg	return FALSE;
726209ff23fSmrg    }
727b7e1c893Smrg    info->accel_state->exa = exaDriverAlloc();
728b7e1c893Smrg    if (info->accel_state->exa == NULL)
729209ff23fSmrg	return FALSE;
730209ff23fSmrg
731209ff23fSmrg    /* Need to adjust screen size for 16 line tiles, and then make it align to.
732209ff23fSmrg     * the buffer alignment requirement.
733209ff23fSmrg     */
734209ff23fSmrg    if (info->allowColorTiling)
735209ff23fSmrg	screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride;
736209ff23fSmrg    else
737209ff23fSmrg	screen_size = pScrn->virtualY * byteStride;
738209ff23fSmrg
739b7e1c893Smrg    info->accel_state->exa->memoryBase = info->FB;
740b7e1c893Smrg    info->accel_state->exa->memorySize = info->FbMapSize - info->FbSecureSize;
741b7e1c893Smrg    info->accel_state->exa->offScreenBase = screen_size;
742209ff23fSmrg
743209ff23fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n",
744b7e1c893Smrg	       info->accel_state->exa->memorySize / 1024);
745209ff23fSmrg
746209ff23fSmrg    /* Reserve static area for hardware cursor */
747209ff23fSmrg    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
748b7e1c893Smrg        int cursor_size = 64 * 4 * 64;
749b7e1c893Smrg        int align = IS_AVIVO_VARIANT ? 4096 : 256;
750b7e1c893Smrg        int c;
751b7e1c893Smrg
752b7e1c893Smrg        for (c = 0; c < xf86_config->num_crtc; c++) {
753b7e1c893Smrg            xf86CrtcPtr crtc = xf86_config->crtc[c];
754b7e1c893Smrg            RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
755b7e1c893Smrg
756b7e1c893Smrg            radeon_crtc->cursor_offset =
757b7e1c893Smrg                RADEON_ALIGN(info->accel_state->exa->offScreenBase, align);
758b7e1c893Smrg            info->accel_state->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size;
759b7e1c893Smrg
760b7e1c893Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
761b7e1c893Smrg                       "Will use %d kb for hardware cursor %d at offset 0x%08x\n",
762b7e1c893Smrg                       (cursor_size * xf86_config->num_crtc) / 1024,
763b7e1c893Smrg                       c,
764b7e1c893Smrg                       (unsigned int)radeon_crtc->cursor_offset);
765b7e1c893Smrg        }
766209ff23fSmrg    }
767209ff23fSmrg
768209ff23fSmrg#if defined(XF86DRI)
769209ff23fSmrg    if (info->directRenderingEnabled) {
770b7e1c893Smrg	int depthCpp = (info->dri->depthBits - 8) / 4, l, next, depth_size;
771209ff23fSmrg
772b7e1c893Smrg	info->dri->frontOffset = 0;
773b7e1c893Smrg	info->dri->frontPitch = pScrn->displayWidth;
774209ff23fSmrg
775209ff23fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
776209ff23fSmrg	       "Will use %d kb for front buffer at offset 0x%08x\n",
777b7e1c893Smrg	       screen_size / 1024, info->dri->frontOffset);
778209ff23fSmrg	RADEONDRIAllocatePCIGARTTable(pScreen);
779209ff23fSmrg
780209ff23fSmrg	if (info->cardType==CARD_PCIE)
781209ff23fSmrg	  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
782209ff23fSmrg		     "Will use %d kb for PCI GART at offset 0x%08x\n",
783b7e1c893Smrg		     info->dri->pciGartSize / 1024,
784b7e1c893Smrg		     (int)info->dri->pciGartOffset);
785209ff23fSmrg
786209ff23fSmrg	/* Reserve a static area for the back buffer the same size as the
787209ff23fSmrg	 * visible screen.  XXX: This would be better initialized in ati_dri.c
788209ff23fSmrg	 * when GLX is set up, but the offscreen memory manager's allocations
789209ff23fSmrg	 * don't last through VT switches, while the kernel's understanding of
790209ff23fSmrg	 * offscreen locations does.
791209ff23fSmrg	 */
792b7e1c893Smrg	info->dri->backPitch = pScrn->displayWidth;
793ad43ddacSmrg	next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE);
794b7e1c893Smrg	if (!info->dri->noBackBuffer &&
795b7e1c893Smrg	    next + screen_size <= info->accel_state->exa->memorySize)
796209ff23fSmrg	{
797b7e1c893Smrg	    info->dri->backOffset = next;
798b7e1c893Smrg	    info->accel_state->exa->offScreenBase = next + screen_size;
799209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
800209ff23fSmrg		       "Will use %d kb for back buffer at offset 0x%08x\n",
801b7e1c893Smrg		       screen_size / 1024, info->dri->backOffset);
802209ff23fSmrg	}
803209ff23fSmrg
804209ff23fSmrg	/* Reserve the static depth buffer, and adjust pitch and height to
805209ff23fSmrg	 * handle tiling.
806209ff23fSmrg	 */
807b7e1c893Smrg	info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32);
808b7e1c893Smrg	depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp;
809ad43ddacSmrg	next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE);
810b7e1c893Smrg	if (next + depth_size <= info->accel_state->exa->memorySize)
811209ff23fSmrg	{
812b7e1c893Smrg	    info->dri->depthOffset = next;
813b7e1c893Smrg	    info->accel_state->exa->offScreenBase = next + depth_size;
814209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
815209ff23fSmrg		       "Will use %d kb for depth buffer at offset 0x%08x\n",
816b7e1c893Smrg		       depth_size / 1024, info->dri->depthOffset);
817209ff23fSmrg	}
818209ff23fSmrg
819b7e1c893Smrg	info->dri->textureSize *= (info->accel_state->exa->memorySize -
820b7e1c893Smrg				   info->accel_state->exa->offScreenBase) / 100;
821209ff23fSmrg
822b7e1c893Smrg	l = RADEONLog2(info->dri->textureSize / RADEON_NR_TEX_REGIONS);
823209ff23fSmrg	if (l < RADEON_LOG_TEX_GRANULARITY)
824209ff23fSmrg	    l = RADEON_LOG_TEX_GRANULARITY;
825b7e1c893Smrg	info->dri->textureSize = (info->dri->textureSize >> l) << l;
826b7e1c893Smrg	if (info->dri->textureSize >= 512 * 1024) {
827b7e1c893Smrg	    info->dri->textureOffset = info->accel_state->exa->offScreenBase;
828b7e1c893Smrg	    info->accel_state->exa->offScreenBase += info->dri->textureSize;
829209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
830209ff23fSmrg		       "Will use %d kb for textures at offset 0x%08x\n",
831b7e1c893Smrg		       info->dri->textureSize / 1024, info->dri->textureOffset);
832209ff23fSmrg	} else {
833209ff23fSmrg	    /* Minimum texture size is for 2 256x256x32bpp textures */
834b7e1c893Smrg	    info->dri->textureSize = 0;
835209ff23fSmrg	}
836209ff23fSmrg    } else
837209ff23fSmrg#endif /* XF86DRI */
838209ff23fSmrg    	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
839209ff23fSmrg		       "Will use %d kb for front buffer at offset 0x%08x\n",
840209ff23fSmrg		       screen_size / 1024, 0);
841209ff23fSmrg
842209ff23fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
843209ff23fSmrg	       "Will use %ld kb for X Server offscreen at offset 0x%08lx\n",
844b7e1c893Smrg	       (info->accel_state->exa->memorySize - info->accel_state->exa->offScreenBase) /
845b7e1c893Smrg	       1024, info->accel_state->exa->offScreenBase);
846209ff23fSmrg
847209ff23fSmrg    return TRUE;
848209ff23fSmrg}
849209ff23fSmrg
850209ff23fSmrg#ifdef XF86DRI
851209ff23fSmrg
852209ff23fSmrg#ifndef ExaOffscreenMarkUsed
853209ff23fSmrgextern void ExaOffscreenMarkUsed(PixmapPtr);
854209ff23fSmrg#endif
855209ff23fSmrg
856209ff23fSmrgunsigned long long
857209ff23fSmrgRADEONTexOffsetStart(PixmapPtr pPix)
858209ff23fSmrg{
859b7e1c893Smrg    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
860b7e1c893Smrg    unsigned long long offset;
861ad43ddacSmrg
862ad43ddacSmrg    if (exaGetPixmapDriverPrivate(pPix))
863ad43ddacSmrg	return -1;
864ad43ddacSmrg
865209ff23fSmrg    exaMoveInPixmap(pPix);
866209ff23fSmrg    ExaOffscreenMarkUsed(pPix);
867209ff23fSmrg
868b7e1c893Smrg    offset = exaGetPixmapOffset(pPix);
869b7e1c893Smrg
870b7e1c893Smrg    if (offset > info->FbMapSize)
871b7e1c893Smrg	return ~0ULL;
872b7e1c893Smrg    else
873b7e1c893Smrg	return info->fbLocation + offset;
874209ff23fSmrg}
875209ff23fSmrg#endif
876