[WIN32K]
[reactos.git] / reactos / subsystems / win32 / win32k / eng / surface.c
index 48ecf35..464e7d0 100644 (file)
@@ -1,23 +1,4 @@
 /*
- *  ReactOS W32 Subsystem
- *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id$
- *
  * COPYRIGHT:         See COPYING in the top level directory
  * PROJECT:           ReactOS kernel
  * PURPOSE:           GDI Driver Surace Functions
 
 enum Rle_EscapeCodes
 {
-  RLE_EOL   = 0, /* End of line */
-  RLE_END   = 1, /* End of bitmap */
-  RLE_DELTA = 2  /* Delta */
+    RLE_EOL   = 0, /* End of line */
+    RLE_END   = 1, /* End of bitmap */
+    RLE_DELTA = 2  /* Delta */
 };
 
 INT FASTCALL BitsPerFormat(ULONG Format)
 {
-  switch(Format)
-  {
-    case BMF_1BPP: return 1;
-    case BMF_4BPP:
-    case BMF_4RLE: return 4;
-    case BMF_8BPP:
-    case BMF_8RLE: return 8;
-    case BMF_16BPP: return 16;
-    case BMF_24BPP: return 24;
-    case BMF_32BPP: return 32;
-    default: return 0;
-  }
+    switch (Format)
+    {
+        case BMF_1BPP:
+            return 1;
+
+        case BMF_4BPP:
+            /* Fall through */
+        case BMF_4RLE:
+            return 4;
+
+        case BMF_8BPP:
+            /* Fall through */
+        case BMF_8RLE:
+            return 8;
+
+        case BMF_16BPP:
+            return 16;
+
+        case BMF_24BPP:
+            return 24;
+
+        case BMF_32BPP:
+            return 32;
+
+        default:
+            return 0;
+    }
 }
 
 ULONG FASTCALL BitmapFormat(WORD Bits, DWORD Compression)
 {
-  switch(Compression)
-  {
-    case BI_RGB:
-    case BI_BITFIELDS:
-      switch(Bits)
-      {
-        case 1: return BMF_1BPP;
-        case 4: return BMF_4BPP;
-        case 8: return BMF_8BPP;
-        case 16: return BMF_16BPP;
-        case 24: return BMF_24BPP;
-        case 32: return BMF_32BPP;
-      }
-      return 0;
-
-    case BI_RLE4: return BMF_4RLE;
-    case BI_RLE8: return BMF_8RLE;
-
-    default: return 0;
-  }
+    switch (Compression)
+    {
+        case BI_RGB:
+            /* Fall through */
+        case BI_BITFIELDS:
+            switch (Bits)
+            {
+                case 1:
+                    return BMF_1BPP;
+                case 4:
+                    return BMF_4BPP;
+                case 8:
+                    return BMF_8BPP;
+                case 16:
+                    return BMF_16BPP;
+                case 24:
+                    return BMF_24BPP;
+                case 32:
+                    return BMF_32BPP;
+            }
+            return 0;
+
+        case BI_RLE4:
+            return BMF_4RLE;
+
+        case BI_RLE8:
+            return BMF_8RLE;
+
+        default:
+            return 0;
+    }
 }
 
 BOOL INTERNAL_CALL
-BITMAPOBJ_InitBitsLock(BITMAPOBJ *BitmapObj)
+SURFACE_Cleanup(PVOID ObjectBody)
 {
-  BitmapObj->BitsLock = ExAllocatePoolWithTag(NonPagedPool,
-                                              sizeof(FAST_MUTEX),
-                                              TAG_BITMAPOBJ);
-  if (NULL == BitmapObj->BitsLock)
+    PSURFACE psurf = (PSURFACE)ObjectBody;
+    PVOID pvBits = psurf->SurfObj.pvBits;
+
+    /* If this is an API bitmap, free the bits */
+    if (pvBits != NULL &&
+        (psurf->flFlags & BITMAPOBJ_IS_APIBITMAP))
     {
-      return FALSE;
+        /* Check if we have a DIB section */
+        if (psurf->hSecure)
+        {
+            // FIXME: IMPLEMENT ME!
+            // MmUnsecureVirtualMemory(psurf->hSecure);
+            if (psurf->hDIBSection)
+            {
+                /* DIB was created from a section */
+                NTSTATUS Status;
+
+                pvBits = (PVOID)((ULONG_PTR)pvBits - psurf->dwOffset);
+                Status = ZwUnmapViewOfSection(NtCurrentProcess(), pvBits);
+                if (!NT_SUCCESS(Status))
+                {
+                    DPRINT1("Could not unmap section view!\n");
+                    // Should we BugCheck here?
+                }
+            }
+            else
+            {
+                /* DIB was allocated */
+                EngFreeUserMem(pvBits);
+            }
+        }
+        else
+        {
+            // FIXME: use TAG
+            ExFreePool(psurf->SurfObj.pvBits);
+        }
+
+        if (psurf->hDIBPalette != NULL)
+        {
+            GreDeleteObject(psurf->hDIBPalette);
+        }
     }
 
-  ExInitializeFastMutex(BitmapObj->BitsLock);
+    if (NULL != psurf->BitsLock)
+    {
+        ExFreePoolWithTag(psurf->BitsLock, TAG_SURFACE);
+        psurf->BitsLock = NULL;
+    }
 
-  return TRUE;
+    return TRUE;
+}
+
+BOOL INTERNAL_CALL
+SURFACE_InitBitsLock(PSURFACE psurf)
+{
+    psurf->BitsLock = ExAllocatePoolWithTag(NonPagedPool,
+                          sizeof(FAST_MUTEX),
+                          TAG_SURFACE);
+    if (NULL == psurf->BitsLock)
+    {
+        return FALSE;
+    }
+
+    ExInitializeFastMutex(psurf->BitsLock);
+
+    return TRUE;
 }
 
 void INTERNAL_CALL
-BITMAPOBJ_CleanupBitsLock(BITMAPOBJ *BitmapObj)
+SURFACE_CleanupBitsLock(PSURFACE psurf)
 {
-  if (NULL != BitmapObj->BitsLock)
+    if (NULL != psurf->BitsLock)
     {
-      ExFreePoolWithTag(BitmapObj->BitsLock, TAG_BITMAPOBJ);
-      BitmapObj->BitsLock = NULL;
+        ExFreePoolWithTag(psurf->BitsLock, TAG_SURFACE);
+        psurf->BitsLock = NULL;
     }
 }
 
@@ -113,472 +175,733 @@ BITMAPOBJ_CleanupBitsLock(BITMAPOBJ *BitmapObj)
 /*
  * @implemented
  */
-HBITMAP STDCALL
+HBITMAP APIENTRY
 EngCreateDeviceBitmap(IN DHSURF dhsurf,
-                     IN SIZEL Size,
-                     IN ULONG Format)
+                      IN SIZEL Size,
+                      IN ULONG Format)
 {
-  HBITMAP NewBitmap;
-  SURFOBJ *SurfObj;
+    HBITMAP NewBitmap;
+    SURFOBJ *pso;
+
+    NewBitmap = EngCreateBitmap(Size, DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format)), Format, 0, NULL);
+    if (!NewBitmap)
+    {
+        DPRINT1("EngCreateBitmap failed\n");
+        return 0;
+    }
 
-  NewBitmap = EngCreateBitmap(Size, DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format)), Format, 0, NULL);
-  if(!NewBitmap)
-  {
-    DPRINT1("EngCreateBitmap failed\n");
-    return 0;
-  }
+    pso = EngLockSurface((HSURF)NewBitmap);
+    if (!pso)
+    {
+        DPRINT1("EngLockSurface failed on newly created bitmap!\n");
+        GreDeleteObject(NewBitmap);
+        return NULL;
+    }
 
-  SurfObj = EngLockSurface((HSURF)NewBitmap);
-  SurfObj->dhsurf = dhsurf;
-  EngUnlockSurface(SurfObj);
+    pso->dhsurf = dhsurf;
+    EngUnlockSurface(pso);
 
-  return NewBitmap;
+    return NewBitmap;
 }
 
 VOID Decompress4bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta)
 {
-       int x = 0;
-       int y = Size.cy - 1;
-       int c;
-       int length;
-       int width = ((Size.cx+1)/2);
-       int height = Size.cy - 1;
-       BYTE *begin = CompressedBits;
-       BYTE *bits = CompressedBits;
-       BYTE *temp;
-       while (y >= 0)
-       {
-               length = *bits++ / 2;
-               if (length)
-               {
-                       c = *bits++;
-                       while (length--)
-                       {
-                               if (x >= width) break;
-                               temp = UncompressedBits + (((height - y) * Delta) + x);
-                               x++;
-                               *temp = c;
-                       }
-               } else {
-                       length = *bits++;
-                       switch (length)
-                       {
-                       case RLE_EOL:
-                               x = 0;
-                               y--;
-                               break;
-                       case RLE_END:
-                               return;
-                       case RLE_DELTA:
-                               x += (*bits++)/2;
-                               y -= (*bits++)/2;
-                               break;
-                       default:
-                               length /= 2;
-                               while (length--)
-                               {
-                                       c = *bits++;
-                                       if (x < width)
-                                       {
-                                               temp = UncompressedBits + (((height - y) * Delta) + x);
-                                               x++;
-                                               *temp = c;
-                                       }
-                               }
-                               if ((bits - begin) & 1)
-                                       bits++;
-                       }
-               }
-       }
+    int x = 0;
+    int y = Size.cy - 1;
+    int c;
+    int length;
+    int width = ((Size.cx+1)/2);
+    int height = Size.cy - 1;
+    BYTE *begin = CompressedBits;
+    BYTE *bits = CompressedBits;
+    BYTE *temp;
+    while (y >= 0)
+    {
+        length = *bits++ / 2;
+        if (length)
+        {
+            c = *bits++;
+            while (length--)
+            {
+                if (x >= width) break;
+                temp = UncompressedBits + (((height - y) * Delta) + x);
+                x++;
+                *temp = c;
+            }
+        }
+        else
+        {
+            length = *bits++;
+            switch (length)
+            {
+                case RLE_EOL:
+                    x = 0;
+                    y--;
+                    break;
+                case RLE_END:
+                    return;
+                case RLE_DELTA:
+                    x += (*bits++)/2;
+                    y -= (*bits++)/2;
+                    break;
+                default:
+                    length /= 2;
+                    while (length--)
+                    {
+                        c = *bits++;
+                        if (x < width)
+                        {
+                            temp = UncompressedBits + (((height - y) * Delta) + x);
+                            x++;
+                            *temp = c;
+                        }
+                    }
+                    if ((bits - begin) & 1)
+                    {
+                        bits++;
+                    }
+            }
+        }
+    }
 }
 
 VOID Decompress8bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta)
 {
-       int x = 0;
-       int y = Size.cy - 1;
-       int c;
-       int length;
-       int width = Size.cx;
-       int height = Size.cy - 1;
-       BYTE *begin = CompressedBits;
-       BYTE *bits = CompressedBits;
-       BYTE *temp;
-       while (y >= 0)
-       {
-               length = *bits++;
-               if (length)
-               {
-                       c = *bits++;
-                       while (length--)
-                       {
-                               if (x >= width) break;
-                               temp = UncompressedBits + (((height - y) * Delta) + x);
-                               x++;
-                               *temp = c;
-                       }
-               } else {
-                       length = *bits++;
-                       switch (length)
-                       {
-                       case RLE_EOL:
-                               x = 0;
-                               y--;
-                               break;
-                       case RLE_END:
-                               return;
-                       case RLE_DELTA:
-                               x += *bits++;
-                               y -= *bits++;
-                               break;
-                       default:
-                               while (length--)
-                               {
-                                       c = *bits++;
-                                       if (x < width)
-                                       {
-                                               temp = UncompressedBits + (((height - y) * Delta) + x);
-                                               x++;
-                                               *temp = c;
-                                       }
-                               }
-                               if ((bits - begin) & 1)
-                                       bits++;
-                       }
-               }
-       }
+    int x = 0;
+    int y = Size.cy - 1;
+    int c;
+    int length;
+    int width = Size.cx;
+    int height = Size.cy - 1;
+    BYTE *begin = CompressedBits;
+    BYTE *bits = CompressedBits;
+    BYTE *temp;
+    while (y >= 0)
+    {
+        length = *bits++;
+        if (length)
+        {
+            c = *bits++;
+            while (length--)
+            {
+                if (x >= width) break;
+                temp = UncompressedBits + (((height - y) * Delta) + x);
+                x++;
+                *temp = c;
+            }
+        }
+        else
+        {
+            length = *bits++;
+            switch (length)
+            {
+                case RLE_EOL:
+                    x = 0;
+                    y--;
+                    break;
+                case RLE_END:
+                    return;
+                case RLE_DELTA:
+                    x += *bits++;
+                    y -= *bits++;
+                    break;
+                default:
+                    while (length--)
+                    {
+                        c = *bits++;
+                        if (x < width)
+                        {
+                            temp = UncompressedBits + (((height - y) * Delta) + x);
+                            x++;
+                            *temp = c;
+                        }
+                    }
+                    if ((bits - begin) & 1)
+                    {
+                        bits++;
+                    }
+            }
+        }
+    }
 }
 
 HBITMAP FASTCALL
 IntCreateBitmap(IN SIZEL Size,
-               IN LONG Width,
-               IN ULONG Format,
-               IN ULONG Flags,
-               IN PVOID Bits)
+                IN LONG Width,
+                IN ULONG Format,
+                IN ULONG Flags,
+                IN PVOID Bits)
 {
-  HBITMAP NewBitmap;
-  SURFOBJ *SurfObj;
-  BITMAPOBJ *BitmapObj;
-  PVOID UncompressedBits;
-  ULONG UncompressedFormat;
+    HBITMAP hbmp;
+    SURFOBJ *pso;
+    PSURFACE psurf;
+    PVOID UncompressedBits;
+    ULONG UncompressedFormat;
 
-  if (Format == 0)
-       return 0;
+    if (Format == 0)
+        return 0;
 
-  NewBitmap = BITMAPOBJ_AllocBitmapDepricated();
-  if (NewBitmap == NULL)
-       return 0;
+    psurf = SURFACE_AllocSurfaceWithHandle();
+    if (psurf == NULL)
+    {
+        return 0;
+    }
+    hbmp = psurf->BaseObject.hHmgr;
 
-  BitmapObj = BITMAPOBJ_LockBitmap(NewBitmap);
-  if (! BITMAPOBJ_InitBitsLock(BitmapObj))
+    if (! SURFACE_InitBitsLock(psurf))
     {
-      BITMAPOBJ_UnlockBitmap(BitmapObj);
-      BITMAPOBJ_FreeBitmapByHandle(NewBitmap);
-      return 0;
+        SURFACE_UnlockSurface(psurf);
+        SURFACE_FreeSurfaceByHandle(hbmp);
+        return 0;
     }
-  SurfObj = &BitmapObj->SurfObj;
+    pso = &psurf->SurfObj;
 
-  if (Format == BMF_4RLE)
+    if (Format == BMF_4RLE)
     {
-      SurfObj->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_4BPP));
-      SurfObj->cjBits = SurfObj->lDelta * Size.cy;
-      UncompressedFormat = BMF_4BPP;
-      UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, SurfObj->cjBits, 0);
-      Decompress4bpp(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, SurfObj->lDelta);
+        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)
+    else if (Format == BMF_8RLE)
     {
-      SurfObj->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_8BPP));
-      SurfObj->cjBits = SurfObj->lDelta * Size.cy;
-      UncompressedFormat = BMF_8BPP;
-      UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, SurfObj->cjBits, 0);
-      Decompress8bpp(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, SurfObj->lDelta);
+        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
+    else
     {
-      SurfObj->lDelta = abs(Width);
-      SurfObj->cjBits = SurfObj->lDelta * Size.cy;
-      UncompressedBits = Bits;
-      UncompressedFormat = Format;
+        pso->lDelta = abs(Width);
+        pso->cjBits = pso->lDelta * Size.cy;
+        UncompressedBits = Bits;
+        UncompressedFormat = Format;
     }
 
-  if (UncompressedBits != NULL)
+    if (UncompressedBits != NULL)
     {
-      SurfObj->pvBits = UncompressedBits;
+        pso->pvBits = UncompressedBits;
     }
-  else
+    else
     {
-      if (SurfObj->cjBits == 0)
+        if (pso->cjBits == 0)
         {
-          SurfObj->pvBits = NULL;
+            pso->pvBits = NULL;
         }
-      else
+        else
         {
-          if (0 != (Flags & BMF_USERMEM))
+            if (0 != (Flags & BMF_USERMEM))
             {
-              SurfObj->pvBits = EngAllocUserMem(SurfObj->cjBits, 0);
+                pso->pvBits = EngAllocUserMem(pso->cjBits, 0);
             }
-          else
+            else
             {
-              SurfObj->pvBits = EngAllocMem(0 != (Flags & BMF_NOZEROINIT) ? 0 : FL_ZERO_MEMORY,
-                                            SurfObj->cjBits, 0);
+                pso->pvBits = EngAllocMem(0 != (Flags & BMF_NOZEROINIT) ?
+                                                  0 : FL_ZERO_MEMORY,
+                                              pso->cjBits, TAG_DIB);
             }
-          if (SurfObj->pvBits == NULL)
+            if (pso->pvBits == NULL)
             {
-              BITMAPOBJ_UnlockBitmap(BitmapObj);
-              BITMAPOBJ_FreeBitmapByHandle(NewBitmap);
-              return 0;
+                SURFACE_UnlockSurface(psurf);
+                SURFACE_FreeSurfaceByHandle(hbmp);
+                SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+                return 0;
             }
         }
-     }
-
+    }
 
-  if (0 == (Flags & BMF_TOPDOWN))
+    if (0 == (Flags & BMF_TOPDOWN))
     {
-      SurfObj->pvScan0 = (PVOID) ((ULONG_PTR) SurfObj->pvBits + SurfObj->cjBits - SurfObj->lDelta);
-      SurfObj->lDelta = - SurfObj->lDelta;
+        pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - pso->lDelta);
+        pso->lDelta = - pso->lDelta;
     }
-  else
+    else
+    {
+        pso->pvScan0 = pso->pvBits;
+    }
+
+    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;
+
+    SURFACE_UnlockSurface(psurf);
+
+    return hbmp;
+}
+
+/* Name gleaned from C++ symbol information for SURFMEM::bInitDIB */
+typedef struct _DEVBITMAPINFO
+{
+    ULONG Format;
+    ULONG Width;
+    ULONG Height;
+    ULONG Flags;
+    ULONG Size;
+} DEVBITMAPINFO, *PDEVBITMAPINFO;
+
+SURFOBJ*
+FASTCALL
+SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
+                   IN PVOID Bits)
+{
+    BOOLEAN Compressed = FALSE;
+    ULONG ScanLine = 0; // Compiler is dumb
+    ULONG Size;
+    SURFOBJ *pso;
+    PSURFACE psurf;
+    SIZEL LocalSize;
+    BOOLEAN AllocatedLocally = FALSE;
+
+    /*
+     * First, check the format so we can get the aligned scanline width.
+     * RLE and the newer fancy-smanshy JPG/PNG support do NOT have scanlines
+     * since they are compressed surfaces!
+     */
+    switch (BitmapInfo->Format)
     {
-      SurfObj->pvScan0 = SurfObj->pvBits;
+        case BMF_1BPP:
+            ScanLine = ((BitmapInfo->Width + 31) & ~31) >> 3;
+            break;
+
+        case BMF_4BPP:
+            ScanLine = ((BitmapInfo->Width + 7) & ~7) >> 1;
+            break;
+
+        case BMF_8BPP:
+            ScanLine = (BitmapInfo->Width + 3) & ~3;
+            break;
+
+        case BMF_16BPP:
+            ScanLine = ((BitmapInfo->Width + 1) & ~1) << 1;
+            break;
+
+        case BMF_24BPP:
+            ScanLine = ((BitmapInfo->Width * 3) + 3) & ~3;
+            break;
+
+        case BMF_32BPP:
+            ScanLine = BitmapInfo->Width << 2;
+            break;
+
+        case BMF_8RLE:
+        case BMF_4RLE:
+        case BMF_JPEG:
+        case BMF_PNG:
+            Compressed = TRUE;
+            break;
+
+        default:
+            DPRINT1("Invalid bitmap format\n");
+            return NULL;
     }
 
-  SurfObj->dhsurf = 0; /* device managed surface */
-  SurfObj->hsurf = (HSURF)NewBitmap;
-  SurfObj->dhpdev = NULL;
-  SurfObj->hdev = NULL;
-  SurfObj->sizlBitmap = Size;
-  SurfObj->iBitmapFormat = UncompressedFormat;
-  SurfObj->iType = STYPE_BITMAP;
-  SurfObj->fjBitmap = Flags & (BMF_TOPDOWN | BMF_NOZEROINIT);
-  SurfObj->iUniq = 0;
+    /* Does the device manage its own surface? */
+    if (!Bits)
+    {
+        /* We need to allocate bits for the caller, figure out the size */
+        if (Compressed)
+        {
+            /* Note: we should not be seeing this scenario from ENGDDI */
+            ASSERT(FALSE);
+            Size = BitmapInfo->Size;
+        }
+        else
+        {
+            /* The height times the bytes for each scanline */
+            Size = BitmapInfo->Height * ScanLine;
+        }
+        
+        if (Size)
+        {
+            /* Check for allocation flag */
+            if (BitmapInfo->Flags & BMF_USERMEM)
+            {
+                /* Get the bits from user-mode memory */
+                Bits = EngAllocUserMem(Size, 'mbuG');
+            }
+            else
+            {
+                /* Get kernel bits (zeroed out if requested) */
+                Bits = EngAllocMem((BitmapInfo->Flags & BMF_NOZEROINIT) ? 0 : FL_ZERO_MEMORY,
+                                   Size,
+                                   TAG_DIB);
+            }
+            AllocatedLocally = TRUE;
+            /* Bail out if that failed */
+            if (!Bits) return NULL;
+        }
+    }
+    else
+    {
+        /* Should not have asked for user memory */
+        ASSERT((BitmapInfo->Flags & BMF_USERMEM) == 0);
+    }
 
-  BitmapObj->flHooks = 0;
-  BitmapObj->flFlags = 0;
-  BitmapObj->dimension.cx = 0;
-  BitmapObj->dimension.cy = 0;
-  BitmapObj->dib = NULL;
+    /* Allocate the actual surface object structure */
+    psurf = SURFACE_AllocSurfaceWithHandle();
+    if (!psurf)
+    {
+        if(Bits && AllocatedLocally)
+        {
+            if(BitmapInfo->Flags & BMF_USERMEM)
+                EngFreeUserMem(Bits);
+            else
+                EngFreeMem(Bits);
+        }
+        return NULL;
+    }
 
-  BITMAPOBJ_UnlockBitmap(BitmapObj);
+    /* Lock down the surface */
+    if (!SURFACE_InitBitsLock(psurf))
+    {
+        /* Bail out if that failed */
+        SURFACE_UnlockSurface(psurf);
+        SURFACE_FreeSurfaceByHandle(psurf->BaseObject.hHmgr);
+        return NULL;
+    }
 
-  return NewBitmap;
+    /* We should now have our surface object */
+    pso = &psurf->SurfObj;
+
+    /* Save format and flags */
+    pso->iBitmapFormat = BitmapInfo->Format;
+    pso->fjBitmap = BitmapInfo->Flags & (BMF_TOPDOWN | BMF_UMPDMEM | BMF_USERMEM);
+
+    /* Save size and type */
+    LocalSize.cy = BitmapInfo->Height;
+    LocalSize.cx = BitmapInfo->Width;
+    pso->sizlBitmap = LocalSize;
+    pso->iType = STYPE_BITMAP;
+    
+    /* Device-managed surface, no flags or dimension */
+    pso->dhsurf = 0;
+    pso->dhpdev = NULL;
+    pso->hdev = NULL;
+    psurf->flFlags = 0;
+    psurf->dimension.cx = 0;
+    psurf->dimension.cy = 0;
+    psurf->hSecure = NULL;
+    psurf->hDIBSection = NULL;
+    psurf->flHooks = 0;
+    
+    /* Set bits */
+    pso->pvBits = Bits;
+    
+    /* Check for bitmap type */
+    if (!Compressed)
+    {
+        /* Number of bits is based on the height times the scanline */
+        pso->cjBits = BitmapInfo->Height * ScanLine;
+        if (BitmapInfo->Flags & BMF_TOPDOWN)
+        {
+            /* For topdown, the base address starts with the bits */
+            pso->pvScan0 = pso->pvBits;
+            pso->lDelta = ScanLine;
+        }
+        else
+        {
+            /* Otherwise we start with the end and go up */
+            pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ScanLine);
+            pso->lDelta = -ScanLine;
+        }
+    }
+    else
+    {
+        /* Compressed surfaces don't have scanlines! */
+        ASSERT(FALSE); // Should not get here on ENGDDI
+        pso->lDelta = 0;
+        pso->cjBits = BitmapInfo->Size;
+        
+        /* Check for JPG or PNG */
+        if ((BitmapInfo->Format != BMF_JPEG) && (BitmapInfo->Format != BMF_PNG))
+        {
+            /* Wherever the bit data is */
+            pso->pvScan0 = pso->pvBits;
+        }
+        else
+        {
+            /* Fancy formats don't use a base address */
+            pso->pvScan0 = NULL;
+            ASSERT(FALSE); // ENGDDI shouldn't be creating PNGs for drivers ;-)
+        }
+    }
+    
+    /* 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;
 }
 
 /*
  * @implemented
  */
-HBITMAP STDCALL
+HBITMAP
+APIENTRY
 EngCreateBitmap(IN SIZEL Size,
-               IN LONG Width,
-               IN ULONG Format,
-               IN ULONG Flags,
-               IN PVOID Bits)
+                IN LONG Width,
+                IN ULONG Format,
+                IN ULONG Flags,
+                IN PVOID Bits)
 {
-  HBITMAP NewBitmap;
-
-  NewBitmap = IntCreateBitmap(Size, Width, Format, Flags, Bits);
-  if ( !NewBitmap )
-         return 0;
-
-  GDIOBJ_SetOwnership(NewBitmap, NULL);
-
-  return NewBitmap;
+    SURFOBJ* Surface;
+    DEVBITMAPINFO BitmapInfo;
+    
+    /* Capture the parameters */
+    BitmapInfo.Format = Format;
+    BitmapInfo.Width = Size.cx;
+    BitmapInfo.Height = Size.cy;
+    BitmapInfo.Flags = Flags;
+
+    /*
+     * If the display driver supports framebuffer access, use the scanline width
+     * to determine the actual width of the bitmap, and convert it to pels instead
+     * of bytes.
+     */
+    if ((Bits) && (Width))
+    {
+        switch (BitmapInfo.Format)
+        {
+            /* Do the conversion for each bit depth we support */
+            case BMF_1BPP:
+                BitmapInfo.Width = Width * 8;
+                break;
+            case BMF_4BPP:
+                BitmapInfo.Width = Width * 2;
+                break;
+            case BMF_8BPP:
+                BitmapInfo.Width = Width;
+                break;
+            case BMF_16BPP:
+                BitmapInfo.Width = Width / 2;
+                break;
+            case BMF_24BPP:
+                BitmapInfo.Width = Width / 3;
+                break;
+            case BMF_32BPP:
+                BitmapInfo.Width = Width / 4;
+                break;
+        }
+    }
+    
+    /* Now create the surface */
+    Surface = SURFMEM_bCreateDib(&BitmapInfo, Bits);
+    if (!Surface) return 0;
+
+    /* Set public ownership and reutrn the handle */
+    GDIOBJ_SetOwnership(Surface->hsurf, NULL);
+    return Surface->hsurf;
 }
 
 /*
  * @unimplemented
  */
-HSURF STDCALL
+HSURF APIENTRY
 EngCreateDeviceSurface(IN DHSURF dhsurf,
-                      IN SIZEL Size,
-                      IN ULONG Format)
+                       IN SIZEL Size,
+                       IN ULONG Format)
 {
-  HSURF NewSurface;
-  SURFOBJ *SurfObj;
-  BITMAPOBJ *BitmapObj;
+    HSURF hsurf;
+    SURFOBJ *pso;
+    PSURFACE psurf;
 
-  NewSurface = (HSURF)BITMAPOBJ_AllocBitmapDepricated();
-  if (NewSurface == NULL)
-       return 0;
+    psurf = SURFACE_AllocSurfaceWithHandle();
+    if (!psurf)
+    {
+        return 0;
+    }
 
-  GDIOBJ_SetOwnership(NewSurface, NULL);
+    hsurf = psurf->BaseObject.hHmgr;
+    GDIOBJ_SetOwnership(hsurf, NULL);
 
-  BitmapObj = BITMAPOBJ_LockBitmap(NewSurface);
-  if (! BITMAPOBJ_InitBitsLock(BitmapObj))
+    if (!SURFACE_InitBitsLock(psurf))
     {
-      BITMAPOBJ_UnlockBitmap(BitmapObj);
-      BITMAPOBJ_FreeBitmapByHandle(NewSurface);
-      return 0;
+        SURFACE_UnlockSurface(psurf);
+        SURFACE_FreeSurfaceByHandle(hsurf);
+        return 0;
     }
-  SurfObj = &BitmapObj->SurfObj;
+    pso = &psurf->SurfObj;
 
-  SurfObj->dhsurf = dhsurf;
-  SurfObj->hsurf = NewSurface;
-  SurfObj->sizlBitmap = Size;
-  SurfObj->iBitmapFormat = Format;
-  SurfObj->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format));
-  SurfObj->iType = STYPE_DEVICE;
-  SurfObj->iUniq = 0;
+    pso->dhsurf = dhsurf;
+    pso->hsurf = hsurf;
+    pso->sizlBitmap = Size;
+    pso->iBitmapFormat = Format;
+    pso->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format));
+    pso->iType = STYPE_DEVICE;
+    pso->iUniq = 0;
 
-  BitmapObj->flHooks = 0;
+    psurf->flHooks = 0;
 
-  BITMAPOBJ_UnlockBitmap(BitmapObj);
+    SURFACE_UnlockSurface(psurf);
 
-  return NewSurface;
-}
-
-PFN FASTCALL DriverFunction(DRVENABLEDATA *DED, ULONG DriverFunc)
-{
-  ULONG i;
-
-  for(i=0; i<DED->c; i++)
-  {
-    if(DED->pdrvfn[i].iFunc == DriverFunc)
-      return DED->pdrvfn[i].pfn;
-  }
-  return NULL;
+    return hsurf;
 }
 
 /*
  * @implemented
  */
-BOOL STDCALL
-EngAssociateSurface(IN HSURF Surface,
-                   IN HDEV Dev,
-                   IN ULONG Hooks)
+BOOL
+APIENTRY
+EngAssociateSurface(
+    IN HSURF hsurf,
+    IN HDEV hdev,
+    IN FLONG flHooks)
 {
-  SURFOBJ *SurfObj;
-  BITMAPOBJ *BitmapObj;
-  GDIDEVICE* Device;
+    SURFOBJ *pso;
+    PSURFACE psurf;
+    PDEVOBJ* ppdev;
 
-  Device = (GDIDEVICE*)Dev;
+    ppdev = (PDEVOBJ*)hdev;
 
-  BitmapObj = BITMAPOBJ_LockBitmap(Surface);
-  ASSERT(BitmapObj);
-  SurfObj = &BitmapObj->SurfObj;
+    /* Lock the surface */
+    psurf = SURFACE_LockSurface(hsurf);
+    if (!psurf)
+    {
+        return FALSE;
+    }
+    pso = &psurf->SurfObj;
 
-  /* Associate the hdev */
-  SurfObj->hdev = Dev;
-  SurfObj->dhpdev = Device->hPDev;
+    /* Associate the hdev */
+    pso->hdev = hdev;
+    pso->dhpdev = ppdev->dhpdev;
 
-  /* Hook up specified functions */
-  BitmapObj->flHooks = Hooks;
+    /* Hook up specified functions */
+    psurf->flHooks = flHooks;
 
-  BITMAPOBJ_UnlockBitmap(BitmapObj);
+    SURFACE_UnlockSurface(psurf);
 
-  return TRUE;
+    return TRUE;
 }
 
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL APIENTRY
 EngModifySurface(
-   IN HSURF hsurf,
-   IN HDEV hdev,
-   IN FLONG flHooks,
-   IN FLONG flSurface,
-   IN DHSURF dhsurf,
-   OUT VOID *pvScan0,
-   IN LONG lDelta,
-   IN VOID *pvReserved)
+    IN HSURF hsurf,
+    IN HDEV hdev,
+    IN FLONG flHooks,
+    IN FLONG flSurface,
+    IN DHSURF dhsurf,
+    OUT VOID *pvScan0,
+    IN LONG lDelta,
+    IN VOID *pvReserved)
 {
-   SURFOBJ *pso;
+    SURFOBJ *pso;
+    PSURFACE psurf;
+    PDEVOBJ* ppdev;
 
-   pso = EngLockSurface(hsurf);
-   if (pso == NULL)
-   {
-      return FALSE;
-   }
+    psurf = SURFACE_LockSurface(hsurf);
+    if (psurf == NULL)
+    {
+        return FALSE;
+    }
 
-   if (!EngAssociateSurface(hsurf, hdev, flHooks))
-   {
-      EngUnlockSurface(pso);
+    ppdev = (PDEVOBJ*)hdev;
+    pso = &psurf->SurfObj;
+    pso->dhsurf = dhsurf;
+    pso->lDelta = lDelta;
+    pso->pvScan0 = pvScan0;
 
-      return FALSE;
-   }
+    /* Associate the hdev */
+    pso->hdev = hdev;
+    pso->dhpdev = ppdev->dhpdev;
 
-   pso->dhsurf = dhsurf;
-   pso->lDelta = lDelta;
-   pso->pvScan0 = pvScan0;
+    /* Hook up specified functions */
+    psurf->flHooks = flHooks;
 
-   EngUnlockSurface(pso);
+    SURFACE_UnlockSurface(psurf);
 
-   return TRUE;
+    return TRUE;
 }
 
 /*
  * @implemented
  */
-BOOL STDCALL
-EngDeleteSurface(IN HSURF Surface)
+BOOL APIENTRY
+EngDeleteSurface(IN HSURF hsurf)
 {
-   GDIOBJ_SetOwnership(Surface, PsGetCurrentProcess());
-   BITMAPOBJ_FreeBitmapByHandle(Surface);
-   return TRUE;
+    GDIOBJ_SetOwnership(hsurf, PsGetCurrentProcess());
+    SURFACE_FreeSurfaceByHandle(hsurf);
+    return TRUE;
 }
 
 /*
  * @implemented
  */
-BOOL STDCALL
-EngEraseSurface(SURFOBJ *Surface,
-               RECTL *Rect,
-               ULONG iColor)
+BOOL APIENTRY
+EngEraseSurface(SURFOBJ *pso,
+                RECTL *Rect,
+                ULONG iColor)
 {
-  ASSERT(Surface);
-  ASSERT(Rect);
-  return FillSolid(Surface, Rect, iColor);
+    ASSERT(pso);
+    ASSERT(Rect);
+    return FillSolid(pso, Rect, iColor);
 }
 
-#define GDIBdyToHdr(body)                                                      \
-  ((PGDIOBJHDR)(body) - 1)
-
-
 /*
  * @implemented
  */
-SURFOBJ * STDCALL
-NtGdiEngLockSurface(IN HSURF Surface)
+SURFOBJ * APIENTRY
+NtGdiEngLockSurface(IN HSURF hsurf)
 {
-    return EngLockSurface(Surface);
+    return EngLockSurface(hsurf);
 }
 
 
 /*
  * @implemented
  */
-SURFOBJ * STDCALL
-EngLockSurface(IN HSURF Surface)
+SURFOBJ * APIENTRY
+EngLockSurface(IN HSURF hsurf)
 {
-   BITMAPOBJ *bmp = GDIOBJ_ShareLockObj(Surface, GDI_OBJECT_TYPE_BITMAP);
+    SURFACE *psurf = GDIOBJ_ShareLockObj(hsurf, GDI_OBJECT_TYPE_BITMAP);
 
-   if (bmp != NULL)
-      return &bmp->SurfObj;
+    if (psurf != NULL)
+        return &psurf->SurfObj;
 
-   return NULL;
+    return NULL;
 }
 
 
 /*
  * @implemented
  */
-VOID STDCALL
-NtGdiEngUnlockSurface(IN SURFOBJ *Surface)
+VOID APIENTRY
+NtGdiEngUnlockSurface(IN SURFOBJ *pso)
 {
-    EngUnlockSurface(Surface);
+    EngUnlockSurface(pso);
 }
 
 /*
  * @implemented
  */
-VOID STDCALL
-EngUnlockSurface(IN SURFOBJ *Surface)
+VOID APIENTRY
+EngUnlockSurface(IN SURFOBJ *pso)
 {
-   if (Surface != NULL)
-   {
-      BITMAPOBJ *bmp = CONTAINING_RECORD(Surface, BITMAPOBJ, SurfObj);
-      GDIOBJ_ShareUnlockObjByPtr((POBJ)bmp);
-   }
+    if (pso != NULL)
+    {
+        SURFACE *psurf = CONTAINING_RECORD(pso, SURFACE, SurfObj);
+        GDIOBJ_ShareUnlockObjByPtr((POBJ)psurf);
+    }
 }