📄 r128_accel.c
字号:
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c,v 1.17 2003/10/03 20:11:11 herrb Exp $ *//* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and * VA Linux Systems Inc., Fremont, California. * * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation on the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */#ifdef HAVE_CONFIG_H#include "config.h"#endif/* * Authors: * Rickard E. Faith <faith@valinux.com> * Kevin E. Martin <martin@valinux.com> * Alan Hourihane <alanh@fairlite.demon.co.uk> * * Credits: * * Thanks to Alan Hourihane <alanh@fairlite.demon..co.uk> and SuSE for * providing source code to their 3.3.x Rage 128 driver. Portions of * this file are based on the acceleration code for that driver. * * References: * * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April * 1999. * * RAGE 128 Software Development Manual (Technical Reference Manual P/N * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999. * * Notes on unimplemented XAA optimizations: * * SetClipping: The Rage128 doesn't support the full 16bit registers needed * for XAA clip rect support. * SolidFillTrap: This will probably work if we can compute the correct * Bresenham error values. * TwoPointLine: The Rage 128 supports Bresenham lines instead. * DashedLine with non-power-of-two pattern length: Apparently, there is * no way to set the length of the pattern -- it is always * assumed to be 8 or 32 (or 1024?). * ScreenToScreenColorExpandFill: See p. 4-17 of the Technical Reference * Manual where it states that monochrome expansion of frame * buffer data is not supported. * CPUToScreenColorExpandFill, direct: The implementation here uses a hybrid * direct/indirect method. If we had more data registers, * then we could do better. If XAA supported a trigger write * address, the code would be simpler. * (Alan Hourihane) Update. We now use purely indirect and clip the full * rectangle. Seems as the direct method has some problems * with this, although this indirect method is much faster * than the old method of setting up the engine per scanline. * This code was the basis of the Radeon work we did. * Color8x8PatternFill: Apparently, an 8x8 color brush cannot take an 8x8 * pattern from frame buffer memory. * ImageWrites: See CPUToScreenColorExpandFill. * */#define R128_TRAPEZOIDS 0 /* Trapezoids don't work */ /* Driver data structures */#include <errno.h>#include "r128.h"#include "r128_reg.h"#include "r128_probe.h"#ifdef XF86DRI#include "r128_sarea.h"#define _XF86DRI_SERVER_#include "r128_dri.h"#include "r128_common.h"#endif /* Line support */#include "miline.h" /* X and server generic header files */#include "xf86.h"static struct { int rop; int pattern;} R128_ROP[] = { { R128_ROP3_ZERO, R128_ROP3_ZERO }, /* GXclear */ { R128_ROP3_DSa, R128_ROP3_DPa }, /* Gxand */ { R128_ROP3_SDna, R128_ROP3_PDna }, /* GXandReverse */ { R128_ROP3_S, R128_ROP3_P }, /* GXcopy */ { R128_ROP3_DSna, R128_ROP3_DPna }, /* GXandInverted */ { R128_ROP3_D, R128_ROP3_D }, /* GXnoop */ { R128_ROP3_DSx, R128_ROP3_DPx }, /* GXxor */ { R128_ROP3_DSo, R128_ROP3_DPo }, /* GXor */ { R128_ROP3_DSon, R128_ROP3_DPon }, /* GXnor */ { R128_ROP3_DSxn, R128_ROP3_PDxn }, /* GXequiv */ { R128_ROP3_Dn, R128_ROP3_Dn }, /* GXinvert */ { R128_ROP3_SDno, R128_ROP3_PDno }, /* GXorReverse */ { R128_ROP3_Sn, R128_ROP3_Pn }, /* GXcopyInverted */ { R128_ROP3_DSno, R128_ROP3_DPno }, /* GXorInverted */ { R128_ROP3_DSan, R128_ROP3_DPan }, /* GXnand */ { R128_ROP3_ONE, R128_ROP3_ONE } /* GXset */};extern int getR128EntityIndex(void);/* Flush all dirty data in the Pixel Cache to memory. */void R128EngineFlush(ScrnInfoPtr pScrn){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; int i; OUTREGP(R128_PC_NGUI_CTLSTAT, R128_PC_FLUSH_ALL, ~R128_PC_FLUSH_ALL); for (i = 0; i < R128_TIMEOUT; i++) { if (!(INREG(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) break; }}/* Reset graphics card to known state. */void R128EngineReset(ScrnInfoPtr pScrn){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; CARD32 clock_cntl_index; CARD32 mclk_cntl; CARD32 gen_reset_cntl; R128EngineFlush(pScrn); clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX); mclk_cntl = INPLL(pScrn, R128_MCLK_CNTL); OUTPLL(R128_MCLK_CNTL, mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP); gen_reset_cntl = INREG(R128_GEN_RESET_CNTL); OUTREG(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI); INREG(R128_GEN_RESET_CNTL); OUTREG(R128_GEN_RESET_CNTL, gen_reset_cntl & (CARD32)(~R128_SOFT_RESET_GUI)); INREG(R128_GEN_RESET_CNTL); OUTPLL(R128_MCLK_CNTL, mclk_cntl); OUTREG(R128_CLOCK_CNTL_INDEX, clock_cntl_index); OUTREG(R128_GEN_RESET_CNTL, gen_reset_cntl);}/* The FIFO has 64 slots. This routines waits until at least `entries' of these slots are empty. */void R128WaitForFifoFunction(ScrnInfoPtr pScrn, int entries){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; int i; for (;;) { for (i = 0; i < R128_TIMEOUT; i++) { info->fifo_slots = INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK; if (info->fifo_slots >= entries) return; } R128TRACE(("FIFO timed out: %d entries, stat=0x%08x, probe=0x%08x\n", INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK, INREG(R128_GUI_STAT), INREG(R128_GUI_PROBE))); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FIFO timed out, resetting engine...\n"); R128EngineReset(pScrn);#ifdef XF86DRI R128CCE_RESET(pScrn, info); if (info->directRenderingEnabled) { R128CCE_START(pScrn, info); }#endif }}/* Wait for the graphics engine to be completely idle: the FIFO has drained, the Pixel Cache is flushed, and the engine is idle. This is a standard "sync" function that will make the hardware "quiescent". */void R128WaitForIdle(ScrnInfoPtr pScrn){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; int i; R128WaitForFifoFunction(pScrn, 64); for (;;) { for (i = 0; i < R128_TIMEOUT; i++) { if (!(INREG(R128_GUI_STAT) & R128_GUI_ACTIVE)) { R128EngineFlush(pScrn); return; } } R128TRACE(("Idle timed out: %d entries, stat=0x%08x, probe=0x%08x\n", INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK, INREG(R128_GUI_STAT), INREG(R128_GUI_PROBE))); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Idle timed out, resetting engine...\n");#ifdef XF86DRI R128CCE_STOP(pScrn, info);#endif R128EngineReset(pScrn);#ifdef XF86DRI R128CCE_RESET(pScrn, info); if (info->directRenderingEnabled) { R128CCE_START(pScrn, info); }#endif }}#ifdef XF86DRI/* Wait until the CCE is completely idle: the FIFO has drained and the * CCE is idle. */void R128CCEWaitForIdle(ScrnInfoPtr pScrn){ R128InfoPtr info = R128PTR(pScrn); int ret, i; FLUSH_RING(); for (;;) { i = 0; do { ret = drmCommandNone(info->drmFD, DRM_R128_CCE_IDLE); } while ( ret && errno == EBUSY && i++ < (R128_IDLE_RETRY * R128_IDLE_RETRY) ); if (ret && ret != -EBUSY) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: CCE idle %d\n", __FUNCTION__, ret); } if (i > R128_IDLE_RETRY) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: (DEBUG) CCE idle took i = %d\n", __FUNCTION__, i); } if (ret == 0) return; xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Idle timed out, resetting engine...\n"); R128CCE_STOP(pScrn, info); R128EngineReset(pScrn); /* Always restart the engine when doing CCE 2D acceleration */ R128CCE_RESET(pScrn, info); R128CCE_START(pScrn, info); }}int R128CCEStop(ScrnInfoPtr pScrn){ R128InfoPtr info = R128PTR(pScrn); drmR128CCEStop stop; int ret, i; stop.flush = 1; stop.idle = 1; ret = drmCommandWrite( info->drmFD, DRM_R128_CCE_STOP, &stop, sizeof(drmR128CCEStop) ); if ( ret == 0 ) { return 0; } else if ( errno != EBUSY ) { return -errno; } stop.flush = 0; i = 0; do { ret = drmCommandWrite( info->drmFD, DRM_R128_CCE_STOP, &stop, sizeof(drmR128CCEStop) ); } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY ); if ( ret == 0 ) { return 0; } else if ( errno != EBUSY ) { return -errno; } stop.idle = 0; if ( drmCommandWrite( info->drmFD, DRM_R128_CCE_STOP, &stop, sizeof(drmR128CCEStop) )) { return -errno; } else { return 0; }}#endif/* Setup for XAA SolidFill. */static void R128SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, unsigned int planemask){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; R128WaitForFifo(pScrn, 4); OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl | R128_GMC_BRUSH_SOLID_COLOR | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP[rop].pattern)); OUTREG(R128_DP_BRUSH_FRGD_CLR, color); OUTREG(R128_DP_WRITE_MASK, planemask); OUTREG(R128_DP_CNTL, (R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM));}/* Subsequent XAA SolidFillRect. Tests: xtest CH06/fllrctngl, xterm*/static void R128SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; R128WaitForFifo(pScrn, 2); OUTREG(R128_DST_Y_X, (y << 16) | x); OUTREG(R128_DST_WIDTH_HEIGHT, (w << 16) | h);}/* Setup for XAA solid lines. */static void R128SetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, unsigned int planemask){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; R128WaitForFifo(pScrn, 3); OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl | R128_GMC_BRUSH_SOLID_COLOR | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP[rop].pattern)); OUTREG(R128_DP_BRUSH_FRGD_CLR, color); OUTREG(R128_DP_WRITE_MASK, planemask);}/* Subsequent XAA solid Bresenham line. Tests: xtest CH06/drwln, ico, Mark Vojkovich's linetest program [See http://www.xfree86.org/devel/archives/devel/1999-Jun/0102.shtml for Mark Vojkovich's linetest program, posted 2Jun99 to devel@xfree86.org.]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -