/**************************************************************************** REMARKS: Test the Direct3D8 device for "lameness" with respect to GLDirect. This is done on per-chipset basis, as in GLD CAD driver (DGLCONTEXT.C). If bTestForWHQL is set then the device is tested to see if it is certified, and bIsWHQL is set to indicate TRUE or FALSE. Otherwise bIsWHQL is not set. [WHQL = Windows Hardware Quality Labs] NOTE: There is a one- or two-second time penalty incurred in determining the WHQL certification date. ****************************************************************************/ BOOL IsThisD3D8Lame( IDirect3D8 *pD3D, DWORD dwAdapter, BOOL bTestForWHQL, BOOL *bIsWHQL) { DWORD dwFlags = bTestForWHQL ? 0 : D3DENUM_NO_WHQL_LEVEL; D3DADAPTER_IDENTIFIER8 d3dai; HRESULT hr; hr = IDirect3D8_GetAdapterIdentifier(pD3D, dwAdapter, dwFlags, &d3dai); if (FAILED(hr)) return TRUE; // Definitely lame if adapter details can't be obtained! if (bTestForWHQL) { *bIsWHQL = d3dai.WHQLLevel ? TRUE : FALSE; } // Vendor 1: ATI if (d3dai.VendorId == VENDORID_ATI) { // Test A: ATI Rage PRO if (IsDevice(devATIRagePro, d3dai.DeviceId, sizeof(devATIRagePro))) return TRUE; // bad mipmapping // Test B: ATI Rage II+ if (IsDevice(devATIRageIIplus, d3dai.DeviceId, sizeof(devATIRageIIplus))) return TRUE; // bad HW alpha testing } return FALSE; }
static HRESULT d3d_get_adapter_identifier(d3d *d3dptr, UINT adapter, DWORD flags, d3d_adapter_identifier *identifier) { IDirect3D8 *d3d8 = (IDirect3D8 *)d3dptr->d3dobj; D3DADAPTER_IDENTIFIER8 id; HRESULT result = IDirect3D8_GetAdapterIdentifier(d3d8, adapter, flags, &id); memcpy(identifier->Driver, id.Driver, sizeof(identifier->Driver)); memcpy(identifier->Description, id.Description, sizeof(identifier->Description)); identifier->DriverVersion = id.DriverVersion; identifier->VendorId = id.VendorId; identifier->DeviceId = id.DeviceId; identifier->SubSysId = id.SubSysId; identifier->Revision = id.Revision; identifier->DeviceIdentifier = id.DeviceIdentifier; identifier->WHQLLevel = id.WHQLLevel; return result; }
BOOL gldCreateDrawable_DX( DGL_ctx *ctx, // BOOL bDefaultDriver, BOOL bDirectDrawPersistant, BOOL bPersistantBuffers) { // // bDirectDrawPersistant: applies to IDirect3D8 // bPersistantBuffers: applies to IDirect3DDevice8 // HRESULT hResult; GLD_driver_dx8 *lpCtx = NULL; D3DDEVTYPE d3dDevType; D3DPRESENT_PARAMETERS d3dpp; D3DDISPLAYMODE d3ddm; DWORD dwBehaviourFlags; D3DADAPTER_IDENTIFIER8 d3dIdent; // Error if context is NULL. if (ctx == NULL) return FALSE; if (ctx->glPriv) { lpCtx = ctx->glPriv; // Release any existing interfaces SAFE_RELEASE(lpCtx->pDev); SAFE_RELEASE(lpCtx->pD3D); } else { lpCtx = (GLD_driver_dx8*)malloc(sizeof(GLD_driver_dx8)); ZeroMemory(lpCtx, sizeof(lpCtx)); } d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; // TODO: Check this // if (bDefaultDriver) // d3dDevType = D3DDEVTYPE_REF; // Use persistant interface if needed if (bDirectDrawPersistant && dx8Globals.bDirect3D) { lpCtx->pD3D = dx8Globals.pD3D; IDirect3D8_AddRef(lpCtx->pD3D); goto SkipDirectDrawCreate; } // Create Direct3D8 object lpCtx->pD3D = dx8Globals.fnDirect3DCreate8(D3D_SDK_VERSION_DX8_SUPPORT_WIN95); if (lpCtx->pD3D == NULL) { MessageBox(NULL, "Unable to initialize Direct3D8", "GLDirect", MB_OK); ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D8 interface"); nContextError = GLDERR_D3D; goto return_with_error; } // Cache Direct3D interface for subsequent GLRCs if (bDirectDrawPersistant && !dx8Globals.bDirect3D) { dx8Globals.pD3D = lpCtx->pD3D; IDirect3D8_AddRef(dx8Globals.pD3D); dx8Globals.bDirect3D = TRUE; } SkipDirectDrawCreate: // Get the display mode so we can make a compatible backbuffer hResult = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm); if (FAILED(hResult)) { nContextError = GLDERR_D3D; goto return_with_error; } // Get device caps hResult = IDirect3D8_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps8); if (FAILED(hResult)) { ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_GetDeviceCaps failed", hResult); nContextError = GLDERR_D3D; goto return_with_error; } // Check for hardware transform & lighting lpCtx->bHasHWTnL = lpCtx->d3dCaps8.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE; // If this flag is present then we can't default to Mesa // SW rendering between BeginScene() and EndScene(). if (lpCtx->d3dCaps8.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) { ddlogMessage(DDLOG_WARN, "Warning : No 2D allowed during 3D scene.\n"); } // // Create the Direct3D context // // Re-use original IDirect3DDevice if persistant buffers exist. // Note that we test for persistant IDirect3D8 as well // bDirectDrawPersistant == persistant IDirect3D8 (DirectDraw8 does not exist) if (bDirectDrawPersistant && bPersistantBuffers && dx8Globals.pD3D && dx8Globals.pDev) { lpCtx->pDev = dx8Globals.pDev; IDirect3DDevice8_AddRef(dx8Globals.pDev); goto skip_direct3ddevice_create; } // Clear the presentation parameters (sets all members to zero) ZeroMemory(&d3dpp, sizeof(d3dpp)); // Recommended by MS; needed for MultiSample. // Be careful if altering this for FullScreenBlit d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = d3ddm.Format; d3dpp.BackBufferCount = 1; d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen); d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData; d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE; if (ctx->bFullscreen) { ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen d3dpp.Windowed = FALSE; d3dpp.BackBufferWidth = d3ddm.Width; d3dpp.BackBufferHeight = d3ddm.Height; d3dpp.hDeviceWindow = ctx->hWnd; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; // Support for vertical retrace synchronisation. // Set default presentation interval in case caps bits are missing d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; if (glb.bWaitForRetrace) { if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; } else { if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; } } else { ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages d3dpp.Windowed = TRUE; d3dpp.BackBufferWidth = ctx->dwWidth; d3dpp.BackBufferHeight = ctx->dwHeight; d3dpp.hDeviceWindow = ctx->hWnd; d3dpp.FullScreen_RefreshRateInHz = 0; // FullScreen_PresentationInterval must be default for Windowed mode d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; } // Decide if we can use hardware TnL dwBehaviourFlags = (lpCtx->bHasHWTnL) ? D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING; // Add flag to tell D3D to be thread-safe if (glb.bMultiThreaded) dwBehaviourFlags |= D3DCREATE_MULTITHREADED; // Add flag to tell D3D to be FPU-safe if (!glb.bFastFPU) dwBehaviourFlags |= D3DCREATE_FPU_PRESERVE; hResult = IDirect3D8_CreateDevice(lpCtx->pD3D, glb.dwAdapter, d3dDevType, ctx->hWnd, dwBehaviourFlags, &d3dpp, &lpCtx->pDev); if (FAILED(hResult)) { ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_CreateDevice failed", hResult); nContextError = GLDERR_D3D; goto return_with_error; } if (bDirectDrawPersistant && bPersistantBuffers && dx8Globals.pD3D) { dx8Globals.pDev = lpCtx->pDev; dx8Globals.bDirect3DDevice = TRUE; } /* // See if DDraw interfaces are available (DaveM) hResult = IDirect3D8_QueryInterface(lpCtx->pDev, &IID_IDirectDraw7, (LPVOID*)&lpOpaque1); if (FAILED(hResult) || lpOpaque1 == NULL) { ddlogMessage(DDLOG_INFO, "DirectDraw QueryInterface unavailable\n"); } hResult = IDirect3DDevice8_QueryInterface(lpCtx->pDev, &IID_IDirectDrawSurface7, (LPVOID*)&lpOpaque2); if (FAILED(hResult) || lpOpaque2 == NULL) { ddlogMessage(DDLOG_INFO, "DirectDrawSurface QueryInterface unavialable\n"); } */ // Dump some useful stats hResult = IDirect3D8_GetAdapterIdentifier( lpCtx->pD3D, glb.dwAdapter, D3DENUM_NO_WHQL_LEVEL, // Avoids 1 to 2 second delay &d3dIdent); if (SUCCEEDED(hResult)) { ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description); ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]", d3dIdent.Driver, HIWORD(d3dIdent.DriverVersion.HighPart), LOWORD(d3dIdent.DriverVersion.HighPart), HIWORD(d3dIdent.DriverVersion.LowPart), LOWORD(d3dIdent.DriverVersion.LowPart)); ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]", d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision); } // Init projection matrix for D3D TnL D3DXMatrixIdentity(&lpCtx->matProjection); lpCtx->matModelView = lpCtx->matProjection; // gld->bUseMesaProjection = TRUE; skip_direct3ddevice_create: // Create buffers to hold primitives lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX; lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM; lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX); lpCtx->PB2d.dwUsage = D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY; hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d); if (FAILED(hResult)) goto return_with_error; lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX; lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT; lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX); lpCtx->PB3d.dwUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY; hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d); if (FAILED(hResult)) goto return_with_error; /* // NOTE: A FVF code of zero indicates a non-FVF vertex buffer (for vertex shaders) lpCtx->PBtwosidelight.dwFVF = 0; //GLD_FVF_TWOSIDED_VERTEX; lpCtx->PBtwosidelight.dwPool = D3DPOOL_DEFAULT; lpCtx->PBtwosidelight.dwStride = sizeof(GLD_TWOSIDED_VERTEX); lpCtx->PBtwosidelight.dwUsage = D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY; hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PBtwosidelight); if (FAILED(hResult)) goto return_with_error;*/ // Now try and create the DX8 Vertex Shaders // _gldCreateVertexShaders(lpCtx); // Zero the pipeline usage counters lpCtx->PipelineUsage.qwMesa.QuadPart = // lpCtx->PipelineUsage.dwD3D2SVS.QuadPart = lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0; // Assign drawable to GL private ctx->glPriv = lpCtx; return TRUE; return_with_error: // Clean up and bail // _gldDestroyVertexShaders(lpCtx); // _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight); _gldDestroyPrimitiveBuffer(&lpCtx->PB3d); _gldDestroyPrimitiveBuffer(&lpCtx->PB2d); SAFE_RELEASE(lpCtx->pDev); SAFE_RELEASE(lpCtx->pD3D); return FALSE; }
BOOL gldCreateDrawable_DX( DGL_ctx *ctx, // BOOL bDefaultDriver, BOOL bDirectDrawPersistant, BOOL bPersistantBuffers) { // // bDirectDrawPersistant: applies to IDirect3D8 // bPersistantBuffers: applies to IDirect3DDevice8 // // D3DDEVTYPE d3dDevType; // D3DPRESENT_PARAMETERS d3dpp; // D3DDISPLAYMODE d3ddm; // DWORD dwBehaviourFlags; // D3DADAPTER_IDENTIFIER8 d3dIdent; HRESULT hr; GLD_driver_dx7 *lpCtx = NULL; D3DX_VIDMODEDESC d3ddm; // Parameters for D3DXCreateContextEx // These will be different for fullscreen and windowed DWORD dwDeviceIndex; DWORD dwFlags; HWND hwnd; HWND hwndFocus; DWORD numColorBits; DWORD numAlphaBits; DWORD numDepthBits; DWORD numStencilBits; DWORD numBackBuffers; DWORD dwWidth; DWORD dwHeight; DWORD refreshRate; // Error if context is NULL. if (ctx == NULL) return FALSE; if (ctx->glPriv) { lpCtx = ctx->glPriv; // Release any existing interfaces (in reverse order) SAFE_RELEASE(lpCtx->pDev); SAFE_RELEASE(lpCtx->pD3D); lpCtx->pD3DXContext->lpVtbl->Release(lpCtx->pD3DXContext); lpCtx->pD3DXContext = NULL; } else { lpCtx = (GLD_driver_dx7*)malloc(sizeof(GLD_driver_dx7)); ZeroMemory(lpCtx, sizeof(lpCtx)); } // d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; // Use REF device if requested. Otherwise D3DX_DEFAULT will choose highest level // of HW acceleration. dwDeviceIndex = (glb.dwDriver == GLDS_DRIVER_REF) ? D3DX_HWLEVEL_REFERENCE : D3DX_DEFAULT; // TODO: Check this // if (bDefaultDriver) // d3dDevType = D3DDEVTYPE_REF; #ifdef _GLD_PERSISTANT // Use persistant interface if needed if (bDirectDrawPersistant && dx7Globals.bDirect3D) { lpCtx->pD3D = dx7Globals.pD3D; IDirect3D7_AddRef(lpCtx->pD3D); goto SkipDirectDrawCreate; } #endif /* // Create Direct3D7 object lpCtx->pD3D = dx7Globals.fnDirect3DCreate8(D3D_SDK_VERSION_DX8_SUPPORT_WIN95); if (lpCtx->pD3D == NULL) { MessageBox(NULL, "Unable to initialize Direct3D8", "GLDirect", MB_OK); ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D8 interface"); nContextError = GLDERR_D3D; goto return_with_error; } */ #ifdef _GLD_PERSISTANT // Cache Direct3D interface for subsequent GLRCs if (bDirectDrawPersistant && !dx8Globals.bDirect3D) { dx7Globals.pD3D = lpCtx->pD3D; IDirect3D7_AddRef(dx7Globals.pD3D); dx7Globals.bDirect3D = TRUE; } SkipDirectDrawCreate: #endif /* // Get the display mode so we can make a compatible backbuffer hResult = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm); if (FAILED(hResult)) { nContextError = GLDERR_D3D; goto return_with_error; } */ #if 0 // Get device caps hResult = IDirect3D8_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps8); if (FAILED(hResult)) { ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_GetDeviceCaps failed", hResult); nContextError = GLDERR_D3D; goto return_with_error; } // Check for hardware transform & lighting lpCtx->bHasHWTnL = lpCtx->d3dCaps8.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE; // If this flag is present then we can't default to Mesa // SW rendering between BeginScene() and EndScene(). if (lpCtx->d3dCaps8.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) { ddlogMessage(DDLOG_WARN, "Warning : No 2D allowed during 3D scene.\n"); } #endif // // Create the Direct3D context // #ifdef _GLD_PERSISTANT // Re-use original IDirect3DDevice if persistant buffers exist. // Note that we test for persistant IDirect3D8 as well // bDirectDrawPersistant == persistant IDirect3D8 (DirectDraw8 does not exist) if (bDirectDrawPersistant && bPersistantBuffers && dx7Globals.pD3D && dx7Globals.pDev) { lpCtx->pDev = dx7Globals.pDev; IDirect3DDevice7_AddRef(dx7Globals.pDev); goto skip_direct3ddevice_create; } #endif /* // Clear the presentation parameters (sets all members to zero) ZeroMemory(&d3dpp, sizeof(d3dpp)); // Recommended by MS; needed for MultiSample. // Be careful if altering this for FullScreenBlit d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = d3ddm.Format; d3dpp.BackBufferCount = 1; d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen); d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData; d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE; if (ctx->bFullscreen) { ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen d3dpp.Windowed = FALSE; d3dpp.BackBufferWidth = d3ddm.Width; d3dpp.BackBufferHeight = d3ddm.Height; d3dpp.hDeviceWindow = ctx->hWnd; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; // Support for vertical retrace synchronisation. // Set default presentation interval in case caps bits are missing d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; if (glb.bWaitForRetrace) { if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; } else { if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; } } else { ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages d3dpp.Windowed = TRUE; d3dpp.BackBufferWidth = ctx->dwWidth; d3dpp.BackBufferHeight = ctx->dwHeight; d3dpp.hDeviceWindow = ctx->hWnd; d3dpp.FullScreen_RefreshRateInHz = 0; // FullScreen_PresentationInterval must be default for Windowed mode d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; } // Decide if we can use hardware TnL dwBehaviourFlags = (lpCtx->bHasHWTnL) ? D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING; // Add flag to tell D3D to be thread-safe if (glb.bMultiThreaded) dwBehaviourFlags |= D3DCREATE_MULTITHREADED; hResult = IDirect3D8_CreateDevice(lpCtx->pD3D, glb.dwAdapter, d3dDevType, ctx->hWnd, dwBehaviourFlags, &d3dpp, &lpCtx->pDev); if (FAILED(hResult)) { ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_CreateDevice failed", hResult); nContextError = GLDERR_D3D; goto return_with_error; } */ // Create D3DX context if (ctx->bFullscreen) { // // FULLSCREEN // // Get display mode D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm); // Fullscreen Parameters dwFlags = D3DX_CONTEXT_FULLSCREEN; hwnd = ctx->hWnd; hwndFocus = ctx->hWnd; numColorBits = ctx->lpPF->pfd.cColorBits; numAlphaBits = ctx->lpPF->pfd.cAlphaBits; numDepthBits = ctx->lpPF->pfd.cDepthBits + ctx->lpPF->pfd.cStencilBits; numStencilBits = ctx->lpPF->pfd.cStencilBits; numBackBuffers = D3DX_DEFAULT; // Default is 1 backbuffer dwWidth = d3ddm.width; dwHeight = d3ddm.height; refreshRate = d3ddm.refreshRate; // D3DX_DEFAULT; } else { // // WINDOWED // // Windowed Parameters dwFlags = 0; // No flags means "windowed" hwnd = ctx->hWnd; hwndFocus = (HWND)D3DX_DEFAULT; numColorBits = D3DX_DEFAULT; // Use Desktop depth numAlphaBits = ctx->lpPF->pfd.cAlphaBits; numDepthBits = ctx->lpPF->pfd.cDepthBits + ctx->lpPF->pfd.cStencilBits; numStencilBits = ctx->lpPF->pfd.cStencilBits; numBackBuffers = D3DX_DEFAULT; // Default is 1 backbuffer dwWidth = ctx->dwWidth; dwHeight = ctx->dwHeight; refreshRate = D3DX_DEFAULT; } hr = D3DXCreateContextEx(dwDeviceIndex, dwFlags, hwnd, hwndFocus, numColorBits, numAlphaBits, numDepthBits, numStencilBits, numBackBuffers, dwWidth, dwHeight, refreshRate, &lpCtx->pD3DXContext); if (FAILED(hr)) { ddlogError(DDLOG_CRITICAL_OR_WARN, "D3DXCreateContextEx failed", hr); nContextError = GLDERR_D3D; goto return_with_error; } // Obtain D3D7 interfaces from ID3DXContext // lpCtx->pDD = ID3DXContext_GetDD(lpCtx->pD3DXContext); lpCtx->pDD = lpCtx->pD3DXContext->lpVtbl->GetDD(lpCtx->pD3DXContext); if (lpCtx->pDD == NULL) goto return_with_error; lpCtx->pD3D = lpCtx->pD3DXContext->lpVtbl->GetD3D(lpCtx->pD3DXContext); if (lpCtx->pD3D == NULL) goto return_with_error; lpCtx->pDev = lpCtx->pD3DXContext->lpVtbl->GetD3DDevice(lpCtx->pD3DXContext); if (lpCtx->pDev == NULL) goto return_with_error; // Need to manage clipper manually for multiple windows // since DX7 D3DX utility lib does not appear to do that. (DaveM) if (!ctx->bFullscreen) { // Get primary surface too lpDDSPrimary = lpCtx->pD3DXContext->lpVtbl->GetPrimary(lpCtx->pD3DXContext); if (lpDDSPrimary == NULL) { ddlogPrintf(DDLOG_WARN, "GetPrimary"); goto return_with_error; } // Create clipper for correct window updates if (IDirectDraw7_CreateClipper(lpCtx->pDD, 0, &lpDDClipper, NULL) != DD_OK) { ddlogPrintf(DDLOG_WARN, "CreateClipper"); goto return_with_error; } // Set the window that the clipper belongs to if (IDirectDrawClipper_SetHWnd(lpDDClipper, 0, hwnd) != DD_OK) { ddlogPrintf(DDLOG_WARN, "SetHWnd"); goto return_with_error; } // Attach the clipper to the primary surface if (IDirectDrawSurface7_SetClipper(lpDDSPrimary, lpDDClipper) != DD_OK) { ddlogPrintf(DDLOG_WARN, "SetClipper"); goto return_with_error; } } // Get device caps IDirect3DDevice7_GetCaps(lpCtx->pDev, &lpCtx->d3dCaps); // Determine HW TnL lpCtx->bHasHWTnL = lpCtx->d3dCaps.dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE; #ifdef _GLD_PERSISTANT if (bDirectDrawPersistant && bPersistantBuffers && dx7Globals.pD3D) { dx7Globals.pDev = lpCtx->pDev; dx7Globals.bDirect3DDevice = TRUE; } #endif #if 0 // Dump some useful stats hResult = IDirect3D8_GetAdapterIdentifier( lpCtx->pD3D, glb.dwAdapter, D3DENUM_NO_WHQL_LEVEL, // Avoids 1 to 2 second delay &d3dIdent); if (SUCCEEDED(hResult)) { ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description); ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]", d3dIdent.Driver, HIWORD(d3dIdent.DriverVersion.HighPart), LOWORD(d3dIdent.DriverVersion.HighPart), HIWORD(d3dIdent.DriverVersion.LowPart), LOWORD(d3dIdent.DriverVersion.LowPart)); ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]", d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision); } #endif // Init projection matrix for D3D TnL D3DXMatrixIdentity((D3DXMATRIX*)&lpCtx->matProjection); lpCtx->matModelView = lpCtx->matProjection; // gld->bUseMesaProjection = TRUE; skip_direct3ddevice_create: // Create buffers to hold primitives lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX; // lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM; lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX); lpCtx->PB2d.dwCreateFlags = D3DVBCAPS_DONOTCLIP | D3DVBCAPS_SYSTEMMEMORY | D3DVBCAPS_WRITEONLY; hr = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d); if (FAILED(hr)) goto return_with_error; lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX; // lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT; lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX); lpCtx->PB3d.dwCreateFlags = D3DVBCAPS_WRITEONLY; hr = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d); if (FAILED(hr)) goto return_with_error; // Zero the pipeline usage counters lpCtx->PipelineUsage.qwMesa.QuadPart = // lpCtx->PipelineUsage.dwD3D2SVS.QuadPart = lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0; // Assign drawable to GL private ctx->glPriv = lpCtx; return TRUE; return_with_error: // Clean up and bail _gldDestroyPrimitiveBuffer(&lpCtx->PB3d); _gldDestroyPrimitiveBuffer(&lpCtx->PB2d); SAFE_RELEASE(lpCtx->pDev); SAFE_RELEASE(lpCtx->pD3D); //SAFE_RELEASE(lpCtx->pD3DXContext); lpCtx->pD3DXContext->lpVtbl->Release(lpCtx->pD3DXContext); return FALSE; }