[YAROTOWS] Reintegrate the branch. For a brighter future.
[reactos.git] / reactos / subsystems / win32 / win32k / objects / gdibatch.c
index ba06e09..7ddb1fa 100644 (file)
@@ -1,5 +1,5 @@
 
-#include <w32k.h>
+#include <win32k.h>
 
 #define NDEBUG
 #include <debug.h>
 // Gdi Batch Flush support functions.
 //
 
+//
+// DoDeviceSync
+//
+// based on IntEngEnter from eng/engmisc.c
+//
+VOID
+FASTCALL
+DoDeviceSync( SURFOBJ *Surface, PRECTL Rect, FLONG fl)
+{
+  PPDEVOBJ Device = (PDEVOBJ*)Surface->hdev;
+// No punting and "Handle to a surface, provided that the surface is device-managed. 
+// Otherwise, dhsurf is zero".
+  if (!(Device->flFlags & PDEV_DRIVER_PUNTED_CALL) && (Surface->dhsurf))
+  {
+     if (Device->DriverFunctions.SynchronizeSurface)
+     {
+       Device->DriverFunctions.SynchronizeSurface(Surface, Rect, fl);
+     }
+     else
+     {
+       if (Device->DriverFunctions.Synchronize)
+       {
+         Device->DriverFunctions.Synchronize(Surface->dhpdev, Rect);
+       }
+     }
+  }
+}
+
+VOID
+FASTCALL
+SynchonizeDriver(FLONG Flags)
+{
+  SURFOBJ *SurfObj; 
+  PPDEVOBJ Device;
+  
+  if (Flags & GCAPS2_SYNCFLUSH)
+      Flags = DSS_FLUSH_EVENT;
+  if (Flags & GCAPS2_SYNCTIMER)
+      Flags = DSS_TIMER_EVENT;
+
+  Device = IntEnumHDev();
+//  UNIMPLEMENTED;
+//ASSERT(FALSE);
+  SurfObj = 0;// EngLockSurface( Device->pSurface );
+  if(!SurfObj) return;
+  DoDeviceSync( SurfObj, NULL, Flags);
+  EngUnlockSurface(SurfObj);
+  return;
+}
 
 //
 // Process the batch.
 //
 ULONG
 FASTCALL
-GdiFlushUserBatch(HDC hDC, PGDIBATCHHDR pHdr)
+GdiFlushUserBatch(PDC dc, PGDIBATCHHDR pHdr)
 {
-  PDC dc = NULL;
-  PDC_ATTR Dc_Attr = NULL;
-  PGDIBSSETBRHORG pgSBO;
-  if (hDC)
+  BOOL Hit = FALSE;
+  ULONG Cmd = 0, Size = 0;
+  PDC_ATTR pdcattr = NULL;
+
+  if (dc)
+  {
+     pdcattr = dc->pdcattr;
+  }
+
+  _SEH2_TRY
   {
-    dc = DC_LockDc(hDC);
-    Dc_Attr = dc->pDc_Attr;
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+     Cmd = pHdr->Cmd;
+     Size = pHdr->Size; // Return the full size of the structure.
   }
-  // The thread is approaching the end of sunset.
-  switch(pHdr->Cmd)
+  _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+  {
+     Hit = TRUE;
+  }
+  _SEH2_END;
+
+  if (Hit)
+  {
+     DPRINT1("WARNING! GdiBatch Fault!\n");
+     return 0;
+  }
+
+  // FYI! The thread is approaching the end of sunset.
+  switch(Cmd)
   {
      case GdiBCPatBlt: // Highest pri first!
         break;
@@ -40,27 +106,50 @@ GdiFlushUserBatch(HDC hDC, PGDIBATCHHDR pHdr)
         break;
      case GdiBCSetBrushOrg:
      {
+        PGDIBSSETBRHORG pgSBO;
         if (!dc) break;
         pgSBO = (PGDIBSSETBRHORG) pHdr;
-        Dc_Attr->ptlBrushOrigin = pgSBO->ptlBrushOrigin;
+        pdcattr->ptlBrushOrigin = pgSBO->ptlBrushOrigin;
+        IntptlBrushOrigin(dc, pgSBO->ptlBrushOrigin.x, pgSBO->ptlBrushOrigin.y);
         break;
      }
      case GdiBCExtSelClipRgn:
         break;
      case GdiBCSelObj:
+     {
+        PGDIBSOBJECT pgO;
+        PTEXTOBJ pNewFnt = NULL;
+
+        if (!dc) break;
+        pgO = (PGDIBSOBJECT) pHdr;
+
+        if (NT_SUCCESS(TextIntRealizeFont((HFONT)pgO->hgdiobj,NULL)))
+        {
+           /* LFONTOBJ use share and locking. */
+           pNewFnt = TEXTOBJ_LockText(pgO->hgdiobj);
+
+           dc->dclevel.plfnt = pNewFnt;
+           dc->hlfntCur = pgO->hgdiobj;
+           pdcattr->hlfntNew = pgO->hgdiobj;
+           pdcattr->ulDirty_ |= DIRTY_CHARSET;
+           pdcattr->ulDirty_ &= ~SLOW_WIDTHS;
+        }
+        if (pNewFnt) TEXTOBJ_UnlockText(pNewFnt);
         break;
-     case GdiBCDelObj:
+     }
      case GdiBCDelRgn:
+        DPRINT("Delete Region Object!\n");
+     case GdiBCDelObj:
      {
         PGDIBSOBJECT pgO = (PGDIBSOBJECT) pHdr;
-        NtGdiDeleteObject( pgO->hgdiobj );
+        GreDeleteObject( pgO->hgdiobj );
         break;
      }
      default:
         break;
   }
-  if (dc) DC_UnlockDc(dc);
-  return pHdr->Size; // Return the full size of the structure.
+
+  return Size; 
 }
 
 /*
@@ -72,7 +161,7 @@ VOID
 APIENTRY
 NtGdiFlush(VOID)
 {
-  UNIMPLEMENTED;
+  SynchonizeDriver(GCAPS2_SYNCFLUSH);
 }
 
 /*
@@ -92,25 +181,44 @@ NtGdiFlushUserBatch(VOID)
   if( (GdiBatchCount > 0) && (GdiBatchCount <= (GDIBATCHBUFSIZE/4)))
   {
     HDC hDC = (HDC) pTeb->GdiTebBatch.HDC;
-//
-//  If hDC is zero and the buffer fills up with delete objects we need to run
-//  anyway. So, hard code to the system batch limit.
-//
-    if ((hDC) || ((!hDC) && (GdiBatchCount >= GDI_BATCH_LIMIT)))
+
+    /*  If hDC is zero and the buffer fills up with delete objects we need
+        to run anyway.
+     */
+    if (hDC || GdiBatchCount)
     {
-       PULONG pHdr = &pTeb->GdiTebBatch.Buffer[0];
+      PCHAR pHdr = (PCHAR)&pTeb->GdiTebBatch.Buffer[0];
+      PDC pDC = NULL;
+
+      if (hDC && !IsObjectDead(hDC))
+      {
+          pDC = DC_LockDc(hDC);
+      }
+
        // No need to init anything, just go!
        for (; GdiBatchCount > 0; GdiBatchCount--)
        {
+           ULONG Size;
            // Process Gdi Batch!
-           pHdr += GdiFlushUserBatch( hDC, (PGDIBATCHHDR) pHdr );
+           Size = GdiFlushUserBatch(pDC, (PGDIBATCHHDR) pHdr);
+           if (!Size) break;
+           pHdr += Size;
        }
+
+       if (pDC)
+       {
+           DC_UnlockDc(pDC);
+       }
+
        // Exit and clear out for the next round.
        pTeb->GdiTebBatch.Offset = 0;
        pTeb->GdiBatchCount = 0;
        pTeb->GdiTebBatch.HDC = 0;
     }
   }
+
+  // FIXME: on xp the function returns &pTeb->RealClientId, maybe VOID?
   return STATUS_SUCCESS;
 }
 
+