* PROJECT: ReactOS kernel
* PURPOSE: GDI Driver Surace Functions
* FILE: subsys/win32k/eng/surface.c
- * PROGRAMER: Jason Filby
+ * PROGRAMERS: Jason Filby
+ * Timo Kreuzer
* REVISION HISTORY:
* 3/7/1999: Created
* 9/11/2000: Updated to handle real pixel packed bitmaps (UPDATE TO DATE COMPLETED)
* refer to \test\microwin\src\engine\devdraw.c for info on correct pixel plotting for various formats
*/
-#include <w32k.h>
+#include <win32k.h>
#define NDEBUG
#include <debug.h>
-enum Rle_EscapeCodes
-{
- RLE_EOL = 0, /* End of line */
- RLE_END = 1, /* End of bitmap */
- RLE_DELTA = 2 /* Delta */
-};
+ULONG giUniqueSurface = 0;
-INT FASTCALL BitsPerFormat(ULONG Format)
+UCHAR
+gajBitsPerFormat[11] =
{
- 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;
+ 0, /* 0: unused */
+ 1, /* 1: BMF_1BPP */
+ 4, /* 2: BMF_4BPP */
+ 8, /* 3: BMF_8BPP */
+ 16, /* 4: BMF_16BPP */
+ 24, /* 5: BMF_24BPP */
+ 32, /* 6: BMF_32BPP */
+ 4, /* 7: BMF_4RLE */
+ 8, /* 8: BMF_8RLE */
+ 0, /* 9: BMF_JPEG */
+ 0, /* 10: BMF_PNG */
+};
- default:
- return 0;
- }
-}
ULONG FASTCALL BitmapFormat(WORD Bits, DWORD Compression)
{
}
}
-BOOL INTERNAL_CALL
+BOOL
+INTERNAL_CALL
SURFACE_Cleanup(PVOID ObjectBody)
{
PSURFACE psurf = (PSURFACE)ObjectBody;
PVOID pvBits = psurf->SurfObj.pvBits;
+ NTSTATUS Status;
- /* If this is an API bitmap, free the bits */
- if (pvBits != NULL &&
- (psurf->flFlags & BITMAPOBJ_IS_APIBITMAP))
+ /* Check if the surface has bits */
+ if (pvBits)
{
- /* Check if we have a DIB section */
- if (psurf->hSecure)
+ /* Only bitmaps can have bits */
+ ASSERT(psurf->SurfObj.iType == STYPE_BITMAP);
+
+ /* Check if it is a DIB section */
+ if (psurf->hDIBSection)
{
- // FIXME: IMPLEMENT ME!
- // MmUnsecureVirtualMemory(psurf->hSecure);
- if (psurf->hDIBSection)
+ /* Unsecure the memory */
+ EngUnsecureMem(psurf->hSecure);
+
+ /* Calculate the real start of the section */
+ pvBits = (PVOID)((ULONG_PTR)pvBits - psurf->dwOffset);
+
+ /* Unmap the section */
+ Status = MmUnmapViewOfSection(PsGetCurrentProcess(), pvBits);
+ if (!NT_SUCCESS(Status))
{
- /* 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?
- }
+ DPRINT1("Could not unmap section view!\n");
+ // Should we BugCheck here?
+ ASSERT(FALSE);
}
- else
+ }
+ else if (psurf->SurfObj.fjBitmap & BMF_USERMEM)
+ {
+ /* Bitmap was allocated from usermode memory */
+ EngFreeUserMem(pvBits);
+ }
+ else if (psurf->SurfObj.fjBitmap & BMF_KMSECTION)
+ {
+ /* Bitmap was allocated from a kernel section */
+ if (!EngFreeSectionMem(NULL, pvBits))
{
- /* DIB was allocated */
- EngFreeUserMem(pvBits);
+ DPRINT1("EngFreeSectionMem failed for %p!\n", pvBits);
+ // Should we BugCheck here?
+ ASSERT(FALSE);
}
}
- else
+ else if (psurf->SurfObj.fjBitmap & BMF_RLE_HACK)
{
- // FIXME: use TAG
- ExFreePool(psurf->SurfObj.pvBits);
+ /* HACK: Free RLE decompressed bits */
+ EngFreeMem(pvBits);
}
-
- if (psurf->hDIBPalette != NULL)
+ else
{
- GreDeleteObject(psurf->hDIBPalette);
+ /* There should be nothing to free */
+ ASSERT(psurf->SurfObj.fjBitmap & BMF_DONT_FREE);
}
}
- if (NULL != psurf->BitsLock)
+ /* Free palette */
+ if(psurf->ppal)
{
- ExFreePoolWithTag(psurf->BitsLock, TAG_SURFACE);
- psurf->BitsLock = NULL;
+ PALETTE_ShareUnlockPalette(psurf->ppal);
}
return TRUE;
}
-BOOL INTERNAL_CALL
-SURFACE_InitBitsLock(PSURFACE psurf)
+
+PSURFACE
+NTAPI
+SURFACE_AllocSurface(
+ IN ULONG iType,
+ IN ULONG cx,
+ IN ULONG cy,
+ IN ULONG iFormat)
{
- psurf->BitsLock = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(FAST_MUTEX),
- TAG_SURFACE);
- if (NULL == psurf->BitsLock)
+ PSURFACE psurf;
+ SURFOBJ *pso;
+
+ /* Verify format */
+ if (iFormat < BMF_1BPP || iFormat > BMF_PNG)
{
- return FALSE;
+ DPRINT1("Invalid bitmap format: %ld\n", iFormat);
+ return NULL;
}
- ExInitializeFastMutex(psurf->BitsLock);
-
- return TRUE;
-}
+ /* Allocate a SURFACE object */
+ psurf = (PSURFACE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP);
-void INTERNAL_CALL
-SURFACE_CleanupBitsLock(PSURFACE psurf)
-{
- if (NULL != psurf->BitsLock)
+ if (psurf)
{
- ExFreePoolWithTag(psurf->BitsLock, TAG_SURFACE);
- psurf->BitsLock = NULL;
+ /* Initialize the basic fields */
+ pso = &psurf->SurfObj;
+ pso->hsurf = psurf->BaseObject.hHmgr;
+ pso->sizlBitmap.cx = cx;
+ pso->sizlBitmap.cy = cy;
+ pso->iBitmapFormat = iFormat;
+ pso->iType = iType;
+ pso->iUniq = InterlockedIncrement((PLONG)&giUniqueSurface);
+
+ /* Assign a default palette amd increment its reference count */
+ psurf->ppal = appalSurfaceDefault[iFormat];
+ GDIOBJ_IncrementShareCount(&psurf->ppal->BaseObject);
}
-}
+ return psurf;
+}
-/*
- * @implemented
- */
-HBITMAP APIENTRY
-EngCreateDeviceBitmap(IN DHSURF dhsurf,
- IN SIZEL Size,
- IN ULONG Format)
+BOOL
+NTAPI
+SURFACE_bSetBitmapBits(
+ IN PSURFACE psurf,
+ IN USHORT fjBitmap,
+ IN ULONG ulWidth,
+ IN PVOID pvBits OPTIONAL)
{
- HBITMAP NewBitmap;
- SURFOBJ *pso;
+ SURFOBJ *pso = &psurf->SurfObj;
+ PVOID pvSection;
+ UCHAR cBitsPixel;
- NewBitmap = EngCreateBitmap(Size, DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format)), Format, 0, NULL);
- if (!NewBitmap)
- {
- DPRINT1("EngCreateBitmap failed\n");
- return 0;
- }
+ /* Only bitmaps can have bits */
+ ASSERT(psurf->SurfObj.iType == STYPE_BITMAP);
+
+ /* Get bits per pixel from the format */
+ cBitsPixel = gajBitsPerFormat[pso->iBitmapFormat];
- pso = EngLockSurface((HSURF)NewBitmap);
- if (!pso)
+ /* Is a width in bytes given? */
+ if (!ulWidth)
{
- DPRINT1("EngLockSurface failed on newly created bitmap!\n");
- GreDeleteObject(NewBitmap);
- return NULL;
+ /* Calculate width from the bitmap width in pixels */
+ ulWidth = DIB_GetDIBWidthBytes(psurf->SurfObj.sizlBitmap.cx, cBitsPixel);
}
+ else
+ {
+ /* Align the width (windows compatibility, drivers expect that) */
+ ulWidth = ((((ulWidth << 3) / cBitsPixel) * cBitsPixel + 31) & ~31) >> 3;
+ }
- pso->dhsurf = dhsurf;
- EngUnlockSurface(pso);
- return NewBitmap;
-}
+ /* Calculate the bitmap size in bytes */
+ pso->cjBits = ulWidth * pso->sizlBitmap.cy;
-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)
+ /* Did the caller provide bits? */
+ if (pvBits)
{
- 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++;
- }
- }
- }
+ /* Yes, so let him free it */
+ fjBitmap |= BMF_DONT_FREE;
}
-}
-
-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)
+ else if (pso->cjBits)
{
- length = *bits++;
- if (length)
+ /* We must allocate memory, check what kind */
+ if (fjBitmap & BMF_USERMEM)
{
- c = *bits++;
- while (length--)
- {
- if (x >= width) break;
- temp = UncompressedBits + (((height - y) * Delta) + x);
- x++;
- *temp = c;
- }
+ /* User mode memory was requested */
+ pvBits = EngAllocUserMem(pso->cjBits, 0);
}
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++;
- }
- }
+ /* Use a kernel mode section */
+ fjBitmap |= BMF_KMSECTION;
+ pvBits = EngAllocSectionMem(&pvSection,
+ (fjBitmap & BMF_NOZEROINIT) ?
+ 0 : FL_ZERO_MEMORY,
+ pso->cjBits, TAG_DIB);
+
+ /* Free the section already, but keep the mapping */
+ if (pvBits) EngFreeSectionMem(pvSection, NULL);
}
- }
-}
-HBITMAP FASTCALL
-IntCreateBitmap(IN SIZEL Size,
- IN LONG Width,
- IN ULONG Format,
- IN ULONG Flags,
- IN PVOID Bits)
-{
- HBITMAP hbmp;
- SURFOBJ *pso;
- PSURFACE psurf;
- PVOID UncompressedBits;
- ULONG UncompressedFormat;
-
- if (Format == 0)
- return 0;
-
- psurf = SURFACE_AllocSurfaceWithHandle();
- if (psurf == NULL)
- {
- return 0;
+ /* Check for failure */
+ if (!pvBits) return FALSE;
}
- hbmp = psurf->BaseObject.hHmgr;
- if (! SURFACE_InitBitsLock(psurf))
+ /* Set pvBits, pvScan0 and lDelta */
+ pso->pvBits = pvBits;
+ if (fjBitmap & BMF_TOPDOWN)
{
- 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);
+ /* Topdown is the normal way */
+ pso->pvScan0 = pso->pvBits;
+ pso->lDelta = ulWidth;
}
else
{
- pso->lDelta = abs(Width);
- pso->cjBits = pso->lDelta * Size.cy;
- UncompressedBits = Bits;
- UncompressedFormat = Format;
+ /* Inversed bitmap (bottom up) */
+ pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ulWidth);
+ pso->lDelta = -ulWidth;
}
- if (UncompressedBits != NULL)
- {
- pso->pvBits = UncompressedBits;
- }
- else
- {
- if (pso->cjBits == 0)
- {
- pso->pvBits = NULL;
- }
- else
- {
- if (0 != (Flags & BMF_USERMEM))
- {
- pso->pvBits = EngAllocUserMem(pso->cjBits, 0);
- }
- else
- {
- 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;
- }
- }
- }
+ pso->fjBitmap = fjBitmap;
- if (0 == (Flags & BMF_TOPDOWN))
+ /* Success */
+ return TRUE;
+}
+
+HBITMAP
+APIENTRY
+EngCreateBitmap(
+ IN SIZEL sizl,
+ IN LONG lWidth,
+ IN ULONG iFormat,
+ IN ULONG fl,
+ IN PVOID pvBits)
+{
+ PSURFACE psurf;
+ HBITMAP hbmp;
+
+ /* Allocate a surface */
+ psurf = SURFACE_AllocSurface(STYPE_BITMAP, sizl.cx, sizl.cy, iFormat);
+ if (!psurf)
{
- pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - pso->lDelta);
- pso->lDelta = - pso->lDelta;
+ DPRINT1("SURFACE_AllocSurface failed.\n");
+ return NULL;
}
- else
+
+ /* Get the handle for the bitmap */
+ hbmp = (HBITMAP)psurf->SurfObj.hsurf;
+
+ /* Set the bitmap bits */
+ if (!SURFACE_bSetBitmapBits(psurf, fl, lWidth, pvBits))
{
- pso->pvScan0 = pso->pvBits;
+ /* Bail out if that failed */
+ DPRINT1("SURFACE_bSetBitmapBits failed.\n");
+ SURFACE_FreeSurfaceByHandle(hbmp);
+ return NULL;
}
- 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;
+ /* Set public ownership */
+ GDIOBJ_SetOwnership(hbmp, NULL);
+ /* Unlock the surface and return */
SURFACE_UnlockSurface(psurf);
-
return hbmp;
}
/*
* @implemented
*/
-HBITMAP APIENTRY
-EngCreateBitmap(IN SIZEL Size,
- IN LONG Width,
- IN ULONG Format,
- IN ULONG Flags,
- IN PVOID Bits)
+HBITMAP
+APIENTRY
+EngCreateDeviceBitmap(
+ IN DHSURF dhsurf,
+ IN SIZEL sizl,
+ IN ULONG iFormat)
{
- HBITMAP hNewBitmap;
+ PSURFACE psurf;
+ HBITMAP hbmp;
- hNewBitmap = IntCreateBitmap(Size, Width, Format, Flags, Bits);
- if ( !hNewBitmap )
+ /* Allocate a surface */
+ psurf = SURFACE_AllocSurface(STYPE_DEVBITMAP, sizl.cx, sizl.cy, iFormat);
+ if (!psurf)
+ {
return 0;
+ }
+
+ /* Set the device handle */
+ psurf->SurfObj.dhsurf = dhsurf;
+
+ /* Get the handle for the bitmap */
+ hbmp = (HBITMAP)psurf->SurfObj.hsurf;
- GDIOBJ_SetOwnership(hNewBitmap, NULL);
+ /* Set public ownership */
+ GDIOBJ_SetOwnership(hbmp, NULL);
- return hNewBitmap;
+ /* Unlock the surface and return */
+ SURFACE_UnlockSurface(psurf);
+ return hbmp;
}
-/*
- * @unimplemented
- */
-HSURF APIENTRY
-EngCreateDeviceSurface(IN DHSURF dhsurf,
- IN SIZEL Size,
- IN ULONG Format)
+HSURF
+APIENTRY
+EngCreateDeviceSurface(
+ IN DHSURF dhsurf,
+ IN SIZEL sizl,
+ IN ULONG iFormat)
{
- HSURF hsurf;
- SURFOBJ *pso;
PSURFACE psurf;
+ HSURF hsurf;
- psurf = SURFACE_AllocSurfaceWithHandle();
+ /* Allocate a surface */
+ psurf = SURFACE_AllocSurface(STYPE_DEVICE, sizl.cx, sizl.cy, iFormat);
if (!psurf)
{
return 0;
}
- hsurf = psurf->BaseObject.hHmgr;
- GDIOBJ_SetOwnership(hsurf, NULL);
-
- if (!SURFACE_InitBitsLock(psurf))
- {
- SURFACE_UnlockSurface(psurf);
- SURFACE_FreeSurfaceByHandle(hsurf);
- return 0;
- }
- pso = &psurf->SurfObj;
+ /* Set the device handle */
+ psurf->SurfObj.dhsurf = dhsurf;
- 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;
+ /* Get the handle for the surface */
+ hsurf = psurf->SurfObj.hsurf;
- psurf->flHooks = 0;
+ /* Set public ownership */
+ GDIOBJ_SetOwnership(hsurf, NULL);
+ /* Unlock the surface and return */
SURFACE_UnlockSurface(psurf);
-
return hsurf;
}
-/*
- * @implemented
- */
BOOL
APIENTRY
EngAssociateSurface(
pso->dhpdev = ppdev->dhpdev;
/* Hook up specified functions */
- psurf->flHooks = flHooks;
+ psurf->flags &= ~HOOK_FLAGS;
+ psurf->flags |= (flHooks & HOOK_FLAGS);
+
+ /* Get palette */
+ psurf->ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault);
SURFACE_UnlockSurface(psurf);
return TRUE;
}
-/*
- * @implemented
- */
-BOOL APIENTRY
+BOOL
+APIENTRY
EngModifySurface(
IN HSURF hsurf,
IN HDEV hdev,
pso->dhpdev = ppdev->dhpdev;
/* Hook up specified functions */
- psurf->flHooks = flHooks;
+ psurf->flags &= ~HOOK_FLAGS;
+ psurf->flags |= (flHooks & HOOK_FLAGS);
+
+ /* Get palette */
+ psurf->ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault);
SURFACE_UnlockSurface(psurf);
return TRUE;
}
-/*
- * @implemented
- */
-BOOL APIENTRY
+
+BOOL
+APIENTRY
EngDeleteSurface(IN HSURF hsurf)
{
GDIOBJ_SetOwnership(hsurf, PsGetCurrentProcess());
return TRUE;
}
-/*
- * @implemented
- */
-BOOL APIENTRY
-EngEraseSurface(SURFOBJ *pso,
- RECTL *Rect,
- ULONG iColor)
+BOOL
+APIENTRY
+EngEraseSurface(
+ SURFOBJ *pso,
+ RECTL *prcl,
+ ULONG iColor)
{
ASSERT(pso);
- ASSERT(Rect);
- return FillSolid(pso, Rect, iColor);
+ ASSERT(prcl);
+ return FillSolid(pso, prcl, iColor);
}
/*
}
-/*
- * @implemented
- */
-SURFOBJ * APIENTRY
+SURFOBJ *
+APIENTRY
EngLockSurface(IN HSURF hsurf)
{
SURFACE *psurf = GDIOBJ_ShareLockObj(hsurf, GDI_OBJECT_TYPE_BITMAP);
return NULL;
}
-
-/*
- * @implemented
- */
-VOID APIENTRY
+VOID
+APIENTRY
NtGdiEngUnlockSurface(IN SURFOBJ *pso)
{
EngUnlockSurface(pso);
}
-/*
- * @implemented
- */
-VOID APIENTRY
+VOID
+APIENTRY
EngUnlockSurface(IN SURFOBJ *pso)
{
if (pso != NULL)
}
}
-
/* EOF */