📄 dglwgl.c
字号:
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; } // (Re)Initialise all the Direct3D renderstates dglInitStateD3D(ctx); // Now we have to recreate all of our textures (+ mipmaps). // Walk over all textures in hash table // XXX what about the default texture objects (id=0)? { struct _mesa_HashTable *textures = ctx->Shared->TexObjects; GLuint id; for (id = _mesa_HashFirstEntry(textures); id; id = _mesa_HashNextEntry(textures, id)) { tObj = (struct gl_texture_object *) _mesa_HashLookup(textures, id); if (tObj->DriverData) { // We could call our TexImage function directly, but it's // safer to use the driver pointer. for (i=0; i<MAX_TEXTURE_LEVELS; i++) { image = tObj->Image[i]; if (image) { switch (tObj->Dimensions){ case 1: if (ctx->Driver.TexImage) (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, tObj, i, image->Format, image); break; case 2: if (ctx->Driver.TexImage) (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, tObj, i, image->Format, image); break; default: break; } } } } } } // Re-Bind each texture Unit for (i=0; i<glb.wMaxSimultaneousTextures; i++) { tObj = ctx->Texture.Unit[i].Current; if (tObj) { DGL_texture *lpTex = (DGL_texture *)tObj->DriverData; hResult = dglSetTexture(dgl, i, lpTex ? lpTex->lpTexture : NULL); if (FAILED(hResult)) { ddlogError(DDLOG_ERROR, "dglResize: SetTexture failed", hResult); } } }#endif // _USE_GLD3_WGL dgl->bCanRender = TRUE;#ifdef GLD_THREADS // Release serialized access if (glb.bMultiThreaded)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -