radeon_exa_shared.c revision 68105dcb
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 12968105dcbSveegoPixmapPtr RADEONSolidPixmap(ScreenPtr pScreen, uint32_t solid) 13068105dcbSveego{ 13168105dcbSveego ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 13268105dcbSveego RADEONInfoPtr info = RADEONPTR(pScrn); 13368105dcbSveego PixmapPtr pPix = pScreen->CreatePixmap(pScreen, 1, 1, 32, 0); 13468105dcbSveego 13568105dcbSveego exaMoveInPixmap(pPix); 13668105dcbSveego 13768105dcbSveego#if defined(XF86DRM_MODE) 13868105dcbSveego if (info->cs) { 13968105dcbSveego struct radeon_bo *bo; 14068105dcbSveego 14168105dcbSveego bo = radeon_get_pixmap_bo(pPix); 14268105dcbSveego 14368105dcbSveego if (radeon_bo_map(bo, 1)) { 14468105dcbSveego pScreen->DestroyPixmap(pPix); 14568105dcbSveego return NULL; 14668105dcbSveego } 14768105dcbSveego 14868105dcbSveego memcpy(bo->ptr, &solid, 4); 14968105dcbSveego radeon_bo_unmap(bo); 15068105dcbSveego 15168105dcbSveego return pPix; 15268105dcbSveego } 15368105dcbSveego#endif 15468105dcbSveego 15568105dcbSveego if (!exaDrawableIsOffscreen(&pPix->drawable)) { 15668105dcbSveego pScreen->DestroyPixmap(pPix); 15768105dcbSveego return NULL; 15868105dcbSveego } 15968105dcbSveego 16068105dcbSveego /* XXX: Big hammer... */ 16168105dcbSveego info->accel_state->exa->WaitMarker(pScreen, info->accel_state->exaSyncMarker); 16268105dcbSveego memcpy(info->FB + exaGetPixmapOffset(pPix), &solid, 4); 16368105dcbSveego 16468105dcbSveego return pPix; 16568105dcbSveego} 16668105dcbSveego 1670974d292Smrgstatic Bool radeon_vb_get(ScrnInfoPtr pScrn) 1680974d292Smrg{ 1690974d292Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 1700974d292Smrg struct radeon_accel_state *accel_state = info->accel_state; 1710974d292Smrg 172921a55d8Smrg accel_state->vbo.vb_mc_addr = info->gartLocation + info->dri->bufStart + 1730974d292Smrg (accel_state->ib->idx*accel_state->ib->total)+ 1740974d292Smrg (accel_state->ib->total / 2); 175921a55d8Smrg accel_state->vbo.vb_total = (accel_state->ib->total / 2); 176921a55d8Smrg accel_state->vbo.vb_ptr = (pointer)((char*)accel_state->ib->address + 1770974d292Smrg (accel_state->ib->total / 2)); 178921a55d8Smrg accel_state->vbo.vb_offset = 0; 1790974d292Smrg return TRUE; 1800974d292Smrg} 1810974d292Smrg 1820974d292Smrgint radeon_cp_start(ScrnInfoPtr pScrn) 1830974d292Smrg{ 1840974d292Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 1850974d292Smrg struct radeon_accel_state *accel_state = info->accel_state; 1860974d292Smrg 1870974d292Smrg#if defined(XF86DRM_MODE) 1880974d292Smrg if (info->cs) { 1890974d292Smrg if (CS_FULL(info->cs)) { 1900974d292Smrg radeon_cs_flush_indirect(pScrn); 1910974d292Smrg } 1920974d292Smrg accel_state->ib_reset_op = info->cs->cdw; 1930974d292Smrg } else 1940974d292Smrg#endif 1950974d292Smrg { 1960974d292Smrg accel_state->ib = RADEONCPGetBuffer(pScrn); 1970974d292Smrg if (!radeon_vb_get(pScrn)) { 1980974d292Smrg return -1; 1990974d292Smrg } 2000974d292Smrg } 201921a55d8Smrg accel_state->vbo.vb_start_op = accel_state->vbo.vb_offset; 202921a55d8Smrg accel_state->cbuf.vb_start_op = accel_state->cbuf.vb_offset; 2030974d292Smrg return 0; 2040974d292Smrg} 2050974d292Smrg 206921a55d8Smrgvoid radeon_vb_no_space(ScrnInfoPtr pScrn, 207921a55d8Smrg struct radeon_vbo_object *vbo, 208921a55d8Smrg int vert_size) 2090974d292Smrg{ 2100974d292Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 211921a55d8Smrg struct radeon_accel_state *accel_state = info->accel_state; 2120974d292Smrg 2130974d292Smrg#if defined(XF86DRM_MODE) 2140974d292Smrg if (info->cs) { 215921a55d8Smrg if (vbo->vb_bo) { 216921a55d8Smrg if (vbo->vb_start_op != vbo->vb_offset) { 2170974d292Smrg accel_state->finish_op(pScrn, vert_size); 2180974d292Smrg accel_state->ib_reset_op = info->cs->cdw; 2190974d292Smrg } 2200974d292Smrg 2210974d292Smrg /* release the current VBO */ 222921a55d8Smrg radeon_vbo_put(pScrn, vbo); 2230974d292Smrg } 2240974d292Smrg /* get a new one */ 225921a55d8Smrg radeon_vbo_get(pScrn, vbo); 2260974d292Smrg return; 2270974d292Smrg } 2280974d292Smrg#endif 229921a55d8Smrg if (vbo->vb_start_op != -1) { 2300974d292Smrg accel_state->finish_op(pScrn, vert_size); 2310974d292Smrg radeon_cp_start(pScrn); 2320974d292Smrg } 2330974d292Smrg return; 2340974d292Smrg} 2350974d292Smrg 2360974d292Smrg#if defined(XF86DRM_MODE) 2370974d292Smrgvoid radeon_ib_discard(ScrnInfoPtr pScrn) 2380974d292Smrg{ 2390974d292Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 2400974d292Smrg int ret; 2410974d292Smrg 2420974d292Smrg if (info->accel_state->ib_reset_op) { 2430974d292Smrg /* if we have data just reset the CS and ignore the operation */ 2440974d292Smrg info->cs->cdw = info->accel_state->ib_reset_op; 2450974d292Smrg info->accel_state->ib_reset_op = 0; 2460974d292Smrg goto out; 2470974d292Smrg } 2480974d292Smrg 249921a55d8Smrg info->accel_state->vbo.vb_offset = 0; 250921a55d8Smrg info->accel_state->vbo.vb_start_op = -1; 251921a55d8Smrg info->accel_state->cbuf.vb_offset = 0; 252921a55d8Smrg info->accel_state->cbuf.vb_start_op = -1; 2530974d292Smrg 2540974d292Smrg if (CS_FULL(info->cs)) { 2550974d292Smrg radeon_cs_flush_indirect(pScrn); 2560974d292Smrg return; 2570974d292Smrg } 2580974d292Smrg radeon_cs_erase(info->cs); 2590974d292Smrg ret = radeon_cs_space_check_with_bo(info->cs, 260921a55d8Smrg info->accel_state->vbo.vb_bo, 2610974d292Smrg RADEON_GEM_DOMAIN_GTT, 0); 2620974d292Smrg if (ret) 2630974d292Smrg ErrorF("space check failed in flush\n"); 2640974d292Smrg 265921a55d8Smrg if (info->accel_state->cbuf.vb_bo) { 266921a55d8Smrg ret = radeon_cs_space_check_with_bo(info->cs, 267921a55d8Smrg info->accel_state->cbuf.vb_bo, 268921a55d8Smrg RADEON_GEM_DOMAIN_GTT, 0); 269921a55d8Smrg if (ret) 270921a55d8Smrg ErrorF("space check failed in flush\n"); 271921a55d8Smrg } 272921a55d8Smrg 2730974d292Smrg out: 2740974d292Smrg if (info->dri2.enabled) { 2750974d292Smrg info->accel_state->XInited3D = FALSE; 2760974d292Smrg info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN; 2770974d292Smrg } 2780974d292Smrg 2790974d292Smrg} 2800974d292Smrg#endif 281