📄 dglwgl.c
字号:
{
// 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 + -