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