/*==========================================================================; * * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved. * * File: d3di.h * Content: Direct3D HAL include file *@@BEGIN_MSINTERNAL * * History: * Date By Reason * ==== == ====== * 09/11/95 stevela Initial rev with this header. * 07/12/95 stevela Merged Colin's changes. * 10/12/95 stevela Removed AGGREGATE_D3D. * Validate args. * 17/04/96 colinmc Bug 17008: DirectDraw/Direct3D deadlock * 29/04/96 colinmc Bug 19954: Must query for Direct3D before texture * or device * 27/08/96 stevela Ifdefed out definition of ghEvent as we're using * DirectDraw's critical section. *@@END_MSINTERNAL * ***************************************************************************/ #include "pch.cpp" #pragma hdrstop /* * Create an api for the Direct3D object */ // Remove DDraw's type unsafe definition and replace with our C++ friendly def #ifdef VALIDEX_CODE_PTR #undef VALIDEX_CODE_PTR #endif #define VALIDEX_CODE_PTR( ptr ) \ (!IsBadCodePtr( (FARPROC) ptr ) ) LPCRITICAL_SECTION lpD3DCSect; #if DBG int iD3DCSCnt; #endif #if COLLECTSTATS void DIRECT3DI::ResetTexStats() { ((LPDDRAWI_DIRECTDRAW_INT)lpDD7)->lpLcl->dwNumTexLocks = ((LPDDRAWI_DIRECTDRAW_INT)lpDD7)->lpLcl->dwNumTexGetDCs = 0; m_setpris = m_setLODs = m_texCreates = m_texDestroys = 0; } void DIRECT3DI::GetTexStats(LPD3DDEVINFO_TEXTURING pStats) { pStats->dwNumSetPriorities = GetNumSetPris(); pStats->dwNumSetLODs = GetNumSetLODs(); pStats->dwNumCreates = GetNumTexCreates(); pStats->dwNumDestroys = GetNumTexDestroys(); pStats->dwNumLocks = GetNumTexLocks(); pStats->dwNumGetDCs = GetNumTexGetDCs(); } #endif //--------------------------------------------------------------------- // for use by fns that take a GUID param before device is created BOOL IsValidD3DDeviceGuid(REFCLSID riid) { if (IsBadReadPtr(&riid, sizeof(CLSID))) { return FALSE; } if( IsEqualIID(riid, IID_IDirect3DRampDevice) || IsEqualIID(riid, IID_IDirect3DRGBDevice) || IsEqualIID(riid, IID_IDirect3DMMXDevice) || IsEqualIID(riid, IID_IDirect3DHALDevice) || IsEqualIID(riid, IID_IDirect3DRefDevice) || IsEqualIID(riid, IID_IDirect3DNullDevice) || IsEqualIID(riid, IID_IDirect3DTnLHalDevice)) { return TRUE; } else { return FALSE; } } //--------------------------------------------------------------------- #undef DPF_MODNAME #define DPF_MODNAME "Direct3DCreate" DIRECT3DI::DIRECT3DI() { lpDD = NULL; lpDD7 = NULL; numDevs = 0; mD3DUnk.pD3DI = this; mD3DUnk.refCnt = 1; LIST_INITIALIZE(&devices); LIST_INITIALIZE(&textures); lpFreeList = NULL; /* nothing is allocated initially */ lpBufferList = NULL; lpTextureManager = NULL; #ifdef __DISABLE_VIDMEM_VBS__ bDisableVidMemVBs = FALSE; #endif } HRESULT DIRECT3DI::Initialize(IUnknown* pUnkOuter, LPDDRAWI_DIRECTDRAW_INT pDDrawInt) { // HACK. D3D needs a DD1 DDRAWI interface because it uses CreateSurface1 internally // for exebufs, among other things. Because pDDrawInt could be any DDRAWI type, // we need to QI to find a DD1 interface. But the D3DI object cannot keep a reference // to its parent DD object because it is aggegrated with the DD obj, so that would constitute // a circular reference that would prevent deletion. So we QI for DD1 interface, copy it into D3DI // and release it, then point lpDD at the copy. (disgusting) // another HACK alert: dont know which DDRAWI type pDDrawInt is, but a cast to LPDIRECTDRAW should // work because QI is in the same place in all the DDRAWI vtables and is the same fn for all HRESULT ret; ret = ((LPDIRECTDRAW)pDDrawInt)->QueryInterface(IID_IDirectDraw, (LPVOID*)&lpDD); if(FAILED(ret)) { D3D_ERR( "QueryInterface for IDDraw failed" ); return ret; } memcpy(&DDInt_DD1,lpDD,sizeof(DDInt_DD1)); lpDD->Release(); lpDD=(LPDIRECTDRAW)&DDInt_DD1; // We know that the pointer that is handed in is a DD7 interface, hence just typecast and assign lpDD7 = reinterpret_cast(pDDrawInt); lpTextureManager = new TextureCacheManager(this); if(lpTextureManager == 0) { D3D_ERR("Out of memory allocating texture manager"); return E_OUTOFMEMORY; } ret = lpTextureManager->Initialize(); if(ret != D3D_OK) { D3D_ERR("Failed to initialize texture manager"); return ret; } #if COLLECTSTATS DWORD value = 0; GetD3DRegValue(REG_DWORD, "DisplayStats", &value, sizeof(DWORD)); if(value != 0) { LOGFONT font; strcpy(font.lfFaceName, STATS_FONT_FACE); font.lfCharSet = DEFAULT_CHARSET; font.lfClipPrecision = CLIP_DEFAULT_PRECIS; font.lfEscapement = 0; font.lfHeight = STATS_FONT_SIZE; font.lfItalic = FALSE; font.lfOrientation = 0; font.lfOutPrecision = OUT_DEFAULT_PRECIS; font.lfPitchAndFamily = DEFAULT_PITCH; font.lfQuality = DEFAULT_QUALITY; font.lfStrikeOut = FALSE; font.lfUnderline = FALSE; font.lfWeight = FW_DONTCARE; font.lfWidth = 0; m_hFont = CreateFontIndirect(&font); } else { m_hFont = 0; } #endif #ifdef __DISABLE_VIDMEM_VBS__ { bDisableVidMemVBs = FALSE; DWORD value = 0; GetD3DRegValue(REG_DWORD, "DisableVidMemVBs", &value, sizeof(DWORD)); if(value != 0) { // Disable VidMemVBs bDisableVidMemVBs = TRUE; } // We also disable vidmem VBs unless the driver explicitly asks us to turn them on... if (((LPDDRAWI_DIRECTDRAW_INT)lpDD7)->lpLcl->lpGbl->lpD3DGlobalDriverData) { if (0 == (((LPDDRAWI_DIRECTDRAW_INT)lpDD7)->lpLcl->lpGbl->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_HWVERTEXBUFFER) ) { bDisableVidMemVBs = TRUE; } } } #endif //__DISABLE_VIDMEM_VBS__ /* * Are we really being aggregated? */ if (pUnkOuter != NULL) { /* * Yup - we are being aggregated. Store the supplied * IUnknown so we can punt to that. * NOTE: We explicitly DO NOT AddRef here. */ this->lpOwningIUnknown = pUnkOuter; /* * Store away the interface pointer */ } else { /* * Nope - but we pretend we are anyway by storing our * own IUnknown as the parent IUnknown. This makes the * code much neater. */ this->lpOwningIUnknown = static_cast(&this->mD3DUnk); } return D3D_OK; } extern "C" HRESULT WINAPI Direct3DCreate(LPCRITICAL_SECTION lpDDCSect, LPUNKNOWN* lplpDirect3D, IUnknown* pUnkOuter) { LPDIRECT3DI pd3d; try { DPFINIT(); /* * No need to validate params as DirectDraw is giving them to us. */ /* * Is another thread coming in and is this the first time? */ /* * We can let every invocation of this function assign * the critical section as we know its always going to * be the same value (for a D3D session). */ lpD3DCSect = lpDDCSect; CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock. // Release in the destructor *lplpDirect3D = NULL; // We do not support non aggregated Direct3D object yet if (!pUnkOuter) return DDERR_INVALIDPARAMS; if (!(pd3d = static_cast(new DIRECT3DI))) { D3D_ERR("Out of memory allocating DIRECT3DI"); return E_OUTOFMEMORY; } HRESULT hr = pd3d->Initialize(pUnkOuter, (LPDDRAWI_DIRECTDRAW_INT)pUnkOuter); if(hr != D3D_OK) { D3D_ERR("Failed to initialize Direct3D."); delete pd3d; return hr; } /* * NOTE: The special IUnknown is returned and not the actual * Direct3D interface so you can't use this to drive Direct3D. * You must query off this interface for the Direct3D interface. */ *lplpDirect3D = static_cast(&(pd3d->mD3DUnk)); return (D3D_OK); } catch (HRESULT ret) { return ret; } } #undef DPF_MODNAME #define DPF_MODNAME "Direct3D::EnumDevices" extern BOOL isMMXprocessor(void); typedef struct _D3DI_DeviceType { CONST GUID *pGuid; char name[256]; char description[512]; } D3DI_DeviceType; // Static definitions for various enumerable devices static D3DI_DeviceType RGBDevice = { &IID_IDirect3DRGBDevice, "RGB Emulation", "Microsoft Direct3D RGB Software Emulation" }; static D3DI_DeviceType HALDevice = { &IID_IDirect3DHALDevice, "Direct3D HAL", "Microsoft Direct3D Hardware acceleration through Direct3D HAL" }; static D3DI_DeviceType RefDevice = { &IID_IDirect3DRefDevice, "Reference Rasterizer", "Microsoft Reference Rasterizer" }; static D3DI_DeviceType NullDevice = { &IID_IDirect3DNullDevice, "Null device", "Microsoft Null Device" }; static D3DI_DeviceType TnLHALDevice = { &IID_IDirect3DTnLHalDevice, "Direct3D T&L HAL", "Microsoft Direct3D Hardware Transform and Lighting acceleration capable device" }; static D3DI_DeviceType *AllDevices[] = { &RGBDevice, &HALDevice, &RefDevice, &NullDevice, &TnLHALDevice, NULL }; HRESULT DIRECT3DI::EnumDevices(LPD3DENUMDEVICESCALLBACK7 lpEnumCallback, LPVOID lpContext, DWORD dwSize, DWORD dwVer) { HRESULT err, userRet; HKEY hKey; LONG result; int i; try { CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock. // Release in the destructor if (!VALIDEX_CODE_PTR((FARPROC)lpEnumCallback)) { D3D_ERR( "Invalid callback pointer" ); return DDERR_INVALIDPARAMS; } BOOL bSoftwareOnly = FALSE; BOOL bEnumReference = FALSE; BOOL bEnumNullDevice = FALSE; BOOL bEnumSeparateMMX = FALSE; result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RESPATH, 0, KEY_READ, &hKey); if (result == ERROR_SUCCESS) { DWORD dwData, dwType; DWORD dwDataSize; // Enumerate software rasterizers only ? dwDataSize = sizeof(dwData); result = RegQueryValueEx(hKey, "SoftwareOnly", NULL, &dwType, (BYTE *) &dwData, &dwDataSize); if ( result == ERROR_SUCCESS && dwType == REG_DWORD ) { bSoftwareOnly = ( dwData != 0 ); } // Enumerate Reference Rasterizer ? dwDataSize = sizeof(dwData); result = RegQueryValueEx(hKey, "EnumReference", NULL, &dwType, (BYTE *)&dwData, &dwDataSize); if (result == ERROR_SUCCESS && dwType == REG_DWORD && dwDataSize == sizeof(dwData)) { bEnumReference = (BOOL)dwData; } // Enumerate Null Device ? dwDataSize = sizeof(dwData); result = RegQueryValueEx(hKey, "EnumNullDevice", NULL, &dwType, (BYTE *)&dwData, &dwDataSize); if (result == ERROR_SUCCESS && dwType == REG_DWORD && dwDataSize == sizeof(dwData)) { bEnumNullDevice = (BOOL)dwData; } RegCloseKey( hKey ); } D3DI_DeviceType **lpDevices = AllDevices; userRet = D3DENUMRET_OK; for (i = 0; lpDevices[i] && userRet == D3DENUMRET_OK; i++) { LPSTR drvName = lpDevices[i]->name; LPSTR drvDesc = lpDevices[i]->description; REFCLSID riid = *lpDevices[i]->pGuid; D3DDEVICEDESC7 HWDesc; D3DDEVICEDESC7 HELDesc; LPDDRAWI_DIRECTDRAW_GBL lpDDGbl; IHalProvider *pHalProv; HINSTANCE hDll; if ( !bEnumReference && IsEqualIID(riid, IID_IDirect3DRefDevice)) { // Not enumerating the reference. continue; } if (!bEnumNullDevice && IsEqualIID(riid, IID_IDirect3DNullDevice)) { // Not enumerating the Null device. continue; } // By COM definition, our owning IUnknown is a pointer to the // DirectDraw object that was used to create us. // Check this for the existence of a Direct3D HAL. lpDDGbl = ((LPDDRAWI_DIRECTDRAW_INT)this->lpDD)->lpLcl->lpGbl; if (IsEqualIID(riid, IID_IDirect3DTnLHalDevice) && (lpDDGbl->lpD3DGlobalDriverData)) { if (!(lpDDGbl->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)) { // Not enumerating the T&L device if the hardware doesnt support // T&L continue; } } // See if this is a software driver. err = GetSwHalProvider(riid, &pHalProv, &hDll); if (err == S_OK) { // Successfully got a software driver. } else if (err == E_NOINTERFACE && ! bSoftwareOnly && GetHwHalProvider(riid, &pHalProv, &hDll, lpDDGbl) == S_OK) { // Successfully got a hardware driver. } else { // Unrecognized driver. continue; } err = pHalProv->GetCaps(lpDDGbl, &HWDesc, &HELDesc, dwVer); pHalProv->Release(); if (hDll != NULL) { FreeLibrary(hDll); } if (err != S_OK) { continue; } if( HWDesc.wMaxVertexBlendMatrices == 1 ) HWDesc.wMaxVertexBlendMatrices = 0; if( HELDesc.wMaxVertexBlendMatrices == 1 ) HELDesc.wMaxVertexBlendMatrices = 0; // If Hal device is being enumerated, strip out the // HWTRANSFORM... flag if (IsEqualIID(riid, IID_IDirect3DHALDevice)) { HWDesc.dwMaxActiveLights = 0xffffffff; HWDesc.wMaxVertexBlendMatrices = 4; HWDesc.wMaxUserClipPlanes = __MAXUSERCLIPPLANES; HWDesc.dwVertexProcessingCaps = D3DVTXPCAPS_ALL; HWDesc.dwDevCaps &= ~(D3DDEVCAPS_HWTRANSFORMANDLIGHT); } if (IsEqualIID(riid, IID_IDirect3DRGBDevice)) { HELDesc.dwMaxActiveLights = 0xffffffff; HELDesc.wMaxVertexBlendMatrices = 4; HELDesc.wMaxUserClipPlanes = __MAXUSERCLIPPLANES; HELDesc.dwVertexProcessingCaps = D3DVTXPCAPS_ALL; } if (IsEqualIID(riid, IID_IDirect3DHALDevice) || IsEqualIID(riid, IID_IDirect3DTnLHalDevice)) { memcpy(&HWDesc.deviceGUID, lpDevices[i]->pGuid, sizeof(GUID)); userRet = (*lpEnumCallback)(drvDesc, drvName, &HWDesc, lpContext); } else { memcpy(&HELDesc.deviceGUID, lpDevices[i]->pGuid, sizeof(GUID)); userRet = (*lpEnumCallback)(drvDesc, drvName, &HELDesc, lpContext); } } return D3D_OK; } catch (HRESULT ret) { return ret; } } HRESULT D3DAPI DIRECT3DI::EnumDevices(LPD3DENUMDEVICESCALLBACK7 lpEnumCallback, LPVOID lpContext) { return EnumDevices(lpEnumCallback, lpContext, D3DDEVICEDESC7SIZE, 4); } #undef DPF_MODNAME #define DPF_MODNAME "Direct3DI::EnumZBufferFormats" HRESULT D3DAPI DIRECT3DI::EnumZBufferFormats(REFCLSID riid, LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback, LPVOID lpContext) { HRESULT ret, userRet; LPDDPIXELFORMAT lpTmpPixFmts; DWORD i,cPixFmts; try { CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock. ret = D3D_OK; if (!VALID_DIRECT3D_PTR(this)) { D3D_ERR( "Invalid Direct3D3 pointer" ); return DDERR_INVALIDOBJECT; } if (!VALIDEX_CODE_PTR(lpEnumCallback)) { D3D_ERR( "Invalid callback pointer" ); return DDERR_INVALIDPARAMS; } if(!IsValidD3DDeviceGuid(riid)) { D3D_ERR( "Invalid D3D Device GUID" ); return DDERR_INVALIDPARAMS; } if( IsEqualIID(riid, IID_IDirect3DHALDevice) || IsEqualIID(riid, IID_IDirect3DTnLHalDevice) ) { LPDDRAWI_DIRECTDRAW_GBL pDdGbl=((LPDDRAWI_DIRECTDRAW_INT)this->lpDD)->lpLcl->lpGbl; LPD3DHAL_GLOBALDRIVERDATA lpD3DHALGlobalDriverData=pDdGbl->lpD3DGlobalDriverData; DWORD dwHW_ZBitDepthFlags; if (NULL == lpD3DHALGlobalDriverData) { D3D_ERR("No HAL Support ZBufferBitDepths!"); return (DDERR_NOZBUFFERHW); } cPixFmts=pDdGbl->dwNumZPixelFormats; if (cPixFmts==0) { // driver is pre-dx6, so it doesn't support stencil buffer pix fmts or this callback. // we can fake support using DD_BD bits in dwZBufferBitDepth in D3DDEVICEDESC D3D_WARN(6,"EnumZBufferFormats not supported directly by driver, faking it using dwDeviceZBufferBitDepth DD_BD bits"); dwHW_ZBitDepthFlags=lpD3DHALGlobalDriverData->hwCaps.dwDeviceZBufferBitDepth; if(!(dwHW_ZBitDepthFlags & (DDBD_8|DDBD_16|DDBD_24|DDBD_32))) { D3D_ERR("No Supported ZBufferBitDepths!"); return (DDERR_NOZBUFFERHW); } // malloc space for 4 DDPIXELFORMATs, since that the most there could be (DDBD_8,16,24,32) if (D3DMalloc((void**)&lpTmpPixFmts, 4*sizeof(DDPIXELFORMAT)) != D3D_OK) { D3D_ERR("failed to alloc space for return descriptions"); return (DDERR_OUTOFMEMORY); } DWORD zdepthflags[4]= {DDBD_8,DDBD_16,DDBD_24,DDBD_32}; DWORD zbitdepths[4]= {8,16,24,32}; DWORD zbitmasks[4]= {0xff,0xffff,0xffffff,0xffffffff}; memset(lpTmpPixFmts,0,sizeof(4*sizeof(DDPIXELFORMAT))); // create some DDPIXELFORMATs the app can look at for(i=0;i<4;i++) { if(dwHW_ZBitDepthFlags & zdepthflags[i]) { lpTmpPixFmts[cPixFmts].dwSize=sizeof(DDPIXELFORMAT); lpTmpPixFmts[cPixFmts].dwFlags=DDPF_ZBUFFER; lpTmpPixFmts[cPixFmts].dwZBufferBitDepth=zbitdepths[i]; lpTmpPixFmts[cPixFmts].dwZBitMask= zbitmasks[i]; cPixFmts++; } } } else { // only show the app a temp copy of DDraw's real records if (D3DMalloc((void**)&lpTmpPixFmts, cPixFmts*sizeof(DDPIXELFORMAT)) != D3D_OK) { D3D_ERR("Out of memory allocating space for return descriptions"); return (DDERR_OUTOFMEMORY); } memcpy(lpTmpPixFmts, pDdGbl->lpZPixelFormats, cPixFmts*sizeof(DDPIXELFORMAT)); } } else { // Handle SW rasterizers DDPIXELFORMAT *pDDPF; // malloc space for 10 DDPIXELFORMAT's, which is currently more than enough for the SW rasterizers if (D3DMalloc((void**)&lpTmpPixFmts, 10*sizeof(DDPIXELFORMAT)) != D3D_OK) { D3D_ERR("Out of memory allocating space for return descriptions"); return (DDERR_OUTOFMEMORY); } cPixFmts=GetSwZBufferFormats(riid,&pDDPF); memcpy(lpTmpPixFmts, pDDPF, cPixFmts*sizeof(DDPIXELFORMAT)); } userRet = D3DENUMRET_OK; for (i = 0; (i < cPixFmts) && (userRet == D3DENUMRET_OK); i++) { userRet = (*lpEnumCallback)(&lpTmpPixFmts[i], lpContext); } D3DFree(lpTmpPixFmts); return (D3D_OK); } catch (HRESULT ret) { return ret; } } #undef DPF_MODNAME #define DPF_MODNAME "DIRECT3D::EvictManagedTextures" HRESULT D3DAPI DIRECT3DI::EvictManagedTextures() { try { CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock. if (!VALID_DIRECT3D_PTR(this)) { D3D_ERR( "Invalid Direct3D3 pointer" ); return DDERR_INVALIDOBJECT; } LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&this->devices); while (lpDevI) { if (lpDevI->dwFEFlags & D3DFE_REALHAL) { if (DDCAPS2_CANMANAGETEXTURE & ((LPDDRAWI_DIRECTDRAW_INT)this->lpDD)->lpLcl->lpGbl->ddCaps.dwCaps2) { lpDevI->SetRenderStateI((D3DRENDERSTATETYPE)D3DRENDERSTATE_EVICTMANAGEDTEXTURES,1); lpDevI->FlushStates(); } lpTextureManager->EvictTextures(); break; } lpDevI = LIST_NEXT(lpDevI,list); } return D3D_OK; } catch (HRESULT ret) { return ret; } } #undef DPF_MODNAME #define DPF_MODNAME "DIRECT3D::FlushDevicesExcept" HRESULT DIRECT3DI::FlushDevicesExcept(LPDIRECT3DDEVICEI pDev) { LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&this->devices); while (lpDevI) { if(lpDevI != pDev) { HRESULT hr = lpDevI->FlushStates(); if(hr != D3D_OK) { DPF_ERR("Error flushing device in FlushDevicesExcept"); return hr; } } lpDevI = LIST_NEXT(lpDevI,list); } return D3D_OK; } #undef DPF_MODNAME #define DPF_MODNAME "FlushD3DDevices" extern "C" HRESULT WINAPI FlushD3DDevices(LPDDRAWI_DDRAWSURFACE_LCL surf_lcl) { try { ULONGLONG qwBatch = (surf_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP) && (surf_lcl->lpAttachListFrom != NULL) ? surf_lcl->lpAttachListFrom->lpAttached->lpSurfMore->qwBatch.QuadPart : surf_lcl->lpSurfMore->qwBatch.QuadPart; LPDIRECT3DI lpD3D = static_cast(surf_lcl->lpSurfMore->lpDD_lcl->pD3DIUnknown)->pD3DI; DDASSERT(lpD3D); LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&lpD3D->devices); while (lpDevI) { if(lpDevI->m_qwBatch <= qwBatch) { HRESULT hr = lpDevI->FlushStates(); if(hr != D3D_OK) { DPF_ERR("Error flushing device in FlushD3DDevices"); return hr; } } lpDevI = LIST_NEXT(lpDevI,list); } return DD_OK; } catch (HRESULT ret) { return ret; } } extern "C" void WINAPI PaletteUpdateNotify( LPVOID pD3DIUnknown, DWORD dwPaletteHandle, DWORD dwStartIndex, DWORD dwNumberOfIndices, LPPALETTEENTRY pFirstIndex) { try { LPDIRECT3DI lpD3D = static_cast(pD3DIUnknown)->pD3DI; DDASSERT(lpD3D); LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&lpD3D->devices); while (lpDevI) { D3D_INFO(4,"PaletteUpdateNotify lpDevI(%x) %08lx %08lx %08lx %08lx", lpDevI,dwPaletteHandle,dwStartIndex,dwNumberOfIndices,*(DWORD*)&pFirstIndex[10]); if (IS_DX7HAL_DEVICE(lpDevI) && (lpDevI->dwFEFlags & D3DFE_REALHAL) ) { if(lpD3D->numDevs > 1) lpD3D->FlushDevicesExcept(lpDevI); static_cast(lpDevI)->UpdatePalette(dwPaletteHandle,dwStartIndex,dwNumberOfIndices,pFirstIndex); if(lpD3D->numDevs > 1) lpDevI->FlushStates(); break; } lpDevI = LIST_NEXT(lpDevI,list); } } catch (HRESULT ret) { D3D_ERR("PaletteUpdateNotify: FlushStates failed"); } } extern "C" void WINAPI PaletteAssociateNotify( LPVOID pD3DIUnknown, DWORD dwPaletteHandle, DWORD dwPaletteFlags, LPDDRAWI_DDRAWSURFACE_LCL surf_lcl ) { try { LPDIRECT3DI lpD3D = static_cast(pD3DIUnknown)->pD3DI; DDASSERT(lpD3D); LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&lpD3D->devices); while (lpDevI) { D3D_INFO(4,"PaletteAssociateNotify lpDevI(%x) %08lx %08lx", lpDevI,dwPaletteHandle,surf_lcl->lpSurfMore->dwSurfaceHandle); if (IS_DX7HAL_DEVICE(lpDevI) && (lpDevI->dwFEFlags & D3DFE_REALHAL) ) { if(lpD3D->numDevs > 1) lpD3D->FlushDevicesExcept(lpDevI); static_cast(lpDevI)->SetPalette(dwPaletteHandle,dwPaletteFlags,surf_lcl->lpSurfMore->dwSurfaceHandle); lpDevI->BatchTexture(surf_lcl); if(lpD3D->numDevs > 1) lpDevI->FlushStates(); break; } lpDevI = LIST_NEXT(lpDevI,list); } } catch (HRESULT ret) { D3D_ERR("PaletteAssociateNotify: FlushStates failed"); } } extern "C" void WINAPI SurfaceFlipNotify(LPVOID pD3DIUnknown) { LPDIRECT3DI lpD3D = static_cast(pD3DIUnknown)->pD3DI; DDASSERT(lpD3D); LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&lpD3D->devices); D3D_INFO(4,"SurfaceFlipNotify"); while (lpDevI) { if (IS_DX7HAL_DEVICE(lpDevI)) { try { CDirect3DDevice7* lpDevI7 = static_cast(lpDevI); #ifndef WIN95 if(lpDevI->hSurfaceTarget != ((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->hDDSurface) { lpDevI7->SetRenderTargetINoFlush(lpDevI->lpDDSTarget,lpDevI->lpDDSZBuffer); lpDevI->hSurfaceTarget=((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->hDDSurface; } #else if(lpDevI->hSurfaceTarget != ((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->lpSurfMore->dwSurfaceHandle) { lpDevI7->SetRenderTargetINoFlush(lpDevI->lpDDSTarget,lpDevI->lpDDSZBuffer); lpDevI->hSurfaceTarget=((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->lpSurfMore->dwSurfaceHandle; } #endif } catch (HRESULT ret) { D3D_ERR("SetRenderTarget Failed on SurfaceFlipNotify!"); } } lpDevI = LIST_NEXT(lpDevI,list); } } #undef DPF_MODNAME #define DPF_MODNAME "D3DTextureUpdate" extern "C" void WINAPI D3DTextureUpdate(IUnknown FAR * pD3DIUnknown) { LPDIRECT3DI lpD3D = static_cast(pD3DIUnknown)->pD3DI; DDASSERT(lpD3D); LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&lpD3D->devices); while (lpDevI) { lpDevI->dwFEFlags |= D3DFE_NEED_TEXTURE_UPDATE; lpDevI = LIST_NEXT(lpDevI,list); } } #undef DPF_MODNAME #define DPF_MODNAME "D3DTextureUpdate" extern "C" void WINAPI D3DBreakVBLock(LPVOID lpVB) { DDASSERT(lpVB); CDirect3DVertexBuffer* lpVBI = static_cast(lpVB); lpVBI->BreakLock(); }