/** @file $Id: vboxvideo_dri.c 55192 2015-04-10 17:43:53Z vboxsync $ * * VirtualBox X11 Additions graphics driver, DRI support */ /* * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. * -------------------------------------------------------------------- * * This code is based on: * * X11 TDFX driver, src/tdfx_dri.c * * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. * 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 the rights to use, copy, modify, merge, publish, * distribute, sub license, 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 PRECISION INSIGHT AND/OR ITS 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: * Daryll Strauss */ #include "xf86.h" #include "vboxvideo.h" #ifndef PCIACCESS # include "xf86Pci.h" #endif #include #include #include #include static Bool VBOXCreateContext(ScreenPtr pScreen, VisualPtr visual, drm_context_t hwContext, void *pVisualConfigPriv, DRIContextType contextStore); static void VBOXDestroyContext(ScreenPtr pScreen, drm_context_t hwContext, DRIContextType contextStore); static void VBOXDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, DRIContextType oldContextType, void *oldContext, DRIContextType newContextType, void *newContext); static void VBOXDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index); static void VBOXDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, RegionPtr prgnSrc, CARD32 index); static Bool VBOXDRIOpenFullScreen(ScreenPtr pScreen); static Bool VBOXDRICloseFullScreen(ScreenPtr pScreen); static void VBOXDRITransitionTo2d(ScreenPtr pScreen); static void VBOXDRITransitionTo3d(ScreenPtr pScreen); static Bool VBOXInitVisualConfigs(ScrnInfoPtr pScrn, VBOXPtr pVBox) { Bool rc = TRUE; TRACE_ENTRY(); int cConfigs = 2; /* With and without double buffering */ __GLXvisualConfig *pConfigs = NULL; pConfigs = (__GLXvisualConfig*) calloc(sizeof(__GLXvisualConfig), cConfigs); if (!pConfigs) { rc = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Disabling DRI: out of memory.\n"); } for (int i = 0; rc && i < cConfigs; ++i) { pConfigs[i].vid = -1; pConfigs[i].class = -1; pConfigs[i].rgba = TRUE; if (pScrn->bitsPerPixel == 16) { pConfigs[i].redSize = 5; pConfigs[i].greenSize = 6; pConfigs[i].blueSize = 5; pConfigs[i].redMask = 0x0000F800; pConfigs[i].greenMask = 0x000007E0; pConfigs[i].blueMask = 0x0000001F; } else if (pScrn->bitsPerPixel == 32) { 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; } else rc = FALSE; pConfigs[i].bufferSize = pScrn->bitsPerPixel; pConfigs[i].visualRating = GLX_NONE; pConfigs[i].transparentPixel = GLX_NONE; } if (rc) { pConfigs[0].doubleBuffer = FALSE; pConfigs[1].doubleBuffer = TRUE; pVBox->cVisualConfigs = cConfigs; pVBox->pVisualConfigs = pConfigs; TRACE_LOG("Calling GlxSetVisualConfigs\n"); GlxSetVisualConfigs(cConfigs, pConfigs, NULL); } if (!rc && pConfigs) free(pConfigs); TRACE_LOG("returning %s\n", BOOL_STR(rc)); return rc; } #if 0 static void VBOXDoWakeupHandler(int screenNum, pointer wakeupData, unsigned long result, pointer pReadmask) { } #endif #if 0 static void VBOXDoBlockHandler(int screenNum, pointer blockData, pointer pTimeout, pointer pReadmask) { } #endif Bool VBOXDRIScreenInit(ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox) { DRIInfoPtr pDRIInfo = NULL; Bool rc = TRUE; TRACE_ENTRY(); pVBox->drmFD = -1; if ( pScrn->bitsPerPixel != 16 && pScrn->bitsPerPixel != 32) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DRI is only available in 16bpp or 32bpp graphics modes.\n"); rc = FALSE; } /* Assertion */ if ( (pScrn->displayWidth == 0) || (pVBox->pciInfo == NULL) || (pVBox->base == NULL) || (pVBox->cbFBMax == 0)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: preconditions failed\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__); rc = FALSE; } /* Check that the GLX, DRI, and DRM modules have been loaded by testing for * canonical symbols in each module, the way all existing _dri drivers do. */ if (rc) { TRACE_LOG("Checking symbols\n"); if ( !xf86LoaderCheckSymbol("GlxSetVisualConfigs") || !xf86LoaderCheckSymbol("drmAvailable") || !xf86LoaderCheckSymbol("DRIQueryVersion")) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Disabling DRI due to missing server functionality.\n"); rc = FALSE; } } /* Check the DRI version */ if (rc) { int major, minor, patch; TRACE_LOG("Checking DRI version\n"); DRIQueryVersion(&major, &minor, &patch); if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Disabling DRI due to a version mismatch between server and driver. Server version: %d.%d. Driver version: %d.%d\n", major, minor, DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION); rc = FALSE; } } if (rc) { TRACE_LOG("Creating DRIInfoRec\n"); pDRIInfo = DRICreateInfoRec(); if (!pDRIInfo) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Disabling DRI: out of memory.\n"); rc = FALSE; } else pVBox->pDRIInfo = pDRIInfo; } if (rc) { pDRIInfo->CreateContext = VBOXCreateContext; pDRIInfo->DestroyContext = VBOXDestroyContext; pDRIInfo->SwapContext = VBOXDRISwapContext; pDRIInfo->InitBuffers = VBOXDRIInitBuffers; pDRIInfo->MoveBuffers = VBOXDRIMoveBuffers; pDRIInfo->OpenFullScreen = VBOXDRIOpenFullScreen; pDRIInfo->CloseFullScreen = VBOXDRICloseFullScreen; pDRIInfo->TransitionTo2d = VBOXDRITransitionTo2d; pDRIInfo->TransitionTo3d = VBOXDRITransitionTo3d; /* These two are set in DRICreateInfoRec(). */ pDRIInfo->wrap.ValidateTree = NULL; pDRIInfo->wrap.PostValidateTree = NULL; pDRIInfo->drmDriverName = VBOX_DRM_DRIVER_NAME; pDRIInfo->clientDriverName = VBOX_DRI_DRIVER_NAME; #ifdef PCIACCESS pDRIInfo->busIdString = DRICreatePCIBusID(pVBox->pciInfo); #else pDRIInfo->busIdString = alloc(64); sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", ((pciConfigPtr)pVBox->pciInfo->thisCard)->busnum, ((pciConfigPtr)pVBox->pciInfo->thisCard)->devnum, ((pciConfigPtr)pVBox->pciInfo->thisCard)->funcnum); #endif pDRIInfo->ddxDriverMajorVersion = VBOX_VIDEO_MAJOR; pDRIInfo->ddxDriverMinorVersion = VBOX_VIDEO_MINOR; pDRIInfo->ddxDriverPatchVersion = 0; pDRIInfo->ddxDrawableTableEntry = VBOX_MAX_DRAWABLES; pDRIInfo->maxDrawableTableEntry = VBOX_MAX_DRAWABLES; pDRIInfo->frameBufferPhysicalAddress = (pointer)pScrn->memPhysBase; pDRIInfo->frameBufferSize = pVBox->cbFBMax; pDRIInfo->frameBufferStride = pScrn->displayWidth * pScrn->bitsPerPixel / 8; pDRIInfo->SAREASize = SAREA_MAX; /* we have no private bits yet. */ /* This can't be zero, as the server callocs this size and checks for * non-NULL... */ pDRIInfo->contextSize = 4; pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; TRACE_LOG("Calling DRIScreenInit\n"); if (!DRIScreenInit(pScreen, pDRIInfo, &pVBox->drmFD)) { rc = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DRIScreenInit failed, disabling DRI.\n"); if (pVBox->drmFD) { drmClose(pVBox->drmFD); pVBox->drmFD = -1; } } } if (rc && !VBOXInitVisualConfigs(pScrn, pVBox)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "VBOXInitVisualConfigs failed, disabling DRI.\n"); rc = FALSE; } else xf86DrvMsg(pScrn->scrnIndex, X_INFO, "visual configurations initialized\n"); /* Check the DRM version */ if (rc) { drmVersionPtr version = drmGetVersion(pVBox->drmFD); TRACE_LOG("Checking DRM version\n"); if (version) { if (version->version_major != 1 || version->version_minor < 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad DRM driver version %d.%d, expected version 1.0. Disabling DRI.\n", version->version_major, version->version_minor); rc = FALSE; } drmFreeVersion(version); } } /* Clean up on failure. */ if (!rc) { if (pVBox->drmFD >= 0) VBOXDRICloseScreen(pScreen, pVBox); pVBox->drmFD = -1; if (pVBox->pDRIInfo) DRIDestroyInfoRec(pVBox->pDRIInfo); pVBox->pDRIInfo = NULL; } TRACE_LOG("returning %s\n", BOOL_STR(rc)); return rc; } void VBOXDRIUpdateStride(ScrnInfoPtr pScrn, VBOXPtr pVBox) { DRIInfoPtr pDRIInfo = pVBox->pDRIInfo; pDRIInfo->frameBufferStride = pScrn->displayWidth * pScrn->bitsPerPixel / 8; } void VBOXDRICloseScreen(ScreenPtr pScreen, VBOXPtr pVBox) { DRICloseScreen(pScreen); DRIDestroyInfoRec(pVBox->pDRIInfo); pVBox->pDRIInfo=0; if (pVBox->pVisualConfigs) free(pVBox->pVisualConfigs); pVBox->cVisualConfigs = 0; pVBox->pVisualConfigs = NULL; } static Bool VBOXCreateContext(ScreenPtr pScreen, VisualPtr visual, drm_context_t hwContext, void *pVisualConfigPriv, DRIContextType contextStore) { return TRUE; } static void VBOXDestroyContext(ScreenPtr pScreen, drm_context_t hwContext, DRIContextType contextStore) { } Bool VBOXDRIFinishScreenInit(ScreenPtr pScreen) { return DRIFinishScreenInit(pScreen); } static void VBOXDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, DRIContextType oldContextType, void *oldContext, DRIContextType newContextType, void *newContext) { } static void VBOXDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) { } static void VBOXDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, RegionPtr prgnSrc, CARD32 index) { } /* Apparently the next two are just legacy. */ static Bool VBOXDRIOpenFullScreen(ScreenPtr pScreen) { return TRUE; } static Bool VBOXDRICloseFullScreen(ScreenPtr pScreen) { return TRUE; } static void VBOXDRITransitionTo2d(ScreenPtr pScreen) { } static void VBOXDRITransitionTo3d(ScreenPtr pScreen) { }