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

📄 dglwgl.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
{
	// Validate license
	if (!dglValidate())
		return FALSE;

	return dglSwapBuffers(a);
}

// ***********************************************************************

// ***********************************************************************
// Note: This ResizeBuffers() function may be called from
// either MESA glViewport() or GLD wglMakeCurrent().

BOOL dglWglResizeBuffers(
	GLcontext *ctx,
	BOOL bDefaultDriver)
{
	DGL_ctx						*dgl = NULL;
	RECT						rcScreenRect;
	DWORD						dwWidth;
	DWORD						dwHeight;
	DDSURFACEDESC2				ddsd2;
	DDSCAPS2					ddscaps2;
	IDirectDrawClipper			*lpddClipper = NULL;
	DWORD						dwFlags;
	HRESULT						hResult;

	DWORD						dwMemoryType;

	int							i;
	struct gl_texture_object	*tObj;
	struct gl_texture_image		*image;

	BOOL						bWasFullscreen;
	BOOL						bSaveDesktop;
	BOOL						bFullScrnWin = FALSE;
	DDSURFACEDESC2 				ddsd2DisplayMode;

	DDBLTFX						ddbltfx;
	POINT						pt;
	RECT						rcDst;
#ifdef _USE_GLD3_WGL
	GLD_displayMode				glddm;
#endif

#define DDLOG_CRITICAL_OR_WARN	(bDefaultDriver ? DDLOG_WARN : DDLOG_CRITICAL)

	// Validate license
	if (!dglValidate())
		return FALSE;

	// Sanity checks
	if (ctx == NULL)
		return FALSE;
	dgl = ctx->DriverCtx;
	if (dgl == NULL)
		return FALSE;

	// Get the window size and calculate its dimensions
	if (dgl->hWnd == NULL) {
		// Check for non-window DC = memory DC ?
		if (GetClipBox(dgl->hDC, &rcScreenRect) == ERROR)
			SetRect(&rcScreenRect, 0, 0, 0, 0);
	}
	else if (!GetClientRect(dgl->hWnd, &rcScreenRect))
		SetRect(&rcScreenRect, 0, 0, 0, 0);
	dwWidth = rcScreenRect.right - rcScreenRect.left;
	dwHeight = rcScreenRect.bottom - rcScreenRect.top;
    CopyRect(&dgl->rcScreenRect, &rcScreenRect);

	// This will occur on Alt-Tab
	if ((dwWidth == 0) && (dwHeight == 0)) {
		//dgl->bCanRender = FALSE;
		return TRUE; // No resize possible!
	}

	// Some apps zero only 1 dimension for non-visible window... (DaveM)
	if ((dwWidth == 0) || (dwHeight == 0)) {
		dwWidth = 8;
		dwHeight = 8;
	}

	// Test to see if a resize is required.
	// Note that the dimensions will be the same if a prior resize attempt failed.
	if ((dwWidth == dgl->dwWidth) && (dwHeight == dgl->dwHeight) && bDefaultDriver) {
		return TRUE; // No resize required
	}

	ddlogPrintf(DDLOG_SYSTEM, "dglResize: %dx%d", dwWidth, dwHeight);
#ifndef _USE_GLD3_WGL
	// Work out where we want our surfaces created
	dwMemoryType = (bDefaultDriver) ? glb.dwMemoryType : DDSCAPS_SYSTEMMEMORY;
#endif // _USE_GLD3_WGL

	// Note previous fullscreen vs window display status
	bWasFullscreen = dgl->bFullscreen;

#ifdef _USE_GLD3_WGL
	if (_gldDriver.GetDisplayMode(dgl, &glddm)) {
		if ( (dwWidth == glddm.Width) &&
				 (dwHeight == glddm.Height) ) {
			bFullScrnWin = TRUE;
		}
		if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
			dgl->bFullscreen = TRUE;
			ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
		}
		else {
			dgl->bFullscreen = FALSE;
			ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
		}
		// Cache the display mode dimensions
		dgl->dwModeWidth = glddm.Width;
		dgl->dwModeHeight = glddm.Height;
	}

	// 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 (dgl->dwWidth > glddm.Width)
		dgl->dwWidth = glddm.Width;
	if (dgl->dwHeight > glddm.Height)
		dgl->dwHeight = glddm.Height;
#else // _USE_GLD3_WGL
	// Window resize may have changed to fullscreen
	ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
	ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
	hResult = IDirectDraw4_GetDisplayMode(
					dgl->lpDD4,
					&ddsd2DisplayMode);
	if (SUCCEEDED(hResult)) {
		if ( (dwWidth == ddsd2DisplayMode.dwWidth) &&
				 (dwHeight == ddsd2DisplayMode.dwHeight) ) {
			bFullScrnWin = TRUE;
		}
		if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
			dgl->bFullscreen = TRUE;
			ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
		}
		else {
			dgl->bFullscreen = FALSE;
			ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
		}
		// Cache the display mode dimensions
		dgl->dwModeWidth = ddsd2DisplayMode.dwWidth;
		dgl->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 (dgl->dwWidth > ddsd2DisplayMode.dwWidth)
		dgl->dwWidth = ddsd2DisplayMode.dwWidth;
	if (dgl->dwHeight > ddsd2DisplayMode.dwHeight)
		dgl->dwHeight = ddsd2DisplayMode.dwHeight;
#endif // _USE_GLD3_WGL

	// Note if fullscreen vs window display has changed?
	bSaveDesktop = (!bWasFullscreen && !dgl->bFullscreen) ? TRUE : FALSE;
	// Save the desktop primary surface from being destroyed
	// whenever remaining in windowed mode, since the stereo mode
	// switches are expensive...

#ifndef _USE_GLD3_WGL
	// Don't need to re-allocate persistant buffers. (DaveM)
	// Though we should clear the back buffers to hide artifacts.
	if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
		dgl->dwWidth = dwWidth;
		dgl->dwHeight = dwHeight;
		ZeroMemory(&ddbltfx, sizeof(ddbltfx));
		ddbltfx.dwSize = sizeof(ddbltfx);
		ddbltfx.dwFillColor = dgl->dwClearColorPF;
		IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
			DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
		return TRUE;
	}

	// Ensure all rendering is complete
	if (ctx->Driver.Finish)
		(*ctx->Driver.Finish)(ctx);
	if (dgl->bSceneStarted == TRUE) {
		IDirect3DDevice3_EndScene(dgl->lpDev3);
		dgl->bSceneStarted = FALSE;
	}
#endif // _USE_GLD3_WGL
	dgl->bCanRender = FALSE;

#ifdef GLD_THREADS
	// Serialize access to DirectDraw and DDS operations
	if (glb.bMultiThreaded)
		EnterCriticalSection(&CriticalSection);
#endif

#ifndef _USE_GLD3_WGL
	// Release existing surfaces
	RELEASE(dgl->lpDev3);
	RELEASE(dgl->lpDepth4);
	RELEASE(dgl->lpBack4);
	if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
        ;
	else
	RELEASE(dgl->lpFront4);
#endif // _USE_GLD3_WGL
	dgl->dwWidth = dwWidth;
	dgl->dwHeight = dwHeight;

	// Set defaults
	dgl->dwModeWidth = dgl->dwWidth;
	dgl->dwModeHeight = dgl->dwHeight;

#ifdef _USE_GLD3_WGL
	if (!_gldDriver.ResizeDrawable(dgl, bDefaultDriver, glb.bDirectDrawPersistant, glb.bPersistantBuffers))
		goto cleanup_and_return_with_error;
#else // _USE_GLD3_WGL

	if (dgl->bFullscreen) {
		//
		// FULLSCREEN
		//

        // Disable warning popups when in fullscreen mode
        ddlogWarnOption(FALSE);

		// Have to release the persistant DirectDraw primary surface
		// if switching to fullscreen mode. So if application wants
		// persistant display in fullscreen mode, a fullscreen-size
		// window should be used instead via fullscreen-blit option.
		if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
			RELEASE(glb.lpPrimary4);
			glb.bDirectDrawPrimary = FALSE;
		}

		dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
		if (glb.bFastFPU)
			dwFlags |= DDSCL_FPUSETUP;	// optional
		hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4, dgl->hWnd, dwFlags);
		if (FAILED(hResult)) {
			ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Exclusive Fullscreen mode", hResult);
			goto cleanup_and_return_with_error;
		}

		hResult = IDirectDraw4_SetDisplayMode(dgl->lpDD4,
											  dgl->dwModeWidth,
											  dgl->dwModeHeight,
											  dgl->dwBPP,
											  0,
											  0);
		if (FAILED(hResult)) {
			ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetDisplayMode failed", hResult);
			goto cleanup_and_return_with_error;
		}

		// ** The display mode has changed, so dont use MessageBox! **

		ZeroMemory(&ddsd2, sizeof(ddsd2));
		ddsd2.dwSize = sizeof(ddsd2);

		if (dgl->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(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
			if (FAILED(hResult)) {
				ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
				goto cleanup_and_return_with_error;
			}
			// Render target surface
			ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
			ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
			hResult = IDirectDrawSurface4_GetAttachedSurface(dgl->lpFront4, &ddscaps2, &dgl->lpBack4);
			if (FAILED(hResult)) {
				ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: GetAttachedSurface failed", hResult);
				goto cleanup_and_return_with_error;
			}
		} else {
			// Single buffered
			// Primary surface
			ddsd2.dwFlags = DDSD_CAPS;
			ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
								   //DDSCAPS_3DDEVICE |
								   dwMemoryType;

			hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
			if (FAILED(hResult)) {
				ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
				goto cleanup_and_return_with_error;
			}

			dgl->lpBack4 = NULL;
		}
	} else {
		// WINDOWED

        // OK to enable warning popups in windowed mode
        ddlogWarnOption(glb.bMessageBoxWarnings);

		// Ditto if persistant DirectDraw primary
		if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
			goto DoClipperOnly;

		// WINDOWED
		dwFlags = DDSCL_NORMAL;
		if (glb.bMultiThreaded)
			dwFlags |= DDSCL_MULTITHREADED;
		if (glb.bFastFPU)
			dwFlags |= DDSCL_FPUSETUP;	// optional
		hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4,
												  dgl->hWnd,
												  dwFlags);
		if (FAILED(hResult)) {
			ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Normal coop level", hResult);
			goto cleanup_and_return_with_error;
		}
		// Primary surface
		ZeroMemory(&ddsd2, sizeof(ddsd2));
		ddsd2.dwSize = sizeof(ddsd2);
		ddsd2.dwFlags = DDSD_CAPS;
		ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
		hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
		if (FAILED(hResult)) {
			ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
			goto cleanup_and_return_with_error;
		}

		// Cache the primary surface for persistant DirectDraw state
		if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
			glb.lpPrimary4 = dgl->lpFront4;
			IDirectDrawSurface4_AddRef(glb.lpPrimary4);
			glb.bDirectDrawPrimary = TRUE;
		}

		// Clipper object
		hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
		if (FAILED(hResult)) {
			ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateClipper failed", hResult);
			goto cleanup_and_return_with_error;
		}
		hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
		if (FAILED(hResult)) {
			RELEASE(lpddClipper);
			ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetHWnd failed", hResult);
			goto cleanup_and_return_with_error;
		}
		hResult = IDirectDrawSurface4_SetClipper(dgl->lpFront4, lpddClipper);
		RELEASE(lpddClipper); // We have finished with it.
		if (FAILED(hResult)) {
			ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetClipper failed", hResult);
			goto cleanup_and_return_with_error;
		}
DoClipperOnly:
		// Update the window for the original clipper
		if ((glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) || bSaveDesktop) {
			IDirectDrawSurface4_GetClipper(dgl->lpFront4, &lpddClipper);
			IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
			RELEASE(lpddClipper);
		}

		if (dgl->bDoubleBuffer) {
			// Render target surface
			ZeroMemory(&ddsd2, sizeof(ddsd2));
			ddsd2.dwSize = sizeof(ddsd2);
			ddsd2.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
			ddsd2.dwWidth        = dgl->dwWidth;
			ddsd2.dwHeight       = dgl->dwHeight;
			ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
								   DDSCAPS_OFFSCREENPLAIN |
								   dwMemoryType;
			hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpBack4, NULL);
			if (FAILED(hResult)) {
				ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Create Backbuffer failed", hResult);
				goto cleanup_and_return_with_error;
			}

		} else {
			dgl->lpBack4 = NULL;
		}
	}

	//
	// Now create the Zbuffer
	//
	if (dgl->bDepthBuffer) {
		// 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 = dgl->dwWidth;
		ddsd2.dwHeight = dgl->dwHeight;
		memcpy(&ddsd2.ddpfPixelFormat,
			   &glb.lpZBufferPF[dgl->iZBufferPF],
			   sizeof(DDPIXELFORMAT) );

		// Create a z-buffer
		hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpDepth4, NULL);
		if (FAILED(hResult)) {
			ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (ZBuffer) failed", hResult);
			goto cleanup_and_return_with_error;
		}

		// Attach Zbuffer to render target
		TRY(IDirectDrawSurface4_AddAttachedSurface(
			dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
			dgl->lpDepth4),
			"dglResize: Attach Zbuffer");

	}

	// Clear the newly resized back buffers for the window client area.
	ZeroMemory(&ddbltfx, sizeof(ddbltfx));
	ddbltfx.dwSize = sizeof(ddbltfx);
	ddbltfx.dwFillColor = dgl->dwClearColorPF;
	IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
		DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);

	//
	// Now that we have a zbuffer we can create the 3D device
	//
	hResult = IDirect3D3_CreateDevice(dgl->lpD3D3,
									  bDefaultDriver ? &glb.d3dGuid : &IID_IDirect3DRGBDevice,
									  dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
									  &dgl->lpDev3,
									  NULL);
	if (FAILED(hResult)) {
		ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Could not create Direct3D device", hResult);
		goto cleanup_and_return_with_error;
	}

	// We must do this as soon as the device is created
	dglInitStateCaches(dgl);

	//
	// Viewport
	//
	hResult = IDirect3DDevice3_AddViewport(dgl->lpDev3, dgl->lpViewport3);
	if (FAILED(hResult)) {
		ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: AddViewport failed", hResult);
		goto cleanup_and_return_with_error;
	}

	// Initialise the viewport
	dgl->d3dViewport.dwSize = sizeof(dgl->d3dViewport);
	dgl->d3dViewport.dwX = 0;
	dgl->d3dViewport.dwY = 0;
	dgl->d3dViewport.dwWidth = dgl->dwWidth;
	dgl->d3dViewport.dwHeight = dgl->dwHeight;
	dgl->d3dViewport.dvClipX = 0;
	dgl->d3dViewport.dvClipY = 0;
	dgl->d3dViewport.dvClipWidth = dgl->dwWidth;
	dgl->d3dViewport.dvClipHeight = dgl->dwHeight;
//	dgl->d3dViewport.dvMinZ = 0.0f;
//	dgl->d3dViewport.dvMaxZ = 1.0f;
	TRY(IDirect3DViewport3_SetViewport2(dgl->lpViewport3, &dgl->d3dViewport),
		"dglResize: SetViewport2");

	hResult = IDirect3DDevice3_SetCurrentViewport(dgl->lpDev3, dgl->lpViewport3);
	if (FAILED(hResult)) {
		ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetCurrentViewport failed", hResult);
		goto cleanup_and_return_with_error;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -