radeon_exa_shared.c revision 0974d292
10974d292Smrg/*
20974d292Smrg * Copyright 2005 Eric Anholt
30974d292Smrg * Copyright 2005 Benjamin Herrenschmidt
40974d292Smrg * Copyright 2008 Advanced Micro Devices, Inc.
50974d292Smrg * All Rights Reserved.
60974d292Smrg *
70974d292Smrg * Permission is hereby granted, free of charge, to any person obtaining a
80974d292Smrg * copy of this software and associated documentation files (the "Software"),
90974d292Smrg * to deal in the Software without restriction, including without limitation
100974d292Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
110974d292Smrg * and/or sell copies of the Software, and to permit persons to whom the
120974d292Smrg * Software is furnished to do so, subject to the following conditions:
130974d292Smrg *
140974d292Smrg * The above copyright notice and this permission notice (including the next
150974d292Smrg * paragraph) shall be included in all copies or substantial portions of the
160974d292Smrg * Software.
170974d292Smrg *
180974d292Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
190974d292Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
200974d292Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
210974d292Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
220974d292Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
230974d292Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
240974d292Smrg * SOFTWARE.
250974d292Smrg *
260974d292Smrg * Authors:
270974d292Smrg *    Eric Anholt <anholt@FreeBSD.org>
280974d292Smrg *    Zack Rusin <zrusin@trolltech.com>
290974d292Smrg *    Benjamin Herrenschmidt <benh@kernel.crashing.org>
300974d292Smrg *    Alex Deucher <alexander.deucher@amd.com>
310974d292Smrg *    Matthias Hopf <mhopf@suse.de>
320974d292Smrg */
330974d292Smrg#ifdef HAVE_CONFIG_H
340974d292Smrg#include "config.h"
350974d292Smrg#endif
360974d292Smrg
370974d292Smrg#include "radeon.h"
380974d292Smrg#ifdef XF86DRI
390974d292Smrg#include "radeon_drm.h"
400974d292Smrg#endif
410974d292Smrg#include "radeon_macros.h"
420974d292Smrg#include "radeon_probe.h"
430974d292Smrg#include "radeon_version.h"
440974d292Smrg#include "radeon_vbo.h"
450974d292Smrg
460974d292SmrgPixmapPtr
470974d292SmrgRADEONGetDrawablePixmap(DrawablePtr pDrawable)
480974d292Smrg{
490974d292Smrg    if (pDrawable->type == DRAWABLE_WINDOW)
500974d292Smrg	return pDrawable->pScreen->GetWindowPixmap((WindowPtr)pDrawable);
510974d292Smrg    else
520974d292Smrg	return (PixmapPtr)pDrawable;
530974d292Smrg}
540974d292Smrg
550974d292Smrgvoid RADEONVlineHelperClear(ScrnInfoPtr pScrn)
560974d292Smrg{
570974d292Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
580974d292Smrg    struct radeon_accel_state *accel_state = info->accel_state;
590974d292Smrg
600974d292Smrg    accel_state->vline_crtc = NULL;
610974d292Smrg    accel_state->vline_y1 = -1;
620974d292Smrg    accel_state->vline_y2 = 0;
630974d292Smrg}
640974d292Smrg
650974d292Smrgvoid RADEONVlineHelperSet(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2)
660974d292Smrg{
670974d292Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
680974d292Smrg    struct radeon_accel_state *accel_state = info->accel_state;
690974d292Smrg
700974d292Smrg    accel_state->vline_crtc = radeon_pick_best_crtc(pScrn, x1, x2, y1, y2);
710974d292Smrg    if (accel_state->vline_y1 == -1)
720974d292Smrg	accel_state->vline_y1 = y1;
730974d292Smrg    if (y1 < accel_state->vline_y1)
740974d292Smrg	accel_state->vline_y1 = y1;
750974d292Smrg    if (y2 > accel_state->vline_y2)
760974d292Smrg	accel_state->vline_y2 = y2;
770974d292Smrg}
780974d292Smrg
790974d292SmrgBool RADEONValidPM(uint32_t pm, int bpp)
800974d292Smrg{
810974d292Smrg    uint8_t r, g, b, a;
820974d292Smrg    Bool ret = FALSE;
830974d292Smrg
840974d292Smrg    switch (bpp) {
850974d292Smrg    case 8:
860974d292Smrg	a = pm & 0xff;
870974d292Smrg	if ((a == 0) || (a == 0xff))
880974d292Smrg	    ret = TRUE;
890974d292Smrg	break;
900974d292Smrg    case 16:
910974d292Smrg	r = (pm >> 11) & 0x1f;
920974d292Smrg	g = (pm >> 5) & 0x3f;
930974d292Smrg	b = (pm >> 0) & 0x1f;
940974d292Smrg	if (((r == 0) || (r == 0x1f)) &&
950974d292Smrg	    ((g == 0) || (g == 0x3f)) &&
960974d292Smrg	    ((b == 0) || (b == 0x1f)))
970974d292Smrg	    ret = TRUE;
980974d292Smrg	break;
990974d292Smrg    case 32:
1000974d292Smrg	a = (pm >> 24) & 0xff;
1010974d292Smrg	r = (pm >> 16) & 0xff;
1020974d292Smrg	g = (pm >> 8) & 0xff;
1030974d292Smrg	b = (pm >> 0) & 0xff;
1040974d292Smrg	if (((a == 0) || (a == 0xff)) &&
1050974d292Smrg	    ((r == 0) || (r == 0xff)) &&
1060974d292Smrg	    ((g == 0) || (g == 0xff)) &&
1070974d292Smrg	    ((b == 0) || (b == 0xff)))
1080974d292Smrg	    ret = TRUE;
1090974d292Smrg	break;
1100974d292Smrg    default:
1110974d292Smrg	break;
1120974d292Smrg    }
1130974d292Smrg    return ret;
1140974d292Smrg}
1150974d292Smrg
1160974d292SmrgBool RADEONCheckBPP(int bpp)
1170974d292Smrg{
1180974d292Smrg	switch (bpp) {
1190974d292Smrg	case 8:
1200974d292Smrg	case 16:
1210974d292Smrg	case 32:
1220974d292Smrg		return TRUE;
1230974d292Smrg	default:
1240974d292Smrg		break;
1250974d292Smrg	}
1260974d292Smrg	return FALSE;
1270974d292Smrg}
1280974d292Smrg
1290974d292Smrgstatic Bool radeon_vb_get(ScrnInfoPtr pScrn)
1300974d292Smrg{
1310974d292Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1320974d292Smrg    struct radeon_accel_state *accel_state = info->accel_state;
1330974d292Smrg
1340974d292Smrg    accel_state->vb_mc_addr = info->gartLocation + info->dri->bufStart +
1350974d292Smrg	(accel_state->ib->idx*accel_state->ib->total)+
1360974d292Smrg	(accel_state->ib->total / 2);
1370974d292Smrg    accel_state->vb_total = (accel_state->ib->total / 2);
1380974d292Smrg    accel_state->vb_ptr = (pointer)((char*)accel_state->ib->address +
1390974d292Smrg				    (accel_state->ib->total / 2));
1400974d292Smrg    accel_state->vb_offset = 0;
1410974d292Smrg    return TRUE;
1420974d292Smrg}
1430974d292Smrg
1440974d292Smrgvoid radeon_vb_discard(ScrnInfoPtr pScrn)
1450974d292Smrg{
1460974d292Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1470974d292Smrg
1480974d292Smrg    info->accel_state->vb_start_op = -1;
1490974d292Smrg}
1500974d292Smrg
1510974d292Smrgint radeon_cp_start(ScrnInfoPtr pScrn)
1520974d292Smrg{
1530974d292Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1540974d292Smrg    struct radeon_accel_state *accel_state = info->accel_state;
1550974d292Smrg
1560974d292Smrg#if defined(XF86DRM_MODE)
1570974d292Smrg    if (info->cs) {
1580974d292Smrg	if (CS_FULL(info->cs)) {
1590974d292Smrg	    radeon_cs_flush_indirect(pScrn);
1600974d292Smrg	}
1610974d292Smrg	accel_state->ib_reset_op = info->cs->cdw;
1620974d292Smrg	accel_state->vb_start_op = accel_state->vb_offset;
1630974d292Smrg    } else
1640974d292Smrg#endif
1650974d292Smrg    {
1660974d292Smrg	accel_state->ib = RADEONCPGetBuffer(pScrn);
1670974d292Smrg	if (!radeon_vb_get(pScrn)) {
1680974d292Smrg	    return -1;
1690974d292Smrg	}
1700974d292Smrg	accel_state->vb_start_op = accel_state->vb_offset;
1710974d292Smrg    }
1720974d292Smrg    return 0;
1730974d292Smrg}
1740974d292Smrg
1750974d292Smrgvoid radeon_vb_no_space(ScrnInfoPtr pScrn, int vert_size)
1760974d292Smrg{
1770974d292Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1780974d292Smrg    struct radeon_accel_state *accel_state = info->accel_state;
1790974d292Smrg
1800974d292Smrg#if defined(XF86DRM_MODE)
1810974d292Smrg    if (info->cs) {
1820974d292Smrg	if (accel_state->vb_bo) {
1830974d292Smrg	    if (accel_state->vb_start_op != accel_state->vb_offset) {
1840974d292Smrg		accel_state->finish_op(pScrn, vert_size);
1850974d292Smrg		accel_state->ib_reset_op = info->cs->cdw;
1860974d292Smrg	    }
1870974d292Smrg
1880974d292Smrg	    /* release the current VBO */
1890974d292Smrg	    radeon_vbo_put(pScrn);
1900974d292Smrg	}
1910974d292Smrg	/* get a new one */
1920974d292Smrg	radeon_vbo_get(pScrn);
1930974d292Smrg	return;
1940974d292Smrg    }
1950974d292Smrg#endif
1960974d292Smrg    if (accel_state->vb_start_op != -1) {
1970974d292Smrg        accel_state->finish_op(pScrn, vert_size);
1980974d292Smrg        radeon_cp_start(pScrn);
1990974d292Smrg    }
2000974d292Smrg    return;
2010974d292Smrg}
2020974d292Smrg
2030974d292Smrg#if defined(XF86DRM_MODE)
2040974d292Smrgvoid radeon_ib_discard(ScrnInfoPtr pScrn)
2050974d292Smrg{
2060974d292Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2070974d292Smrg    int ret;
2080974d292Smrg
2090974d292Smrg    if (info->accel_state->ib_reset_op) {
2100974d292Smrg        /* if we have data just reset the CS and ignore the operation */
2110974d292Smrg	info->cs->cdw = info->accel_state->ib_reset_op;
2120974d292Smrg	info->accel_state->ib_reset_op = 0;
2130974d292Smrg	goto out;
2140974d292Smrg    }
2150974d292Smrg
2160974d292Smrg    info->accel_state->vb_offset = 0;
2170974d292Smrg    info->accel_state->vb_start_op = -1;
2180974d292Smrg
2190974d292Smrg    if (CS_FULL(info->cs)) {
2200974d292Smrg	radeon_cs_flush_indirect(pScrn);
2210974d292Smrg	return;
2220974d292Smrg    }
2230974d292Smrg    radeon_cs_erase(info->cs);
2240974d292Smrg    ret = radeon_cs_space_check_with_bo(info->cs,
2250974d292Smrg					info->accel_state->vb_bo,
2260974d292Smrg					RADEON_GEM_DOMAIN_GTT, 0);
2270974d292Smrg    if (ret)
2280974d292Smrg	ErrorF("space check failed in flush\n");
2290974d292Smrg
2300974d292Smrg out:
2310974d292Smrg    if (info->dri2.enabled) {
2320974d292Smrg	info->accel_state->XInited3D = FALSE;
2330974d292Smrg	info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
2340974d292Smrg    }
2350974d292Smrg
2360974d292Smrg}
2370974d292Smrg#endif
238