- Introduce DC_vPrepareDCsForBlit and DC_vFinishBlit and use them in NtGdiAlphaBlend
  - Get rid of now unnecessary call for MouseSafetyOnDraw{Start,End} in IntEngAlphaBlend
  - Yet Another Rewrite of GDIOBJ_LockMultipleObjs :-/ and use it in NtGdiAlphaBlend

svn path=/branches/reactos-yarotows/; revision=46902
This commit is contained in:
Jérôme Gardou 2010-04-17 14:20:48 +00:00
parent 4ec4675b9e
commit 0cdfd4399d
6 changed files with 100 additions and 76 deletions

View file

@ -1,4 +1,4 @@
/*
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: GDI alpha blending functions
@ -71,7 +71,7 @@ EngAlphaBlend(IN SURFOBJ *psoDest,
InputRect = *SourceRect;
if ( (InputRect.top < 0) || (InputRect.bottom < 0) ||
(InputRect.left < 0) || (InputRect.right < 0) ||
InputRect.right > psoSource->sizlBitmap.cx ||
InputRect.right > psoSource->sizlBitmap.cx ||
InputRect.bottom > psoSource->sizlBitmap.cy )
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
@ -306,13 +306,9 @@ IntEngAlphaBlend(IN SURFOBJ *psoDest,
}
SURFACE_LockBitmapBits(psurfDest);
MouseSafetyOnDrawStart(psoDest, DestRect->left, DestRect->top,
DestRect->right, DestRect->bottom);
if (psoSource != psoDest)
SURFACE_LockBitmapBits(psurfSource);
MouseSafetyOnDrawStart(psoSource, SourceRect->left, SourceRect->top,
SourceRect->right, SourceRect->bottom);
/* Call the driver's DrvAlphaBlend if available */
if (psurfDest->flHooks & HOOK_ALPHABLEND)
@ -328,10 +324,8 @@ IntEngAlphaBlend(IN SURFOBJ *psoDest,
DestRect, SourceRect, BlendObj);
}
MouseSafetyOnDrawEnd(psoSource);
if (psoSource != psoDest)
SURFACE_UnlockBitmapBits(psurfSource);
MouseSafetyOnDrawEnd(psoDest);
SURFACE_UnlockBitmapBits(psurfDest);
return ret;

View file

@ -220,6 +220,8 @@ VOID FASTCALL DC_vUpdateFillBrush(PDC pdc);
VOID FASTCALL DC_vUpdateLineBrush(PDC pdc);
VOID FASTCALL DC_vUpdateTextBrush(PDC pdc);
VOID FASTCALL DC_vUpdateBackgroundBrush(PDC pdc);
VOID FASTCALL DC_vFinishBlit(PDC pdc1, PDC pdc2);
VOID FASTCALL DC_vPrepareDCsForBlit(PDC pdc1, RECT rc1, PDC pdc2, RECT rc2);
VOID NTAPI DC_vRestoreDC(IN PDC pdc, INT iSaveLevel);

View file

@ -34,7 +34,6 @@ extern PGDI_HANDLE_TABLE GdiHandleTable;
typedef PVOID PGDIOBJ;
typedef BOOL (INTERNAL_CALL *GDICLEANUPPROC)(PVOID ObjectBody);
typedef VOID (INTERNAL_CALL *GDILOCKOBJPROC)(PVOID ObjectBody);
/* Every GDI Object must have this standard type of header.
* It's for thread locking. */
@ -72,7 +71,7 @@ VOID INTERNAL_CALL GDIOBJ_FreeObj (POBJ pObj, UCHAR ObjectType);
BOOL INTERNAL_CALL GDIOBJ_FreeObjByHandle (HGDIOBJ hObj, DWORD ObjectType);
PGDIOBJ INTERNAL_CALL GDIOBJ_LockObj (HGDIOBJ hObj, DWORD ObjectType);
PGDIOBJ INTERNAL_CALL GDIOBJ_ShareLockObj (HGDIOBJ hObj, DWORD ObjectType);
VOID INTERNAL_CALL GDIOBJ_LockMultipleObjs(ULONG ulCount, IN HGDIOBJ* ahObj, OUT PGDIOBJ* apObj);
VOID INTERNAL_CALL GDIOBJ_LockMultipleObjs(ULONG ulCount, IN HGDIOBJ* ahObj, OUT PGDIOBJ* apObj);
PVOID INTERNAL_CALL GDI_MapHandleTable(PSECTION_OBJECT SectionObject, PEPROCESS Process);

View file

@ -42,6 +42,8 @@ NtGdiAlphaBlend(
{
PDC DCDest;
PDC DCSrc;
HDC ahDC[2];
PGDIOBJ apObj[2];
SURFACE *BitmapDest, *BitmapSrc;
RECTL DestRect, SourceRect;
BOOL bResult;
@ -55,43 +57,29 @@ NtGdiAlphaBlend(
return FALSE;
}
DCDest = DC_LockDc(hDCDest);
if (NULL == DCDest)
DPRINT("Locking DCs\n");
ahDC[0] = hDCDest;
ahDC[1] = hDCSrc ;
GDIOBJ_LockMultipleObjs(2, ahDC, apObj);
DCDest = apObj[0];
DCSrc = apObj[1];
if ((NULL == DCDest) || (NULL == DCSrc))
{
DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCDest);
DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
SetLastWin32Error(ERROR_INVALID_HANDLE);
if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
if(DCDest) GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
return FALSE;
}
if (DCDest->dctype == DC_TYPE_INFO)
if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO)
{
DC_UnlockDc(DCDest);
GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
/* Yes, Windows really returns TRUE in this case */
return TRUE;
}
if (hDCSrc != hDCDest)
{
DCSrc = DC_LockDc(hDCSrc);
if (NULL == DCSrc)
{
DC_UnlockDc(DCDest);
DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCSrc);
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
if (DCSrc->dctype == DC_TYPE_INFO)
{
DC_UnlockDc(DCSrc);
DC_UnlockDc(DCDest);
/* Yes, Windows really returns TRUE in this case */
return TRUE;
}
}
else
{
DCSrc = DCDest;
bResult = TRUE;
goto leave;
}
DestRect.left = XOriginDest;
@ -121,35 +109,35 @@ NtGdiAlphaBlend(
!SourceRect.right ||
!SourceRect.bottom)
{
if (hDCSrc != hDCDest)
DC_UnlockDc(DCSrc);
DC_UnlockDc(DCDest);
GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
return TRUE;
}
/* Prepare DCs for blit */
DPRINT("Preparing DCs for blit\n");
DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
/* Determine surfaces to be used in the bitblt */
BitmapDest = DCDest->dclevel.pSurface;
if (!BitmapDest)
{
if (hDCSrc != hDCDest)
DC_UnlockDc(DCSrc);
DC_UnlockDc(DCDest);
return FALSE;
bResult = FALSE ;
goto leave ;
}
BitmapSrc = DCSrc->dclevel.pSurface;
if (!BitmapSrc)
{
if (hDCSrc != hDCDest)
DC_UnlockDc(DCSrc);
DC_UnlockDc(DCDest);
return FALSE;
bResult = FALSE;
goto leave;
}
/* Create the XLATEOBJ. */
EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
/* Perform the alpha blend operation */
DPRINT("Performing the alpha Blend\n");
bResult = IntEngAlphaBlend(&BitmapDest->SurfObj,
&BitmapSrc->SurfObj,
DCDest->rosdc.CombinedClip,
@ -159,9 +147,11 @@ NtGdiAlphaBlend(
&BlendObj);
EXLATEOBJ_vCleanup(&exlo);
DC_UnlockDc(DCDest);
if (hDCSrc != hDCDest)
DC_UnlockDc(DCSrc);
leave :
DPRINT("Finishing blit\n");
DC_vFinishBlit(DCDest, DCSrc);
GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
return bResult;
}
@ -833,8 +823,8 @@ GreStretchBltMask(
(BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc ||
BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc))
{
DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n",
BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy,
DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n",
BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy,
WidthSrc, HeightSrc);
goto failed;
}

View file

@ -451,6 +451,49 @@ leave:
return ret;
}
/* Prepare a blit for up to 2 DCs */
/* rc1 and rc2 are the rectangles where we want to draw or
* from where we take pixels. */
VOID
FASTCALL
DC_vPrepareDCsForBlit(PDC pdc1,
RECT rc1,
PDC pdc2,
RECT rc2)
{
if(pdc1->dctype == DCTYPE_DIRECT)
{
EngAcquireSemaphore(pdc1->ppdev->hsemDevLock);
MouseSafetyOnDrawStart(&pdc1->dclevel.pSurface->SurfObj, rc1.left, rc1.top, rc1.right, rc1.bottom) ;
}
if(pdc2 && pdc2->dctype == DCTYPE_DIRECT)
{
EngAcquireSemaphore(pdc2->ppdev->hsemDevLock);
MouseSafetyOnDrawStart(&pdc2->dclevel.pSurface->SurfObj, rc2.left, rc2.top, rc2.right, rc2.bottom) ;
}
}
/* Finishes a blit for one or two DCs */
VOID
FASTCALL
DC_vFinishBlit(PDC pdc1, PDC pdc2)
{
if(pdc1->dctype == DCTYPE_DIRECT)
{
MouseSafetyOnDrawEnd(&pdc1->dclevel.pSurface->SurfObj);
EngReleaseSemaphore(pdc1->ppdev->hsemDevLock);
}
if(pdc2)
{
if(pdc2->dctype == DCTYPE_DIRECT)
{
MouseSafetyOnDrawEnd(&pdc2->dclevel.pSurface->SurfObj);
EngReleaseSemaphore(pdc2->ppdev->hsemDevLock);
}
}
}
HDC
NTAPI
GreOpenDCW(

View file

@ -1625,39 +1625,35 @@ GDI_MapHandleTable(PSECTION_OBJECT SectionObject, PEPROCESS Process)
return MappedView;
}
/* Locks up to 3 objects at a time */
/* Locks 2 or 3 objects at a time */
VOID
INTERNAL_CALL
GDIOBJ_LockMultipleObjs(ULONG ulCount,
IN HGDIOBJ* ahObj,
OUT PGDIOBJ* apObj)
{
UINT iFirst = 0, iSecond = 0, iThird = 0;
UINT i ;
UINT auiIndices[3] = {0,1,2};
UINT i, tmp ;
BOOL bUnsorted = TRUE;
/* First is greatest */
for(i=1; i<ulCount; i++)
while(bUnsorted)
{
if((ULONG_PTR)ahObj[i] >= (ULONG_PTR)ahObj[iFirst])
bUnsorted = FALSE;
for(i=1; i<ulCount; i++)
{
iSecond = iFirst ;
iFirst = i;
continue ;
if((ULONG_PTR)ahObj[auiIndices[i-1]] < (ULONG_PTR)ahObj[auiIndices[i]])
{
tmp = auiIndices[i-1];
auiIndices[i-1] = auiIndices[i];
auiIndices[i] = tmp;
bUnsorted = TRUE;
}
}
if((ULONG_PTR)ahObj[i] >= (ULONG_PTR)ahObj[iSecond])
{
iSecond = i;
continue;
}
iThird = i;
}
/* We consider that at least two handles were passed */
apObj[iFirst] = GDIOBJ_LockObj(ahObj[iFirst], GDI_OBJECT_TYPE_DONTCARE);
apObj[iSecond] = GDIOBJ_LockObj(ahObj[iSecond], GDI_OBJECT_TYPE_DONTCARE);
if(ulCount == 3)
apObj[iThird] = GDIOBJ_LockObj(ahObj[iThird], GDI_OBJECT_TYPE_DONTCARE);
for(i=0;i<ulCount;i++)
apObj[auiIndices[i]] = GDIOBJ_LockObj(ahObj[auiIndices[i]], GDI_OBJECT_TYPE_DONTCARE);
}