* PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
*/
-#include <w32k.h>
+#include <win32k.h>
#include <bugcodes.h>
#define NDEBUG
/** Internal functions ********************************************************/
+INIT_FUNCTION
NTSTATUS
+NTAPI
InitDcImpl()
{
psurfDefaultBitmap = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]);
DC_AllocDcWithHandle()
{
PDC pdc;
- pdc = (PDC)GDIOBJ_AllocObjWithHandle(GDILoObjType_LO_DC_TYPE);
+
+ pdc = (PDC)GDIOBJ_AllocateObject(GDIObjType_DC_TYPE,
+ sizeof(DC),
+ BASEFLAG_LOOKASIDE);
+ if (!pdc)
+ {
+ DPRINT1("Could not allocate a DC.\n");
+ return NULL;
+ }
+
+ if (!GDIOBJ_hInsertObject(&pdc->BaseObject, GDI_OBJ_HMGR_POWNED))
+ {
+ DPRINT1("Could not insert DC into handle table.\n");
+ GDIOBJ_vFreeObject(&pdc->BaseObject);
+ return NULL;
+ }
pdc->pdcattr = &pdc->dcattr;
void
DC_InitHack(PDC pdc)
{
- HRGN hVisRgn;
-
TextIntRealizeFont(pdc->pdcattr->hlfntNew,NULL);
pdc->pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0);
ASSERT(pdc->dclevel.ppal);
/* Select regions */
- // FIXME: too complicated, broken error handling
pdc->rosdc.hClipRgn = NULL;
pdc->rosdc.hGCClipRgn = NULL;
- hVisRgn = NtGdiCreateRectRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
- ASSERT(hVisRgn);
- GdiSelectVisRgn(pdc->BaseObject.hHmgr, hVisRgn);
- GreDeleteObject(hVisRgn);
- ASSERT(pdc->prgnVis);
- pdc->rosdc.bitsPerPixel = pdc->ppdev->gdiinfo.cBitsPixel *
- pdc->ppdev->gdiinfo.cPlanes;
}
VOID
DCTYPE dctype,
PPDEVOBJ ppdev)
{
- /* Lock ppdev */
- EngAcquireSemaphoreShared(ppdev->hsemDevLock);
-
/* Setup some basic fields */
pdc->dctype = dctype;
pdc->ppdev = ppdev;
pdc->dcattr.ptlViewportOrg.y = 0;
pdc->dcattr.szlViewportExt.cx = 1;
pdc->dcattr.szlViewportExt.cy = 1;
- pdc->dcattr.szlVirtualDevicePixel.cx = 0;
- pdc->dcattr.szlVirtualDevicePixel.cy = 0;
- pdc->dcattr.szlVirtualDeviceMm.cx = 0;
- pdc->dcattr.szlVirtualDeviceMm.cy = 0;
+ pdc->dcattr.szlVirtualDevicePixel.cx = ppdev->gdiinfo.ulHorzRes;
+ pdc->dcattr.szlVirtualDevicePixel.cy = ppdev->gdiinfo.ulVertRes;
+ pdc->dcattr.szlVirtualDeviceMm.cx = ppdev->gdiinfo.ulHorzSize;
+ pdc->dcattr.szlVirtualDeviceMm.cy = ppdev->gdiinfo.ulVertSize;
pdc->dcattr.szlVirtualDeviceSize.cx = 0;
pdc->dcattr.szlVirtualDeviceSize.cy = 0;
/* Setup regions */
pdc->prgnAPI = NULL;
- pdc->prgnVis = NULL; // FIXME
- pdc->prgnRao = NULL;
+ pdc->prgnRao = NULL;
+ /* Allocate a Vis region */
+ pdc->prgnVis = IntSysCreateRectpRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
+ ASSERT(pdc->prgnVis);
/* Setup palette */
pdc->dclevel.hpal = StockObjects[DEFAULT_PALETTE];
EBRUSHOBJ_vCleanup(&pdc->eboBackground);
/* Free regions */
- if (pdc->rosdc.hClipRgn)
+ if (pdc->rosdc.hClipRgn && GreIsHandleValid(pdc->rosdc.hClipRgn))
GreDeleteObject(pdc->rosdc.hClipRgn);
if (pdc->prgnVis)
- REGION_FreeRgnByHandle(((PROSRGNDATA)pdc->prgnVis)->BaseObject.hHmgr);
-ASSERT(pdc->rosdc.hGCClipRgn);
- if (pdc->rosdc.hGCClipRgn)
+ {
+ REGION_Delete(pdc->prgnVis);
+ }
+ if (pdc->rosdc.hGCClipRgn && GreIsHandleValid(pdc->rosdc.hGCClipRgn))
+ {
GreDeleteObject(pdc->rosdc.hGCClipRgn);
+ }
if (NULL != pdc->rosdc.CombinedClip)
IntEngDeleteClipRegion(pdc->rosdc.CombinedClip);
PATH_Delete(pdc->dclevel.hPath);
+ if(pdc->dclevel.pSurface)
+ SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface);
+
+ PDEVOBJ_vRelease(pdc->ppdev) ;
+
return TRUE;
}
-BOOL
-FASTCALL
-DC_SetOwnership(HDC hDC, PEPROCESS Owner)
+VOID
+NTAPI
+DC_vSetOwner(PDC pdc, ULONG ulOwner)
{
- INT Index;
- PGDI_TABLE_ENTRY Entry;
- PDC pDC;
- /* FIXME: This function has broken error handling */
+ if (pdc->rosdc.hClipRgn)
+ {
+ IntGdiSetRegionOwner(pdc->rosdc.hClipRgn, ulOwner);
+ }
- if (!GDIOBJ_SetOwnership(hDC, Owner))
+ if (pdc->rosdc.hGCClipRgn)
{
- DPRINT1("GDIOBJ_SetOwnership failed\n");
- return FALSE;
+ IntGdiSetRegionOwner(pdc->rosdc.hGCClipRgn, ulOwner);
}
- pDC = DC_LockDc(hDC);
- if (!pDC)
+ if (pdc->dclevel.hPath)
{
- DPRINT1("Could not lock DC\n");
+ GreSetObjectOwner(pdc->dclevel.hPath, ulOwner);
+ }
+
+ IntGdiSetBrushOwner(pdc->dclevel.pbrFill, ulOwner);
+ IntGdiSetBrushOwner(pdc->dclevel.pbrLine, ulOwner);
+
+ /* Allocate or free DC attribute */
+ if (ulOwner == GDI_OBJ_HMGR_PUBLIC || ulOwner == GDI_OBJ_HMGR_NONE)
+ {
+ if (pdc->pdcattr != &pdc->dcattr)
+ DC_vFreeDcAttr(pdc);
+ }
+ else if (ulOwner == GDI_OBJ_HMGR_POWNED)
+ {
+ if (pdc->pdcattr == &pdc->dcattr)
+ DC_bAllocDcAttr(pdc);
+ }
+
+ /* Set the DC's ownership */
+ GDIOBJ_vSetObjectOwner(&pdc->BaseObject, ulOwner);
+}
+
+BOOL
+NTAPI
+GreSetDCOwner(HDC hdc, ULONG ulOwner)
+{
+ PDC pdc;
+
+ pdc = DC_LockDc(hdc);
+ if (!pdc)
+ {
+ DPRINT1("GreSetDCOwner: Could not lock DC\n");
return FALSE;
}
- /*
- System Regions:
- These regions do not use attribute sections and when allocated, use
- gdiobj level functions.
- */
- if (pDC->rosdc.hClipRgn)
- { // FIXME! HAX!!!
- Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hClipRgn);
- Entry = &GdiHandleTable->Entries[Index];
- if (Entry->UserData) FreeObjectAttr(Entry->UserData);
- Entry->UserData = NULL;
- //
- if (!GDIOBJ_SetOwnership(pDC->rosdc.hClipRgn, Owner)) return FALSE;
+ /* Call the internal DC function */
+ DC_vSetOwner(pdc, ulOwner);
+
+ DC_UnlockDc(pdc);
+ return TRUE;
+}
+
+int FASTCALL
+CLIPPING_UpdateGCRegion(DC* Dc);
+
+static
+void
+DC_vUpdateDC(PDC pdc)
+{
+ HRGN hVisRgn ;
+ PPDEVOBJ ppdev = pdc->ppdev ;
+
+ pdc->dhpdev = ppdev->dhpdev;
+
+ SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface);
+ pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev);
+
+ PDEVOBJ_sizl(pdc->ppdev, &pdc->dclevel.sizl);
+ hVisRgn = NtGdiCreateRectRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
+ ASSERT(hVisRgn);
+ GdiSelectVisRgn(pdc->BaseObject.hHmgr, hVisRgn);
+ GreDeleteObject(hVisRgn);
+
+ pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps;
+ pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2;
+
+ /* Mark EBRUSHOBJs as dirty */
+ pdc->pdcattr->ulDirty_ |= DIRTY_DEFAULT ;
+}
+
+/* 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)
+{
+ PDC pdcFirst, pdcSecond;
+ PRECT prcFirst, prcSecond;
+
+ /* Update brushes */
+ if (pdc1->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(pdc1);
+ if (pdc1->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+ DC_vUpdateLineBrush(pdc1);
+ if(pdc1->pdcattr->ulDirty_ & DIRTY_TEXT)
+ DC_vUpdateTextBrush(pdc1);
+
+ /* Lock them in good order */
+ if(pdc2)
+ {
+ if((ULONG_PTR)pdc1->ppdev->hsemDevLock >= (ULONG_PTR)pdc2->ppdev->hsemDevLock)
+ {
+ pdcFirst = pdc1;
+ prcFirst = &rc1;
+ pdcSecond = pdc2;
+ prcSecond = &rc2;
}
- if (pDC->prgnVis)
- { // FIXME! HAX!!!
- Index = GDI_HANDLE_GET_INDEX(((PROSRGNDATA)pDC->prgnVis)->BaseObject.hHmgr);
- Entry = &GdiHandleTable->Entries[Index];
- if (Entry->UserData) FreeObjectAttr(Entry->UserData);
- Entry->UserData = NULL;
- //
- if (!GDIOBJ_SetOwnership(((PROSRGNDATA)pDC->prgnVis)->BaseObject.hHmgr, Owner)) return FALSE;
+ else
+ {
+ pdcFirst = pdc2;
+ prcFirst = &rc2;
+ pdcSecond = pdc1;
+ prcSecond = &rc1;
}
- if (pDC->rosdc.hGCClipRgn)
- { // FIXME! HAX!!!
- Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hGCClipRgn);
- Entry = &GdiHandleTable->Entries[Index];
- if (Entry->UserData) FreeObjectAttr(Entry->UserData);
- Entry->UserData = NULL;
- //
- if (!GDIOBJ_SetOwnership(pDC->rosdc.hGCClipRgn, Owner)) return FALSE;
+ }
+ else
+ {
+ pdcFirst = pdc1 ;
+ prcFirst = &rc1;
+ pdcSecond = NULL;
+ prcSecond = NULL;
+ }
+
+ if(pdcFirst && pdcFirst->dctype == DCTYPE_DIRECT)
+ {
+ EngAcquireSemaphore(pdcFirst->ppdev->hsemDevLock);
+ MouseSafetyOnDrawStart(pdcFirst->ppdev,
+ prcFirst->left,
+ prcFirst->top,
+ prcFirst->right,
+ prcFirst->bottom) ;
+ /* Update surface if needed */
+ if(pdcFirst->ppdev->pSurface != pdcFirst->dclevel.pSurface)
+ {
+ DC_vUpdateDC(pdcFirst);
}
- if (pDC->dclevel.hPath)
+ }
+ if(pdcSecond && pdcSecond->dctype == DCTYPE_DIRECT)
+ {
+ EngAcquireSemaphore(pdcSecond->ppdev->hsemDevLock);
+ MouseSafetyOnDrawStart(pdcSecond->ppdev,
+ prcSecond->left,
+ prcSecond->top,
+ prcSecond->right,
+ prcSecond->bottom) ;
+ /* Update surface if needed */
+ if(pdcSecond->ppdev->pSurface != pdcSecond->dclevel.pSurface)
{
- if (!GDIOBJ_SetOwnership(pDC->dclevel.hPath, Owner)) return FALSE;
+ DC_vUpdateDC(pdcSecond);
}
- DC_UnlockDc(pDC);
+ }
+}
- return TRUE;
+/* Finishes a blit for one or two DCs */
+VOID
+FASTCALL
+DC_vFinishBlit(PDC pdc1, PDC pdc2)
+{
+ if(pdc1->dctype == DCTYPE_DIRECT)
+ {
+ MouseSafetyOnDrawEnd(pdc1->ppdev);
+ EngReleaseSemaphore(pdc1->ppdev->hsemDevLock);
+ }
+
+ if(pdc2)
+ {
+ if(pdc2->dctype == DCTYPE_DIRECT)
+ {
+ MouseSafetyOnDrawEnd(pdc2->ppdev);
+ EngReleaseSemaphore(pdc2->ppdev->hsemDevLock);
+ }
+ }
}
HDC
/* FIXME: HACK! */
DC_InitHack(pdc);
- DC_AllocDcAttr(pdc);
+ DC_bAllocDcAttr(pdc);
DC_UnlockDc(pdc);
/* Call the internal function */
hdc = GreOpenDCW(pustrDevice ? &ustrDevice : NULL,
pdmInit ? &dmInit : NULL,
- NULL, // fixme pwszLogAddress
+ NULL, // FIXME: pwszLogAddress
iType,
bDisplay,
hspool,
- NULL, //FIXME: pDriverInfo2
+ NULL, // FIXME: pDriverInfo2
pUMdhpdev ? &dhpdev : NULL);
/* If we got a HDC and a UM dhpdev is requested,... */
if (hdc && pUMdhpdev)
{
- /* Copy dhpdev to caller (FIXME: use dhpdev?? */
+ /* Copy dhpdev to caller (FIXME: use dhpdev?) */
_SEH2_TRY
{
/* Pointer was already probed */
DC_InitHack(pdcNew);
/* Allocate a dc attribute */
- DC_AllocDcAttr(pdcNew);
-
- PDEVOBJ_vRelease(ppdev);
+ DC_bAllocDcAttr(pdcNew);
// HACK!
DC_vSelectSurface(pdcNew, psurfDefaultBitmap);
if (DCToDelete == NULL)
{
- SetLastWin32Error(ERROR_INVALID_HANDLE);
+ EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!Force)
{
+ /* Windows permits NtGdiDeleteObjectApp to delete a permanent DC
+ * For some reason, it's still a valid handle, pointing to some kernel data.
+ * Not sure if this is a bug, a feature, some cache stuff... Who knows?
+ * See NtGdiDeleteObjectApp test for details */
if (DCToDelete->fs & DC_FLAG_PERMANENT)
{
- DPRINT1("No! You Naughty Application!\n");
DC_UnlockDc(DCToDelete);
- return UserReleaseDC(NULL, hDC, FALSE);
+ if(UserReleaseDC(NULL, hDC, FALSE))
+ {
+ /* ReactOs feature : call UserReleaseDC
+ * I don't think windows does it.
+ * Still, complain, no one should ever call DeleteDC
+ * on a window DC */
+ DPRINT1("No, you naughty application!\n");
+ return TRUE;
+ }
+ else
+ {
+ /* This is not a window owned DC.
+ * Force its deletion */
+ return IntGdiDeleteDC(hDC, TRUE);
+ }
}
}
DC_UnlockDc(DCToDelete);
- if (!IsObjectDead(hDC))
+ if (GreIsHandleValid(hDC))
{
- if (!GDIOBJ_FreeObjByHandle(hDC, GDI_OBJECT_TYPE_DC))
+ if (!GreDeleteObject(hDC))
{
DPRINT1("DC_FreeDC failed\n");
}
BOOL
APIENTRY
-NtGdiDeleteObjectApp(HANDLE DCHandle)
+NtGdiDeleteObjectApp(HANDLE hobj)
{
/* Complete all pending operations */
- NtGdiFlushUserBatch();
-
- if (GDI_HANDLE_IS_STOCKOBJ(DCHandle)) return TRUE;
+ NtGdiFlushUserBatch(); // FIXME: we shouldn't need this
- if (GDI_HANDLE_GET_TYPE(DCHandle) != GDI_OBJECT_TYPE_DC)
- return GreDeleteObject((HGDIOBJ) DCHandle);
+ if (GDI_HANDLE_IS_STOCKOBJ(hobj)) return TRUE;
- if (IsObjectDead((HGDIOBJ)DCHandle)) return TRUE;
-
- if (!GDIOBJ_OwnedByCurrentProcess(DCHandle))
+ if (GreGetObjectOwner(hobj) != GDI_OBJ_HMGR_POWNED)
{
- SetLastWin32Error(ERROR_INVALID_HANDLE);
+ EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
- return IntGdiDeleteDC(DCHandle, FALSE);
+ if (GDI_HANDLE_GET_TYPE(hobj) != GDI_OBJECT_TYPE_DC)
+ return GreDeleteObject(hobj);
+
+ // FIXME: everything should be callback based
+ return IntGdiDeleteDC(hobj, FALSE);
+}
+
+BOOL
+FASTCALL
+MakeInfoDC(PDC pdc, BOOL bSet)
+{
+ PSURFACE pSurface;
+ SIZEL sizl;
+
+ /* Can not be a display DC. */
+ if (pdc->fs & DC_FLAG_DISPLAY) return FALSE;
+ if (bSet)
+ {
+ if (pdc->fs & DC_FLAG_TEMPINFODC || pdc->dctype == DC_TYPE_DIRECT)
+ return FALSE;
+
+ pSurface = pdc->dclevel.pSurface;
+ pdc->fs |= DC_FLAG_TEMPINFODC;
+ pdc->pSurfInfo = pSurface;
+ pdc->dctype = DC_TYPE_INFO;
+ pdc->dclevel.pSurface = NULL;
+
+ PDEVOBJ_sizl(pdc->ppdev, &sizl);
+
+ if ( sizl.cx == pdc->dclevel.sizl.cx &&
+ sizl.cy == pdc->dclevel.sizl.cy )
+ return TRUE;
+
+ pdc->dclevel.sizl.cx = sizl.cx;
+ pdc->dclevel.sizl.cy = sizl.cy;
+ }
+ else
+ {
+ if (!(pdc->fs & DC_FLAG_TEMPINFODC) || pdc->dctype != DC_TYPE_INFO)
+ return FALSE;
+
+ pSurface = pdc->pSurfInfo;
+ pdc->fs &= ~DC_FLAG_TEMPINFODC;
+ pdc->dclevel.pSurface = pSurface;
+ pdc->dctype = DC_TYPE_DIRECT;
+ pdc->pSurfInfo = NULL;
+
+ if ( !pSurface ||
+ (pSurface->SurfObj.sizlBitmap.cx == pdc->dclevel.sizl.cx &&
+ pSurface->SurfObj.sizlBitmap.cy == pdc->dclevel.sizl.cy) )
+ return TRUE;
+
+ pdc->dclevel.sizl.cx = pSurface->SurfObj.sizlBitmap.cx;
+ pdc->dclevel.sizl.cy = pSurface->SurfObj.sizlBitmap.cy;
+ }
+ return IntSetDefaultRegion(pdc);
}
+/*
+* @implemented
+*/
BOOL
APIENTRY
NtGdiMakeInfoDC(
IN HDC hdc,
IN BOOL bSet)
{
- UNIMPLEMENTED;
- ASSERT(FALSE);
+ BOOL Ret;
+ PDC pdc = DC_LockDc(hdc);
+ if (pdc)
+ {
+ Ret = MakeInfoDC(pdc, bSet);
+ DC_UnlockDc(pdc);
+ return Ret;
+ }
return FALSE;
}