VirtualBox

Changeset 39412 in vbox for trunk/src/VBox/HostServices


Ignore:
Timestamp:
Nov 24, 2011 5:23:56 PM (13 years ago)
Author:
vboxsync
Message:

CrOpenGL: work around ATI fullscreen issue

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c

    r38505 r39412  
    1818#include "renderspu.h"
    1919#include "cr_mem.h"
     20
     21
     22/* IAT patcher stuff */
     23#define RVA2PTR(_t, _base, _off) ((_t*)(((uint8_t*)(_base)) + (_off)))
     24
     25int renderspuIatPatcherGetImportAddress(HMODULE hModule, LPCSTR pszLib, LPCSTR pszName, void** ppAdr)
     26{
     27    PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hModule;
     28    PIMAGE_NT_HEADERS pNtHdr;
     29    PIMAGE_IMPORT_DESCRIPTOR pImportDr;
     30    DWORD rvaImport;
     31
     32    crDebug("searching entry %s from %s", pszName, pszLib);
     33
     34    *ppAdr = 0;
     35
     36    if (pDosHdr->e_magic != IMAGE_DOS_SIGNATURE)
     37    {
     38        crWarning("invalid dos signature");
     39        return VERR_INVALID_HANDLE;
     40    }
     41    pNtHdr = RVA2PTR(IMAGE_NT_HEADERS, pDosHdr, pDosHdr->e_lfanew);
     42    if (pNtHdr->Signature != IMAGE_NT_SIGNATURE)
     43    {
     44        crWarning("invalid nt signature");
     45        return VERR_INVALID_HANDLE;
     46    }
     47    rvaImport = pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
     48    if (!rvaImport)
     49    {
     50        crWarning("no imports found");
     51        return VERR_NOT_FOUND;
     52    }
     53    pImportDr =  RVA2PTR(IMAGE_IMPORT_DESCRIPTOR, pDosHdr, rvaImport);
     54
     55    for ( ;pImportDr->TimeDateStamp != 0 || pImportDr->Name != 0; ++pImportDr)
     56    {
     57        DWORD rvaINT, rvaIAT;
     58        PIMAGE_THUNK_DATA pINT, pIAT;
     59        LPCSTR pszLibCur = RVA2PTR(char, pDosHdr, pImportDr->Name);
     60        if (stricmp(pszLibCur, pszLib))
     61            continue;
     62
     63        /* got the necessary lib! */
     64        crDebug("got info for lib");
     65
     66        rvaINT = pImportDr->OriginalFirstThunk;
     67        rvaIAT = pImportDr->FirstThunk;
     68
     69        if (!rvaINT  || !rvaIAT)
     70        {
     71            crWarning("either rvaINT(0x%x) or rvaIAT(0x%x) are NULL, nothing found!", rvaINT, rvaIAT);
     72            return VERR_NOT_FOUND;
     73        }
     74
     75        pINT = RVA2PTR(IMAGE_THUNK_DATA, pDosHdr, rvaINT);
     76        pIAT = RVA2PTR(IMAGE_THUNK_DATA, pDosHdr, rvaIAT);
     77
     78        for ( ; pINT->u1.AddressOfData; ++pINT, ++pIAT)
     79        {
     80            PIMAGE_IMPORT_BY_NAME pIbn;
     81
     82            if (IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal))
     83                continue;
     84
     85            pIbn = RVA2PTR(IMAGE_IMPORT_BY_NAME, pDosHdr, pINT->u1.AddressOfData);
     86
     87            if (stricmp(pszName, (char*)pIbn->Name))
     88                continue;
     89
     90            *ppAdr = &pIAT->u1.Function;
     91
     92            crDebug("search succeeded!");
     93            return VINF_SUCCESS;
     94        }
     95    }
     96
     97    crDebug("not found");
     98    return VERR_NOT_FOUND;
     99}
     100
     101int renderspuIatPatcherPatchEntry(void *pvEntry, void *pvValue, void **ppvOldVal)
     102{
     103    void **ppfn = (void**)pvEntry;
     104    DWORD dwOldProtect = 0;
     105
     106    if (!VirtualProtect(pvEntry, sizeof (pvEntry), PAGE_READWRITE, &dwOldProtect))
     107    {
     108        crWarning("VirtualProtect 1 failed, %d", GetLastError());
     109        return VERR_ACCESS_DENIED;
     110    }
     111
     112    if (ppvOldVal)
     113        *ppvOldVal = *ppfn;
     114    *ppfn = pvValue;
     115
     116    if (!VirtualProtect(pvEntry, sizeof (pvEntry), dwOldProtect, &dwOldProtect))
     117    {
     118        crWarning("VirtualProtect 2 failed, %d.. ignoring", GetLastError());
     119    }
     120
     121    return VINF_SUCCESS;
     122}
     123
     124
     125int renderspuIatPatcherPatchFunction(HMODULE hModule, LPCSTR pszLib, LPCSTR pszName, void* pfn)
     126{
     127    void* pAdr;
     128    int rc = renderspuIatPatcherGetImportAddress(hModule, pszLib, pszName, &pAdr);
     129    if (RT_FAILURE(rc))
     130    {
     131        crDebug("renderspuIatPatcherGetImportAddress failed, %d", rc);
     132        return rc;
     133    }
     134
     135    rc = renderspuIatPatcherPatchEntry(pAdr, pfn, NULL);
     136    if (RT_FAILURE(rc))
     137    {
     138        crWarning("renderspuIatPatcherPatchEntry failed, %d", rc);
     139        return rc;
     140    }
     141
     142    return VINF_SUCCESS;
     143}
     144
     145/* patch */
     146static HWND __stdcall renderspuAtiQuirk_GetForegroundWindow()
     147{
     148    crDebug("renderspuAtiQuirk_GetForegroundWindow");
     149    return NULL;
     150}
     151
     152
     153#define CRREG_MAXKEYNAME 8
     154static int renderspuAtiQuirk_GetICDDriverList(char *pBuf, DWORD cbBuf, DWORD *pcbResult)
     155{
     156    static LPCSTR aValueNames[] = {"OpenGLVendorName", "OpenGLDriverName"};
     157    char *pBufPos = pBuf;
     158    DWORD cbBufRemain = cbBuf, cbTotal = 0;
     159    HKEY hKey;
     160    DWORD dwIndex = 0;
     161    int i;
     162    int rc = VINF_SUCCESS;
     163    char NameBuf[CRREG_MAXKEYNAME];
     164    LONG lRc;
     165
     166    if (pcbResult)
     167        *pcbResult = 0;
     168
     169    lRc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
     170            "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}",
     171            0, /* reserved*/
     172            KEY_READ,
     173            &hKey);
     174    if (ERROR_SUCCESS != lRc)
     175    {
     176        crDebug("RegOpenKeyEx 1 failed, %d", lRc);
     177        return VERR_OPEN_FAILED;
     178    }
     179
     180    for ( ; ; ++dwIndex)
     181    {
     182        lRc = RegEnumKeyA(hKey, dwIndex, NameBuf, CRREG_MAXKEYNAME);
     183        if (lRc == ERROR_NO_MORE_ITEMS)
     184            break;
     185        if (lRc == ERROR_MORE_DATA)
     186            continue;
     187        if (lRc != ERROR_SUCCESS)
     188        {
     189            crWarning("RegEnumKeyA failed, %d", lRc);
     190            continue;
     191        }
     192
     193        for (i = 0; i < RT_ELEMENTS(aValueNames); ++i)
     194        {
     195            DWORD cbCur = cbBufRemain;
     196            lRc = RegGetValueA(hKey, NameBuf, aValueNames[i], RRF_RT_REG_MULTI_SZ,
     197                    NULL, /* LPDWORD pdwType */
     198                    pBufPos,
     199                    &cbCur);
     200            /* exclude second null termination */
     201            --cbCur;
     202            if (ERROR_MORE_DATA == lRc)
     203            {
     204                rc = VERR_BUFFER_OVERFLOW;
     205                pBufPos = NULL;
     206                cbBufRemain = 0;
     207                CRASSERT(cbCur > 0 && cbCur < UINT32_MAX/2);
     208                cbTotal += cbCur;
     209                continue;
     210            }
     211            if (ERROR_SUCCESS != lRc)
     212            {
     213                crWarning("RegGetValueA failed, %d", lRc);
     214                continue;
     215            }
     216
     217            /* succeeded */
     218            CRASSERT(cbCur > 0 && cbCur < UINT32_MAX/2);
     219            pBufPos += cbCur;
     220            cbBufRemain -= cbCur;
     221            cbTotal += cbCur;
     222            CRASSERT(cbBufRemain < UINT32_MAX/2);
     223        }
     224    }
     225
     226    if (cbTotal)
     227    {
     228        /* include second null termination */
     229        CRASSERT(!pBufPos || pBufPos[0] == '\0');
     230        ++cbTotal;
     231    }
     232
     233    if (pcbResult)
     234        *pcbResult = cbTotal;
     235
     236    return rc;
     237}
     238
     239static int renderspuAtiQuirk_ApplyForModule(LPCSTR pszAtiDll)
     240{
     241    int rc;
     242    HMODULE hAtiDll;
     243
     244    crDebug("renderspuAtiQuirk_ApplyForModule (%s)", pszAtiDll);
     245
     246    hAtiDll = GetModuleHandleA(pszAtiDll);
     247    if (!hAtiDll)
     248    {
     249        crDebug("GetModuleHandle failed, %d", GetLastError());
     250        return VERR_NOT_FOUND;
     251    }
     252
     253    rc = renderspuIatPatcherPatchFunction(hAtiDll, "user32.dll", "GetForegroundWindow", (void*)renderspuAtiQuirk_GetForegroundWindow);
     254    if (RT_FAILURE(rc))
     255    {
     256        crDebug("renderspuIatPatcherPatchFunction failed, %d", rc);
     257        return rc;
     258    }
     259
     260    crDebug("renderspuAtiQuirk_ApplyForModule SUCCEEDED!");
     261    crInfo("ATI Fullscreen qwirk for SUCCEEDED!");
     262
     263    return VINF_SUCCESS;
     264}
     265
     266static LPCSTR renderspuRegMultiSzNextVal(LPCSTR pszBuf)
     267{
     268    pszBuf += strlen(pszBuf) + sizeof (pszBuf[0]);
     269
     270    if (pszBuf[0] == '\0')
     271        return NULL;
     272
     273    return pszBuf;
     274}
     275
     276static LPCSTR renderspuRegMultiSzCurVal(LPCSTR pszBuf)
     277{
     278    if (pszBuf[0] == '\0')
     279        return NULL;
     280
     281    return pszBuf;
     282}
     283
     284
     285static int renderspuAtiQuirk_Apply()
     286{
     287    char aBuf[4096];
     288    DWORD cbResult = 0;
     289    LPCSTR pszVal;
     290    int rc;
     291
     292    crDebug("renderspuAtiQuirk_Apply..");
     293
     294    rc = renderspuAtiQuirk_GetICDDriverList(aBuf, sizeof (aBuf), &cbResult);
     295    if (RT_FAILURE(rc))
     296    {
     297        crDebug("renderspuAtiQuirk_GetICDDriverList failed, rc(%d)", rc);
     298        return rc;
     299    }
     300
     301    for (pszVal = renderspuRegMultiSzCurVal(aBuf);
     302            pszVal;
     303            pszVal = renderspuRegMultiSzNextVal(pszVal))
     304    {
     305        renderspuAtiQuirk_ApplyForModule(pszVal);
     306    }
     307
     308    return VINF_SUCCESS;
     309}
     310
     311static GLboolean renderspuAtiQuirk_Needed()
     312{
     313    const char * pszString = render_spu.ws.glGetString(GL_VENDOR);
     314    if (pszString && strstr(pszString, "ATI"))
     315        return GL_TRUE;
     316    pszString = render_spu.ws.glGetString(GL_RENDERER);
     317    if (pszString && strstr(pszString, "ATI"))
     318        return GL_TRUE;
     319    return GL_FALSE;
     320}
     321
     322
     323static void renderspuAtiQuirk_ChkApply()
     324{
     325    static GLboolean fChecked = GL_FALSE;
     326    if (fChecked)
     327        return;
     328
     329    fChecked = GL_TRUE;
     330    if (!renderspuAtiQuirk_Needed())
     331        return;
     332
     333    crInfo("This is an ATI card, taking care of fullscreen..");
     334
     335    renderspuAtiQuirk_Apply();
     336}
    20337
    21338#define WINDOW_NAME window->title
     
    9031220        }
    9041221
     1222        renderspuAtiQuirk_ChkApply();
    9051223    }
    9061224    else {
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette