- Move RLE specific code to it's own file (rlecomp.c)
- Relace BitsPerFormat function with an array of UCHARs
- Rewrite surface creation. Surfaces are now allocated from one central function SURFACE_AllocSurface, which sets the size, iType, iUniq, the handle and the default palette.
- Implement SURFACE_vSetDefaultPalette, which sets the default RGB palette, based on bit depth.
- Implement SURFACE_bSetBitmapBits, wich sets cjBits, pvBits, pvScan0 and lDelta and allocates memory if neccessary.
- Use these functions for EngCreateBitmap, EngCreateDeviceBitmap, EngCreateDeviceSurface and IntCreateBitmap

svn path=/branches/reactos-yarotows/; revision=47612
This commit is contained in:
Timo Kreuzer 2010-06-06 07:02:15 +00:00
parent ca7f8096ff
commit 6068cac704
5 changed files with 454 additions and 594 deletions

View file

@ -0,0 +1,140 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: RLE compression
* FILE: subsystems/win32k/eng/rlecomp.c
* PROGRAMER: Jason Filby
*/
#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 */
};
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++;
}
}
}
}
}
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++;
}
}
}
}
}

View file

@ -3,7 +3,8 @@
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* PURPOSE: GDI Driver Surace Functions * PURPOSE: GDI Driver Surace Functions
* FILE: subsys/win32k/eng/surface.c * FILE: subsys/win32k/eng/surface.c
* PROGRAMER: Jason Filby * PROGRAMERS: Jason Filby
* Timo Kreuzer
* REVISION HISTORY: * REVISION HISTORY:
* 3/7/1999: Created * 3/7/1999: Created
* 9/11/2000: Updated to handle real pixel packed bitmaps (UPDATE TO DATE COMPLETED) * 9/11/2000: Updated to handle real pixel packed bitmaps (UPDATE TO DATE COMPLETED)
@ -17,43 +18,24 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
enum Rle_EscapeCodes ULONG giUniqueSurface = 0;
UCHAR
gajBitsPerFormat[11] =
{ {
RLE_EOL = 0, /* End of line */ 0, /* 0: unused */
RLE_END = 1, /* End of bitmap */ 1, /* 1: BMF_1BPP */
RLE_DELTA = 2 /* Delta */ 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 */
}; };
INT FASTCALL BitsPerFormat(ULONG Format)
{
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) ULONG FASTCALL BitmapFormat(WORD Bits, DWORD Compression)
{ {
@ -158,484 +140,189 @@ SURFACE_Cleanup(PVOID ObjectBody)
return TRUE; return TRUE;
} }
/* static
* @implemented void
*/ SURFACE_vSetDefaultPalette(
HBITMAP APIENTRY PSURFACE psurfBmp)
EngCreateDeviceBitmap(IN DHSURF dhsurf,
IN SIZEL Size,
IN ULONG Format)
{ {
HBITMAP NewBitmap; ULONG cBitsPixel = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat);
SURFOBJ *pso;
NewBitmap = EngCreateBitmap(Size, DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format)), Format, 0, NULL); /* Find a suitable palette for this bitmap
if (!NewBitmap) * Increment internal objects share count
* so we can call PALETTE_ShareUnlockPalette
* or GDIOBJ_IncrementShareCount safely */
switch(cBitsPixel)
{ {
DPRINT1("EngCreateBitmap failed\n"); case 1:
return 0; psurfBmp->ppal = &gpalMono;
} GDIOBJ_IncrementShareCount(&gpalMono.BaseObject);
pso = EngLockSurface((HSURF)NewBitmap);
if (!pso)
{
DPRINT1("EngLockSurface failed on newly created bitmap!\n");
GreDeleteObject(NewBitmap);
return NULL;
}
pso->dhsurf = dhsurf;
pso->iType = STYPE_DEVBITMAP;
EngUnlockSurface(pso);
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; break;
case RLE_END: case 4:
return; case 8:
case RLE_DELTA: psurfBmp->ppal = PALETTE_ShareLockPalette(StockObjects[DEFAULT_PALETTE]);
x += (*bits++)/2; break;
y -= (*bits++)/2; case 15:
psurfBmp->ppal = &gpalRGB555;
GDIOBJ_IncrementShareCount(&gpalRGB555.BaseObject);
break;
case 16:
psurfBmp->ppal = &gpalRGB565;
GDIOBJ_IncrementShareCount(&gpalRGB565.BaseObject);
break;
case 24:
case 32:
psurfBmp->ppal = &gpalRGB;
GDIOBJ_IncrementShareCount((POBJ)&gpalRGB);
break; break;
default: default:
length /= 2; DPRINT1("Could not determine palette for bit depth %u.\n", cBitsPixel);
while (length--) break;
{
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) PSURFACE
NTAPI
SURFACE_AllocSurface(
IN ULONG iType,
IN ULONG cx,
IN ULONG cy,
IN ULONG iFormat)
{ {
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)
{
HBITMAP hbmp;
SURFOBJ *pso;
PSURFACE psurf; PSURFACE psurf;
PVOID UncompressedBits; SURFOBJ *pso;
ULONG UncompressedFormat;
if (Format == 0) /* Allocate a SURFACE object */
return 0; psurf = (PSURFACE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP);
psurf = SURFACE_AllocSurfaceWithHandle(); if (psurf)
if (psurf == NULL)
{ {
return 0; /* Initialize the basic fields */
}
hbmp = psurf->BaseObject.hHmgr;
pso = &psurf->SurfObj; 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);
if (Format == BMF_4RLE) SURFACE_vSetDefaultPalette(psurf);
{
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);
Flags |= BMF_RLE_HACK;
}
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);
Flags |= BMF_RLE_HACK;
}
else
{
pso->lDelta = abs(Width);
pso->cjBits = pso->lDelta * Size.cy;
UncompressedBits = Bits;
UncompressedFormat = Format;
} }
if (UncompressedBits != NULL) return psurf;
{ }
pso->pvBits = UncompressedBits;
Flags |= BMF_DONT_FREE; BOOL
} NTAPI
else SURFACE_bSetBitmapBits(
{ IN PSURFACE psurf,
if (pso->cjBits == 0) IN USHORT fjBitmap,
{ IN ULONG ulWidth,
pso->pvBits = NULL; IN PVOID pvBits OPTIONAL)
} {
else SURFOBJ *pso = &psurf->SurfObj;
{
if (0 != (Flags & BMF_USERMEM))
{
pso->pvBits = EngAllocUserMem(pso->cjBits, 0);
}
else
{
PVOID pvSection; PVOID pvSection;
Flags |= BMF_KMSECTION;
pso->pvBits = EngAllocSectionMem(&pvSection, /* Only bitmaps can have bits */
(Flags & BMF_NOZEROINIT) ? ASSERT(psurf->SurfObj.iType == STYPE_BITMAP);
/* If no width is given, calculate it */
if (!ulWidth)
ulWidth = DIB_GetDIBWidthBytes(pso->sizlBitmap.cx,
BitsPerFormat(pso->iBitmapFormat));
/* Calculate the bitmap size in bytes */
pso->cjBits = ulWidth * pso->sizlBitmap.cy;
/* Did the caller provide bits? */
if (pvBits)
{
/* Yes, so let him free it */
fjBitmap |= BMF_DONT_FREE;
}
else if (pso->cjBits)
{
/* We must allocate memory, check what kind */
if (fjBitmap & BMF_USERMEM)
{
/* User mode memory was requested */
pvBits = EngAllocUserMem(pso->cjBits, 0);
}
else
{
/* Use a kernel mode section */
fjBitmap |= BMF_KMSECTION;
pvBits = EngAllocSectionMem(&pvSection,
(fjBitmap & BMF_NOZEROINIT) ?
0 : FL_ZERO_MEMORY, 0 : FL_ZERO_MEMORY,
pso->cjBits, TAG_DIB); pso->cjBits, TAG_DIB);
/* Free the section already, keep the mapping */ /* Free the section already, but keep the mapping */
EngFreeSectionMem(pvSection, NULL); if (pvBits) EngFreeSectionMem(pvSection, NULL);
}
if (pso->pvBits == NULL)
{
SURFACE_UnlockSurface(psurf);
SURFACE_FreeSurfaceByHandle(hbmp);
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
}
} }
if (0 == (Flags & BMF_TOPDOWN)) /* Check for failure */
if (!pvBits) return FALSE;
}
/* Set pvBits, pvScan0 and lDelta */
pso->pvBits = pvBits;
if (fjBitmap & BMF_TOPDOWN)
{ {
pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - pso->lDelta); /* Topdown is the normal way */
pso->lDelta = - pso->lDelta; pso->pvScan0 = pso->pvBits;
pso->lDelta = ulWidth;
} }
else else
{ {
pso->pvScan0 = pso->pvBits; /* Inversed bitmap (bottom up) */
pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ulWidth);
pso->lDelta = -ulWidth;
} }
pso->dhsurf = 0; /* device managed surface */ pso->fjBitmap = fjBitmap;
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|BMF_KMSECTION|BMF_USERMEM|BMF_DONT_FREE);
pso->iUniq = 0;
psurf->flags = 0; /* Success */
psurf->sizlDim.cx = 0; return TRUE;
psurf->sizlDim.cy = 0;
psurf->hSecure = NULL;
psurf->hDIBSection = NULL;
SURFACE_UnlockSurface(psurf);
return hbmp;
} }
/* Name gleaned from C++ symbol information for SURFMEM::bInitDIB */ HBITMAP
typedef struct _DEVBITMAPINFO APIENTRY
EngCreateBitmap(
IN SIZEL sizl,
IN LONG lWidth,
IN ULONG iFormat,
IN ULONG fl,
IN PVOID pvBits)
{ {
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; PSURFACE psurf;
SIZEL LocalSize; HBITMAP hbmp;
BOOLEAN AllocatedLocally = FALSE;
/* /* Allocate a surface */
* First, check the format so we can get the aligned scanline width. psurf = SURFACE_AllocSurface(STYPE_BITMAP, sizl.cx, sizl.cy, iFormat);
* RLE and the newer fancy-smanshy JPG/PNG support do NOT have scanlines
* since they are compressed surfaces!
*/
switch (BitmapInfo->Format)
{
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;
}
/* 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
{
PVOID pvSection;
BitmapInfo->Flags |= BMF_KMSECTION;
Bits = EngAllocSectionMem(&pvSection,
(BitmapInfo->Flags & BMF_NOZEROINIT) ?
0 : FL_ZERO_MEMORY,
Size, TAG_DIB);
/* Free the section already, keep the mapping */
EngFreeSectionMem(pvSection, NULL);
}
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);
/* Must not free anything */
BitmapInfo->Flags |= BMF_DONT_FREE;
}
/* Allocate the actual surface object structure */
psurf = SURFACE_AllocSurfaceWithHandle();
if (!psurf) if (!psurf)
{ {
if(Bits && AllocatedLocally) DPRINT1("SURFACE_AllocSurface failed.\n");
{
if(BitmapInfo->Flags & BMF_USERMEM)
EngFreeUserMem(Bits);
else
EngFreeMem(Bits);
}
return NULL; return NULL;
} }
/* We should now have our surface object */ /* Get the handle for the bitmap */
pso = &psurf->SurfObj; hbmp = (HBITMAP)psurf->SurfObj.hsurf;
/* Save format and flags */ /* Set the bitmap bits */
pso->iBitmapFormat = BitmapInfo->Format; if (!SURFACE_bSetBitmapBits(psurf, fl, lWidth, pvBits))
pso->fjBitmap = BitmapInfo->Flags & (BMF_TOPDOWN | BMF_UMPDMEM | BMF_USERMEM | BMF_KMSECTION | BMF_DONT_FREE);
/* 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->flags = 0;
psurf->sizlDim.cx = 0;
psurf->sizlDim.cy = 0;
psurf->hSecure = NULL;
psurf->hDIBSection = NULL;
/* Set bits */
pso->pvBits = Bits;
/* Check for bitmap type */
if (!Compressed)
{ {
/* Number of bits is based on the height times the scanline */ /* Bail out if that failed */
pso->cjBits = BitmapInfo->Height * ScanLine; DPRINT1("SURFACE_bSetBitmapBits failed.\n");
if (BitmapInfo->Flags & BMF_TOPDOWN) SURFACE_FreeSurfaceByHandle(hbmp);
{ return NULL;
/* 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! */
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 */ /* Set public ownership */
pso->hsurf = (HSURF)psurf->BaseObject.hHmgr; GDIOBJ_SetOwnership(hbmp, NULL);
pso->iUniq = 0;
/* Unlock and return the surface */ /* Unlock the surface and return */
SURFACE_UnlockSurface(psurf); SURFACE_UnlockSurface(psurf);
return pso; return hbmp;
} }
/* /*
@ -643,103 +330,66 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
*/ */
HBITMAP HBITMAP
APIENTRY APIENTRY
EngCreateBitmap(IN SIZEL Size, EngCreateDeviceBitmap(
IN LONG Width, IN DHSURF dhsurf,
IN ULONG Format, IN SIZEL sizl,
IN ULONG Flags, IN ULONG iFormat)
IN PVOID Bits)
{ {
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 APIENTRY
EngCreateDeviceSurface(IN DHSURF dhsurf,
IN SIZEL Size,
IN ULONG Format)
{
HSURF hsurf;
SURFOBJ *pso;
PSURFACE psurf; PSURFACE psurf;
HBITMAP hbmp;
psurf = SURFACE_AllocSurfaceWithHandle(); /* Allocate a surface */
psurf = SURFACE_AllocSurface(STYPE_DEVBITMAP, sizl.cx, sizl.cy, iFormat);
if (!psurf) if (!psurf)
{ {
return 0; return 0;
} }
hsurf = psurf->BaseObject.hHmgr; /* Set the device handle */
psurf->SurfObj.dhsurf = dhsurf;
/* Get the handle for the bitmap */
hbmp = (HBITMAP)psurf->SurfObj.hsurf;
/* Set public ownership */
GDIOBJ_SetOwnership(hbmp, NULL);
/* Unlock the surface and return */
SURFACE_UnlockSurface(psurf);
return hbmp;
}
HSURF
APIENTRY
EngCreateDeviceSurface(
IN DHSURF dhsurf,
IN SIZEL sizl,
IN ULONG iFormat)
{
PSURFACE psurf;
HSURF hsurf;
/* Allocate a surface */
psurf = SURFACE_AllocSurface(STYPE_DEVICE, sizl.cx, sizl.cy, iFormat);
if (!psurf)
{
return 0;
}
/* Set the device handle */
psurf->SurfObj.dhsurf = dhsurf;
/* Get the handle for the surface */
hsurf = psurf->SurfObj.hsurf;
/* Set public ownership */
GDIOBJ_SetOwnership(hsurf, NULL); GDIOBJ_SetOwnership(hsurf, NULL);
pso = &psurf->SurfObj; /* Unlock the surface and return */
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;
pso->pvBits = NULL;
psurf->flags = 0;
SURFACE_UnlockSurface(psurf); SURFACE_UnlockSurface(psurf);
return hsurf; return hsurf;
} }
/*
* @implemented
*/
BOOL BOOL
APIENTRY APIENTRY
EngAssociateSurface( EngAssociateSurface(
@ -777,10 +427,8 @@ EngAssociateSurface(
return TRUE; return TRUE;
} }
/* BOOL
* @implemented APIENTRY
*/
BOOL APIENTRY
EngModifySurface( EngModifySurface(
IN HSURF hsurf, IN HSURF hsurf,
IN HDEV hdev, IN HDEV hdev,
@ -823,10 +471,9 @@ EngModifySurface(
return TRUE; return TRUE;
} }
/*
* @implemented BOOL
*/ APIENTRY
BOOL APIENTRY
EngDeleteSurface(IN HSURF hsurf) EngDeleteSurface(IN HSURF hsurf)
{ {
GDIOBJ_SetOwnership(hsurf, PsGetCurrentProcess()); GDIOBJ_SetOwnership(hsurf, PsGetCurrentProcess());
@ -834,17 +481,16 @@ EngDeleteSurface(IN HSURF hsurf)
return TRUE; return TRUE;
} }
/* BOOL
* @implemented APIENTRY
*/ EngEraseSurface(
BOOL APIENTRY SURFOBJ *pso,
EngEraseSurface(SURFOBJ *pso, RECTL *prcl,
RECTL *Rect,
ULONG iColor) ULONG iColor)
{ {
ASSERT(pso); ASSERT(pso);
ASSERT(Rect); ASSERT(prcl);
return FillSolid(pso, Rect, iColor); return FillSolid(pso, prcl, iColor);
} }
/* /*
@ -857,10 +503,8 @@ NtGdiEngLockSurface(IN HSURF hsurf)
} }
/* SURFOBJ *
* @implemented APIENTRY
*/
SURFOBJ * APIENTRY
EngLockSurface(IN HSURF hsurf) EngLockSurface(IN HSURF hsurf)
{ {
SURFACE *psurf = GDIOBJ_ShareLockObj(hsurf, GDI_OBJECT_TYPE_BITMAP); SURFACE *psurf = GDIOBJ_ShareLockObj(hsurf, GDI_OBJECT_TYPE_BITMAP);
@ -871,20 +515,15 @@ EngLockSurface(IN HSURF hsurf)
return NULL; return NULL;
} }
VOID
/* APIENTRY
* @implemented
*/
VOID APIENTRY
NtGdiEngUnlockSurface(IN SURFOBJ *pso) NtGdiEngUnlockSurface(IN SURFOBJ *pso)
{ {
EngUnlockSurface(pso); EngUnlockSurface(pso);
} }
/* VOID
* @implemented APIENTRY
*/
VOID APIENTRY
EngUnlockSurface(IN SURFOBJ *pso) EngUnlockSurface(IN SURFOBJ *pso)
{ {
if (pso != NULL) if (pso != NULL)
@ -894,5 +533,74 @@ EngUnlockSurface(IN SURFOBJ *pso)
} }
} }
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;
/* Allocate a surface */
psurf = SURFACE_AllocSurface(STYPE_BITMAP, Size.cx, Size.cy, Format);
if (!psurf)
{
DPRINT1("SURFACE_AllocSurface failed.\n");
return NULL;
}
/* Get the handle for the bitmap and the surfobj */
hbmp = (HBITMAP)psurf->SurfObj.hsurf;
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);
Flags |= BMF_RLE_HACK;
}
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);
Flags |= BMF_RLE_HACK;
}
else
{
pso->lDelta = abs(Width);
pso->cjBits = pso->lDelta * Size.cy;
UncompressedBits = Bits;
UncompressedFormat = Format;
}
/* Set the bitmap bits */
if (!SURFACE_bSetBitmapBits(psurf, Flags, Width, UncompressedBits))
{
/* Bail out if that failed */
DPRINT1("SURFACE_bSetBitmapBits failed.\n");
SURFACE_FreeSurfaceByHandle(hbmp);
return NULL;
}
/* Unlock the surface and return */
SURFACE_UnlockSurface(psurf);
return hbmp;
}
/* EOF */ /* EOF */

View file

@ -36,3 +36,6 @@ EngAllocSectionMem(
IN SIZE_T cjSize, IN SIZE_T cjSize,
IN ULONG ulTag); IN ULONG ulTag);
VOID Decompress4bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta);
VOID Decompress8bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta);

View file

@ -92,7 +92,6 @@ typedef struct _SURFACE
/* Internal interface */ /* Internal interface */
#define SURFACE_AllocSurface() ((PSURFACE) GDIOBJ_AllocObj(GDIObjType_SURF_TYPE))
#define SURFACE_AllocSurfaceWithHandle() ((PSURFACE) GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP)) #define SURFACE_AllocSurfaceWithHandle() ((PSURFACE) GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP))
#define SURFACE_FreeSurface(pBMObj) GDIOBJ_FreeObj((POBJ) pBMObj, GDIObjType_SURF_TYPE) #define SURFACE_FreeSurface(pBMObj) GDIOBJ_FreeObj((POBJ) pBMObj, GDIObjType_SURF_TYPE)
#define SURFACE_FreeSurfaceByHandle(hBMObj) GDIOBJ_FreeObjByHandle((HGDIOBJ) hBMObj, GDI_OBJECT_TYPE_BITMAP) #define SURFACE_FreeSurfaceByHandle(hBMObj) GDIOBJ_FreeObjByHandle((HGDIOBJ) hBMObj, GDI_OBJECT_TYPE_BITMAP)
@ -109,8 +108,17 @@ typedef struct _SURFACE
BOOL INTERNAL_CALL SURFACE_Cleanup(PVOID ObjectBody); BOOL INTERNAL_CALL SURFACE_Cleanup(PVOID ObjectBody);
PSURFACE
NTAPI
SURFACE_AllocSurface(
IN ULONG iType,
IN ULONG cx,
IN ULONG cy,
IN ULONG iFormat);
#define GDIDEV(SurfObj) ((PDEVOBJ *)((SurfObj)->hdev)) #define GDIDEV(SurfObj) ((PDEVOBJ *)((SurfObj)->hdev))
#define GDIDEVFUNCS(SurfObj) ((PDEVOBJ *)((SurfObj)->hdev))->DriverFunctions #define GDIDEVFUNCS(SurfObj) ((PDEVOBJ *)((SurfObj)->hdev))->DriverFunctions
INT FASTCALL BitsPerFormat (ULONG Format);
ULONG FASTCALL BitmapFormat (WORD Bits, DWORD Compression); ULONG FASTCALL BitmapFormat (WORD Bits, DWORD Compression);
extern UCHAR gajBitsPerFormat[];
#define BitsPerFormat(Format) gajBitsPerFormat[Format]

View file

@ -78,6 +78,7 @@
<file>paint.c</file> <file>paint.c</file>
<file>pdevobj.c</file> <file>pdevobj.c</file>
<file>perfcnt.c</file> <file>perfcnt.c</file>
<file>rlecomp.c</file>
<file>semaphor.c</file> <file>semaphor.c</file>
<file>sort.c</file> <file>sort.c</file>
<file>string.c</file> <file>string.c</file>