⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dglcontext.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
	}
*/
	// 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 + -