📄 radeon_dri.c
字号:
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c,v 1.39 2003/11/06 18:38:00 tsi 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. */#ifdef HAVE_CONFIG_H#include "config.h"#endif/* * Authors: * Kevin E. Martin <martin@xfree86.org> * Rickard E. Faith <faith@valinux.com> * Gareth Hughes <gareth@valinux.com> * */#include <string.h>#include <stdio.h> /* Driver data structures */#include "radeon.h"#include "radeon_video.h"#include "radeon_reg.h"#include "radeon_macros.h"#include "radeon_dri.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"static size_t radeon_drm_page_size;static void RADEONDRITransitionTo2d(ScreenPtr pScreen);static void RADEONDRITransitionTo3d(ScreenPtr pScreen);static void RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen);static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen);#ifdef USE_XAAstatic void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);#endif/* 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 = use_db; db >= 0; 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 = info->depthBits; if (pConfigs[i].depthSize == 24 ? (RADEON_USE_STENCIL - stencil) : stencil) { pConfigs[i].stencilSize = 8; } else { pConfigs[i].stencilSize = 0; } pConfigs[i].auxBuffers = 0; pConfigs[i].level = 0; if (accum || (pConfigs[i].stencilSize && pConfigs[i].depthSize == 16)) { 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 = use_db; db >= 0; 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; pConfigs[i].depthSize = info->depthBits; if (pConfigs[i].depthSize == 24 ? (RADEON_USE_STENCIL - stencil) : stencil) { pConfigs[i].stencilSize = 8; } else { pConfigs[i].stencilSize = 0; } pConfigs[i].auxBuffers = 0; pConfigs[i].level = 0; if (accum || (pConfigs[i].stencilSize && pConfigs[i].depthSize == 16)) { 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, drm_context_t 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, drm_context_t 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); RADEONSAREAPrivPtr pSAREAPriv; RADEON_MARK_SYNC(info, pScrn); pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); if (pSAREAPriv->ctxOwner != DRIGetContext(pScrn->pScreen)) info->XInited3D = FALSE; /* TODO: Fix this more elegantly. * Sometimes (especially with multiple DRI clients), this code * runs immediately after a DRI client issues a rendering command. * * The accel code regularly inserts WAIT_UNTIL_IDLE into the * command buffer that is sent with the indirect buffer below. * The accel code fails to set the 3D cache flush registers for * the R300 before sending WAIT_UNTIL_IDLE. Sending a cache flush * on these new registers is not necessary for pure 2D functionality, * but it *is* necessary after 3D operations. * Without the cache flushes before WAIT_UNTIL_IDLE, the R300 locks up. * * The CP_IDLE call into the DRM indirectly flushes all caches and * thus avoids the lockup problem, but the solution is far from ideal. * Better solutions could be: * - always flush caches when entering the X server * - track the type of rendering commands somewhere and issue * cache flushes when they change * However, I don't feel confident enough with the control flow * inside the X server to implement either fix. -- nh */ /* On my computer (Radeon Mobility M10) The fix below results in x11perf -shmput500 rate of 245.0/sec which is lower than 264.0/sec I get without it. Doing the same each time before indirect buffer is submitted results in x11perf -shmput500 rate of 225.0/sec. On the other hand, not using CP acceleration at all benchmarks at 144.0/sec. For now let us accept this as a lesser evil, especially as the DRM driver for R300 is still in flux. Once the code is more stable this should probably be moved into DRM driver. */ if (info->ChipFamily>=CHIP_FAMILY_R300) drmCommandNone(info->drmFD, DRM_RADEON_CP_IDLE);}/* 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -