📄 dglcontext.c
字号:
}
*/
// Misc initialisation
lpCtx->bCanRender = FALSE; // No rendering allowed yet
lpCtx->bSceneStarted = FALSE;
lpCtx->bFrameStarted = FALSE;
// Detect OS (specifically 'Windows 2000' or 'Windows XP')
DetectOS();
// NOTE: WinNT not supported
ddlogPrintf(DDLOG_INFO, "OS: %s", bHaveWin95 ? "Win9x" : (bHaveWin2K ? "Win2000/XP" : "Unsupported") );
// Test for Fullscreen
if (bHaveWin95) { // Problems with fullscreen on Win2K/XP
if ((GetSystemMetrics(SM_CXSCREEN) == lpCtx->dwWidth) &&
(GetSystemMetrics(SM_CYSCREEN) == lpCtx->dwHeight))
{
// Workaround for some apps that crash when going fullscreen.
//lpCtx->bFullscreen = TRUE;
}
}
#ifdef _USE_GLD3_WGL
_gldDriver.CreateDrawable(lpCtx, glb.bDirectDrawPersistant, glb.bPersistantBuffers);
#else
// Check if DirectDraw has already been created by original GLRC (DaveM)
if (glb.bDirectDrawPersistant && glb.bDirectDraw) {
lpCtx->lpDD4 = glb.lpDD4;
IDirectDraw4_AddRef(lpCtx->lpDD4);
goto SkipDirectDrawCreate;
}
// Create DirectDraw object
if (glb.bPrimary)
hResult = DirectDrawCreate(NULL, &lpCtx->lpDD1, NULL);
else {
// A non-primary device is to be used.
// Force context to be Fullscreen, secondary adaptors can not
// be used in a window.
hResult = DirectDrawCreate(&glb.ddGuid, &lpCtx->lpDD1, NULL);
lpCtx->bFullscreen = TRUE;
}
if (FAILED(hResult)) {
MessageBox(NULL, "Unable to initialize DirectDraw", "GLDirect", MB_OK);
ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw interface", hResult);
nContextError = GLDERR_DDRAW;
goto return_with_error;
}
// Query for DX6 IDirectDraw4.
hResult = IDirectDraw_QueryInterface(lpCtx->lpDD1,
&IID_IDirectDraw4,
(void**)&lpCtx->lpDD4);
if (FAILED(hResult)) {
MessageBox(NULL, "GLDirect requires DirectX 6.0 or above", "GLDirect", MB_OK);
ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw4 interface", hResult);
nContextError = GLDERR_DDRAW;
goto return_with_error;
}
// Cache DirectDraw interface for subsequent GLRCs
if (glb.bDirectDrawPersistant && !glb.bDirectDraw) {
glb.lpDD4 = lpCtx->lpDD4;
IDirectDraw4_AddRef(glb.lpDD4);
glb.bDirectDraw = TRUE;
}
SkipDirectDrawCreate:
// Now we have a DD4 interface we can check for broken cards
dglTestForBrokenCards(lpCtx);
// Test if primary device can use flipping instead of blitting
ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
hResult = IDirectDraw4_GetDisplayMode(
lpCtx->lpDD4,
&ddsd2DisplayMode);
if (SUCCEEDED(hResult)) {
if ( (lpCtx->dwWidth == ddsd2DisplayMode.dwWidth) &&
(lpCtx->dwHeight == ddsd2DisplayMode.dwHeight) ) {
// We have a fullscreen-size window
bFullScrnWin = TRUE;
// OK to use DirectDraw fullscreen mode ?
if (glb.bPrimary && !glb.bFullscreenBlit && !lpCtx->EmulateSingle && !glb.bDirectDrawPersistant) {
lpCtx->bFullscreen = TRUE;
ddlogMessage(DDLOG_INFO, "Primary upgraded to page flipping.\n");
}
}
// Cache the display mode dimensions
lpCtx->dwModeWidth = ddsd2DisplayMode.dwWidth;
lpCtx->dwModeHeight = ddsd2DisplayMode.dwHeight;
}
// Clamp the effective window dimensions to primary surface.
// We need to do this for D3D viewport dimensions even if wide
// surfaces are supported. This also is a good idea for handling
// whacked-out window dimensions passed for non-drawable windows
// like Solid Edge. (DaveM)
if (lpCtx->dwWidth > ddsd2DisplayMode.dwWidth)
lpCtx->dwWidth = ddsd2DisplayMode.dwWidth;
if (lpCtx->dwHeight > ddsd2DisplayMode.dwHeight)
lpCtx->dwHeight = ddsd2DisplayMode.dwHeight;
// Check for non-RGB desktop resolution
if (!lpCtx->bFullscreen && ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount <= 8) {
ddlogPrintf(DDLOG_CRITICAL_OR_WARN, "Desktop color depth %d bpp not supported",
ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount);
nContextError = GLDERR_BPP;
goto return_with_error;
}
#endif // _USE_GLD3_WGL
ddlogPrintf(DDLOG_INFO, "Window: w=%i, h=%i (%s)",
lpCtx->dwWidth,
lpCtx->dwHeight,
lpCtx->bFullscreen ? "fullscreen" : "windowed");
#ifndef _USE_GLD3_WGL
// Obtain ddraw caps
ZeroMemory(&lpCtx->ddCaps, sizeof(DDCAPS));
lpCtx->ddCaps.dwSize = sizeof(DDCAPS);
if (glb.bHardware) {
// Get HAL caps
IDirectDraw4_GetCaps(lpCtx->lpDD4, &lpCtx->ddCaps, NULL);
} else {
// Get HEL caps
IDirectDraw4_GetCaps(lpCtx->lpDD4, NULL, &lpCtx->ddCaps);
}
// If this flag is present then we can't default to Mesa
// SW rendering between BeginScene() and EndScene().
if (lpCtx->ddCaps.dwCaps2 & DDCAPS2_NO2DDURING3DSCENE) {
ddlogMessage(DDLOG_INFO,
"Warning : No 2D allowed during 3D scene.\n");
}
// Query for DX6 Direct3D3 interface
hResult = IDirectDraw4_QueryInterface(lpCtx->lpDD4,
&IID_IDirect3D3,
(void**)&lpCtx->lpD3D3);
if (FAILED(hResult)) {
MessageBox(NULL, "Unable to initialize Direct3D", "GLDirect", MB_OK);
ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D interface", hResult);
nContextError = GLDERR_D3D;
goto return_with_error;
}
// Context creation
if (lpCtx->bFullscreen) {
// FULLSCREEN
// Disable warning popups when in fullscreen mode
ddlogWarnOption(FALSE);
// Have to release persistant primary surface if fullscreen mode
if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
RELEASE(glb.lpPrimary4);
glb.bDirectDrawPrimary = FALSE;
}
dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
if (glb.bFastFPU)
dwFlags |= DDSCL_FPUSETUP; // fast FPU setup optional (DaveM)
hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, lpCtx->hWnd, dwFlags);
if (FAILED(hResult)) {
ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Exclusive Fullscreen mode", hResult);
goto return_with_error;
}
hResult = IDirectDraw4_SetDisplayMode(lpCtx->lpDD4,
lpCtx->dwModeWidth,
lpCtx->dwModeHeight,
lpPFD->cColorBits,
0,
0);
if (FAILED(hResult)) {
ddlogError(DDLOG_CRITICAL_OR_WARN, "SetDisplayMode failed", hResult);
goto return_with_error;
}
// ** The display mode has changed, so dont use MessageBox! **
ZeroMemory(&ddsd2, sizeof(ddsd2));
ddsd2.dwSize = sizeof(ddsd2);
if (bDoubleBuffer) {
// Double buffered
// Primary surface
ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
DDSCAPS_FLIP |
DDSCAPS_COMPLEX |
DDSCAPS_3DDEVICE |
dwMemoryType;
ddsd2.dwBackBufferCount = 1;
hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
if (FAILED(hResult)) {
ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
nContextError = GLDERR_MEM;
goto return_with_error;
}
// Render target surface
ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
hResult = IDirectDrawSurface4_GetAttachedSurface(lpCtx->lpFront4, &ddscaps2, &lpCtx->lpBack4);
if (FAILED(hResult)) {
ddlogError(DDLOG_CRITICAL_OR_WARN, "GetAttachedSurface failed", hResult);
nContextError = GLDERR_MEM;
goto return_with_error;
}
} else {
// Single buffered
// Primary surface
ddsd2.dwFlags = DDSD_CAPS;
ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
//DDSCAPS_3DDEVICE |
dwMemoryType;
hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
if (FAILED(hResult)) {
ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
nContextError = GLDERR_MEM;
goto return_with_error;
}
lpCtx->lpBack4 = NULL;
}
} else {
// WINDOWED
// OK to enable warning popups in windowed mode
ddlogWarnOption(glb.bMessageBoxWarnings);
dwFlags = DDSCL_NORMAL;
if (glb.bMultiThreaded)
dwFlags |= DDSCL_MULTITHREADED;
if (glb.bFastFPU)
dwFlags |= DDSCL_FPUSETUP; // fast FPU setup optional (DaveM)
hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4,
lpCtx->hWnd,
dwFlags);
if (FAILED(hResult)) {
ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Normal coop level", hResult);
goto return_with_error;
}
// Has Primary surface already been created for original GLRC ?
// Note this can only be applicable for windowed modes
if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
lpCtx->lpFront4 = glb.lpPrimary4;
IDirectDrawSurface4_AddRef(lpCtx->lpFront4);
// Update the window on the default clipper
IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
IDirectDrawClipper_Release(lpddClipper);
goto SkipPrimaryCreate;
}
// Primary surface
ZeroMemory(&ddsd2, sizeof(ddsd2));
ddsd2.dwSize = sizeof(ddsd2);
ddsd2.dwFlags = DDSD_CAPS;
ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
if (FAILED(hResult)) {
ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
nContextError = GLDERR_MEM;
goto return_with_error;
}
// Cache Primary surface for subsequent GLRCs
// Note this can only be applicable to subsequent windowed modes
if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
glb.lpPrimary4 = lpCtx->lpFront4;
IDirectDrawSurface4_AddRef(glb.lpPrimary4);
glb.bDirectDrawPrimary = TRUE;
}
// Clipper object
hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
if (FAILED(hResult)) {
ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateClipper failed", hResult);
goto return_with_error;
}
hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
if (FAILED(hResult)) {
RELEASE(lpddClipper);
ddlogError(DDLOG_CRITICAL_OR_WARN, "SetHWnd failed", hResult);
goto return_with_error;
}
hResult = IDirectDrawSurface4_SetClipper(lpCtx->lpFront4, lpddClipper);
RELEASE(lpddClipper); // We have finished with it.
if (FAILED(hResult)) {
ddlogError(DDLOG_CRITICAL_OR_WARN, "SetClipper failed", hResult);
goto return_with_error;
}
SkipPrimaryCreate:
if (bDoubleBuffer) {
// Render target surface
ZeroMemory(&ddsd2, sizeof(ddsd2));
ddsd2.dwSize = sizeof(ddsd2);
ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd2.dwWidth = lpCtx->dwWidth;
ddsd2.dwHeight = lpCtx->dwHeight;
ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
DDSCAPS_OFFSCREENPLAIN |
dwMemoryType;
// Reserve the entire desktop size for persistant buffers option
if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
}
// Re-use original back buffer if persistant buffers exist
if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpBack4)
hResult = IDirectDrawSurface4_AddRef(lpCtx->lpBack4 = glb.lpBack4);
else
hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpBack4, NULL);
if (FAILED(hResult)) {
ddlogError(DDLOG_CRITICAL_OR_WARN, "Create Backbuffer failed", hResult);
nContextError = GLDERR_MEM;
goto return_with_error;
}
if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpBack4)
IDirectDrawSurface4_AddRef(glb.lpBack4 = lpCtx->lpBack4);
} else {
lpCtx->lpBack4 = NULL;
}
}
//
// Now create the Z-buffer
//
lpCtx->bStencil = FALSE; // Default to no stencil buffer
if (bDepthBuffer && (lpCtx->lpPF->iZBufferPF != -1)) {
// Get z-buffer dimensions from the render target
// Setup the surface desc for the z-buffer.
ZeroMemory(&ddsd2, sizeof(ddsd2));
ddsd2.dwSize = sizeof(ddsd2);
ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
ddsd2.dwWidth = lpCtx->dwWidth;
ddsd2.dwHeight = lpCtx->dwHeight;
memcpy(&ddsd2.ddpfPixelFormat,
&glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF],
sizeof(DDPIXELFORMAT) );
// Reserve the entire desktop size for persistant buffers option
if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
}
// Create a z-buffer
if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4)
hResult = IDirectDrawSurface4_AddRef(lpCtx->lpDepth4 = glb.lpDepth4);
else
hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpDepth4, NULL);
if (FAILED(hResult)) {
ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (ZBuffer) failed", hResult);
nContextError = GLDERR_MEM;
goto return_with_error;
}
if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpDepth4)
IDirectDrawSurface4_AddRef(glb.lpDepth4 = lpCtx->lpDepth4);
else if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4 && glb.lpBack4)
IDirectDrawSurface4_DeleteAttachedSurface(glb.lpBack4, 0, glb.lpDepth4);
// Attach Zbuffer to render target
TRY(IDirectDrawSurface4_AddAttachedSurface(
bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
lpCtx->lpDepth4),
"dglCreateContext: Attach Zbuffer");
if (glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags & DDPF_STENCILBUFFER) {
lpCtx->bStencil = TRUE;
ddlogMessage(DDLOG_INFO, "Depth buffer has stencil\n");
}
}
// Clear all back buffers and Z-buffers in case of memory recycling.
ZeroMemory(&ddbltfx, sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);
IDirectDrawSurface4_Blt(lpCtx->lpBack4, NULL, NULL, NULL,
DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
if (lpCtx->lpDepth4)
IDirectDrawSurface4_Blt(lpCtx->lpDepth4, NULL, NULL, NULL,
DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
// Now that we have a Z-buffer we can create the 3D device
hResult = IDirect3D3_CreateDevice(lpCtx->lpD3D3,
&glb.d3dGuid,
bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
&lpCtx->lpDev3,
NULL);
if (FAILED(hResult)) {
ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D device", hResult);
nContextError = GLDERR_D3D;
goto return_with_error;
}
// We must do this as soon as the device is created
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -