[CMAKE]
[reactos.git] / subsystems / win32 / win32k / objects / dclife.c
index 0487f60..589e92c 100644 (file)
@@ -6,7 +6,7 @@
  * PROGRAMER:         Timo Kreuzer (timo.kreuzer@rectos.org)
  */
 
-#include <w32k.h>
+#include <win32k.h>
 #include <bugcodes.h>
 
 #define NDEBUG
@@ -58,7 +58,9 @@ static const MATRIX   gmxWorldToPageDefault =
 
 /** Internal functions ********************************************************/
 
+INIT_FUNCTION
 NTSTATUS
+NTAPI
 InitDcImpl()
 {
     psurfDefaultBitmap = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]);
@@ -89,8 +91,6 @@ DC_AllocDcWithHandle()
 void
 DC_InitHack(PDC pdc)
 {
-    HRGN hVisRgn;
-
     TextIntRealizeFont(pdc->pdcattr->hlfntNew,NULL);
     pdc->pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0);
 
@@ -98,16 +98,8 @@ DC_InitHack(PDC pdc)
     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
@@ -117,9 +109,6 @@ DC_vInitDc(
     DCTYPE dctype,
     PPDEVOBJ ppdev)
 {
-    /* Lock ppdev */
-    EngAcquireSemaphoreShared(ppdev->hsemDevLock);
-
     /* Setup some basic fields */
     pdc->dctype = dctype;
     pdc->ppdev = ppdev;
@@ -230,17 +219,20 @@ DC_vInitDc(
        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);
+       GDIOBJ_CopyOwnership(pdc->BaseObject.hHmgr, pdc->prgnVis->BaseObject.hHmgr);
 
     /* Setup palette */
     pdc->dclevel.hpal = StockObjects[DEFAULT_PALETTE];
@@ -366,7 +358,6 @@ DC_Cleanup(PVOID ObjectBody)
         GreDeleteObject(pdc->rosdc.hClipRgn);
     if (pdc->prgnVis)
         REGION_FreeRgnByHandle(pdc->prgnVis->BaseObject.hHmgr);
-ASSERT(pdc->rosdc.hGCClipRgn);
     if (pdc->rosdc.hGCClipRgn)
         GreDeleteObject(pdc->rosdc.hGCClipRgn);
     if (NULL != pdc->rosdc.CombinedClip)
@@ -374,6 +365,9 @@ ASSERT(pdc->rosdc.hGCClipRgn);
 
     PATH_Delete(pdc->dclevel.hPath);
 
+    if(pdc->dclevel.pSurface)
+        SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface);
+
     PDEVOBJ_vRelease(pdc->ppdev) ;
 
     return TRUE;
@@ -388,8 +382,6 @@ DC_SetOwnership(HDC hDC, PEPROCESS Owner)
     PDC pDC;
     BOOL ret = FALSE;
 
-    /* FIXME: This function has broken error handling */
-
     if (!GDIOBJ_SetOwnership(hDC, Owner))
     {
         DPRINT1("GDIOBJ_SetOwnership failed\n");
@@ -447,6 +439,123 @@ leave:
     return ret;
 }
 
+
+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;
+    /* 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;
+        }
+        else
+        {
+            pdcFirst = pdc2;
+            prcFirst = &rc2;
+            pdcSecond = pdc1;
+            prcSecond = &rc1;
+        }
+    }
+    else
+    {
+        pdcFirst = pdc1 ;
+        prcFirst = &rc1;
+        pdcSecond = 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(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)
+        {
+            DC_vUpdateDC(pdcSecond);
+        }
+    }
+}
+
+/* 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
 NTAPI
 GreOpenDCW(
@@ -679,11 +788,28 @@ IntGdiDeleteDC(HDC hDC, BOOL Force)
 
     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);
+            }
         }
     }
 
@@ -700,7 +826,7 @@ IntGdiDeleteDC(HDC hDC, BOOL Force)
     {
         DPRINT1("Attempted to Delete 0x%x currently being destroyed!!!\n", hDC);
     }
-
+    
     return TRUE;
 }
 
@@ -727,14 +853,74 @@ NtGdiDeleteObjectApp(HANDLE DCHandle)
     return IntGdiDeleteDC(DCHandle, 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;
 }