📄 radeon_dri.c
字号:
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c,v 1.38 2003/09/28 20:15:55 alanh Exp $ *//* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, * 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, 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. *//* * Authors: * Kevin E. Martin <martin@xfree86.org> * Rickard E. Faith <faith@valinux.com> * Gareth Hughes <gareth@valinux.com> * */ /* Driver data structures */#include "radeon.h"#include "radeon_macros.h"#include "radeon_dri.h"#include "radeon_reg.h"#include "radeon_version.h" /* X and server generic header files */#include "xf86.h"#include "xf86PciInfo.h"#include "windowstr.h"#include "shadowfb.h" /* GLX/DRI/DRM definitions */#define _XF86DRI_SERVER_#include "GL/glxtokens.h"#include "sarea.h"#include "radeon_sarea.h"/* HACK - for now, put this here... *//* Alpha - this may need to be a variable to handle UP1x00 vs TITAN */#if defined(__alpha__)# define DRM_PAGE_SIZE 8192#elif defined(__ia64__)# define DRM_PAGE_SIZE getpagesize()#else# define DRM_PAGE_SIZE 4096#endifstatic Bool RADEONDRICloseFullScreen(ScreenPtr pScreen);static Bool RADEONDRIOpenFullScreen(ScreenPtr pScreen);static void RADEONDRITransitionTo2d(ScreenPtr pScreen);static void RADEONDRITransitionTo3d(ScreenPtr pScreen);static void RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen);static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen);static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);/* Initialize the visual configs that are supported by the hardware. * These are combined with the visual configs that the indirect * rendering core supports, and the intersection is exported to the * client. */static Bool RADEONInitVisualConfigs(ScreenPtr pScreen){ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); int numConfigs = 0; __GLXvisualConfig *pConfigs = 0; RADEONConfigPrivPtr pRADEONConfigs = 0; RADEONConfigPrivPtr *pRADEONConfigPtrs = 0; int i, accum, stencil, db, use_db; use_db = !info->noBackBuffer ? 1 : 0; switch (info->CurrentLayout.pixel_code) { case 8: /* 8bpp mode is not support */ case 15: /* FIXME */ case 24: /* FIXME */ xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] RADEONInitVisualConfigs failed " "(depth %d not supported). " "Disabling DRI.\n", info->CurrentLayout.pixel_code); return FALSE;#define RADEON_USE_ACCUM 1#define RADEON_USE_STENCIL 1 case 16: numConfigs = 1; if (RADEON_USE_ACCUM) numConfigs *= 2; if (RADEON_USE_STENCIL) numConfigs *= 2; if (use_db) numConfigs *= 2; if (!(pConfigs = (__GLXvisualConfig *)xcalloc(sizeof(__GLXvisualConfig), numConfigs))) { return FALSE; } if (!(pRADEONConfigs = (RADEONConfigPrivPtr)xcalloc(sizeof(RADEONConfigPrivRec), numConfigs))) { xfree(pConfigs); return FALSE; } if (!(pRADEONConfigPtrs = (RADEONConfigPrivPtr *)xcalloc(sizeof(RADEONConfigPrivPtr), numConfigs))) { xfree(pConfigs); xfree(pRADEONConfigs); return FALSE; } i = 0; for (db = 0; db <= use_db; db++) { for (accum = 0; accum <= RADEON_USE_ACCUM; accum++) { for (stencil = 0; stencil <= RADEON_USE_STENCIL; stencil++) { pRADEONConfigPtrs[i] = &pRADEONConfigs[i]; pConfigs[i].vid = (VisualID)(-1); pConfigs[i].class = -1; pConfigs[i].rgba = TRUE; pConfigs[i].redSize = 5; pConfigs[i].greenSize = 6; pConfigs[i].blueSize = 5; pConfigs[i].alphaSize = 0; pConfigs[i].redMask = 0x0000F800; pConfigs[i].greenMask = 0x000007E0; pConfigs[i].blueMask = 0x0000001F; pConfigs[i].alphaMask = 0x00000000; if (accum) { /* Simulated in software */ pConfigs[i].accumRedSize = 16; pConfigs[i].accumGreenSize = 16; pConfigs[i].accumBlueSize = 16; pConfigs[i].accumAlphaSize = 0; } else { pConfigs[i].accumRedSize = 0; pConfigs[i].accumGreenSize = 0; pConfigs[i].accumBlueSize = 0; pConfigs[i].accumAlphaSize = 0; } if (db) pConfigs[i].doubleBuffer = TRUE; else pConfigs[i].doubleBuffer = FALSE; pConfigs[i].stereo = FALSE; pConfigs[i].bufferSize = 16; pConfigs[i].depthSize = 16; if (stencil) pConfigs[i].stencilSize = 8; else pConfigs[i].stencilSize = 0; pConfigs[i].auxBuffers = 0; pConfigs[i].level = 0; if (accum) { pConfigs[i].visualRating = GLX_SLOW_CONFIG; } else { pConfigs[i].visualRating = GLX_NONE; } pConfigs[i].transparentPixel = GLX_NONE; pConfigs[i].transparentRed = 0; pConfigs[i].transparentGreen = 0; pConfigs[i].transparentBlue = 0; pConfigs[i].transparentAlpha = 0; pConfigs[i].transparentIndex = 0; i++; } } } break; case 32: numConfigs = 1; if (RADEON_USE_ACCUM) numConfigs *= 2; if (RADEON_USE_STENCIL) numConfigs *= 2; if (use_db) numConfigs *= 2; if (!(pConfigs = (__GLXvisualConfig *)xcalloc(sizeof(__GLXvisualConfig), numConfigs))) { return FALSE; } if (!(pRADEONConfigs = (RADEONConfigPrivPtr)xcalloc(sizeof(RADEONConfigPrivRec), numConfigs))) { xfree(pConfigs); return FALSE; } if (!(pRADEONConfigPtrs = (RADEONConfigPrivPtr *)xcalloc(sizeof(RADEONConfigPrivPtr), numConfigs))) { xfree(pConfigs); xfree(pRADEONConfigs); return FALSE; } i = 0; for (db = 0; db <= use_db; db++) { for (accum = 0; accum <= RADEON_USE_ACCUM; accum++) { for (stencil = 0; stencil <= RADEON_USE_STENCIL; stencil++) { pRADEONConfigPtrs[i] = &pRADEONConfigs[i]; pConfigs[i].vid = (VisualID)(-1); pConfigs[i].class = -1; pConfigs[i].rgba = TRUE; pConfigs[i].redSize = 8; pConfigs[i].greenSize = 8; pConfigs[i].blueSize = 8; pConfigs[i].alphaSize = 8; pConfigs[i].redMask = 0x00FF0000; pConfigs[i].greenMask = 0x0000FF00; pConfigs[i].blueMask = 0x000000FF; pConfigs[i].alphaMask = 0xFF000000; if (accum) { /* Simulated in software */ pConfigs[i].accumRedSize = 16; pConfigs[i].accumGreenSize = 16; pConfigs[i].accumBlueSize = 16; pConfigs[i].accumAlphaSize = 16; } else { pConfigs[i].accumRedSize = 0; pConfigs[i].accumGreenSize = 0; pConfigs[i].accumBlueSize = 0; pConfigs[i].accumAlphaSize = 0; } if (db) pConfigs[i].doubleBuffer = TRUE; else pConfigs[i].doubleBuffer = FALSE; pConfigs[i].stereo = FALSE; pConfigs[i].bufferSize = 32; if (stencil) { pConfigs[i].depthSize = 24; pConfigs[i].stencilSize = 8; } else { pConfigs[i].depthSize = 24; pConfigs[i].stencilSize = 0; } pConfigs[i].auxBuffers = 0; pConfigs[i].level = 0; if (accum) { pConfigs[i].visualRating = GLX_SLOW_CONFIG; } else { pConfigs[i].visualRating = GLX_NONE; } pConfigs[i].transparentPixel = GLX_NONE; pConfigs[i].transparentRed = 0; pConfigs[i].transparentGreen = 0; pConfigs[i].transparentBlue = 0; pConfigs[i].transparentAlpha = 0; pConfigs[i].transparentIndex = 0; i++; } } } break; } info->numVisualConfigs = numConfigs; info->pVisualConfigs = pConfigs; info->pVisualConfigsPriv = pRADEONConfigs; GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pRADEONConfigPtrs); return TRUE;}/* Create the Radeon-specific context information */static Bool RADEONCreateContext(ScreenPtr pScreen, VisualPtr visual, drmContext hwContext, void *pVisualConfigPriv, DRIContextType contextStore){#ifdef PER_CONTEXT_SAREA ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); RADEONDRIContextPtr ctx_info; ctx_info = (RADEONDRIContextPtr)contextStore; if (!ctx_info) return FALSE; if (drmAddMap(info->drmFD, 0, info->perctx_sarea_size, DRM_SHM, DRM_REMOVABLE, &ctx_info->sarea_handle) < 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] could not create private sarea for ctx id (%d)\n", (int)hwContext); return FALSE; } if (drmAddContextPrivateMapping(info->drmFD, hwContext, ctx_info->sarea_handle) < 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] could not associate private sarea to ctx id (%d)\n", (int)hwContext); drmRmMap(info->drmFD, ctx_info->sarea_handle); return FALSE; } ctx_info->ctx_id = hwContext;#endif return TRUE;}/* Destroy the Radeon-specific context information */static void RADEONDestroyContext(ScreenPtr pScreen, drmContext hwContext, DRIContextType contextStore){#ifdef PER_CONTEXT_SAREA ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); RADEONDRIContextPtr ctx_info; ctx_info = (RADEONDRIContextPtr)contextStore; if (!ctx_info) return; if (drmRmMap(info->drmFD, ctx_info->sarea_handle) < 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] could not remove private sarea for ctx id (%d)\n", (int)hwContext); }#endif}/* Called when the X server is woken up to allow the last client's * context to be saved and the X server's context to be loaded. This is * not necessary for the Radeon since the client detects when it's * context is not currently loaded and then load's it itself. Since the * registers to start and stop the CP are privileged, only the X server * can start/stop the engine. */static void RADEONEnterServer(ScreenPtr pScreen){ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); if (info->accel) info->accel->NeedToSync = TRUE;}/* Called when the X server goes to sleep to allow the X server's * context to be saved and the last client's context to be loaded. This * is not necessary for the Radeon since the client detects when it's * context is not currently loaded and then load's it itself. Since the * registers to start and stop the CP are privileged, only the X server * can start/stop the engine. */static void RADEONLeaveServer(ScreenPtr pScreen){ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); RING_LOCALS; /* The CP is always running, but if we've generated any CP commands * we must flush them to the kernel module now. */ if (info->CPInUse) { RADEON_FLUSH_CACHE(); RADEON_WAIT_UNTIL_IDLE(); RADEONCPReleaseIndirect(pScrn); info->CPInUse = FALSE; }}/* Contexts can be swapped by the X server if necessary. This callback * is currently only used to perform any functions necessary when * entering or leaving the X server, and in the future might not be * necessary. */static void RADEONDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, DRIContextType oldContextType, void *oldContext, DRIContextType newContextType, void *newContext){ if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) && (newContextType==DRI_2D_CONTEXT)) { /* Entering from Wakeup */ RADEONEnterServer(pScreen); } if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) && (newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */ RADEONLeaveServer(pScreen); }}/* The Radeon has depth tiling on all the time, so we have to convert * the x,y coordinates into the memory bus address (mba) in the same * manner as the engine. In each case, the linear block address (ba) * is calculated, and then wired with x and y to produce the final * memory address. */static CARD32 radeon_mba_z16(RADEONInfoPtr info, int x, int y){ CARD32 pitch = info->frontPitch; CARD32 address = 0; /* a[0] = 0 */ CARD32 ba; ba = (y / 16) * (pitch / 32) + (x / 32); address |= (x & 0x7) << 1; /* a[1..3] = x[0..2] */ address |= (y & 0x7) << 4; /* a[4..6] = y[0..2] */ address |= (x & 0x8) << 4; /* a[7] = x[3] */ address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */ address |= (y & 0x8) << 7; /* a[10] = y[3] */ address |= ((x & 0x10) ^ (y & 0x10)) << 7; /* a[11] = x[4] ^ y[4] */ address |= (ba & ~0x3u) << 10; /* a[12..] = ba[2..] */ return address;}static CARD32 radeon_mba_z32(RADEONInfoPtr info, int x, int y){ CARD32 pitch = info->frontPitch; CARD32 address = 0; /* a[0..1] = 0 */ CARD32 ba; ba = (y / 16) * (pitch / 16) + (x / 16); address |= (x & 0x7) << 2; /* a[2..4] = x[0..2] */ address |= (y & 0x3) << 5; /* a[5..6] = y[0..1] */ address |= (((x & 0x10) >> 2) ^ (y & 0x4)) << 5; /* a[7] = x[4] ^ y[2] */ address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */ address |= (y & 0x8) << 7; /* a[10] = y[3] */ address |= (((x & 0x8) << 1) ^ (y & 0x10)) << 7; /* a[11] = x[3] ^ y[4] */ address |= (ba & ~0x3u) << 10; /* a[12..] = ba[2..] */ return address;}/* 16-bit depth buffer functions */#define WRITE_DEPTH16(_x, _y, d) \ *(CARD16 *)(pointer)(buf + radeon_mba_z16(info, (_x), (_y))) = (d)#define READ_DEPTH16(d, _x, _y) \ (d) = *(CARD16 *)(pointer)(buf + radeon_mba_z16(info, (_x), (_y)))/* 24 bit depth, 8 bit stencil depthbuffer functions */#define WRITE_DEPTH32(_x, _y, d) \do { \ CARD32 tmp = \ *(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))); \ tmp &= 0xff000000; \ tmp |= ((d) & 0x00ffffff); \ *(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))) = tmp; \} while (0)#define READ_DEPTH32(d, _x, _y) \ d = (*(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))) \ & 0x00ffffff)/* Screen to screen copy of data in the depth buffer */static void RADEONScreenToScreenCopyDepth(ScrnInfoPtr pScrn, int xa, int ya, int xb, int yb, int w, int h){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -