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" 3843df4709Smrg#ifdef XF86DRI 3943df4709Smrg#include "radeon_drm.h" 4043df4709Smrg#endif 4143df4709Smrg#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 7043df4709Smrg 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{ 13143df4709Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 13243df4709Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 13368105dcbSveego PixmapPtr pPix = pScreen->CreatePixmap(pScreen, 1, 1, 32, 0); 13443df4709Smrg 13568105dcbSveego exaMoveInPixmap(pPix); 13668105dcbSveego 13743df4709Smrg#if defined(XF86DRM_MODE) 13843df4709Smrg if (info->cs) { 13943df4709Smrg struct radeon_bo *bo; 14043df4709Smrg 14143df4709Smrg bo = radeon_get_pixmap_bo(pPix); 14243df4709Smrg 14343df4709Smrg if (radeon_bo_map(bo, 1)) { 14443df4709Smrg pScreen->DestroyPixmap(pPix); 14543df4709Smrg return NULL; 14643df4709Smrg } 14743df4709Smrg 14843df4709Smrg memcpy(bo->ptr, &solid, 4); 14943df4709Smrg radeon_bo_unmap(bo); 15068105dcbSveego 15143df4709Smrg return pPix; 15243df4709Smrg } 15343df4709Smrg#endif 15443df4709Smrg 15543df4709Smrg if (!exaDrawableIsOffscreen(&pPix->drawable)) { 15668105dcbSveego pScreen->DestroyPixmap(pPix); 15768105dcbSveego return NULL; 15868105dcbSveego } 15968105dcbSveego 16043df4709Smrg /* XXX: Big hammer... */ 16143df4709Smrg info->accel_state->exa->WaitMarker(pScreen, info->accel_state->exaSyncMarker); 16243df4709Smrg memcpy(info->FB + exaGetPixmapOffset(pPix), &solid, 4); 16368105dcbSveego 16468105dcbSveego return pPix; 16568105dcbSveego} 16668105dcbSveego 16743df4709Smrgstatic Bool radeon_vb_get(ScrnInfoPtr pScrn) 16843df4709Smrg{ 16943df4709Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 17043df4709Smrg struct radeon_accel_state *accel_state = info->accel_state; 17143df4709Smrg 17243df4709Smrg accel_state->vbo.vb_mc_addr = info->gartLocation + info->dri->bufStart + 17343df4709Smrg (accel_state->ib->idx*accel_state->ib->total)+ 17443df4709Smrg (accel_state->ib->total / 2); 17543df4709Smrg accel_state->vbo.vb_total = (accel_state->ib->total / 2); 17643df4709Smrg accel_state->vbo.vb_ptr = (pointer)((char*)accel_state->ib->address + 17743df4709Smrg (accel_state->ib->total / 2)); 17843df4709Smrg accel_state->vbo.vb_offset = 0; 17943df4709Smrg return TRUE; 18043df4709Smrg} 18143df4709Smrg 1820974d292Smrgint radeon_cp_start(ScrnInfoPtr pScrn) 1830974d292Smrg{ 1840974d292Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 1850974d292Smrg struct radeon_accel_state *accel_state = info->accel_state; 1860974d292Smrg 18743df4709Smrg#if defined(XF86DRM_MODE) 18843df4709Smrg if (info->cs) { 18943df4709Smrg if (CS_FULL(info->cs)) { 19043df4709Smrg radeon_cs_flush_indirect(pScrn); 19143df4709Smrg } 19243df4709Smrg accel_state->ib_reset_op = info->cs->cdw; 19343df4709Smrg } else 19443df4709Smrg#endif 19543df4709Smrg { 19643df4709Smrg accel_state->ib = RADEONCPGetBuffer(pScrn); 19743df4709Smrg if (!radeon_vb_get(pScrn)) { 19843df4709Smrg return -1; 19943df4709Smrg } 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 21343df4709Smrg#if defined(XF86DRM_MODE) 21443df4709Smrg if (info->cs) { 21543df4709Smrg if (vbo->vb_bo) { 21643df4709Smrg if (vbo->vb_start_op != vbo->vb_offset) { 21743df4709Smrg accel_state->finish_op(pScrn, vert_size); 21843df4709Smrg accel_state->ib_reset_op = info->cs->cdw; 21943df4709Smrg } 2206322c902Smrg 22143df4709Smrg /* release the current VBO */ 22243df4709Smrg radeon_vbo_put(pScrn, vbo); 22343df4709Smrg } 22443df4709Smrg /* get a new one */ 22543df4709Smrg radeon_vbo_get(pScrn, vbo); 22643df4709Smrg return; 22743df4709Smrg } 22843df4709Smrg#endif 22943df4709Smrg if (vbo->vb_start_op != -1) { 23043df4709Smrg accel_state->finish_op(pScrn, vert_size); 23143df4709Smrg radeon_cp_start(pScrn); 2320974d292Smrg } 2330974d292Smrg return; 2340974d292Smrg} 2350974d292Smrg 23643df4709Smrg#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} 28043df4709Smrg#endif 281