|
|
/******************************Module*Header*******************************\
* Module Name: pixelfmt.cxx * * This contains the pixel format functions. * * Created: 21-Sep-1993 * Author: Hock San Lee [hockl] * * 02-Nov-1995 -by- Drew Bliss [drewb] * Restored in kernel mode in minimal form * * Copyright (c) 1993-1999 Microsoft Corporation \**************************************************************************/
#include "precomp.hxx"
// Number of generic pixel formats. There are 5 pixel depths (4,8,16,24,32).
// See GreDescribePixelFormat for details.
#define MIN_GENERIC_PFD 1
#define MAX_GENERIC_PFD 24
/******************************Public*Routine******************************\
* LONG XDCOBJ::ipfdDevMaxGet() * * Initialize and return the maximum device supported pixel format index. * * The ipfdDevMax is set to -1 initially but is set to 0 or the maximum * device pixel format index here. This function should be called at most * once for the given DC. * * History: * Tue Sep 21 14:25:04 1993 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
LONG XDCOBJ::ipfdDevMaxGet() { PDEVOBJ pdo(hdev()); int ipfd = 0;
DEVLOCKOBJ dlo(pdo);
#ifdef OPENGL_MM
if (pdo.bMetaDriver()) { // We need to change the meta-PDEV into a hardware specific PDEV
HDEV hdevDevice = hdevFindDeviceHdev( hdev(), (RECTL) pdc->erclWindow(), NULL);
if (hdevDevice) { // replace meta pdevobj with device specific hdev.
pdo.vInit(hdevDevice); } }
#endif // OPENGL_MM
if (PPFNVALID(pdo, DescribePixelFormat)) { ipfd = (*PPFNDRV(pdo, DescribePixelFormat))(pdo.dhpdev(), 1, 0, NULL);
if (ipfd < 0) { ipfd = 0; } }
ipfdDevMax((SHORT)ipfd);
return ipfd; }
/******************************Public*Routine******************************\
* GreDescribePixelFormat * * Request pixel format information from a driver * If cjpfd is 0, just return the maximum driver pixel format index. * * Returns: 0 if error; maximum driver pixel format index otherwise * * History: * 02-Nov-95 -by- Drew Bliss [drewb] * Stripped down to driver-only support for kernel-mode * Mon Apr 25 15:34:32 1994 -by- Hock San Lee [hockl] * Added 16-bit Z buffer formats and removed double buffered formats for bitmaps. * Tue Sep 21 14:25:04 1993 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
int GreDescribePixelFormat(HDC hdc, int ipfd, UINT cjpfd, PPIXELFORMATDESCRIPTOR ppfd) { // Validate DC.
DCOBJ dco(hdc); if (!dco.bValid()) { SAVE_ERROR_CODE(ERROR_INVALID_HANDLE); return(0); }
int ipfdDevMax = dco.ipfdDevMax();
// If cjpfd is 0, just return the maximum pixel format index.
if (cjpfd == 0) return ipfdDevMax;
// Validate the size of the pixel format descriptor.
if (cjpfd < sizeof(PIXELFORMATDESCRIPTOR)) { SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER); return(0); }
// Validate pixel format index.
// If a driver support device pixel formats 1..ipfdDevMax, the generic
// pixel formats will be (ipfdDevMax+1)..(ipfdDevMax+MAX_GENERIC_PFD).
// Otherwise, ipfdDevMax is 0 and the generic pixel formats are
// 1..MAX_GENERIC_PFD.
if ((ipfd < 1) || (ipfd > ipfdDevMax)) { SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER); return(0); }
PDEVOBJ po(dco.hdev());
DEVLOCKOBJ dlo(po);
#ifdef OPENGL_MM
if (po.bMetaDriver()) { // We need to change the meta-PDEV into a hardware specific PDEV
HDEV hdevDevice = hdevFindDeviceHdev( dco.hdev(), (RECTL)dco.erclWindow(), NULL);
if (hdevDevice) { // replace meta pdevobj with device specific hdev.
po.vInit(hdevDevice); } }
#endif // OPENGL_MM
int iRet = 0;
if (PPFNVALID(po, DescribePixelFormat)) { iRet = (int) (*PPFNDRV(po, DescribePixelFormat)) (po.dhpdev(), ipfd, cjpfd, ppfd); }
if (iRet == 0) return(0);
ASSERTGDI(iRet == ipfdDevMax, "Bad ipfdDevMax"); return ipfdDevMax; }
/******************************Public*Routine******************************\
* NtGdiSetPixelFormat * * Set the pixel format. * * This is a special function. It is one of the three (the other two are * ExtEscape for WNDOBJ_SETUP escape and ExtEscape for 3D-DDI * RX_CREATECONTEXT escape) functions that allow WNDOBJ to be created in * the DDI. We need to be in the user critical section and grab the devlock * in the function before calling the DrvSetPixelFormat function to ensure * that the new WNDOBJ created is current. * * Returns: FALSE if error; TRUE otherwise * * History: * 02-Nov-95 -by- Drew Bliss [drewb] * Changed to driver-only kernel-mode form * Tue Sep 21 14:25:04 1993 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
BOOL NtGdiSetPixelFormat(HDC hdc,int ipfd) { // Validate DC and surface. Info DC is not allowed.
DCOBJ dco(hdc); if (!dco.bValid() || !dco.bHasSurface()) { SAVE_ERROR_CODE(ERROR_INVALID_HANDLE); return(FALSE); }
// Validate pixel format index.
// If a driver support device pixel formats 1..ipfdDevMax, the generic
// pixel formats will be (ipfdDevMax+1)..(ipfdDevMax+MAX_GENERIC_PFD).
// Otherwise, ipfdDevMax is 0 and the generic pixel formats are
// 1..MAX_GENERIC_PFD.
int ipfdDevMax = dco.ipfdDevMax(); if ((ipfd < 1) || (ipfd > ipfdDevMax)) { SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER); return(FALSE); }
// Make sure that we don't have devlock before entering user critical section.
// Otherwise, it can cause deadlock.
if (dco.bDisplay()) { ASSERTGDI(dco.dctp() == DCTYPE_DIRECT,"ERROR it has to be direct"); CHECKDEVLOCKOUT(dco); }
// Enter user critical section.
USERCRIT usercrit;
// We are modifying the pixel format of the window for the first time.
// Grab the devlock.
// We don't need to validate the devlock since we do not care if it is full screen.
DEVLOCKOBJ dlo(dco);
// If it is a display DC, get the hwnd that the hdc is associated with.
// If it is a printer or memory DC, hwnd is NULL.
HWND hwnd; if (dco.bDisplay()) { PEWNDOBJ pwo;
ASSERTGDI(dco.dctp() == DCTYPE_DIRECT, "ERROR it has to be direct really");
if (!UserGetHwnd(hdc, &hwnd, (PVOID *) &pwo, FALSE)) { SAVE_ERROR_CODE(ERROR_INVALID_WINDOW_STYLE); return(FALSE); }
// If another thread has changed the pixel format of the window
// after we queried it earlier in this function, make sure that
// the pixel format is compatible.
// If a previous 3D-DDI wndobj with pixel format 0 has been created
// for this window, fail the call here.
if (pwo) { WARNING("GreSetPixelFormat: pixel format set asynchrously!\n");
if (pwo->ipfd != ipfd) { SAVE_ERROR_CODE(ERROR_INVALID_PIXEL_FORMAT); return(FALSE); } return(TRUE); } } else { hwnd = (HWND)NULL; }
// Dispatch driver formats. Call DrvSetPixelFormat.
PDEVOBJ pdo(dco.hdev());
SURFOBJ *pso = dco.pSurface()->pSurfobj();
#ifdef OPENGL_MM
if (pdo.bMetaDriver()) { // We need to change the meta-PDEV into a hardware specific PDEV
HDEV hdevDevice = hdevFindDeviceHdev( dco.hdev(), (RECTL)dco.erclWindow(), NULL);
if (hdevDevice) { // If the surface is pdev's primary surface, we will replace it with
// new device pdev's surface.
if (pdo.bPrimary(dco.pSurface())) { PDEVOBJ pdoDevice(hdevDevice);
pso = pdoDevice.pSurface()->pSurfobj(); }
// replace meta pdevobj with device specific hdev.
pdo.vInit(hdevDevice); } }
#endif // OPENGL_MM
if (!PPFNVALID(pdo,SwapBuffers) || !((SURFOBJ_TO_SURFACE_NOT_NULL(pso)->bDriverCreated()) && (*PPFNDRV(pdo, SetPixelFormat))(pso, ipfd, hwnd))) return(FALSE);
// If a new WNDOBJ is created, we need to update the window client regions
// in the driver.
if (gbWndobjUpdate) { gbWndobjUpdate = FALSE; vForceClientRgnUpdate(); }
return(TRUE); }
/******************************Public*Routine******************************\
* NtGdiSwapBuffers * * Since SwapBuffers is a GDI function, it has to work even if OpenGL is * not called. That is, we will eventually support 2D double buffering in * GDI. As a result, we need to define a DDI function DrvSwapBuffers() that * works with both OpenGL and GDI. The complication is that we have to * deal with the generic opengl server, the install opengl driver and GDI. * I will outline how this function works here: * * 1. On the client side, SwapBuffers() call glFinish() to flush all the * OpenGL functions in the current thread. It then calls the server side * GreSwapBuffers(). Note that this flushes all GDI functions in the * current thread. * 2. Once on the server side, we know that all GDI/OpenGL calls have been * flushed. We first find the hwnd id that corresponding to the hdc. * Note that SwapBuffers really applies to the window but not to the dc. * There is only one back buffer for a window but possibly multiple * dc's referring to the same back buffer. We find out the hwnd id * for the dc and do one of the following: * A. hdc has the device pixel formats. * This is simple. We call the device driver to swap the buffer with * the hwnd id. * B. hdc has the generic pixel formats. * Call the opengl server to swap the buffer. The OpenGL server uses * the hwnd id to bitblt the buffer that is associated with the window. * * Note that in this implementation, we do not flush calls in other threads. * Applications are responsible for coordinating SwapBuffers in multiple * threads. * * History: * 02-Nov-95 -by- Drew Bliss [drewb] * Stripped down to driver-only kernel-mode form * Thu Jan 06 12:32:11 1994 -by- Hock San Lee [hockl] * Added some code and wrote the above comment. * 21-Nov-1993 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
BOOL NtGdiSwapBuffers(HDC hdc) { // Validate DC and surface. Info DC is not allowed.
DCOBJ dco(hdc); if (!dco.bValid() || !dco.bHasSurface()) { WARNING("GreSwapBuffers(): invalid hdc\n"); SAVE_ERROR_CODE(ERROR_INVALID_HANDLE); return(FALSE); }
// Early out -- nothing to do if memory DC.
if (dco.dctp() == DCTYPE_MEMORY) return(TRUE);
// Lock display.
DEVLOCKOBJ_WNDOBJ dlo(dco);
if (!dlo.bValidDevlock()) { if (!dco.bFullScreen()) { WARNING("GreSwapBuffers: could not lock device\n"); return(FALSE); } else return(TRUE); }
if (!dlo.bValidWndobj()) { WARNING("GreSwapBuffers: invalid wndobj\n"); SAVE_ERROR_CODE(ERROR_INVALID_HANDLE); return FALSE; }
if (dlo.pwo()->erclExclude().bEmpty()) return(TRUE);
// Pointer exclusion.
// Increment the surface uniqueness. This only needs to be done once
// per DEVLOCK.
DEVEXCLUDEOBJ dxo;
dxo.vExclude(dco.hdev(), &dlo.pwo()->rclClient, (ECLIPOBJ *) dlo.pwo()); INC_SURF_UNIQ(dco.pSurface());
// Dispatch driver formats.
PEWNDOBJ pwo; pwo = dlo.pwo();
PDEVOBJ pdo(dco.hdev());
SURFOBJ *pso = dco.pSurface()->pSurfobj();
#ifdef OPENGL_MM
if (pdo.bMetaDriver()) { // We need to change the meta-PDEV into a hardware specific PDEV
HDEV hdevDevice = hdevFindDeviceHdev( dco.hdev(), (RECTL)dco.erclWindow(), pwo);
if (hdevDevice) { // If the surface is pdev's primary surface, we will replace it with
// new device pdev's surface.
if (pdo.bPrimary(dco.pSurface())) { PDEVOBJ pdoDevice(hdevDevice);
pso = pdoDevice.pSurface()->pSurfobj(); }
// replace meta pdevobj with device specific hdev.
pdo.vInit(hdevDevice); } }
#endif // OPENGL_MM
if ( !PPFNVALID(pdo,SwapBuffers) || !((*PPFNDRV(pdo,SwapBuffers))(pso, (WNDOBJ *)pwo))) return(FALSE);
return(TRUE); }
|