📄 dglcontext.c
字号:
} // 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 dglInitStateCaches(lpCtx); // Obtain the D3D Device Description D3DHWDevDesc.dwSize = D3DHELDevDesc.dwSize = sizeof(D3DDEVICEDESC); TRY(IDirect3DDevice3_GetCaps(lpCtx->lpDev3, &D3DHWDevDesc, &D3DHELDevDesc), "dglCreateContext: GetCaps failed"); // Choose the relevant description and cache it in the context. // We will use this description later for caps checking memcpy( &lpCtx->D3DDevDesc, glb.bHardware ? &D3DHWDevDesc : &D3DHELDevDesc, sizeof(D3DDEVICEDESC)); // Now we can examine the texture formats if (!dglBuildTextureFormatList(lpCtx->lpDev3)) { ddlogMessage(DDLOG_CRITICAL_OR_WARN, "dglBuildTextureFormatList failed\n"); goto return_with_error; } // Get the pixel format of the back buffer lpCtx->ddpfRender.dwSize = sizeof(lpCtx->ddpfRender); if (bDoubleBuffer) hResult = IDirectDrawSurface4_GetPixelFormat( lpCtx->lpBack4, &lpCtx->ddpfRender); else hResult = IDirectDrawSurface4_GetPixelFormat( lpCtx->lpFront4, &lpCtx->ddpfRender); if (FAILED(hResult)) { ddlogError(DDLOG_CRITICAL_OR_WARN, "GetPixelFormat failed", hResult); goto return_with_error; } // Find a pixel packing function suitable for this surface pxClassifyPixelFormat(&lpCtx->ddpfRender, &lpCtx->fnPackFunc, &lpCtx->fnUnpackFunc, &lpCtx->fnPackSpanFunc); // Viewport hResult = IDirect3D3_CreateViewport(lpCtx->lpD3D3, &lpCtx->lpViewport3, NULL); if (FAILED(hResult)) { ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateViewport failed", hResult); goto return_with_error; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -