[WIN32K]
[reactos.git] / reactos / subsystems / win32 / win32k / eng / surface.c
index a33cf6f..464e7d0 100644 (file)
@@ -332,108 +332,117 @@ IntCreateBitmap(IN SIZEL Size,
                 IN ULONG Flags,
                 IN PVOID Bits)
 {
+    HBITMAP hbmp;
     SURFOBJ *pso;
     PSURFACE psurf;
-    SIZEL LocalSize;
-    ULONG ScanLine = 0; // Compiler is dumb
-    ULONG BitsSize;
-    
-    ScanLine = abs(Width);
+    PVOID UncompressedBits;
+    ULONG UncompressedFormat;
 
-    /* Does the device manage its own surface? */
-    if (!Bits)
+    if (Format == 0)
+        return 0;
+
+    psurf = SURFACE_AllocSurfaceWithHandle();
+    if (psurf == NULL)
+    {
+        return 0;
+    }
+    hbmp = psurf->BaseObject.hHmgr;
+
+    if (! SURFACE_InitBitsLock(psurf))
     {
-        /* The height times the bytes for each scanline */
-        BitsSize = Size.cy * ScanLine;
-        if (BitsSize) 
+        SURFACE_UnlockSurface(psurf);
+        SURFACE_FreeSurfaceByHandle(hbmp);
+        return 0;
+    }
+    pso = &psurf->SurfObj;
+
+    if (Format == BMF_4RLE)
+    {
+        pso->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_4BPP));
+        pso->cjBits = pso->lDelta * Size.cy;
+        UncompressedFormat = BMF_4BPP;
+        UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
+        Decompress4bpp(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, pso->lDelta);
+    }
+    else if (Format == BMF_8RLE)
+    {
+        pso->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_8BPP));
+        pso->cjBits = pso->lDelta * Size.cy;
+        UncompressedFormat = BMF_8BPP;
+        UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
+        Decompress8bpp(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, pso->lDelta);
+    }
+    else
+    {
+        pso->lDelta = abs(Width);
+        pso->cjBits = pso->lDelta * Size.cy;
+        UncompressedBits = Bits;
+        UncompressedFormat = Format;
+    }
+
+    if (UncompressedBits != NULL)
+    {
+        pso->pvBits = UncompressedBits;
+    }
+    else
+    {
+        if (pso->cjBits == 0)
         {
-            /* Check for allocation flag */
-            if (Flags & BMF_USERMEM)
+            pso->pvBits = NULL;
+        }
+        else
+        {
+            if (0 != (Flags & BMF_USERMEM))
             {
-                /* Get the bits from user-mode memory */
-                Bits = EngAllocUserMem(BitsSize, 'mbuG');
+                pso->pvBits = EngAllocUserMem(pso->cjBits, 0);
             }
             else
             {
-                /* Get kernel bits (zeroed out if requested) */
-                Bits = EngAllocMem((Flags & BMF_NOZEROINIT) ? 0 : FL_ZERO_MEMORY,
-                                   BitsSize,
-                                   TAG_DIB);
+                pso->pvBits = EngAllocMem(0 != (Flags & BMF_NOZEROINIT) ?
+                                                  0 : FL_ZERO_MEMORY,
+                                              pso->cjBits, TAG_DIB);
+            }
+            if (pso->pvBits == NULL)
+            {
+                SURFACE_UnlockSurface(psurf);
+                SURFACE_FreeSurfaceByHandle(hbmp);
+                SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+                return 0;
             }
-            
-            /* Bail out if that failed */
-            if (!Bits) return NULL;
         }
     }
-    else
-    {
-        /* Should not have asked for user memory */
-//        ASSERT((Flags & BMF_USERMEM) == 0);
-    }
-
-    /* Allocate the actual surface object structure */
-    psurf = SURFACE_AllocSurfaceWithHandle();
-    if (!psurf) return NULL;
-    
-    /* Lock down the surface */
-    if (!SURFACE_InitBitsLock(psurf))
-    {
-        /* Bail out if that failed */
-        SURFACE_UnlockSurface(psurf);
-        SURFACE_FreeSurface(psurf);
-        return NULL;
-    }
-
-    /* We should now have our surface object */
-    pso = &psurf->SurfObj;
-    
-    /* Set bits */
-    pso->pvBits = Bits;
 
-    /* Number of bits is based on the height times the scanline */
-    pso->cjBits = Size.cy * ScanLine;
-    if (Flags & BMF_TOPDOWN)
+    if (0 == (Flags & BMF_TOPDOWN))
     {
-        /* For topdown, the base address starts with the bits */
-        pso->pvScan0 = pso->pvBits;
-        pso->lDelta = ScanLine;
+        pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - pso->lDelta);
+        pso->lDelta = - pso->lDelta;
     }
     else
     {
-        /* Otherwise we start with the end and go up */
-        pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ScanLine);
-        pso->lDelta = -ScanLine;
+        pso->pvScan0 = pso->pvBits;
     }
 
-    /* Save format and flags */
-    pso->iBitmapFormat = Format;
-    pso->fjBitmap = Flags & (BMF_TOPDOWN | BMF_UMPDMEM | BMF_USERMEM);
-
-    /* Save size and type */
-    LocalSize.cx = Size.cx;
-    LocalSize.cy = Size.cy;
-    pso->sizlBitmap = Size;
-    pso->iType = STYPE_BITMAP;
-    
-    /* Device-managed surface, no flags or dimension */
-    pso->dhsurf = 0;
+    pso->dhsurf = 0; /* device managed surface */
+    pso->hsurf = (HSURF)hbmp;
     pso->dhpdev = NULL;
     pso->hdev = NULL;
+    pso->sizlBitmap = Size;
+    pso->iBitmapFormat = UncompressedFormat;
+    pso->iType = STYPE_BITMAP;
+    pso->fjBitmap = Flags & (BMF_TOPDOWN | BMF_NOZEROINIT);
+    pso->iUniq = 0;
+
+    psurf->flHooks = 0;
     psurf->flFlags = 0;
     psurf->dimension.cx = 0;
     psurf->dimension.cy = 0;
+    
     psurf->hSecure = NULL;
     psurf->hDIBSection = NULL;
-    psurf->flHooks = 0;
 
-
-    /* Finally set the handle and uniq */
-    pso->hsurf = (HSURF)psurf->BaseObject.hHmgr;
-    pso->iUniq = 0;
-    
-    /* Unlock and return the surface */
     SURFACE_UnlockSurface(psurf);
-    return pso->hsurf;
+
+    return hbmp;
 }
 
 /* Name gleaned from C++ symbol information for SURFMEM::bInitDIB */
@@ -457,6 +466,7 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
     SURFOBJ *pso;
     PSURFACE psurf;
     SIZEL LocalSize;
+    BOOLEAN AllocatedLocally = FALSE;
 
     /*
      * First, check the format so we can get the aligned scanline width.
@@ -466,27 +476,27 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
     switch (BitmapInfo->Format)
     {
         case BMF_1BPP:
-            //ScanLine = ((BitmapInfo->Width + 31) & ~31) / 8;
+            ScanLine = ((BitmapInfo->Width + 31) & ~31) >> 3;
             break;
 
         case BMF_4BPP:
-            //ScanLine = ((BitmapInfo->Width + 7) & ~7) / 2;
+            ScanLine = ((BitmapInfo->Width + 7) & ~7) >> 1;
             break;
 
         case BMF_8BPP:
-            //ScanLine = ((BitmapInfo->Width + 3) & ~3);
+            ScanLine = (BitmapInfo->Width + 3) & ~3;
             break;
 
         case BMF_16BPP:
-            //ScanLine = ((BitmapInfo->Width + 1) & ~1) * 2;
+            ScanLine = ((BitmapInfo->Width + 1) & ~1) << 1;
             break;
 
         case BMF_24BPP:
-            //ScanLine = ((BitmapInfo->Width * 3) + 3) & ~3;
+            ScanLine = ((BitmapInfo->Width * 3) + 3) & ~3;
             break;
 
         case BMF_32BPP:
-           // ScanLine = BitmapInfo->Width * 4;
+            ScanLine = BitmapInfo->Width << 2;
             break;
 
         case BMF_8RLE:
@@ -501,8 +511,6 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
             return NULL;
     }
 
-    ScanLine = BitmapInfo->Width;
-
     /* Does the device manage its own surface? */
     if (!Bits)
     {
@@ -519,7 +527,7 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
             Size = BitmapInfo->Height * ScanLine;
         }
         
-        if (Size) 
+        if (Size)
         {
             /* Check for allocation flag */
             if (BitmapInfo->Flags & BMF_USERMEM)
@@ -534,7 +542,7 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
                                    Size,
                                    TAG_DIB);
             }
-            
+            AllocatedLocally = TRUE;
             /* Bail out if that failed */
             if (!Bits) return NULL;
         }
@@ -547,14 +555,24 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
 
     /* Allocate the actual surface object structure */
     psurf = SURFACE_AllocSurfaceWithHandle();
-    if (!psurf) return NULL;
-    
+    if (!psurf)
+    {
+        if(Bits && AllocatedLocally)
+        {
+            if(BitmapInfo->Flags & BMF_USERMEM)
+                EngFreeUserMem(Bits);
+            else
+                EngFreeMem(Bits);
+        }
+        return NULL;
+    }
+
     /* Lock down the surface */
     if (!SURFACE_InitBitsLock(psurf))
     {
         /* Bail out if that failed */
         SURFACE_UnlockSurface(psurf);
-        SURFACE_FreeSurface(psurf);
+        SURFACE_FreeSurfaceByHandle(psurf->BaseObject.hHmgr);
         return NULL;
     }
 
@@ -660,7 +678,6 @@ EngCreateBitmap(IN SIZEL Size,
      */
     if ((Bits) && (Width))
     {
-    #if 0
         switch (BitmapInfo.Format)
         {
             /* Do the conversion for each bit depth we support */
@@ -683,9 +700,6 @@ EngCreateBitmap(IN SIZEL Size,
                 BitmapInfo.Width = Width / 4;
                 break;
         }
-#endif
-        BitmapInfo.Width = Width;
-
     }
     
     /* Now create the surface */