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.
1075 lines
33 KiB
1075 lines
33 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: surfeng.cxx
|
|
*
|
|
* Internal surface routines
|
|
*
|
|
* Created: 13-May-1991 12:53:31
|
|
* Author: Patrick Haluptzok patrickh
|
|
*
|
|
* Copyright (c) 1991-1999 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
extern "C" BOOL bInitBMOBJ();
|
|
|
|
#define MAX_STOCKBITMAPS 4*1024
|
|
LONG gStockBitmapFree = MAX_STOCKBITMAPS;
|
|
|
|
#pragma alloc_text(INIT, bInitBMOBJ)
|
|
|
|
#if DBG_STOCKBITMAPS
|
|
#define STOCKWARNING DbgPrint
|
|
#define STOCKINFO DbgPrint
|
|
#else
|
|
#define STOCKWARNING
|
|
#define STOCKINFO
|
|
#endif
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreSetBitmapOwner
|
|
*
|
|
* Sets the bitmap owner.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
GreSetBitmapOwner(
|
|
HBITMAP hbm,
|
|
W32PID lPid
|
|
)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
SURFREF so((HSURF)hbm);
|
|
|
|
if (so.bValid())
|
|
{
|
|
if (!(so.ps->bDIBSection() && (lPid == OBJECT_OWNER_PUBLIC)))
|
|
{
|
|
if(HmgStockObj(hbm)) {
|
|
WARNING("GreSetBitmapOwner: Cannot set owner for the stock bitmap\n");
|
|
}
|
|
else
|
|
{
|
|
#if TRACE_SURFACE_ALLOCS
|
|
#if TRACE_SURFACE_USER_CHAIN_IN_UM
|
|
BOOL bOwned;
|
|
TRACED_SURFACE *pts = (TRACED_SURFACE *)so.ps;
|
|
|
|
if (pts->bEnabled())
|
|
{
|
|
PENTRY pentTmp = &gpentHmgr[(UINT) HmgIfromH(hbm)];
|
|
|
|
bOwned = ((OBJECTOWNER_PID(pentTmp->ObjectOwner) != OBJECT_OWNER_PUBLIC) &&
|
|
(OBJECTOWNER_PID(pentTmp->ObjectOwner) != OBJECT_OWNER_NONE));
|
|
|
|
if (bOwned && ((lPid == OBJECT_OWNER_PUBLIC) || (lPid == OBJECT_OWNER_NONE)))
|
|
{
|
|
pts->vProcessStackFromUM(TRUE);
|
|
ASSERTGDI(pentTmp->pUser == NULL, "Object becoming unowned, but user mem is still allocated.\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bOwned = TRUE;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
bRet = HmgSetOwner((HOBJ)hbm,lPid,SURF_TYPE);
|
|
|
|
#if TRACE_SURFACE_ALLOCS
|
|
#if TRACE_SURFACE_USER_CHAIN_IN_UM
|
|
if (!bRet && !bOwned)
|
|
{
|
|
pts->vProcessStackFromUM(TRUE);
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING ("GreSetBitmapOnwer - Setting a DIBSECTION to PUBLIC\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING1("GreSetBitmapOnwer - invalid surfobj\n");
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreMakeBitmapStock
|
|
*
|
|
* Makes the bitmap a stock object.
|
|
*
|
|
* Requirements:
|
|
* Bitmap is already not a stock Object.
|
|
* Bitmap is not a dibsection.
|
|
* Bitmap should not be selected into any DCs.
|
|
* Not more than MAX_STOCKBITMAPS gStockBitmaps.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HBITMAP
|
|
GreMakeBitmapStock(HBITMAP hbm)
|
|
{
|
|
HANDLE bRet = 0;
|
|
SURFREFAPI so((HSURF)hbm);
|
|
|
|
if (so.bValid())
|
|
{
|
|
if (!(so.ps->bDIBSection()))
|
|
{
|
|
if (HmgStockObj(hbm) || so.ps->cRef())
|
|
{
|
|
STOCKWARNING("GreMakeBitmapStock: cannot make bitmap (%p) stock\nReason:",hbm);
|
|
if (HmgStockObj(hbm))
|
|
STOCKWARNING(" it is already a stock bitmap\n");
|
|
else
|
|
STOCKWARNING(" it is selected into some DC\n");
|
|
}
|
|
else
|
|
{
|
|
bRet = (HANDLE)((ULONG_PTR)hbm | GDISTOCKOBJ);
|
|
if (InterlockedDecrement(&gStockBitmapFree) >= 0 &&
|
|
HmgLockAndModifyHandleType((HOBJ)bRet))
|
|
{
|
|
so.ps->vSetStockSurface();
|
|
so.ps->hsurf(bRet);
|
|
so.vSetPID(OBJECT_OWNER_PUBLIC);
|
|
}
|
|
else
|
|
{
|
|
InterlockedIncrement(&gStockBitmapFree);
|
|
STOCKWARNING ("GreMakeBitmapStock - HmgLockAndModifyHandleType failed\n");
|
|
bRet = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING ("GreMakeBitmapStock - Setting a DIBSECTION to Stock \n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING1("GreMakeBitmapStock - invalid surfobj\n");
|
|
}
|
|
|
|
return((HBITMAP)bRet);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreMakeBitmapNonStock
|
|
*
|
|
* Makes the bitmap a non stock object.
|
|
*
|
|
* Requirements:
|
|
* Bitmap is not default stock bitmap
|
|
* Bitmap is a stock bitmap
|
|
* Bitmap is not a dibsection
|
|
* Bitmap is not selected into any DC
|
|
* Some stock bitmaps should exist
|
|
* Bitmap must be public
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HBITMAP
|
|
GreMakeBitmapNonStock(HBITMAP hbm)
|
|
{
|
|
HANDLE bRet = 0;
|
|
SURFREFAPI so((HSURF)hbm);
|
|
|
|
ASSERTGDI(GreGetObjectOwner((HOBJ)hbm,SURF_TYPE) == OBJECT_OWNER_PUBLIC,"GreMakeBitmapNonStock() bitmap is not public\n");
|
|
ASSERTGDI(gStockBitmapFree != MAX_STOCKBITMAPS,"GreMakeBitmapNonStock() no stock bitmaps\n");
|
|
|
|
if (so.bValid())
|
|
{
|
|
if (!(so.ps->bDIBSection()))
|
|
{
|
|
if (hbm==STOCKOBJ_BITMAP || !HmgStockObj(hbm))
|
|
{
|
|
STOCKWARNING("GreMakeBitmapNonStock: Cannot make stock bitmap (%p) non Stock\nReason:",hbm);
|
|
if (hbm==STOCKOBJ_BITMAP)
|
|
STOCKWARNING(" it is the default stock bitmap\n");
|
|
else
|
|
STOCKWARNING(" it is not a stock bitmap\n");
|
|
}
|
|
else
|
|
{
|
|
bRet = (HANDLE)((ULONG_PTR)hbm & ~GDISTOCKOBJ);
|
|
|
|
if (so.ps->cRef())
|
|
{
|
|
so.ps->vSetUndoStockSurfaceDelayed();
|
|
STOCKWARNING("GreMakeBitmapNonStock: Delaying make stock bitmap (%p) non Stock\n",hbm);
|
|
}
|
|
else if(HmgLockAndModifyHandleType((HOBJ)bRet))
|
|
{
|
|
InterlockedIncrement(&gStockBitmapFree);
|
|
|
|
so.ps->vClearStockSurface();
|
|
so.ps->hsurf(bRet);
|
|
so.vSetPID(OBJECT_OWNER_CURRENT);
|
|
|
|
}
|
|
else
|
|
{
|
|
STOCKWARNING ("GreMakeBitmapNonStock - HmgLockAndModifyHandleType failed\n");
|
|
bRet = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING ("GreMakeBitmapNonStock - DIBSECTION to set as non stock\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING1("GreMakeBitmapNonStock - invalid surfobj\n");
|
|
}
|
|
|
|
return((HBITMAP)bRet);
|
|
}
|
|
/******************************Public*Routine******************************\
|
|
* bInitBMOBJ
|
|
*
|
|
* Initializes the default bitmap.
|
|
*
|
|
* History:
|
|
* 14-Apr-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
extern "C" BOOL bInitBMOBJ()
|
|
{
|
|
HBITMAP hbmTemp = GreCreateBitmap(1, 1, 1, 1, (LPBYTE) NULL);
|
|
|
|
if (hbmTemp == (HBITMAP) 0)
|
|
{
|
|
WARNING("Failed to create default bitmap\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
SURFREF so((HSURF)hbmTemp);
|
|
|
|
ASSERTGDI(so.bValid(), "ERROR it created but isn't lockable STOCKOBJ_BITMAP");
|
|
ASSERTGDI(so.ps->ppal() == ppalMono, "ERROR the default bitmap has no ppalMono");
|
|
|
|
so.vSetPID(OBJECT_OWNER_PUBLIC);
|
|
|
|
bSetStockObject(hbmTemp,PRIV_STOCK_BITMAP);
|
|
so.ps->hsurf((HANDLE)((ULONG_PTR)hbmTemp | GDISTOCKOBJ));
|
|
|
|
SURFACE::pdibDefault = so.ps;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL bDeleteSurface(HSURF)
|
|
*
|
|
* Delete the surface object
|
|
*
|
|
* History:
|
|
* Sun 14-Apr-1991 -by- Patrick Haluptzok [patrickh]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL bDeleteSurface(HSURF hsurf)
|
|
{
|
|
SURFREF so;
|
|
|
|
so.vAltCheckLockIgnoreStockBit(hsurf);
|
|
|
|
return(so.bDeleteSurface()); // bDeleteSurface() checks bValid()
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* hbmSelectBitmap
|
|
*
|
|
* Select the bitmap into a DC. Provides option to override the
|
|
* DirectDraw surface check.
|
|
*
|
|
* History:
|
|
* Wed 28-Aug-1991 -by- Patrick Haluptzok [patrickh]
|
|
* update it, make palette aware.
|
|
*
|
|
* Mon 13-May-1991 -by- Patrick Haluptzok [patrickh]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
HBITMAP hbmSelectBitmap(HDC hdc, HBITMAP hsurf, BOOL bDirectDrawOverride)
|
|
{
|
|
HSURF hsurfReturn = (HSURF) 0;
|
|
BOOL bDelete = FALSE;
|
|
|
|
//
|
|
// Grab multi-lock so noone can select or delete it.
|
|
//
|
|
|
|
MLOCKOBJ mlo;
|
|
|
|
//
|
|
// Lock bitmap
|
|
//
|
|
|
|
SURFREF SurfBoNew;
|
|
SurfBoNew.vMultiLock((HSURF) hsurf);
|
|
|
|
MDCOBJ dco(hdc);
|
|
|
|
if (dco.bValid() && SurfBoNew.bValid())
|
|
{
|
|
PSURFACE pSurfNew = SurfBoNew.ps;
|
|
|
|
ASSERTGDI(DIFFHANDLE(hsurf,STOCKOBJ_BITMAP) ||
|
|
(pSurfNew->cRef() == 0) , "ERROR STOCKOBJ_BITMAP cRef != 0");
|
|
|
|
PDEVOBJ po(dco.hdev());
|
|
PPALETTE ppalSrc;
|
|
|
|
PROCESS_UM_TRACE(pSurfNew, FALSE);
|
|
|
|
if ((dco.dctp() == DCTYPE_MEMORY) &&
|
|
((pSurfNew->cRef() == 0 || pSurfNew->bStockSurface()) || SAMEHANDLE(pSurfNew->hdc(),dco.hdc())) &&
|
|
(bIsCompatible(&ppalSrc, pSurfNew->ppal(), pSurfNew, dco.hdev())))
|
|
{
|
|
//
|
|
// Note: pSurfOld not safe outside of the MLOCKOBJ.
|
|
//
|
|
|
|
SURFACE *pSurfOld = dco.pSurfaceEff();
|
|
|
|
//
|
|
// Only DirectDraw itself may select DirectDraw surfaces
|
|
// into, or out of, DCs. This is because DirectDraw has
|
|
// to track the DCs to be able to mark them as 'bInFullScreen'
|
|
// when the corresponding DirectDraw surface is 'lost'.
|
|
//
|
|
|
|
if ((pSurfOld->bApiBitmap() && pSurfNew->bApiBitmap()) ||
|
|
(bDirectDrawOverride))
|
|
{
|
|
//
|
|
// If this DC is mirrored then turn the mirroring off
|
|
// And turn it on after selecting the bitmap to set the correct
|
|
// Window Org.
|
|
//
|
|
DWORD dwLayout = dco.pdc->dwLayout();
|
|
if (dwLayout & LAYOUT_ORIENTATIONMASK)
|
|
{
|
|
dco.pdc->dwSetLayout(-1 , 0);
|
|
}
|
|
if (pSurfNew->ppal() != ppalSrc)
|
|
{
|
|
pSurfNew->flags(pSurfNew->flags() | PALETTE_SELECT_SET);
|
|
pSurfNew->ppal(ppalSrc);
|
|
}
|
|
HSURF hsurfDelete = (HSURF)
|
|
(pSurfOld->bLazyDelete() ? pSurfOld->hGet() : NULL);
|
|
hsurfReturn = pSurfOld->hsurf();
|
|
|
|
if (DIFFHANDLE((HSURF) hsurf, hsurfReturn))
|
|
{
|
|
if (pSurfNew->bIsDefault())
|
|
{
|
|
dco.pdc->pSurface((SURFACE *) NULL);
|
|
}
|
|
else
|
|
{
|
|
dco.pdc->pSurface((SURFACE *) pSurfNew);
|
|
|
|
if (pSurfNew->bStockSurface())
|
|
dco.pdc->bStockBitmap(TRUE);
|
|
else
|
|
dco.pdc->bStockBitmap(FALSE);
|
|
}
|
|
|
|
dco.pdc->sizl(pSurfNew->sizl());
|
|
dco.pdc->ulDirtyAdd(DIRTY_BRUSHES);
|
|
|
|
//
|
|
// Lower the reference count on the old handle
|
|
//
|
|
|
|
if (!pSurfOld->bIsDefault())
|
|
{
|
|
pSurfOld->vDec_cRef();
|
|
if (pSurfOld->cRef() == 0)
|
|
{
|
|
//
|
|
// Remove reference to device palette if it has one.
|
|
//
|
|
|
|
if (pSurfOld->flags() & PALETTE_SELECT_SET)
|
|
pSurfOld->ppal(NULL);
|
|
|
|
pSurfOld->flags(pSurfOld->flags() & ~PALETTE_SELECT_SET);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Device Format Bitmaps hooked by the driver must always
|
|
// have devlock synchronization.
|
|
//
|
|
// Other device-dependent bitmaps must have devlock
|
|
// synchronization if they can be affected by dynamic mode
|
|
// changes, because they may have to be converted on-the-fly
|
|
// to DIBs.
|
|
//
|
|
|
|
dco.bSynchronizeAccess(
|
|
(pSurfNew->bUseDevlock()) ||
|
|
(pSurfNew->bDeviceDependentBitmap() && po.bDisplayPDEV()));
|
|
|
|
dco.bShareAccess(dco.bSynchronizeAccess() && pSurfNew->bShareAccess());
|
|
|
|
//
|
|
// Put the relevant DC information into the surface as long as it's not
|
|
// the default surface.
|
|
//
|
|
|
|
if (!pSurfNew->bIsDefault())
|
|
{
|
|
pSurfNew->vInc_cRef();
|
|
if (!pSurfNew->bStockSurface())
|
|
{
|
|
pSurfNew->hdc(dco.hdc());
|
|
pSurfNew->hdev(dco.hdev());
|
|
}
|
|
}
|
|
|
|
//
|
|
// set DIBSection flag in DC
|
|
//
|
|
|
|
dco.pdc->vDIBSection(pSurfNew->bDIBSection());
|
|
|
|
//
|
|
// set DIBColorSpace indentifier.
|
|
//
|
|
|
|
if (pSurfNew->bDIBSection())
|
|
{
|
|
dco.pdc->dwDIBColorSpace(pSurfNew->dwDIBColorSpace());
|
|
}
|
|
else
|
|
{
|
|
dco.pdc->dwDIBColorSpace(0);
|
|
}
|
|
|
|
// Unref the SurfBoNew as we dont use pSurfNew anymore. This
|
|
// will also make sure any mode change logic called code
|
|
// like pConvertDfbSurfaceToDib will not get
|
|
// tripped due to sharelocks held on the pSurfNew.
|
|
|
|
SurfBoNew.vUnreference();
|
|
|
|
mlo.vDisable();
|
|
|
|
dco.pdc->bSetDefaultRegion();
|
|
|
|
dco.pdc->vUpdate_VisRect(dco.pdc->prgnVis());
|
|
|
|
if (hsurfDelete)
|
|
{
|
|
//
|
|
// We need one shared lock for bDeleteSurface to succeed:
|
|
//
|
|
|
|
SURFREF so(hsurfDelete);
|
|
so.bDeleteSurface();
|
|
|
|
hsurfReturn = (HSURF)STOCKOBJ_BITMAP;
|
|
}
|
|
}
|
|
//
|
|
// If it was mirrored then turn back the mirroring on.
|
|
//
|
|
if (dwLayout & LAYOUT_ORIENTATIONMASK)
|
|
{
|
|
dco.pdc->dwSetLayout(-1 , dwLayout);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING("hbmSelectBitmap failed, unselectable surface\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING1("hbmSelectBitmap failed selection, bitmap doesn't fit into DC\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
if (dco.bValid())
|
|
{
|
|
WARNING1("hbmSelectBitmap given invalid bitmap\n");
|
|
}
|
|
else
|
|
{
|
|
WARNING1("hbmSelectBitmap given invalid DC\n");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return((HBITMAP) hsurfReturn);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreSelectBitmap
|
|
*
|
|
* Select the bitmap into a DC. User and the like will call this function.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HBITMAP GreSelectBitmap(HDC hdc, HBITMAP hsurf)
|
|
{
|
|
return(hbmSelectBitmap(hdc, hsurf, FALSE));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* hbmCreateClone
|
|
*
|
|
* Creates an engine managed clone of a bitmap.
|
|
*
|
|
* History:
|
|
* Tue 17-May-1994 -by- Patrick Haluptzok [patrickh]
|
|
* Synchronize the call if it's a DFB that needs synching.
|
|
*
|
|
* 19-Jun-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
HBITMAP hbmCreateClone(SURFACE *pSurfSrc, ULONG cx, ULONG cy)
|
|
{
|
|
|
|
ASSERTGDI(pSurfSrc != NULL, "ERROR hbmCreateClone invalid src");
|
|
|
|
ASSERTGDI((pSurfSrc->iType() == STYPE_BITMAP) ||
|
|
(pSurfSrc->iType() == STYPE_DEVBITMAP), "ERROR hbmCreateClone src type");
|
|
|
|
DEVBITMAPINFO dbmi;
|
|
|
|
dbmi.iFormat = pSurfSrc->iFormat();
|
|
|
|
if ((cx == 0) || (cy == 0))
|
|
{
|
|
dbmi.cxBitmap = pSurfSrc->sizl().cx;
|
|
dbmi.cyBitmap = pSurfSrc->sizl().cy;
|
|
}
|
|
else
|
|
{
|
|
ASSERTGDI(cx <= LONG_MAX, "hbmCreateClone: cx too large\n");
|
|
dbmi.cxBitmap = min(pSurfSrc->sizl().cx,(LONG)cx);
|
|
|
|
ASSERTGDI(cy <= LONG_MAX, "hbmCreateClone: cy too large\n");
|
|
dbmi.cyBitmap = min(pSurfSrc->sizl().cy,(LONG)cy);
|
|
}
|
|
|
|
dbmi.hpal = (HPALETTE) 0;
|
|
|
|
if (pSurfSrc->ppal() != NULL)
|
|
{
|
|
dbmi.hpal = (HPALETTE) pSurfSrc->ppal()->hGet();
|
|
}
|
|
|
|
dbmi.fl = BMF_TOPDOWN;
|
|
|
|
HBITMAP hbmReturn = (HBITMAP) 0;
|
|
|
|
SURFMEM SurfDimo;
|
|
|
|
if (SurfDimo.bCreateDIB(&dbmi, NULL))
|
|
{
|
|
POINTL ptlSrc;
|
|
ptlSrc.x = 0;
|
|
ptlSrc.y = 0;
|
|
|
|
RECTL rclDst;
|
|
rclDst.left = 0;
|
|
rclDst.right = dbmi.cxBitmap;
|
|
rclDst.top = 0;
|
|
rclDst.bottom = dbmi.cyBitmap;
|
|
|
|
HSEMAPHORE hsemDevLock = NULL;
|
|
PPDEV ppdev = NULL;
|
|
|
|
if (pSurfSrc->bUseDevlock())
|
|
{
|
|
PDEVOBJ po(pSurfSrc->hdev());
|
|
ASSERTGDI(po.bValid(), "PDEV invalid");
|
|
hsemDevLock = po.hsemDevLock();
|
|
ppdev = po.ppdev;
|
|
GreAcquireSemaphoreEx(hsemDevLock, SEMORDER_DEVLOCK, NULL);
|
|
GreEnterMonitoredSection(ppdev, WD_DEVLOCK);
|
|
}
|
|
|
|
if (EngCopyBits( SurfDimo.pSurfobj(), // Destination surfobj
|
|
pSurfSrc->pSurfobj(), // Source surfobj.
|
|
(CLIPOBJ *) NULL, // Clip object.
|
|
&xloIdent, // Palette translation object.
|
|
&rclDst, // Destination rectangle.
|
|
&ptlSrc ))
|
|
{
|
|
SurfDimo.vKeepIt();
|
|
hbmReturn = (HBITMAP) SurfDimo.ps->hsurf();
|
|
}
|
|
else
|
|
{
|
|
WARNING("ERROR hbmCreateClone failed EngBitBlt\n");
|
|
}
|
|
|
|
if (hsemDevLock)
|
|
{
|
|
GreExitMonitoredSection(ppdev, WD_DEVLOCK);
|
|
GreReleaseSemaphoreEx(hsemDevLock);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING("ERROR hbmCreateClone failed DIB allocation\n");
|
|
}
|
|
|
|
return(hbmReturn);
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* NtGdiGetDCforBitmap
|
|
*
|
|
* Get the DC that the bitmap is selected into
|
|
*
|
|
* History:
|
|
* 12-12-94 -by- Lingyun Wang[lingyunw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
HDC NtGdiGetDCforBitmap(HBITMAP hsurf)
|
|
{
|
|
HDC hdcReturn = 0;
|
|
SURFREF so((HSURF) hsurf);
|
|
|
|
if (so.bValid())
|
|
{
|
|
hdcReturn = so.ps->hdc();
|
|
}
|
|
|
|
return(hdcReturn);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* NtGdiColorSpaceforBitmap
|
|
*
|
|
* Get the color space data for this bitmap
|
|
*
|
|
* History:
|
|
* 06-06-97 -by- Hideyuki Nagase [hideyukn]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
ULONG_PTR NtGdiGetColorSpaceforBitmap(HBITMAP hsurf)
|
|
{
|
|
ULONG_PTR dwReturn = 0;
|
|
SURFREF so((HSURF) hsurf);
|
|
|
|
if (so.bValid() && so.ps->bDIBSection())
|
|
{
|
|
dwReturn = so.ps->dwDIBColorSpace();
|
|
}
|
|
|
|
return(dwReturn);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreMakeInfoDC()
|
|
*
|
|
* This routine is used to take a printer DC and temporarily make it a
|
|
* Metafile DC for spooled printing. This way it can be associated with
|
|
* an enhanced metafile. During this period, it should look and act just
|
|
* like an info DC.
|
|
*
|
|
* bSet determines if it should be set into the INFO DC state or restored
|
|
* to the Direct state.
|
|
*
|
|
* History:
|
|
* 04-Jan-1995 -by- Eric Kutter [erick]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL NtGdiMakeInfoDC(
|
|
HDC hdc,
|
|
BOOL bSet)
|
|
{
|
|
ASSERTGDI(LO_TYPE(hdc) == LO_ALTDC_TYPE,"GreMakeInfoDC - not alt type\n");
|
|
|
|
BOOL bRet = FALSE;
|
|
|
|
XDCOBJ dco( hdc );
|
|
|
|
if (dco.bValid())
|
|
{
|
|
bRet = dco.pdc->bMakeInfoDC(bSet);
|
|
dco.vUnlockFast();
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
/******************************Private*Routine*****************************\
|
|
* BOOL pConvertDfbSurfaceToDib
|
|
*
|
|
* Converts a compatible bitmap into an engine managed bitmap. Note that
|
|
* if the bitmap is currently selected into a DC, bConvertDfbDcToDib should
|
|
* be called.
|
|
*
|
|
* The devlock must be already be held.
|
|
*
|
|
* History:
|
|
* Wed 5-May-1994 -by- Tom Zakrajsek [tomzak]
|
|
* Wrote it (with lots of help from PatrickH and EricK).
|
|
\*************************************************************************/
|
|
|
|
SURFACE* pConvertDfbSurfaceToDib
|
|
(
|
|
HDEV hdev,
|
|
SURFACE *pSurfOld,
|
|
LONG ExpectedShareCount
|
|
)
|
|
{
|
|
BOOL b;
|
|
SURFACE *pSurfNew;
|
|
SURFACE *pSurfRet;
|
|
|
|
#if TEXTURE_DEMO
|
|
if (ghdevTextureParent)
|
|
{
|
|
return(NULL);
|
|
}
|
|
#endif
|
|
|
|
pSurfRet = NULL;
|
|
|
|
ASSERTGDI((pSurfOld != NULL),
|
|
"pConvertDfbSurfaceToDib: pSurf attached to the DC is NULL\n");
|
|
|
|
ASSERTGDI((pSurfOld->bRedirection() == FALSE),
|
|
"pConvertDfbSurfaceToDib: pSurf is a redirection surface");
|
|
|
|
//
|
|
// GDI surfaces wrapped around DirectDraw surfaces cannot be
|
|
// converted (DirectDraw wouldn't know about its new state).
|
|
//
|
|
// Similarly, we can't convert surfaces that are the primary
|
|
// screen!
|
|
//
|
|
|
|
if (pSurfOld->bDirectDraw() || pSurfOld->bPDEVSurface())
|
|
{
|
|
return(NULL);
|
|
}
|
|
|
|
//
|
|
// Create a DIB (dimoCvt) with the same height,width,
|
|
// and BPP as the DEVBITMAP attached to the DC and
|
|
// then replace the DEVBITMAP with the DIB
|
|
//
|
|
|
|
SURFMEM dimoCvt;
|
|
DEVBITMAPINFO dbmi;
|
|
ERECTL ercl(0, 0, pSurfOld->sizl().cx, pSurfOld->sizl().cy);
|
|
PDEVOBJ po(hdev);
|
|
|
|
//
|
|
// Figure out what format the engine should use by looking at the
|
|
// size of palette. This is a clone from CreateCompatibleBitmap().
|
|
//
|
|
|
|
dbmi.iFormat = pSurfOld->iFormat();
|
|
dbmi.cxBitmap = pSurfOld->sizl().cx;
|
|
dbmi.cyBitmap = pSurfOld->sizl().cy;
|
|
dbmi.hpal = 0;
|
|
dbmi.fl = BMF_TOPDOWN;
|
|
|
|
if (dimoCvt.bCreateDIB(&dbmi, NULL))
|
|
{
|
|
pSurfNew = dimoCvt.ps;
|
|
|
|
//
|
|
// Fill in other necessary fields
|
|
//
|
|
|
|
ASSERTGDI(pSurfOld->hdev() == hdev, "hdev's don't match");
|
|
|
|
pSurfNew->hdev(hdev);
|
|
|
|
//
|
|
// Copy the area as big as the bitmap
|
|
//
|
|
|
|
if ((*PPFNGET(po, CopyBits, pSurfOld->flags()))
|
|
(
|
|
dimoCvt.pSurfobj(), // destination surface
|
|
pSurfOld->pSurfobj(), // source surface
|
|
(CLIPOBJ *)NULL, // clip object
|
|
&xloIdent, // palette translation object
|
|
(RECTL *) &ercl, // destination rectangle
|
|
(POINTL *) &ercl // source origin
|
|
))
|
|
{
|
|
MLOCKOBJ mlo;
|
|
LONG SurfTargShareCount;
|
|
|
|
SurfTargShareCount = HmgQueryAltLock((HOBJ)pSurfOld->hsurf());
|
|
|
|
if (SurfTargShareCount == ExpectedShareCount)
|
|
{
|
|
BOOL bStockSurface = pSurfOld->bStockSurface();
|
|
BOOL bUndoStockSurfaceDelayed = pSurfOld->bUndoStockSurfaceDelayed();
|
|
|
|
if (HmgSwapLockedHandleContents((HOBJ)pSurfOld->hsurf(),
|
|
SurfTargShareCount,
|
|
(HOBJ)pSurfNew->hsurf(),
|
|
HmgQueryAltLock((HOBJ)pSurfNew->hsurf()),
|
|
SURF_TYPE))
|
|
{
|
|
//
|
|
// Swap necessary fields between the bitmaps
|
|
// hsurf, hdc, cRef, hpalHint, sizlDim, ppal, SurfFlags
|
|
//
|
|
|
|
HSURF hsurfTemp = pSurfOld->hsurf();
|
|
pSurfOld->hsurf(pSurfNew->hsurf());
|
|
pSurfNew->hsurf(hsurfTemp);
|
|
|
|
HDC hdcTemp = pSurfOld->hdc();
|
|
pSurfOld->hdc(pSurfNew->hdc());
|
|
pSurfNew->hdc(hdcTemp);
|
|
|
|
ULONG cRefTemp = pSurfOld->cRef();
|
|
pSurfOld->cRef(pSurfNew->cRef());
|
|
pSurfNew->cRef(cRefTemp);
|
|
|
|
HPALETTE hpalTemp = pSurfOld->hpalHint();
|
|
pSurfOld->hpalHint(pSurfNew->hpalHint());
|
|
pSurfNew->hpalHint(hpalTemp);
|
|
|
|
SIZEL sizlTemp = pSurfOld->sizlDim();
|
|
pSurfOld->sizlDim(pSurfNew->sizlDim());
|
|
pSurfNew->sizlDim(sizlTemp);
|
|
|
|
PPALETTE ppalTemp = pSurfOld->ppal();
|
|
pSurfOld->ppal(pSurfNew->ppal());
|
|
pSurfNew->ppal(ppalTemp);
|
|
|
|
FLONG flagsTemp = pSurfOld->flags();
|
|
pSurfOld->flags((pSurfOld->flags() & ~SURF_FLAGS) | (pSurfNew->flags() & SURF_FLAGS));
|
|
pSurfNew->flags((pSurfNew->flags() & ~SURF_FLAGS) | (flagsTemp & SURF_FLAGS));
|
|
|
|
//
|
|
// Some flags have to stay with the original surface,
|
|
// so swap them yet again to go back to the original:
|
|
//
|
|
|
|
#define KEEP_FLAGS ENG_CREATE_DEVICE_SURFACE
|
|
|
|
flagsTemp = pSurfOld->flags();
|
|
pSurfOld->flags((pSurfOld->flags() & ~KEEP_FLAGS) | (pSurfNew->flags() & KEEP_FLAGS));
|
|
pSurfNew->flags((pSurfNew->flags() & ~KEEP_FLAGS) | (flagsTemp & KEEP_FLAGS));
|
|
|
|
#if TRACE_SURFACE_ALLOCS
|
|
// We don't care about copying the current allocation trace
|
|
// to the old object.
|
|
if (TRACED_SURFACE::bEnabled())
|
|
{
|
|
TRACED_SURFACE *ptsOld = (TRACED_SURFACE *)pSurfOld;
|
|
TRACED_SURFACE *ptsNew = (TRACED_SURFACE *)pSurfNew;
|
|
|
|
ptsNew->Trace = ptsOld->Trace;
|
|
|
|
#if TRACE_SURFACE_USER_CHAIN_IN_UM
|
|
// pUser values were swapped in HmgSwapLockedHandleContents.
|
|
// Swap them back since object owners weren't swapped.
|
|
// It doesn't matter if TRACED_SURFACE::bUserChainInUM
|
|
// is enable, since pUser is unused if not enabled.
|
|
PENTRY pEntryOld = &gpentHmgr[HmgIfromH(pSurfOld->hGet())];
|
|
PENTRY pEntryNew = &gpentHmgr[HmgIfromH(pSurfNew->hGet())];
|
|
PVOID pUserTemp = pEntryOld->pUser;
|
|
pEntryOld->pUser = pEntryNew->pUser;
|
|
pEntryNew->pUser = pUserTemp;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
if (bStockSurface)
|
|
{
|
|
DC* pdc;
|
|
HOBJ hObj = 0;
|
|
|
|
pSurfOld->vClearStockSurface();
|
|
pSurfNew->vSetStockSurface();
|
|
|
|
STOCKINFO("Transfer Stock Bitmap State from %p to %p\n", pSurfOld, pSurfNew);
|
|
|
|
if (bUndoStockSurfaceDelayed)
|
|
{
|
|
STOCKINFO("Transfer Delayed Undo Stock Bitmap State from %p to %p\n", pSurfOld, pSurfNew);
|
|
pSurfNew->vSetUndoStockSurfaceDelayed();
|
|
}
|
|
|
|
// As its a Stock surface it may be selected into many DCs. Run thru all of them
|
|
// and replace with new .
|
|
|
|
while (pdc = (DC*) HmgSafeNextObjt(hObj, DC_TYPE))
|
|
{
|
|
hObj = (HOBJ)pdc->hGet();
|
|
|
|
if ((pdc->pSurface() == pSurfOld))
|
|
{
|
|
STOCKINFO("Updating DC (%p) which refs old stockbmp %p with new stockbmp %p\n", pdc, pSurfOld, pSurfNew);
|
|
pdc->flbrushAdd(DIRTY_BRUSHES);
|
|
pdc->pSurface(pSurfNew);
|
|
|
|
MDCOBJA dco((HDC)hObj);
|
|
LONG lNumLeft = dco.lSaveDepth();
|
|
HDC hdcSave = dco.hdcSave();
|
|
|
|
while (lNumLeft > 1)
|
|
{
|
|
MDCOBJA dcoTmp(hdcSave);
|
|
if (dcoTmp.pSurface() == pSurfOld)
|
|
{
|
|
dcoTmp.pdc->pSurface(pSurfNew);
|
|
}
|
|
lNumLeft = dcoTmp.lSaveDepth();
|
|
hdcSave = dcoTmp.hdcSave();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Destroy the DFB
|
|
//
|
|
// If the deletion fails, we're toast, since a bad,
|
|
// stale surface will have been left in the handle
|
|
// table. So on the next mode-change, when we walk
|
|
// the table looking at all surfaces belonging to
|
|
// this HDEV, we'd crash.
|
|
//
|
|
|
|
mlo.vDisable();
|
|
b = pSurfOld->bDeleteSurface();
|
|
ASSERTGDI(b, "A bad surface is left in handle table");
|
|
|
|
//
|
|
// Keep a reference to the new surface.
|
|
//
|
|
|
|
dimoCvt.vKeepIt();
|
|
dimoCvt.ps = NULL;
|
|
|
|
pSurfRet = pSurfNew;
|
|
}
|
|
else
|
|
{
|
|
WARNING("pConvertDfbSurfaceToDib failed to swap bitmap handles\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING("pConvertDfbSurfaceToDib someone else is holding a lock\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING("pConvertDfbSurfaceToDib failed copying DFB to DIB\n");
|
|
}
|
|
}
|
|
|
|
return(pSurfRet);
|
|
}
|
|
|
|
/******************************Private*Routine*****************************\
|
|
* BOOL bConvertDfbDcToDib
|
|
*
|
|
* Converts a compatible bitmap that is currently selected into a DC
|
|
* into an engine managed bitmap.
|
|
*
|
|
* The Devlock must already be held. Some sort of lock must also be held
|
|
* to prevent SaveDC/RestoreDC operations from occuring -- either via an
|
|
* exclusive DC lock or some other lock.
|
|
*
|
|
* History:
|
|
* Wed 5-May-1994 -by- Tom Zakrajsek [tomzak]
|
|
* Wrote it (with lot's of help from PatrickH and EricK).
|
|
\*************************************************************************/
|
|
|
|
BOOL bConvertDfbDcToDib
|
|
(
|
|
XDCOBJ * pdco
|
|
)
|
|
{
|
|
SURFACE *pSurfOld;
|
|
SURFACE *pSurfNew;
|
|
|
|
ASSERTDEVLOCK(pdco->pdc);
|
|
|
|
pSurfOld = pdco->pSurface();
|
|
pSurfNew = pConvertDfbSurfaceToDib(pdco->hdev(),
|
|
pSurfOld,
|
|
pSurfOld->cRef());
|
|
|
|
if (pSurfNew)
|
|
{
|
|
//
|
|
// Make sure that the surface pointers in any EBRUSHOBJ's get
|
|
// updated, by ensuring that vInitBrush() gets called the next
|
|
// time any brush is used in this DC.
|
|
//
|
|
|
|
pdco->pdc->flbrushAdd(DIRTY_BRUSHES);
|
|
|
|
//
|
|
// Replace the pSurf reference in the DCLEVEL
|
|
//
|
|
|
|
pdco->pdc->pSurface(pSurfNew);
|
|
|
|
//
|
|
// Walk the saved DC chain
|
|
//
|
|
|
|
LONG lNumLeft = pdco->lSaveDepth();
|
|
HDC hdcSave = pdco->hdcSave();
|
|
|
|
while (lNumLeft > 1)
|
|
{
|
|
MDCOBJA dcoTmp(hdcSave);
|
|
|
|
//
|
|
// Replace all references to pSurfOld with references to pSurfNew
|
|
//
|
|
|
|
if (dcoTmp.pSurface() == pSurfOld)
|
|
{
|
|
dcoTmp.pdc->pSurface(pSurfNew);
|
|
}
|
|
|
|
lNumLeft = dcoTmp.lSaveDepth();
|
|
hdcSave = dcoTmp.hdcSave();
|
|
}
|
|
}
|
|
|
|
return(pSurfNew != NULL);
|
|
}
|