radeon_exa_shared.c revision 43df4709
1/*
2 * Copyright 2005 Eric Anholt
3 * Copyright 2005 Benjamin Herrenschmidt
4 * Copyright 2008 Advanced Micro Devices, Inc.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 *
26 * Authors:
27 *    Eric Anholt <anholt@FreeBSD.org>
28 *    Zack Rusin <zrusin@trolltech.com>
29 *    Benjamin Herrenschmidt <benh@kernel.crashing.org>
30 *    Alex Deucher <alexander.deucher@amd.com>
31 *    Matthias Hopf <mhopf@suse.de>
32 */
33#ifdef HAVE_CONFIG_H
34#include "config.h"
35#endif
36
37#include "radeon.h"
38#ifdef XF86DRI
39#include "radeon_drm.h"
40#endif
41#include "radeon_macros.h"
42#include "radeon_probe.h"
43#include "radeon_version.h"
44#include "radeon_vbo.h"
45
46PixmapPtr
47RADEONGetDrawablePixmap(DrawablePtr pDrawable)
48{
49    if (pDrawable->type == DRAWABLE_WINDOW)
50	return pDrawable->pScreen->GetWindowPixmap((WindowPtr)pDrawable);
51    else
52	return (PixmapPtr)pDrawable;
53}
54
55void RADEONVlineHelperClear(ScrnInfoPtr pScrn)
56{
57    RADEONInfoPtr info = RADEONPTR(pScrn);
58    struct radeon_accel_state *accel_state = info->accel_state;
59
60    accel_state->vline_crtc = NULL;
61    accel_state->vline_y1 = -1;
62    accel_state->vline_y2 = 0;
63}
64
65void RADEONVlineHelperSet(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2)
66{
67    RADEONInfoPtr info = RADEONPTR(pScrn);
68    struct radeon_accel_state *accel_state = info->accel_state;
69
70    accel_state->vline_crtc = radeon_pick_best_crtc(pScrn, x1, x2, y1, y2);
71    if (accel_state->vline_y1 == -1)
72	accel_state->vline_y1 = y1;
73    if (y1 < accel_state->vline_y1)
74	accel_state->vline_y1 = y1;
75    if (y2 > accel_state->vline_y2)
76	accel_state->vline_y2 = y2;
77}
78
79Bool RADEONValidPM(uint32_t pm, int bpp)
80{
81    uint8_t r, g, b, a;
82    Bool ret = FALSE;
83
84    switch (bpp) {
85    case 8:
86	a = pm & 0xff;
87	if ((a == 0) || (a == 0xff))
88	    ret = TRUE;
89	break;
90    case 16:
91	r = (pm >> 11) & 0x1f;
92	g = (pm >> 5) & 0x3f;
93	b = (pm >> 0) & 0x1f;
94	if (((r == 0) || (r == 0x1f)) &&
95	    ((g == 0) || (g == 0x3f)) &&
96	    ((b == 0) || (b == 0x1f)))
97	    ret = TRUE;
98	break;
99    case 32:
100	a = (pm >> 24) & 0xff;
101	r = (pm >> 16) & 0xff;
102	g = (pm >> 8) & 0xff;
103	b = (pm >> 0) & 0xff;
104	if (((a == 0) || (a == 0xff)) &&
105	    ((r == 0) || (r == 0xff)) &&
106	    ((g == 0) || (g == 0xff)) &&
107	    ((b == 0) || (b == 0xff)))
108	    ret = TRUE;
109	break;
110    default:
111	break;
112    }
113    return ret;
114}
115
116Bool RADEONCheckBPP(int bpp)
117{
118	switch (bpp) {
119	case 8:
120	case 16:
121	case 32:
122		return TRUE;
123	default:
124		break;
125	}
126	return FALSE;
127}
128
129PixmapPtr RADEONSolidPixmap(ScreenPtr pScreen, uint32_t solid)
130{
131    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
132    RADEONInfoPtr info = RADEONPTR(pScrn);
133    PixmapPtr pPix = pScreen->CreatePixmap(pScreen, 1, 1, 32, 0);
134
135    exaMoveInPixmap(pPix);
136
137#if defined(XF86DRM_MODE)
138    if (info->cs) {
139	struct radeon_bo *bo;
140
141	bo = radeon_get_pixmap_bo(pPix);
142
143	if (radeon_bo_map(bo, 1)) {
144	    pScreen->DestroyPixmap(pPix);
145	    return NULL;
146	}
147
148	memcpy(bo->ptr, &solid, 4);
149	radeon_bo_unmap(bo);
150
151	return pPix;
152    }
153#endif
154
155    if (!exaDrawableIsOffscreen(&pPix->drawable)) {
156	pScreen->DestroyPixmap(pPix);
157	return NULL;
158    }
159
160    /* XXX: Big hammer... */
161    info->accel_state->exa->WaitMarker(pScreen, info->accel_state->exaSyncMarker);
162    memcpy(info->FB + exaGetPixmapOffset(pPix), &solid, 4);
163
164    return pPix;
165}
166
167static Bool radeon_vb_get(ScrnInfoPtr pScrn)
168{
169    RADEONInfoPtr info = RADEONPTR(pScrn);
170    struct radeon_accel_state *accel_state = info->accel_state;
171
172    accel_state->vbo.vb_mc_addr = info->gartLocation + info->dri->bufStart +
173	(accel_state->ib->idx*accel_state->ib->total)+
174	(accel_state->ib->total / 2);
175    accel_state->vbo.vb_total = (accel_state->ib->total / 2);
176    accel_state->vbo.vb_ptr = (pointer)((char*)accel_state->ib->address +
177				    (accel_state->ib->total / 2));
178    accel_state->vbo.vb_offset = 0;
179    return TRUE;
180}
181
182int radeon_cp_start(ScrnInfoPtr pScrn)
183{
184    RADEONInfoPtr info = RADEONPTR(pScrn);
185    struct radeon_accel_state *accel_state = info->accel_state;
186
187#if defined(XF86DRM_MODE)
188    if (info->cs) {
189	if (CS_FULL(info->cs)) {
190	    radeon_cs_flush_indirect(pScrn);
191	}
192	accel_state->ib_reset_op = info->cs->cdw;
193    } else
194#endif
195    {
196	accel_state->ib = RADEONCPGetBuffer(pScrn);
197	if (!radeon_vb_get(pScrn)) {
198	    return -1;
199	}
200    }
201    accel_state->vbo.vb_start_op = accel_state->vbo.vb_offset;
202    accel_state->cbuf.vb_start_op = accel_state->cbuf.vb_offset;
203    return 0;
204}
205
206void radeon_vb_no_space(ScrnInfoPtr pScrn,
207			struct radeon_vbo_object *vbo,
208			int vert_size)
209{
210    RADEONInfoPtr info = RADEONPTR(pScrn);
211    struct radeon_accel_state *accel_state = info->accel_state;
212
213#if defined(XF86DRM_MODE)
214    if (info->cs) {
215	if (vbo->vb_bo) {
216	    if (vbo->vb_start_op != vbo->vb_offset) {
217		accel_state->finish_op(pScrn, vert_size);
218		accel_state->ib_reset_op = info->cs->cdw;
219	    }
220
221	    /* release the current VBO */
222	    radeon_vbo_put(pScrn, vbo);
223	}
224	/* get a new one */
225	radeon_vbo_get(pScrn, vbo);
226	return;
227    }
228#endif
229    if (vbo->vb_start_op != -1) {
230        accel_state->finish_op(pScrn, vert_size);
231        radeon_cp_start(pScrn);
232    }
233    return;
234}
235
236#if defined(XF86DRM_MODE)
237void radeon_ib_discard(ScrnInfoPtr pScrn)
238{
239    RADEONInfoPtr info = RADEONPTR(pScrn);
240    int ret;
241
242    if (info->accel_state->ib_reset_op) {
243        /* if we have data just reset the CS and ignore the operation */
244	info->cs->cdw = info->accel_state->ib_reset_op;
245	info->accel_state->ib_reset_op = 0;
246	goto out;
247    }
248
249    info->accel_state->vbo.vb_offset = 0;
250    info->accel_state->vbo.vb_start_op = -1;
251    info->accel_state->cbuf.vb_offset = 0;
252    info->accel_state->cbuf.vb_start_op = -1;
253
254    if (CS_FULL(info->cs)) {
255	radeon_cs_flush_indirect(pScrn);
256	return;
257    }
258    radeon_cs_erase(info->cs);
259    ret = radeon_cs_space_check_with_bo(info->cs,
260					info->accel_state->vbo.vb_bo,
261					RADEON_GEM_DOMAIN_GTT, 0);
262    if (ret)
263	ErrorF("space check failed in flush\n");
264
265    if (info->accel_state->cbuf.vb_bo) {
266	ret = radeon_cs_space_check_with_bo(info->cs,
267					    info->accel_state->cbuf.vb_bo,
268					    RADEON_GEM_DOMAIN_GTT, 0);
269	if (ret)
270	    ErrorF("space check failed in flush\n");
271    }
272
273 out:
274    if (info->dri2.enabled) {
275	info->accel_state->XInited3D = FALSE;
276	info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
277    }
278
279}
280#endif
281