radeon_exa.c revision b7e1c893
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"
45209ff23fSmrg
46209ff23fSmrg#include "xf86.h"
47209ff23fSmrg
48209ff23fSmrg
49209ff23fSmrg/***********************************************************************/
50209ff23fSmrg#define RINFO_FROM_SCREEN(pScr) ScrnInfoPtr pScrn =  xf86Screens[pScr->myNum]; \
51209ff23fSmrg    RADEONInfoPtr info   = RADEONPTR(pScrn)
52209ff23fSmrg
53209ff23fSmrg#define RADEON_TRACE_FALL 0
54209ff23fSmrg#define RADEON_TRACE_DRAW 0
55209ff23fSmrg
56209ff23fSmrg#if RADEON_TRACE_FALL
57209ff23fSmrg#define RADEON_FALLBACK(x)     		\
58209ff23fSmrgdo {					\
59209ff23fSmrg	ErrorF("%s: ", __FUNCTION__);	\
60209ff23fSmrg	ErrorF x;			\
61209ff23fSmrg	return FALSE;			\
62209ff23fSmrg} while (0)
63209ff23fSmrg#else
64209ff23fSmrg#define RADEON_FALLBACK(x) return FALSE
65209ff23fSmrg#endif
66209ff23fSmrg
67209ff23fSmrg#if RADEON_TRACE_DRAW
68209ff23fSmrg#define TRACE do { ErrorF("TRACE: %s\n", __FUNCTION__); } while(0)
69209ff23fSmrg#else
70209ff23fSmrg#define TRACE
71209ff23fSmrg#endif
72209ff23fSmrg
73209ff23fSmrgstatic struct {
74209ff23fSmrg    int rop;
75209ff23fSmrg    int pattern;
76209ff23fSmrg} RADEON_ROP[] = {
77209ff23fSmrg    { RADEON_ROP3_ZERO, RADEON_ROP3_ZERO }, /* GXclear        */
78209ff23fSmrg    { RADEON_ROP3_DSa,  RADEON_ROP3_DPa  }, /* Gxand          */
79209ff23fSmrg    { RADEON_ROP3_SDna, RADEON_ROP3_PDna }, /* GXandReverse   */
80209ff23fSmrg    { RADEON_ROP3_S,    RADEON_ROP3_P    }, /* GXcopy         */
81209ff23fSmrg    { RADEON_ROP3_DSna, RADEON_ROP3_DPna }, /* GXandInverted  */
82209ff23fSmrg    { RADEON_ROP3_D,    RADEON_ROP3_D    }, /* GXnoop         */
83209ff23fSmrg    { RADEON_ROP3_DSx,  RADEON_ROP3_DPx  }, /* GXxor          */
84209ff23fSmrg    { RADEON_ROP3_DSo,  RADEON_ROP3_DPo  }, /* GXor           */
85209ff23fSmrg    { RADEON_ROP3_DSon, RADEON_ROP3_DPon }, /* GXnor          */
86209ff23fSmrg    { RADEON_ROP3_DSxn, RADEON_ROP3_PDxn }, /* GXequiv        */
87209ff23fSmrg    { RADEON_ROP3_Dn,   RADEON_ROP3_Dn   }, /* GXinvert       */
88209ff23fSmrg    { RADEON_ROP3_SDno, RADEON_ROP3_PDno }, /* GXorReverse    */
89209ff23fSmrg    { RADEON_ROP3_Sn,   RADEON_ROP3_Pn   }, /* GXcopyInverted */
90209ff23fSmrg    { RADEON_ROP3_DSno, RADEON_ROP3_DPno }, /* GXorInverted   */
91209ff23fSmrg    { RADEON_ROP3_DSan, RADEON_ROP3_DPan }, /* GXnand         */
92209ff23fSmrg    { RADEON_ROP3_ONE,  RADEON_ROP3_ONE  }  /* GXset          */
93209ff23fSmrg};
94209ff23fSmrg
95209ff23fSmrg/* Compute log base 2 of val. */
96209ff23fSmrgstatic __inline__ int
97209ff23fSmrgRADEONLog2(int val)
98209ff23fSmrg{
99209ff23fSmrg	int bits;
100209ff23fSmrg#if (defined __i386__ || defined __x86_64__) && (defined __GNUC__)
101209ff23fSmrg	__asm volatile("bsrl	%1, %0"
102209ff23fSmrg		: "=r" (bits)
103209ff23fSmrg		: "c" (val)
104209ff23fSmrg	);
105209ff23fSmrg	return bits;
106209ff23fSmrg#else
107209ff23fSmrg	for (bits = 0; val != 0; val >>= 1, ++bits)
108209ff23fSmrg		;
109209ff23fSmrg	return bits - 1;
110209ff23fSmrg#endif
111209ff23fSmrg}
112209ff23fSmrg
113209ff23fSmrgstatic __inline__ uint32_t F_TO_DW(float val)
114209ff23fSmrg{
115209ff23fSmrg    union {
116209ff23fSmrg	float f;
117209ff23fSmrg	uint32_t l;
118209ff23fSmrg    } tmp;
119209ff23fSmrg    tmp.f = val;
120209ff23fSmrg    return tmp.l;
121209ff23fSmrg}
122209ff23fSmrg
123209ff23fSmrg/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
124209ff23fSmrg * require src and dest datatypes to be equal.
125209ff23fSmrg */
126209ff23fSmrgBool RADEONGetDatatypeBpp(int bpp, uint32_t *type)
127209ff23fSmrg{
128209ff23fSmrg	switch (bpp) {
129209ff23fSmrg	case 8:
130209ff23fSmrg		*type = ATI_DATATYPE_CI8;
131209ff23fSmrg		return TRUE;
132209ff23fSmrg	case 16:
133209ff23fSmrg		*type = ATI_DATATYPE_RGB565;
134209ff23fSmrg		return TRUE;
135209ff23fSmrg	case 24:
136209ff23fSmrg		*type = ATI_DATATYPE_CI8;
137209ff23fSmrg		return TRUE;
138209ff23fSmrg	case 32:
139209ff23fSmrg		*type = ATI_DATATYPE_ARGB8888;
140209ff23fSmrg		return TRUE;
141209ff23fSmrg	default:
142209ff23fSmrg		RADEON_FALLBACK(("Unsupported bpp: %d\n", bpp));
143209ff23fSmrg		return FALSE;
144209ff23fSmrg	}
145209ff23fSmrg}
146209ff23fSmrg
147209ff23fSmrgstatic Bool RADEONPixmapIsColortiled(PixmapPtr pPix)
148209ff23fSmrg{
149209ff23fSmrg    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
150209ff23fSmrg
151209ff23fSmrg    /* This doesn't account for the back buffer, which we may want to wrap in
152209ff23fSmrg     * a pixmap at some point for the purposes of DRI buffer moves.
153209ff23fSmrg     */
154209ff23fSmrg    if (info->tilingEnabled && exaGetPixmapOffset(pPix) == 0)
155209ff23fSmrg	return TRUE;
156209ff23fSmrg    else
157209ff23fSmrg	return FALSE;
158209ff23fSmrg}
159209ff23fSmrg
160209ff23fSmrgstatic Bool RADEONGetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset,
161209ff23fSmrg				 unsigned int offset, unsigned int pitch)
162209ff23fSmrg{
163209ff23fSmrg	RINFO_FROM_SCREEN(pPix->drawable.pScreen);
164209ff23fSmrg
165b7e1c893Smrg	if (pitch > 16320 || pitch % info->accel_state->exa->pixmapPitchAlign != 0)
166209ff23fSmrg		RADEON_FALLBACK(("Bad pitch 0x%08x\n", pitch));
167209ff23fSmrg
168b7e1c893Smrg	if (offset % info->accel_state->exa->pixmapOffsetAlign != 0)
169209ff23fSmrg		RADEON_FALLBACK(("Bad offset 0x%08x\n", offset));
170209ff23fSmrg
171209ff23fSmrg	pitch = pitch >> 6;
172209ff23fSmrg	*pitch_offset = (pitch << 22) | (offset >> 10);
173209ff23fSmrg
174209ff23fSmrg	/* If it's the front buffer, we've got to note that it's tiled? */
175209ff23fSmrg	if (RADEONPixmapIsColortiled(pPix))
176209ff23fSmrg		*pitch_offset |= RADEON_DST_TILE_MACRO;
177209ff23fSmrg	return TRUE;
178209ff23fSmrg}
179209ff23fSmrg
180209ff23fSmrgBool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
181209ff23fSmrg{
182209ff23fSmrg	RINFO_FROM_SCREEN(pPix->drawable.pScreen);
183209ff23fSmrg	uint32_t pitch, offset;
184209ff23fSmrg	int bpp;
185209ff23fSmrg
186209ff23fSmrg	bpp = pPix->drawable.bitsPerPixel;
187209ff23fSmrg	if (bpp == 24)
188209ff23fSmrg		bpp = 8;
189209ff23fSmrg
190209ff23fSmrg	offset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
191209ff23fSmrg	pitch = exaGetPixmapPitch(pPix);
192209ff23fSmrg
193209ff23fSmrg	return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
194209ff23fSmrg}
195209ff23fSmrg
196b7e1c893Smrg/*
197b7e1c893Smrg * Used for vblank render stalling.
198b7e1c893Smrg * Ideally we'd have one pixmap per crtc.
199b7e1c893Smrg * syncing per-blit is unrealistic so,
200b7e1c893Smrg * we sync to whichever crtc has a larger area.
201b7e1c893Smrg */
202b7e1c893Smrgint RADEONBiggerCrtcArea(PixmapPtr pPix)
203b7e1c893Smrg{
204b7e1c893Smrg    ScrnInfoPtr pScrn =  xf86Screens[pPix->drawable.pScreen->myNum];
205b7e1c893Smrg    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
206b7e1c893Smrg    int c, crtc_num = -1, area = 0;
207b7e1c893Smrg
208b7e1c893Smrg    for (c = 0; c < xf86_config->num_crtc; c++) {
209b7e1c893Smrg	xf86CrtcPtr crtc = xf86_config->crtc[c];
210b7e1c893Smrg
211b7e1c893Smrg	if (!crtc->enabled)
212b7e1c893Smrg	    continue;
213b7e1c893Smrg
214b7e1c893Smrg	if ((crtc->mode.HDisplay * crtc->mode.VDisplay) > area) {
215b7e1c893Smrg	    area = crtc->mode.HDisplay * crtc->mode.VDisplay;
216b7e1c893Smrg	    crtc_num = c;
217b7e1c893Smrg	}
218b7e1c893Smrg    }
219b7e1c893Smrg
220b7e1c893Smrg    return crtc_num;
221b7e1c893Smrg}
222b7e1c893Smrg
223209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
224209ff23fSmrg
225b7e1c893Smrgstatic unsigned long swapper_surfaces[6];
226209ff23fSmrg
227209ff23fSmrgstatic Bool RADEONPrepareAccess(PixmapPtr pPix, int index)
228209ff23fSmrg{
229209ff23fSmrg    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
230209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
231209ff23fSmrg    uint32_t offset = exaGetPixmapOffset(pPix);
232209ff23fSmrg    int bpp, soff;
233209ff23fSmrg    uint32_t size, flags;
234209ff23fSmrg
235209ff23fSmrg    /* Front buffer is always set with proper swappers */
236209ff23fSmrg    if (offset == 0)
237209ff23fSmrg        return TRUE;
238209ff23fSmrg
239209ff23fSmrg    /* If same bpp as front buffer, just do nothing as the main
240209ff23fSmrg     * swappers will apply
241209ff23fSmrg     */
242209ff23fSmrg    bpp = pPix->drawable.bitsPerPixel;
243209ff23fSmrg    if (bpp == pScrn->bitsPerPixel)
244209ff23fSmrg        return TRUE;
245209ff23fSmrg
246209ff23fSmrg    /* We need to setup a separate swapper, let's request a
247209ff23fSmrg     * surface. We need to align the size first
248209ff23fSmrg     */
249209ff23fSmrg    size = exaGetPixmapSize(pPix);
250209ff23fSmrg    size = (size + RADEON_BUFFER_ALIGN) & ~(RADEON_BUFFER_ALIGN);
251209ff23fSmrg
252209ff23fSmrg    /* Set surface to tiling disabled with appropriate swapper */
253209ff23fSmrg    switch (bpp) {
254209ff23fSmrg    case 16:
255209ff23fSmrg        flags = RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP;
256209ff23fSmrg	break;
257209ff23fSmrg    case 32:
258209ff23fSmrg        flags = RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP;
259209ff23fSmrg	break;
260209ff23fSmrg    default:
261209ff23fSmrg        flags = 0;
262209ff23fSmrg    }
263209ff23fSmrg#if defined(XF86DRI)
264209ff23fSmrg    if (info->directRenderingEnabled && info->allowColorTiling) {
265b7e1c893Smrg	struct drm_radeon_surface_alloc drmsurfalloc;
266209ff23fSmrg	int rc;
267209ff23fSmrg
268209ff23fSmrg        drmsurfalloc.address = offset;
269209ff23fSmrg        drmsurfalloc.size = size;
270209ff23fSmrg	drmsurfalloc.flags = flags | 1; /* bogus pitch to please DRM */
271209ff23fSmrg
272b7e1c893Smrg        rc = drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_ALLOC,
273209ff23fSmrg			     &drmsurfalloc, sizeof(drmsurfalloc));
274209ff23fSmrg	if (rc < 0) {
275209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
276209ff23fSmrg		       "drm: could not allocate surface for access"
277209ff23fSmrg		       " swapper, err: %d!\n", rc);
278209ff23fSmrg	    return FALSE;
279209ff23fSmrg	}
280209ff23fSmrg	swapper_surfaces[index] = offset;
281209ff23fSmrg
282209ff23fSmrg	return TRUE;
283209ff23fSmrg    }
284209ff23fSmrg#endif
285209ff23fSmrg    soff = (index + 1) * 0x10;
286209ff23fSmrg    OUTREG(RADEON_SURFACE0_INFO + soff, flags);
287209ff23fSmrg    OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset);
288209ff23fSmrg    OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1);
289209ff23fSmrg    swapper_surfaces[index] = offset;
290209ff23fSmrg    return TRUE;
291209ff23fSmrg}
292209ff23fSmrg
293209ff23fSmrgstatic void RADEONFinishAccess(PixmapPtr pPix, int index)
294209ff23fSmrg{
295209ff23fSmrg    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
296209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
297209ff23fSmrg    uint32_t offset = exaGetPixmapOffset(pPix);
298209ff23fSmrg    int soff;
299209ff23fSmrg
300209ff23fSmrg    /* Front buffer is always set with proper swappers */
301209ff23fSmrg    if (offset == 0)
302209ff23fSmrg        return;
303209ff23fSmrg
304209ff23fSmrg    if (swapper_surfaces[index] == 0)
305209ff23fSmrg        return;
306209ff23fSmrg#if defined(XF86DRI)
307209ff23fSmrg    if (info->directRenderingEnabled && info->allowColorTiling) {
308b7e1c893Smrg	struct drm_radeon_surface_free drmsurffree;
309209ff23fSmrg
310209ff23fSmrg	drmsurffree.address = offset;
311b7e1c893Smrg	drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_FREE,
312209ff23fSmrg			&drmsurffree, sizeof(drmsurffree));
313209ff23fSmrg	swapper_surfaces[index] = 0;
314209ff23fSmrg	return;
315209ff23fSmrg    }
316209ff23fSmrg#endif
317209ff23fSmrg    soff = (index + 1) * 0x10;
318209ff23fSmrg    OUTREG(RADEON_SURFACE0_INFO + soff, 0);
319209ff23fSmrg    OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, 0);
320209ff23fSmrg    OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, 0);
321209ff23fSmrg    swapper_surfaces[index] = 0;
322209ff23fSmrg}
323209ff23fSmrg
324209ff23fSmrg#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
325209ff23fSmrg
326209ff23fSmrg#define ENTER_DRAW(x) TRACE
327209ff23fSmrg#define LEAVE_DRAW(x) TRACE
328209ff23fSmrg/***********************************************************************/
329209ff23fSmrg
330209ff23fSmrg#define ACCEL_MMIO
331209ff23fSmrg#define ACCEL_PREAMBLE()	unsigned char *RADEONMMIO = info->MMIO
332209ff23fSmrg#define BEGIN_ACCEL(n)		RADEONWaitForFifo(pScrn, (n))
333209ff23fSmrg#define OUT_ACCEL_REG(reg, val)	OUTREG(reg, val)
334209ff23fSmrg#define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val))
335209ff23fSmrg#define FINISH_ACCEL()
336209ff23fSmrg
337209ff23fSmrg#ifdef RENDER
338209ff23fSmrg#include "radeon_exa_render.c"
339209ff23fSmrg#endif
340209ff23fSmrg#include "radeon_exa_funcs.c"
341209ff23fSmrg
342209ff23fSmrg#undef ACCEL_MMIO
343209ff23fSmrg#undef ACCEL_PREAMBLE
344209ff23fSmrg#undef BEGIN_ACCEL
345209ff23fSmrg#undef OUT_ACCEL_REG
346b7e1c893Smrg#undef OUT_ACCEL_REG_F
347209ff23fSmrg#undef FINISH_ACCEL
348209ff23fSmrg
349209ff23fSmrg#ifdef XF86DRI
350209ff23fSmrg
351209ff23fSmrg#define ACCEL_CP
352209ff23fSmrg#define ACCEL_PREAMBLE()						\
353209ff23fSmrg    RING_LOCALS;							\
354209ff23fSmrg    RADEONCP_REFRESH(pScrn, info)
355209ff23fSmrg#define BEGIN_ACCEL(n)		BEGIN_RING(2*(n))
356209ff23fSmrg#define OUT_ACCEL_REG(reg, val)	OUT_RING_REG(reg, val)
357209ff23fSmrg#define FINISH_ACCEL()		ADVANCE_RING()
358209ff23fSmrg
359209ff23fSmrg#define OUT_RING_F(x) OUT_RING(F_TO_DW(x))
360209ff23fSmrg
361209ff23fSmrg#ifdef RENDER
362209ff23fSmrg#include "radeon_exa_render.c"
363209ff23fSmrg#endif
364209ff23fSmrg#include "radeon_exa_funcs.c"
365209ff23fSmrg
366b7e1c893Smrg#undef ACCEL_CP
367b7e1c893Smrg#undef ACCEL_PREAMBLE
368b7e1c893Smrg#undef BEGIN_ACCEL
369b7e1c893Smrg#undef OUT_ACCEL_REG
370b7e1c893Smrg#undef FINISH_ACCEL
371b7e1c893Smrg#undef OUT_RING_F
372b7e1c893Smrg
373209ff23fSmrg#endif /* XF86DRI */
374209ff23fSmrg
375209ff23fSmrg/*
376209ff23fSmrg * Once screen->off_screen_base is set, this function
377209ff23fSmrg * allocates the remaining memory appropriately
378209ff23fSmrg */
379209ff23fSmrgBool RADEONSetupMemEXA (ScreenPtr pScreen)
380209ff23fSmrg{
381209ff23fSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
382209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
383209ff23fSmrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
384209ff23fSmrg    int cpp = info->CurrentLayout.pixel_bytes;
385209ff23fSmrg    int screen_size;
386209ff23fSmrg    int byteStride = pScrn->displayWidth * cpp;
387209ff23fSmrg
388b7e1c893Smrg    if (info->accel_state->exa != NULL) {
389209ff23fSmrg	xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n");
390209ff23fSmrg	return FALSE;
391209ff23fSmrg    }
392b7e1c893Smrg    info->accel_state->exa = exaDriverAlloc();
393b7e1c893Smrg    if (info->accel_state->exa == NULL)
394209ff23fSmrg	return FALSE;
395209ff23fSmrg
396209ff23fSmrg    /* Need to adjust screen size for 16 line tiles, and then make it align to.
397209ff23fSmrg     * the buffer alignment requirement.
398209ff23fSmrg     */
399209ff23fSmrg    if (info->allowColorTiling)
400209ff23fSmrg	screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride;
401209ff23fSmrg    else
402209ff23fSmrg	screen_size = pScrn->virtualY * byteStride;
403209ff23fSmrg
404b7e1c893Smrg    info->accel_state->exa->memoryBase = info->FB;
405b7e1c893Smrg    info->accel_state->exa->memorySize = info->FbMapSize - info->FbSecureSize;
406b7e1c893Smrg    info->accel_state->exa->offScreenBase = screen_size;
407209ff23fSmrg
408209ff23fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n",
409b7e1c893Smrg	       info->accel_state->exa->memorySize / 1024);
410209ff23fSmrg
411209ff23fSmrg    /* Reserve static area for hardware cursor */
412209ff23fSmrg    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
413b7e1c893Smrg        int cursor_size = 64 * 4 * 64;
414b7e1c893Smrg        int align = IS_AVIVO_VARIANT ? 4096 : 256;
415b7e1c893Smrg        int c;
416b7e1c893Smrg
417b7e1c893Smrg        for (c = 0; c < xf86_config->num_crtc; c++) {
418b7e1c893Smrg            xf86CrtcPtr crtc = xf86_config->crtc[c];
419b7e1c893Smrg            RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
420b7e1c893Smrg
421b7e1c893Smrg            radeon_crtc->cursor_offset =
422b7e1c893Smrg                RADEON_ALIGN(info->accel_state->exa->offScreenBase, align);
423b7e1c893Smrg            info->accel_state->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size;
424b7e1c893Smrg
425b7e1c893Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
426b7e1c893Smrg                       "Will use %d kb for hardware cursor %d at offset 0x%08x\n",
427b7e1c893Smrg                       (cursor_size * xf86_config->num_crtc) / 1024,
428b7e1c893Smrg                       c,
429b7e1c893Smrg                       (unsigned int)radeon_crtc->cursor_offset);
430b7e1c893Smrg        }
431209ff23fSmrg    }
432209ff23fSmrg
433209ff23fSmrg#if defined(XF86DRI)
434209ff23fSmrg    if (info->directRenderingEnabled) {
435b7e1c893Smrg	int depthCpp = (info->dri->depthBits - 8) / 4, l, next, depth_size;
436209ff23fSmrg
437b7e1c893Smrg	info->dri->frontOffset = 0;
438b7e1c893Smrg	info->dri->frontPitch = pScrn->displayWidth;
439209ff23fSmrg
440209ff23fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
441209ff23fSmrg	       "Will use %d kb for front buffer at offset 0x%08x\n",
442b7e1c893Smrg	       screen_size / 1024, info->dri->frontOffset);
443209ff23fSmrg	RADEONDRIAllocatePCIGARTTable(pScreen);
444209ff23fSmrg
445209ff23fSmrg	if (info->cardType==CARD_PCIE)
446209ff23fSmrg	  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
447209ff23fSmrg		     "Will use %d kb for PCI GART at offset 0x%08x\n",
448b7e1c893Smrg		     info->dri->pciGartSize / 1024,
449b7e1c893Smrg		     (int)info->dri->pciGartOffset);
450209ff23fSmrg
451209ff23fSmrg	/* Reserve a static area for the back buffer the same size as the
452209ff23fSmrg	 * visible screen.  XXX: This would be better initialized in ati_dri.c
453209ff23fSmrg	 * when GLX is set up, but the offscreen memory manager's allocations
454209ff23fSmrg	 * don't last through VT switches, while the kernel's understanding of
455209ff23fSmrg	 * offscreen locations does.
456209ff23fSmrg	 */
457b7e1c893Smrg	info->dri->backPitch = pScrn->displayWidth;
458b7e1c893Smrg	next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_BUFFER_ALIGN);
459b7e1c893Smrg	if (!info->dri->noBackBuffer &&
460b7e1c893Smrg	    next + screen_size <= info->accel_state->exa->memorySize)
461209ff23fSmrg	{
462b7e1c893Smrg	    info->dri->backOffset = next;
463b7e1c893Smrg	    info->accel_state->exa->offScreenBase = next + screen_size;
464209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
465209ff23fSmrg		       "Will use %d kb for back buffer at offset 0x%08x\n",
466b7e1c893Smrg		       screen_size / 1024, info->dri->backOffset);
467209ff23fSmrg	}
468209ff23fSmrg
469209ff23fSmrg	/* Reserve the static depth buffer, and adjust pitch and height to
470209ff23fSmrg	 * handle tiling.
471209ff23fSmrg	 */
472b7e1c893Smrg	info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32);
473b7e1c893Smrg	depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp;
474b7e1c893Smrg	next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_BUFFER_ALIGN);
475b7e1c893Smrg	if (next + depth_size <= info->accel_state->exa->memorySize)
476209ff23fSmrg	{
477b7e1c893Smrg	    info->dri->depthOffset = next;
478b7e1c893Smrg	    info->accel_state->exa->offScreenBase = next + depth_size;
479209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
480209ff23fSmrg		       "Will use %d kb for depth buffer at offset 0x%08x\n",
481b7e1c893Smrg		       depth_size / 1024, info->dri->depthOffset);
482209ff23fSmrg	}
483209ff23fSmrg
484b7e1c893Smrg	info->dri->textureSize *= (info->accel_state->exa->memorySize -
485b7e1c893Smrg				   info->accel_state->exa->offScreenBase) / 100;
486209ff23fSmrg
487b7e1c893Smrg	l = RADEONLog2(info->dri->textureSize / RADEON_NR_TEX_REGIONS);
488209ff23fSmrg	if (l < RADEON_LOG_TEX_GRANULARITY)
489209ff23fSmrg	    l = RADEON_LOG_TEX_GRANULARITY;
490b7e1c893Smrg	info->dri->textureSize = (info->dri->textureSize >> l) << l;
491b7e1c893Smrg	if (info->dri->textureSize >= 512 * 1024) {
492b7e1c893Smrg	    info->dri->textureOffset = info->accel_state->exa->offScreenBase;
493b7e1c893Smrg	    info->accel_state->exa->offScreenBase += info->dri->textureSize;
494209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
495209ff23fSmrg		       "Will use %d kb for textures at offset 0x%08x\n",
496b7e1c893Smrg		       info->dri->textureSize / 1024, info->dri->textureOffset);
497209ff23fSmrg	} else {
498209ff23fSmrg	    /* Minimum texture size is for 2 256x256x32bpp textures */
499b7e1c893Smrg	    info->dri->textureSize = 0;
500209ff23fSmrg	}
501209ff23fSmrg    } else
502209ff23fSmrg#endif /* XF86DRI */
503209ff23fSmrg    	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
504209ff23fSmrg		       "Will use %d kb for front buffer at offset 0x%08x\n",
505209ff23fSmrg		       screen_size / 1024, 0);
506209ff23fSmrg
507209ff23fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
508209ff23fSmrg	       "Will use %ld kb for X Server offscreen at offset 0x%08lx\n",
509b7e1c893Smrg	       (info->accel_state->exa->memorySize - info->accel_state->exa->offScreenBase) /
510b7e1c893Smrg	       1024, info->accel_state->exa->offScreenBase);
511209ff23fSmrg
512209ff23fSmrg    return TRUE;
513209ff23fSmrg}
514209ff23fSmrg
515209ff23fSmrg#ifdef XF86DRI
516209ff23fSmrg
517209ff23fSmrg#ifndef ExaOffscreenMarkUsed
518209ff23fSmrgextern void ExaOffscreenMarkUsed(PixmapPtr);
519209ff23fSmrg#endif
520209ff23fSmrg
521209ff23fSmrgunsigned long long
522209ff23fSmrgRADEONTexOffsetStart(PixmapPtr pPix)
523209ff23fSmrg{
524b7e1c893Smrg    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
525b7e1c893Smrg    unsigned long long offset;
526209ff23fSmrg    exaMoveInPixmap(pPix);
527209ff23fSmrg    ExaOffscreenMarkUsed(pPix);
528209ff23fSmrg
529b7e1c893Smrg    offset = exaGetPixmapOffset(pPix);
530b7e1c893Smrg
531b7e1c893Smrg    if (offset > info->FbMapSize)
532b7e1c893Smrg	return ~0ULL;
533b7e1c893Smrg    else
534b7e1c893Smrg	return info->fbLocation + offset;
535209ff23fSmrg}
536209ff23fSmrg#endif
537