Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

462 lines
13 KiB

/******************************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);
}