radeon_exa.c revision ad43ddac
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
123ad43ddacSmrg
124ad43ddacSmrg#ifdef XF86DRM_MODE
125ad43ddacSmrg
126ad43ddacSmrgstatic inline void radeon_add_pixmap(struct radeon_cs *cs, PixmapPtr pPix, int read_domains, int write_domain)
127ad43ddacSmrg{
128ad43ddacSmrg    struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix);
129ad43ddacSmrg
130ad43ddacSmrg    radeon_cs_space_add_persistent_bo(cs, driver_priv->bo, read_domains, write_domain);
131ad43ddacSmrg}
132ad43ddacSmrg
133ad43ddacSmrg#endif /* XF86DRM_MODE */
134ad43ddacSmrg
135ad43ddacSmrg
136209ff23fSmrg/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
137209ff23fSmrg * require src and dest datatypes to be equal.
138209ff23fSmrg */
139209ff23fSmrgBool RADEONGetDatatypeBpp(int bpp, uint32_t *type)
140209ff23fSmrg{
141209ff23fSmrg	switch (bpp) {
142209ff23fSmrg	case 8:
143209ff23fSmrg		*type = ATI_DATATYPE_CI8;
144209ff23fSmrg		return TRUE;
145209ff23fSmrg	case 16:
146209ff23fSmrg		*type = ATI_DATATYPE_RGB565;
147209ff23fSmrg		return TRUE;
148209ff23fSmrg	case 24:
149209ff23fSmrg		*type = ATI_DATATYPE_CI8;
150209ff23fSmrg		return TRUE;
151209ff23fSmrg	case 32:
152209ff23fSmrg		*type = ATI_DATATYPE_ARGB8888;
153209ff23fSmrg		return TRUE;
154209ff23fSmrg	default:
155209ff23fSmrg		RADEON_FALLBACK(("Unsupported bpp: %d\n", bpp));
156209ff23fSmrg		return FALSE;
157209ff23fSmrg	}
158209ff23fSmrg}
159209ff23fSmrg
160209ff23fSmrgstatic Bool RADEONPixmapIsColortiled(PixmapPtr pPix)
161209ff23fSmrg{
162209ff23fSmrg    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
163209ff23fSmrg
164209ff23fSmrg    /* This doesn't account for the back buffer, which we may want to wrap in
165209ff23fSmrg     * a pixmap at some point for the purposes of DRI buffer moves.
166209ff23fSmrg     */
167209ff23fSmrg    if (info->tilingEnabled && exaGetPixmapOffset(pPix) == 0)
168209ff23fSmrg	return TRUE;
169209ff23fSmrg    else
170209ff23fSmrg	return FALSE;
171209ff23fSmrg}
172209ff23fSmrg
173209ff23fSmrgstatic Bool RADEONGetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset,
174209ff23fSmrg				 unsigned int offset, unsigned int pitch)
175209ff23fSmrg{
176209ff23fSmrg	RINFO_FROM_SCREEN(pPix->drawable.pScreen);
177209ff23fSmrg
178b7e1c893Smrg	if (pitch > 16320 || pitch % info->accel_state->exa->pixmapPitchAlign != 0)
179209ff23fSmrg		RADEON_FALLBACK(("Bad pitch 0x%08x\n", pitch));
180209ff23fSmrg
181b7e1c893Smrg	if (offset % info->accel_state->exa->pixmapOffsetAlign != 0)
182209ff23fSmrg		RADEON_FALLBACK(("Bad offset 0x%08x\n", offset));
183209ff23fSmrg
184209ff23fSmrg	pitch = pitch >> 6;
185209ff23fSmrg	*pitch_offset = (pitch << 22) | (offset >> 10);
186209ff23fSmrg
187209ff23fSmrg	/* If it's the front buffer, we've got to note that it's tiled? */
188209ff23fSmrg	if (RADEONPixmapIsColortiled(pPix))
189209ff23fSmrg		*pitch_offset |= RADEON_DST_TILE_MACRO;
190209ff23fSmrg	return TRUE;
191209ff23fSmrg}
192209ff23fSmrg
193209ff23fSmrgBool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
194209ff23fSmrg{
195209ff23fSmrg	uint32_t pitch, offset;
196209ff23fSmrg	int bpp;
197209ff23fSmrg
198209ff23fSmrg	bpp = pPix->drawable.bitsPerPixel;
199209ff23fSmrg	if (bpp == 24)
200209ff23fSmrg		bpp = 8;
201209ff23fSmrg
202ad43ddacSmrg	offset = radeonGetPixmapOffset(pPix);
203209ff23fSmrg	pitch = exaGetPixmapPitch(pPix);
204209ff23fSmrg
205209ff23fSmrg	return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
206209ff23fSmrg}
207209ff23fSmrg
208209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
209209ff23fSmrg
210b7e1c893Smrgstatic unsigned long swapper_surfaces[6];
211209ff23fSmrg
212ad43ddacSmrgstatic Bool RADEONPrepareAccess_BE(PixmapPtr pPix, int index)
213209ff23fSmrg{
214209ff23fSmrg    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
215209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
216209ff23fSmrg    uint32_t offset = exaGetPixmapOffset(pPix);
217209ff23fSmrg    int bpp, soff;
218209ff23fSmrg    uint32_t size, flags;
219209ff23fSmrg
220209ff23fSmrg    /* Front buffer is always set with proper swappers */
221209ff23fSmrg    if (offset == 0)
222209ff23fSmrg        return TRUE;
223209ff23fSmrg
224209ff23fSmrg    /* If same bpp as front buffer, just do nothing as the main
225209ff23fSmrg     * swappers will apply
226209ff23fSmrg     */
227209ff23fSmrg    bpp = pPix->drawable.bitsPerPixel;
228209ff23fSmrg    if (bpp == pScrn->bitsPerPixel)
229209ff23fSmrg        return TRUE;
230209ff23fSmrg
231209ff23fSmrg    /* We need to setup a separate swapper, let's request a
232209ff23fSmrg     * surface. We need to align the size first
233209ff23fSmrg     */
234209ff23fSmrg    size = exaGetPixmapSize(pPix);
235ad43ddacSmrg    size = RADEON_ALIGN(size, RADEON_GPU_PAGE_SIZE);
236209ff23fSmrg
237209ff23fSmrg    /* Set surface to tiling disabled with appropriate swapper */
238209ff23fSmrg    switch (bpp) {
239209ff23fSmrg    case 16:
240209ff23fSmrg        flags = RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP;
241209ff23fSmrg	break;
242209ff23fSmrg    case 32:
243209ff23fSmrg        flags = RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP;
244209ff23fSmrg	break;
245209ff23fSmrg    default:
246209ff23fSmrg        flags = 0;
247209ff23fSmrg    }
248209ff23fSmrg#if defined(XF86DRI)
249209ff23fSmrg    if (info->directRenderingEnabled && info->allowColorTiling) {
250b7e1c893Smrg	struct drm_radeon_surface_alloc drmsurfalloc;
251209ff23fSmrg	int rc;
252209ff23fSmrg
253209ff23fSmrg        drmsurfalloc.address = offset;
254209ff23fSmrg        drmsurfalloc.size = size;
255209ff23fSmrg	drmsurfalloc.flags = flags | 1; /* bogus pitch to please DRM */
256209ff23fSmrg
257b7e1c893Smrg        rc = drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_ALLOC,
258209ff23fSmrg			     &drmsurfalloc, sizeof(drmsurfalloc));
259209ff23fSmrg	if (rc < 0) {
260209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
261209ff23fSmrg		       "drm: could not allocate surface for access"
262209ff23fSmrg		       " swapper, err: %d!\n", rc);
263209ff23fSmrg	    return FALSE;
264209ff23fSmrg	}
265209ff23fSmrg	swapper_surfaces[index] = offset;
266209ff23fSmrg
267209ff23fSmrg	return TRUE;
268209ff23fSmrg    }
269209ff23fSmrg#endif
270209ff23fSmrg    soff = (index + 1) * 0x10;
271209ff23fSmrg    OUTREG(RADEON_SURFACE0_INFO + soff, flags);
272209ff23fSmrg    OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset);
273209ff23fSmrg    OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1);
274209ff23fSmrg    swapper_surfaces[index] = offset;
275209ff23fSmrg    return TRUE;
276209ff23fSmrg}
277209ff23fSmrg
278ad43ddacSmrgstatic void RADEONFinishAccess_BE(PixmapPtr pPix, int index)
279209ff23fSmrg{
280209ff23fSmrg    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
281209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
282209ff23fSmrg    uint32_t offset = exaGetPixmapOffset(pPix);
283209ff23fSmrg    int soff;
284209ff23fSmrg
285209ff23fSmrg    /* Front buffer is always set with proper swappers */
286209ff23fSmrg    if (offset == 0)
287209ff23fSmrg        return;
288209ff23fSmrg
289209ff23fSmrg    if (swapper_surfaces[index] == 0)
290209ff23fSmrg        return;
291209ff23fSmrg#if defined(XF86DRI)
292209ff23fSmrg    if (info->directRenderingEnabled && info->allowColorTiling) {
293b7e1c893Smrg	struct drm_radeon_surface_free drmsurffree;
294209ff23fSmrg
295209ff23fSmrg	drmsurffree.address = offset;
296b7e1c893Smrg	drmCommandWrite(info->dri->drmFD, DRM_RADEON_SURF_FREE,
297209ff23fSmrg			&drmsurffree, sizeof(drmsurffree));
298209ff23fSmrg	swapper_surfaces[index] = 0;
299209ff23fSmrg	return;
300209ff23fSmrg    }
301209ff23fSmrg#endif
302209ff23fSmrg    soff = (index + 1) * 0x10;
303209ff23fSmrg    OUTREG(RADEON_SURFACE0_INFO + soff, 0);
304209ff23fSmrg    OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, 0);
305209ff23fSmrg    OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, 0);
306209ff23fSmrg    swapper_surfaces[index] = 0;
307209ff23fSmrg}
308209ff23fSmrg
309209ff23fSmrg#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
310209ff23fSmrg
311ad43ddacSmrg#ifdef XF86DRM_MODE
312ad43ddacSmrgBool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
313ad43ddacSmrg{
314ad43ddacSmrg    ScreenPtr pScreen = pPix->drawable.pScreen;
315ad43ddacSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
316ad43ddacSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
317ad43ddacSmrg    struct radeon_exa_pixmap_priv *driver_priv;
318ad43ddacSmrg    int ret;
319ad43ddacSmrg
320ad43ddacSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
321ad43ddacSmrg    /* May need to handle byte swapping in DownloadFrom/UploadToScreen */
322ad43ddacSmrg    if (pPix->drawable.bitsPerPixel > 8 &&
323ad43ddacSmrg	pPix != pScreen->GetScreenPixmap(pScreen))
324ad43ddacSmrg	return FALSE;
325ad43ddacSmrg#endif
326ad43ddacSmrg
327ad43ddacSmrg    driver_priv = exaGetPixmapDriverPrivate(pPix);
328ad43ddacSmrg    if (!driver_priv)
329ad43ddacSmrg      return FALSE;
330ad43ddacSmrg
331ad43ddacSmrg    /* if we have more refs than just the BO then flush */
332ad43ddacSmrg    if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs))
333ad43ddacSmrg        radeon_cs_flush_indirect(pScrn);
334ad43ddacSmrg
335ad43ddacSmrg    /* flush IB */
336ad43ddacSmrg    ret = radeon_bo_map(driver_priv->bo, 1);
337ad43ddacSmrg    if (ret) {
338ad43ddacSmrg      FatalError("failed to map pixmap %d\n", ret);
339ad43ddacSmrg      return FALSE;
340ad43ddacSmrg    }
341ad43ddacSmrg    driver_priv->bo_mapped = TRUE;
342ad43ddacSmrg
343ad43ddacSmrg    pPix->devPrivate.ptr = driver_priv->bo->ptr;
344ad43ddacSmrg
345ad43ddacSmrg    return TRUE;
346ad43ddacSmrg}
347ad43ddacSmrg
348ad43ddacSmrgvoid RADEONFinishAccess_CS(PixmapPtr pPix, int index)
349ad43ddacSmrg{
350ad43ddacSmrg    struct radeon_exa_pixmap_priv *driver_priv;
351ad43ddacSmrg
352ad43ddacSmrg    driver_priv = exaGetPixmapDriverPrivate(pPix);
353ad43ddacSmrg    if (!driver_priv || !driver_priv->bo_mapped)
354ad43ddacSmrg        return;
355ad43ddacSmrg
356ad43ddacSmrg    radeon_bo_unmap(driver_priv->bo);
357ad43ddacSmrg    pPix->devPrivate.ptr = NULL;
358ad43ddacSmrg}
359ad43ddacSmrg
360ad43ddacSmrg
361ad43ddacSmrgvoid *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
362ad43ddacSmrg{
363ad43ddacSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
364ad43ddacSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
365ad43ddacSmrg    struct radeon_exa_pixmap_priv *new_priv;
366ad43ddacSmrg
367ad43ddacSmrg#ifdef EXA_MIXED_PIXMAPS
368ad43ddacSmrg    if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) {
369ad43ddacSmrg        if (size != 0 && !info->exa_force_create &&
370ad43ddacSmrg	    info->exa_pixmaps == FALSE)
371ad43ddacSmrg            return NULL;
372ad43ddacSmrg    }
373ad43ddacSmrg#endif
374ad43ddacSmrg
375ad43ddacSmrg    new_priv = xcalloc(1, sizeof(struct radeon_exa_pixmap_priv));
376ad43ddacSmrg    if (!new_priv)
377ad43ddacSmrg	return NULL;
378ad43ddacSmrg
379ad43ddacSmrg    if (size == 0)
380ad43ddacSmrg	return new_priv;
381ad43ddacSmrg
382ad43ddacSmrg    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, align,
383ad43ddacSmrg				  RADEON_GEM_DOMAIN_VRAM, 0);
384ad43ddacSmrg    if (!new_priv->bo) {
385ad43ddacSmrg	xfree(new_priv);
386ad43ddacSmrg	ErrorF("Failed to alloc memory\n");
387ad43ddacSmrg	return NULL;
388ad43ddacSmrg    }
389ad43ddacSmrg
390ad43ddacSmrg    return new_priv;
391ad43ddacSmrg
392ad43ddacSmrg}
393ad43ddacSmrg
394ad43ddacSmrgvoid *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
395ad43ddacSmrg			     int depth, int usage_hint, int bitsPerPixel,
396ad43ddacSmrg			     int *new_pitch)
397ad43ddacSmrg{
398ad43ddacSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
399ad43ddacSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
400ad43ddacSmrg    struct radeon_exa_pixmap_priv *new_priv;
401ad43ddacSmrg    int padded_width;
402ad43ddacSmrg    uint32_t size;
403ad43ddacSmrg    uint32_t tiling = 0;
404ad43ddacSmrg    int pixmap_align;
405ad43ddacSmrg
406ad43ddacSmrg#ifdef EXA_MIXED_PIXMAPS
407ad43ddacSmrg    if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) {
408ad43ddacSmrg	if (width != 0 && height != 0 && !info->exa_force_create &&
409ad43ddacSmrg	    info->exa_pixmaps == FALSE)
410ad43ddacSmrg            return NULL;
411ad43ddacSmrg    }
412ad43ddacSmrg#endif
413ad43ddacSmrg
414ad43ddacSmrg    if (usage_hint) {
415ad43ddacSmrg	if (info->allowColorTiling) {
416ad43ddacSmrg    	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO)
417ad43ddacSmrg 	   	tiling |= RADEON_TILING_MACRO;
418ad43ddacSmrg    	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO)
419ad43ddacSmrg                tiling |= RADEON_TILING_MICRO;
420ad43ddacSmrg	}
421ad43ddacSmrg    }
422ad43ddacSmrg
423ad43ddacSmrg    if (tiling) {
424ad43ddacSmrg	height = RADEON_ALIGN(height, 16);
425ad43ddacSmrg	pixmap_align = 256;
426ad43ddacSmrg    } else
427ad43ddacSmrg	pixmap_align = 64;
428ad43ddacSmrg
429ad43ddacSmrg    padded_width = ((width * bitsPerPixel + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
430ad43ddacSmrg    padded_width = RADEON_ALIGN(padded_width, pixmap_align);
431ad43ddacSmrg    size = height * padded_width;
432ad43ddacSmrg
433ad43ddacSmrg    new_priv = xcalloc(1, sizeof(struct radeon_exa_pixmap_priv));
434ad43ddacSmrg    if (!new_priv)
435ad43ddacSmrg	return NULL;
436ad43ddacSmrg
437ad43ddacSmrg    if (size == 0)
438ad43ddacSmrg	return new_priv;
439ad43ddacSmrg
440ad43ddacSmrg    *new_pitch = padded_width;
441ad43ddacSmrg
442ad43ddacSmrg    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, 0,
443ad43ddacSmrg				  RADEON_GEM_DOMAIN_VRAM, 0);
444ad43ddacSmrg    if (!new_priv->bo) {
445ad43ddacSmrg	xfree(new_priv);
446ad43ddacSmrg	ErrorF("Failed to alloc memory\n");
447ad43ddacSmrg	return NULL;
448ad43ddacSmrg    }
449ad43ddacSmrg
450ad43ddacSmrg    if (tiling)
451ad43ddacSmrg	radeon_bo_set_tiling(new_priv->bo, tiling, *new_pitch);
452ad43ddacSmrg
453ad43ddacSmrg    return new_priv;
454ad43ddacSmrg}
455ad43ddacSmrg
456ad43ddacSmrgvoid RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
457ad43ddacSmrg{
458ad43ddacSmrg    struct radeon_exa_pixmap_priv *driver_priv = driverPriv;
459ad43ddacSmrg
460ad43ddacSmrg    if (!driverPriv)
461ad43ddacSmrg      return;
462ad43ddacSmrg
463ad43ddacSmrg    if (driver_priv->bo)
464ad43ddacSmrg	radeon_bo_unref(driver_priv->bo);
465ad43ddacSmrg    xfree(driverPriv);
466ad43ddacSmrg}
467ad43ddacSmrg
468ad43ddacSmrgstruct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
469ad43ddacSmrg{
470ad43ddacSmrg    struct radeon_exa_pixmap_priv *driver_priv;
471ad43ddacSmrg    driver_priv = exaGetPixmapDriverPrivate(pPix);
472ad43ddacSmrg    return driver_priv->bo;
473ad43ddacSmrg}
474ad43ddacSmrg
475ad43ddacSmrgvoid radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
476ad43ddacSmrg{
477ad43ddacSmrg    struct radeon_exa_pixmap_priv *driver_priv;
478ad43ddacSmrg
479ad43ddacSmrg    driver_priv = exaGetPixmapDriverPrivate(pPix);
480ad43ddacSmrg    if (driver_priv) {
481ad43ddacSmrg	if (driver_priv->bo)
482ad43ddacSmrg	    radeon_bo_unref(driver_priv->bo);
483ad43ddacSmrg
484ad43ddacSmrg	radeon_bo_ref(bo);
485ad43ddacSmrg	driver_priv->bo = bo;
486ad43ddacSmrg    }
487ad43ddacSmrg}
488ad43ddacSmrg
489ad43ddacSmrgBool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix)
490ad43ddacSmrg{
491ad43ddacSmrg    struct radeon_exa_pixmap_priv *driver_priv;
492ad43ddacSmrg
493ad43ddacSmrg    driver_priv = exaGetPixmapDriverPrivate(pPix);
494ad43ddacSmrg
495ad43ddacSmrg    if (!driver_priv)
496ad43ddacSmrg       return FALSE;
497ad43ddacSmrg    if (driver_priv->bo)
498ad43ddacSmrg       return TRUE;
499ad43ddacSmrg    return FALSE;
500ad43ddacSmrg}
501ad43ddacSmrg#endif
502ad43ddacSmrg
503209ff23fSmrg#define ENTER_DRAW(x) TRACE
504209ff23fSmrg#define LEAVE_DRAW(x) TRACE
505209ff23fSmrg/***********************************************************************/
506209ff23fSmrg
507209ff23fSmrg#define ACCEL_MMIO
508209ff23fSmrg#define ACCEL_PREAMBLE()	unsigned char *RADEONMMIO = info->MMIO
509209ff23fSmrg#define BEGIN_ACCEL(n)		RADEONWaitForFifo(pScrn, (n))
510209ff23fSmrg#define OUT_ACCEL_REG(reg, val)	OUTREG(reg, val)
511209ff23fSmrg#define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val))
512ad43ddacSmrg#define OUT_RELOC(x, read, write)            do {} while(0)
513209ff23fSmrg#define FINISH_ACCEL()
514209ff23fSmrg
515209ff23fSmrg#ifdef RENDER
516209ff23fSmrg#include "radeon_exa_render.c"
517209ff23fSmrg#endif
518209ff23fSmrg#include "radeon_exa_funcs.c"
519209ff23fSmrg
520209ff23fSmrg#undef ACCEL_MMIO
521209ff23fSmrg#undef ACCEL_PREAMBLE
522209ff23fSmrg#undef BEGIN_ACCEL
523209ff23fSmrg#undef OUT_ACCEL_REG
524b7e1c893Smrg#undef OUT_ACCEL_REG_F
525209ff23fSmrg#undef FINISH_ACCEL
526ad43ddacSmrg#undef OUT_RELOC
527209ff23fSmrg
528209ff23fSmrg#ifdef XF86DRI
529209ff23fSmrg
530209ff23fSmrg#define ACCEL_CP
531209ff23fSmrg#define ACCEL_PREAMBLE()						\
532209ff23fSmrg    RING_LOCALS;							\
533209ff23fSmrg    RADEONCP_REFRESH(pScrn, info)
534209ff23fSmrg#define BEGIN_ACCEL(n)		BEGIN_RING(2*(n))
535209ff23fSmrg#define OUT_ACCEL_REG(reg, val)	OUT_RING_REG(reg, val)
536209ff23fSmrg#define FINISH_ACCEL()		ADVANCE_RING()
537ad43ddacSmrg#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write)
538209ff23fSmrg
539209ff23fSmrg#define OUT_RING_F(x) OUT_RING(F_TO_DW(x))
540209ff23fSmrg
541209ff23fSmrg#ifdef RENDER
542209ff23fSmrg#include "radeon_exa_render.c"
543209ff23fSmrg#endif
544209ff23fSmrg#include "radeon_exa_funcs.c"
545209ff23fSmrg
546b7e1c893Smrg#undef ACCEL_CP
547b7e1c893Smrg#undef ACCEL_PREAMBLE
548b7e1c893Smrg#undef BEGIN_ACCEL
549b7e1c893Smrg#undef OUT_ACCEL_REG
550b7e1c893Smrg#undef FINISH_ACCEL
551b7e1c893Smrg#undef OUT_RING_F
552b7e1c893Smrg
553209ff23fSmrg#endif /* XF86DRI */
554209ff23fSmrg
555209ff23fSmrg/*
556209ff23fSmrg * Once screen->off_screen_base is set, this function
557209ff23fSmrg * allocates the remaining memory appropriately
558209ff23fSmrg */
559209ff23fSmrgBool RADEONSetupMemEXA (ScreenPtr pScreen)
560209ff23fSmrg{
561209ff23fSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
562209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
563209ff23fSmrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
564209ff23fSmrg    int cpp = info->CurrentLayout.pixel_bytes;
565209ff23fSmrg    int screen_size;
566209ff23fSmrg    int byteStride = pScrn->displayWidth * cpp;
567209ff23fSmrg
568b7e1c893Smrg    if (info->accel_state->exa != NULL) {
569209ff23fSmrg	xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n");
570209ff23fSmrg	return FALSE;
571209ff23fSmrg    }
572b7e1c893Smrg    info->accel_state->exa = exaDriverAlloc();
573b7e1c893Smrg    if (info->accel_state->exa == NULL)
574209ff23fSmrg	return FALSE;
575209ff23fSmrg
576209ff23fSmrg    /* Need to adjust screen size for 16 line tiles, and then make it align to.
577209ff23fSmrg     * the buffer alignment requirement.
578209ff23fSmrg     */
579209ff23fSmrg    if (info->allowColorTiling)
580209ff23fSmrg	screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride;
581209ff23fSmrg    else
582209ff23fSmrg	screen_size = pScrn->virtualY * byteStride;
583209ff23fSmrg
584b7e1c893Smrg    info->accel_state->exa->memoryBase = info->FB;
585b7e1c893Smrg    info->accel_state->exa->memorySize = info->FbMapSize - info->FbSecureSize;
586b7e1c893Smrg    info->accel_state->exa->offScreenBase = screen_size;
587209ff23fSmrg
588209ff23fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n",
589b7e1c893Smrg	       info->accel_state->exa->memorySize / 1024);
590209ff23fSmrg
591209ff23fSmrg    /* Reserve static area for hardware cursor */
592209ff23fSmrg    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
593b7e1c893Smrg        int cursor_size = 64 * 4 * 64;
594b7e1c893Smrg        int align = IS_AVIVO_VARIANT ? 4096 : 256;
595b7e1c893Smrg        int c;
596b7e1c893Smrg
597b7e1c893Smrg        for (c = 0; c < xf86_config->num_crtc; c++) {
598b7e1c893Smrg            xf86CrtcPtr crtc = xf86_config->crtc[c];
599b7e1c893Smrg            RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
600b7e1c893Smrg
601b7e1c893Smrg            radeon_crtc->cursor_offset =
602b7e1c893Smrg                RADEON_ALIGN(info->accel_state->exa->offScreenBase, align);
603b7e1c893Smrg            info->accel_state->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size;
604b7e1c893Smrg
605b7e1c893Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
606b7e1c893Smrg                       "Will use %d kb for hardware cursor %d at offset 0x%08x\n",
607b7e1c893Smrg                       (cursor_size * xf86_config->num_crtc) / 1024,
608b7e1c893Smrg                       c,
609b7e1c893Smrg                       (unsigned int)radeon_crtc->cursor_offset);
610b7e1c893Smrg        }
611209ff23fSmrg    }
612209ff23fSmrg
613209ff23fSmrg#if defined(XF86DRI)
614209ff23fSmrg    if (info->directRenderingEnabled) {
615b7e1c893Smrg	int depthCpp = (info->dri->depthBits - 8) / 4, l, next, depth_size;
616209ff23fSmrg
617b7e1c893Smrg	info->dri->frontOffset = 0;
618b7e1c893Smrg	info->dri->frontPitch = pScrn->displayWidth;
619209ff23fSmrg
620209ff23fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
621209ff23fSmrg	       "Will use %d kb for front buffer at offset 0x%08x\n",
622b7e1c893Smrg	       screen_size / 1024, info->dri->frontOffset);
623209ff23fSmrg	RADEONDRIAllocatePCIGARTTable(pScreen);
624209ff23fSmrg
625209ff23fSmrg	if (info->cardType==CARD_PCIE)
626209ff23fSmrg	  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
627209ff23fSmrg		     "Will use %d kb for PCI GART at offset 0x%08x\n",
628b7e1c893Smrg		     info->dri->pciGartSize / 1024,
629b7e1c893Smrg		     (int)info->dri->pciGartOffset);
630209ff23fSmrg
631209ff23fSmrg	/* Reserve a static area for the back buffer the same size as the
632209ff23fSmrg	 * visible screen.  XXX: This would be better initialized in ati_dri.c
633209ff23fSmrg	 * when GLX is set up, but the offscreen memory manager's allocations
634209ff23fSmrg	 * don't last through VT switches, while the kernel's understanding of
635209ff23fSmrg	 * offscreen locations does.
636209ff23fSmrg	 */
637b7e1c893Smrg	info->dri->backPitch = pScrn->displayWidth;
638ad43ddacSmrg	next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE);
639b7e1c893Smrg	if (!info->dri->noBackBuffer &&
640b7e1c893Smrg	    next + screen_size <= info->accel_state->exa->memorySize)
641209ff23fSmrg	{
642b7e1c893Smrg	    info->dri->backOffset = next;
643b7e1c893Smrg	    info->accel_state->exa->offScreenBase = next + screen_size;
644209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
645209ff23fSmrg		       "Will use %d kb for back buffer at offset 0x%08x\n",
646b7e1c893Smrg		       screen_size / 1024, info->dri->backOffset);
647209ff23fSmrg	}
648209ff23fSmrg
649209ff23fSmrg	/* Reserve the static depth buffer, and adjust pitch and height to
650209ff23fSmrg	 * handle tiling.
651209ff23fSmrg	 */
652b7e1c893Smrg	info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32);
653b7e1c893Smrg	depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp;
654ad43ddacSmrg	next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_GPU_PAGE_SIZE);
655b7e1c893Smrg	if (next + depth_size <= info->accel_state->exa->memorySize)
656209ff23fSmrg	{
657b7e1c893Smrg	    info->dri->depthOffset = next;
658b7e1c893Smrg	    info->accel_state->exa->offScreenBase = next + depth_size;
659209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
660209ff23fSmrg		       "Will use %d kb for depth buffer at offset 0x%08x\n",
661b7e1c893Smrg		       depth_size / 1024, info->dri->depthOffset);
662209ff23fSmrg	}
663209ff23fSmrg
664b7e1c893Smrg	info->dri->textureSize *= (info->accel_state->exa->memorySize -
665b7e1c893Smrg				   info->accel_state->exa->offScreenBase) / 100;
666209ff23fSmrg
667b7e1c893Smrg	l = RADEONLog2(info->dri->textureSize / RADEON_NR_TEX_REGIONS);
668209ff23fSmrg	if (l < RADEON_LOG_TEX_GRANULARITY)
669209ff23fSmrg	    l = RADEON_LOG_TEX_GRANULARITY;
670b7e1c893Smrg	info->dri->textureSize = (info->dri->textureSize >> l) << l;
671b7e1c893Smrg	if (info->dri->textureSize >= 512 * 1024) {
672b7e1c893Smrg	    info->dri->textureOffset = info->accel_state->exa->offScreenBase;
673b7e1c893Smrg	    info->accel_state->exa->offScreenBase += info->dri->textureSize;
674209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
675209ff23fSmrg		       "Will use %d kb for textures at offset 0x%08x\n",
676b7e1c893Smrg		       info->dri->textureSize / 1024, info->dri->textureOffset);
677209ff23fSmrg	} else {
678209ff23fSmrg	    /* Minimum texture size is for 2 256x256x32bpp textures */
679b7e1c893Smrg	    info->dri->textureSize = 0;
680209ff23fSmrg	}
681209ff23fSmrg    } else
682209ff23fSmrg#endif /* XF86DRI */
683209ff23fSmrg    	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
684209ff23fSmrg		       "Will use %d kb for front buffer at offset 0x%08x\n",
685209ff23fSmrg		       screen_size / 1024, 0);
686209ff23fSmrg
687209ff23fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
688209ff23fSmrg	       "Will use %ld kb for X Server offscreen at offset 0x%08lx\n",
689b7e1c893Smrg	       (info->accel_state->exa->memorySize - info->accel_state->exa->offScreenBase) /
690b7e1c893Smrg	       1024, info->accel_state->exa->offScreenBase);
691209ff23fSmrg
692209ff23fSmrg    return TRUE;
693209ff23fSmrg}
694209ff23fSmrg
695209ff23fSmrg#ifdef XF86DRI
696209ff23fSmrg
697209ff23fSmrg#ifndef ExaOffscreenMarkUsed
698209ff23fSmrgextern void ExaOffscreenMarkUsed(PixmapPtr);
699209ff23fSmrg#endif
700209ff23fSmrg
701209ff23fSmrgunsigned long long
702209ff23fSmrgRADEONTexOffsetStart(PixmapPtr pPix)
703209ff23fSmrg{
704b7e1c893Smrg    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
705b7e1c893Smrg    unsigned long long offset;
706ad43ddacSmrg
707ad43ddacSmrg    if (exaGetPixmapDriverPrivate(pPix))
708ad43ddacSmrg	return -1;
709ad43ddacSmrg
710209ff23fSmrg    exaMoveInPixmap(pPix);
711209ff23fSmrg    ExaOffscreenMarkUsed(pPix);
712209ff23fSmrg
713b7e1c893Smrg    offset = exaGetPixmapOffset(pPix);
714b7e1c893Smrg
715b7e1c893Smrg    if (offset > info->FbMapSize)
716b7e1c893Smrg	return ~0ULL;
717b7e1c893Smrg    else
718b7e1c893Smrg	return info->fbLocation + offset;
719209ff23fSmrg}
720209ff23fSmrg#endif
721