static HRESULT WINAPI d3d8_QueryInterface(IDirect3D8 *iface, REFIID riid, void **out) { TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); if (IsEqualGUID(riid, &IID_IDirect3D8) || IsEqualGUID(riid, &IID_IUnknown)) { IDirect3D8_AddRef(iface); *out = iface; return S_OK; } WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); *out = NULL; return E_NOINTERFACE; }
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; }