From 3f75eaacdc8f7cab3d6106bad991910f10074cf8 Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Fri, 22 Dec 2000 01:07:57 +0000
Subject: [PATCH] Authors: Ove Kaaven <ovek@transgaming.com>, Gavriel State
 <gav@transgaming.com> More DIB section copy-blitting improvements: Handle
 8bpp DIBs, DC mapping modes, and clipping. Take advantage of the DIBsection's
 XShmImage mechanism to get a really fast blit to the display.

---
 graphics/x11drv/bitblt.c |  40 ++++++++------
 graphics/x11drv/dib.c    | 113 +++++++++++++++++++++++++++++++++------
 include/x11drv.h         |   4 ++
 3 files changed, 125 insertions(+), 32 deletions(-)

diff --git a/graphics/x11drv/bitblt.c b/graphics/x11drv/bitblt.c
index 68f87263c20..4e9ee00dd4d 100644
--- a/graphics/x11drv/bitblt.c
+++ b/graphics/x11drv/bitblt.c
@@ -1490,6 +1490,7 @@ BOOL X11DRV_BitBlt( DC *dcDst, INT xDst, INT yDst,
     struct StretchBlt_params params;
     BOOL result = FALSE;
     INT sSrc, sDst;
+    RECT visRectDst, visRectSrc;
 
     if (((rop >> 16) & 0x55) == ((rop >> 17) & 0x55)) {
       /* FIXME: seems the ROP doesn't include destination;
@@ -1499,29 +1500,36 @@ BOOL X11DRV_BitBlt( DC *dcDst, INT xDst, INT yDst,
     }
     sDst = X11DRV_LockDIBSection( dcDst, DIB_Status_None, FALSE );
     sSrc = X11DRV_LockDIBSection( dcSrc, DIB_Status_None, FALSE );
+
     if ((sSrc == DIB_Status_AppMod) && (rop == SRCCOPY)) {
-      BITMAPOBJ *bmp;
-      BOOL done = FALSE;
+      /* do everything ourselves; map coordinates */
+      xSrc = dcSrc->DCOrgX + XLPTODP( dcSrc, xSrc );
+      ySrc = dcSrc->DCOrgY + YLPTODP( dcSrc, ySrc );
+      xDst = dcDst->DCOrgX + XLPTODP( dcDst, xDst );
+      yDst = dcDst->DCOrgY + YLPTODP( dcDst, yDst );
+      width  = MulDiv(width, dcDst->vportExtX, dcDst->wndExtX);
+      height = MulDiv(height, dcDst->vportExtY, dcDst->wndExtY);
+
+      /* Perform basic clipping */
+      if (!BITBLT_GetVisRectangles( dcDst, xDst, yDst, width, height,
+                                      dcSrc, xSrc, ySrc, width, height,
+                                      &visRectSrc, &visRectDst ))
+        goto END;
       
+      xSrc = visRectSrc.left;
+      ySrc = visRectSrc.top;
+      xDst = visRectDst.left;
+      yDst = visRectDst.top;
+      width = visRectDst.right - visRectDst.left;
+      height = visRectDst.bottom - visRectDst.top;
+
       if (sDst == DIB_Status_AppMod) {
         FIXME("potential optimization - client-side DIB copy\n");
       }
-
       X11DRV_CoerceDIBSection( dcDst, DIB_Status_GdiMod, FALSE );
 
-      bmp = (BITMAPOBJ *)GDI_GetObjPtr( dcSrc->hBitmap, BITMAP_MAGIC );
-      if (bmp->dib) {
-        if (bmp->dib->dsBmih.biBitCount > 8) {
-          if (X11DRV_SetDIBitsToDevice( dcDst, xDst, yDst, width, height, xSrc, ySrc,
-                                        0, bmp->dib->dsBm.bmHeight, bmp->dib->dsBm.bmBits,
-                                        (BITMAPINFO*)&(bmp->dib->dsBmih), 0))
-            result = TRUE;
-          done = TRUE;
-        }
-        else FIXME("potential optimization - 8 bpp SetDIBitsToDevice\n");
-      }
-      GDI_ReleaseObj( dcSrc->hBitmap );
-      if (done) goto END;
+      X11DRV_DIB_CopyDIBSection( dcSrc, dcDst, xSrc, ySrc, xDst, yDst, width, height );
+      goto END;
     }
 
     params.dcDst = dcDst;
diff --git a/graphics/x11drv/dib.c b/graphics/x11drv/dib.c
index 4cdbb582bd1..f2eac0c33fc 100644
--- a/graphics/x11drv/dib.c
+++ b/graphics/x11drv/dib.c
@@ -122,10 +122,15 @@ int *X11DRV_DIB_GenColorMap( DC *dc, int *colorMapping,
     }
     else  /* DIB_PAL_COLORS */
     {
-        WORD * index = (WORD *)colorPtr;
-
-        for (i = start; i < end; i++, index++)
-            colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(*index) );
+        if (colorPtr) {
+            WORD * index = (WORD *)colorPtr;
+
+            for (i = start; i < end; i++, index++)
+                colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(*index) );
+        } else {
+            for (i = start; i < end; i++)
+                colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(i) );
+        }
     }
 
     return colorMapping;
@@ -142,14 +147,14 @@ int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
 {
     int colors;
     BOOL isInfo;
-    WORD *colorPtr;
+    const void *colorPtr;
     int *colorMapping;
 
     if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
     {
         colors = info->bmiHeader.biClrUsed;
         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
-        colorPtr = (WORD *)info->bmiColors;
+        colorPtr = info->bmiColors;
     }
     else  /* assume BITMAPCOREINFO */
     {
@@ -163,6 +168,9 @@ int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
         return NULL;
     }
 
+    /* just so CopyDIBSection doesn't have to create an identity palette */
+    if (coloruse == (WORD)-1) colorPtr = NULL;
+
     if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
                                           colors * sizeof(int) ))) 
 	return NULL;
@@ -2684,6 +2692,10 @@ int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
         break;
     }
 
+    TRACE("XPutImage(%p,%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
+     display, descr->drawable, descr->gc, bmpImage,
+     descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
+     descr->width, descr->height);
     if (descr->useShm)
     {
         XShmPutImage( display, descr->drawable, descr->gc, bmpImage,
@@ -3126,7 +3138,12 @@ static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
 /***********************************************************************
  *           X11DRV_DIB_DoUpdateDIBSection
  */
-static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
+static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
+					void *colorMap, int nColorMap,
+					Drawable dest,
+					DWORD xSrc, DWORD ySrc,
+					DWORD xDest, DWORD yDest,
+					DWORD width, DWORD height)
 {
   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
   X11DRV_DIB_IMAGEBITS_DESCR descr;
@@ -3138,8 +3155,8 @@ static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
   descr.dc        = NULL;
   descr.palentry  = NULL;
   descr.image     = dib->image;
-  descr.colorMap  = (RGBQUAD *)dib->colorMap;
-  descr.nColorMap = dib->nColorMap;
+  descr.colorMap  = colorMap;
+  descr.nColorMap = nColorMap;
   descr.bits      = dib->dibSection.dsBm.bmBits;
   descr.depth     = bmp->bitmap.bmBitsPixel;
   
@@ -3166,14 +3183,14 @@ static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
   }
 
   /* Hack for now */
-  descr.drawable  = (Pixmap)bmp->physBitmap;
+  descr.drawable  = dest;
   descr.gc        = BITMAP_GC(bmp);
-  descr.xSrc      = 0;
-  descr.ySrc      = 0;
-  descr.xDest     = 0;
-  descr.yDest     = 0;
-  descr.width     = bmp->bitmap.bmWidth;
-  descr.height    = bmp->bitmap.bmHeight;
+  descr.xSrc      = xSrc;
+  descr.ySrc      = ySrc;
+  descr.xDest     = xDest;
+  descr.yDest     = yDest;
+  descr.width     = width;
+  descr.height    = height;
 #ifdef HAVE_LIBXXSHM
   descr.useShm = (dib->shminfo.shmid != -1);
 #else
@@ -3197,6 +3214,70 @@ static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
     }
 }
 
+/***********************************************************************
+ *           X11DRV_DIB_CopyDIBSection
+ */
+void X11DRV_DIB_CopyDIBSection(DC *dcSrc, DC *dcDst,
+			       DWORD xSrc, DWORD ySrc,
+			       DWORD xDest, DWORD yDest,
+			       DWORD width, DWORD height)
+{
+  BITMAPOBJ *bmp;
+  X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcDst->physDev;
+  int nColorMap = 0, *colorMap = NULL;
+
+  TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", dcSrc, dcDst,
+    xSrc, ySrc, xDest, yDest, width, height);
+  /* this function is meant as an optimization for BitBlt,
+   * not to be called otherwise */
+  if (!(dcSrc->flags & DC_MEMORY)) {
+    ERR("called for non-memory source DC!?\n");
+    return;
+  }
+
+  bmp = (BITMAPOBJ *)GDI_GetObjPtr( dcSrc->hBitmap, BITMAP_MAGIC );
+  if (!(bmp && bmp->dib)) {
+    ERR("called for non-DIBSection!?\n");
+    GDI_ReleaseObj( dcSrc->hBitmap );
+    return;
+  }
+  /* while BitBlt should already have made sure we only get
+   * positive values, we should check for oversize values */
+  if ((xSrc < bmp->bitmap.bmWidth) &&
+      (ySrc < bmp->bitmap.bmHeight)) {
+    if (xSrc + width > bmp->bitmap.bmWidth)
+      width = bmp->bitmap.bmWidth - xSrc;
+    if (ySrc + height > bmp->bitmap.bmHeight)
+      height = bmp->bitmap.bmHeight - ySrc;
+    /* if the source bitmap is 8bpp or less, we're supposed to use the
+     * DC's palette for color conversion (not the DIB color table) */
+    if (bmp->dib->dsBm.bmBitsPixel <= 8)
+      colorMap = X11DRV_DIB_BuildColorMap( dcSrc, (WORD)-1,
+					   bmp->dib->dsBm.bmBitsPixel,
+					   (BITMAPINFO*)&(bmp->dib->dsBmih),
+					   &nColorMap );
+    /* perform the copy */
+    X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
+				physDev->drawable, xSrc, ySrc, xDest, yDest,
+				width, height);
+    /* free color mapping */
+    if (colorMap)
+      HeapFree(GetProcessHeap(), 0, colorMap);
+  }
+  GDI_ReleaseObj( dcSrc->hBitmap );
+}
+
+/***********************************************************************
+ *           X11DRV_DIB_DoUpdateDIBSection
+ */
+static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
+{
+  X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
+  X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
+			      (Drawable)bmp->physBitmap, 0, 0, 0, 0,
+			      bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
+}
+
 /***********************************************************************
  *           X11DRV_DIB_FaultHandler
  */
diff --git a/include/x11drv.h b/include/x11drv.h
index f0b391fbbd1..17c22d1d914 100644
--- a/include/x11drv.h
+++ b/include/x11drv.h
@@ -298,6 +298,10 @@ extern UINT X11DRV_DIB_GetDIBColorTable(struct tagBITMAPOBJ *,struct tagDC*,UINT
 extern INT X11DRV_DIB_Coerce(struct tagBITMAPOBJ *,INT,BOOL);
 extern INT X11DRV_DIB_Lock(struct tagBITMAPOBJ *,INT,BOOL);
 extern void X11DRV_DIB_Unlock(struct tagBITMAPOBJ *,BOOL);
+void X11DRV_DIB_CopyDIBSection(DC *dcSrc, DC *dcDst,     
+			       DWORD xSrc, DWORD ySrc,   
+			       DWORD xDest, DWORD yDest, 
+			       DWORD width, DWORD height);
 
 /**************************************************************************
  * X11 GDI driver
-- 
GitLab