[CMAKE]
[reactos.git] / subsystems / win32 / win32k / objects / dclife.c
index 1581a14..6b66f8c 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]);
@@ -78,7 +80,22 @@ NTAPI
 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;
 
@@ -89,8 +106,6 @@ DC_AllocDcWithHandle()
 void
 DC_InitHack(PDC pdc)
 {
-    HRGN hVisRgn;
-
     TextIntRealizeFont(pdc->pdcattr->hlfntNew,NULL);
     pdc->pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0);
 
@@ -98,14 +113,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);
 }
 
 VOID
@@ -115,12 +124,6 @@ DC_vInitDc(
     DCTYPE dctype,
     PPDEVOBJ ppdev)
 {
-    if (dctype == DCTYPE_DIRECT)
-    {
-        /* Lock ppdev exclusively */
-        EngAcquireSemaphore(ppdev->hsemDevLock);
-    }
-
     /* Setup some basic fields */
     pdc->dctype = dctype;
     pdc->ppdev = ppdev;
@@ -162,30 +165,6 @@ DC_vInitDc(
         /* Direct DCs get the surface from the PDEV */
         pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev);
 
-        /* Maintain a list of DC attached to this device */
-        if(!pdc->dclevel.pSurface->hDC)
-            pdc->dclevel.pSurface->hDC = pdc->BaseObject.hHmgr ;
-        else
-        {
-            PDC Surf_Dc = DC_LockDc(pdc->dclevel.pSurface->hDC);
-            if(!Surf_Dc)
-            {
-                DPRINT1("Something went wrong with device DC list!\n");
-                /* Save what can be saved ... */
-                pdc->dclevel.pSurface->hDC = pdc->BaseObject.hHmgr;
-            }
-            else
-            {
-                /* Insert this one at the head of the list */
-                pdc->hdcNext = Surf_Dc->BaseObject.hHmgr;
-                /* Sanity check */
-                ASSERT(NULL == Surf_Dc->hdcPrev);
-                Surf_Dc->hdcPrev = pdc->BaseObject.hHmgr ;
-                pdc->dclevel.pSurface->hDC = pdc->BaseObject.hHmgr;
-                DC_UnlockDc(Surf_Dc);
-            }
-        }
-
         pdc->erclBounds.left = 0x7fffffff;
         pdc->erclBounds.top = 0x7fffffff;
         pdc->erclBounds.right = 0x80000000;
@@ -255,17 +234,19 @@ 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);
 
     /* Setup palette */
     pdc->dclevel.hpal = StockObjects[DEFAULT_PALETTE];
@@ -348,6 +329,8 @@ DC_vInitDc(
 //     pdc->dclevel.pFont = LFONT_ShareLockFont(pdc->dcattr.hlfntNew);
 
     /* Other stuff */
+    pdc->hdcNext = NULL;
+    pdc->hdcPrev = NULL;
     pdc->ipfdDevMax = 0x0000ffff;
     pdc->ulCopyCount = -1;
     pdc->ptlDoBanding.x = 0;
@@ -385,117 +368,212 @@ DC_Cleanup(PVOID ObjectBody)
     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(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->dctype == DCTYPE_DIRECT)
-    {
-        EngAcquireSemaphore(pdc->ppdev->hsemDevLock);
-        /* Remove it from the list of DC attached to the Device */
-        PDC tmpDC = DC_LockDc(pdc->hdcNext);
-        if(tmpDC != NULL)
-        {
-            tmpDC->hdcPrev = pdc->hdcPrev ;
-            DC_UnlockDc(tmpDC);
-        }
-        tmpDC = DC_LockDc(pdc->hdcPrev);
-        if(tmpDC != NULL)
-        {
-            tmpDC->hdcNext = pdc->hdcNext ;
-            DC_UnlockDc(tmpDC);
-        }
-        /* Reassign list head if needed */
-        if(pdc->BaseObject.hHmgr == pdc->dclevel.pSurface->hDC)
-        {
-            /* Sanity check */
-            ASSERT(pdc->hdcPrev == NULL);
-            pdc->dclevel.pSurface->hDC = pdc->hdcNext;
-        }
-        EngReleaseSemaphore(pdc->ppdev->hsemDevLock) ;
-    }
-
     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;
-    BOOL ret = FALSE;
 
-    /* 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);
+    }
+
+    if (pdc->dclevel.hPath)
+    {
+        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);
     }
 
-    pDC = DC_LockDc(hDC);
-    if (!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("Could not lock DC\n");
+        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)) goto leave;
-    }
-    if (pDC->prgnVis)
-    {   // FIXME! HAX!!!
-        Index = GDI_HANDLE_GET_INDEX(pDC->prgnVis->BaseObject.hHmgr);
-        Entry = &GdiHandleTable->Entries[Index];
-        if (Entry->UserData) FreeObjectAttr(Entry->UserData);
-        Entry->UserData = NULL;
-        //
-        if (!GDIOBJ_SetOwnership(pDC->prgnVis->BaseObject.hHmgr, Owner)) goto leave;
-    }
-    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)) goto leave;
-    }
-    if (pDC->dclevel.hPath)
-    {
-        if (!GDIOBJ_SetOwnership(pDC->dclevel.hPath, Owner)) goto leave;
-    }
-    ret = TRUE;
-
-leave:
-    DC_UnlockDc(pDC);
-
-    return ret;
+    /* 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;
+        }
+        else
+        {
+            pdcFirst = pdc2;
+            prcFirst = &rc2;
+            pdcSecond = pdc1;
+            prcSecond = &rc1;
+        }
+    }
+    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(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
@@ -541,7 +619,7 @@ GreOpenDCW(
     /* FIXME: HACK! */
     DC_InitHack(pdc);
 
-    DC_AllocDcAttr(pdc);
+    DC_bAllocDcAttr(pdc);
 
     DC_UnlockDc(pdc);
 
@@ -621,17 +699,17 @@ NtGdiOpenDCW(
     /* 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 */
@@ -704,7 +782,7 @@ NtGdiCreateCompatibleDC(HDC hdc)
     DC_InitHack(pdcNew);
 
     /* Allocate a dc attribute */
-    DC_AllocDcAttr(pdcNew);
+    DC_bAllocDcAttr(pdcNew);
 
     // HACK!
     DC_vSelectSurface(pdcNew, psurfDefaultBitmap);
@@ -724,25 +802,42 @@ IntGdiDeleteDC(HDC hDC, BOOL Force)
 
     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");
         }
@@ -757,25 +852,24 @@ IntGdiDeleteDC(HDC hDC, BOOL Force)
 
 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