Author: khornicek
Date: Sat May 8 20:09:45 2010
New Revision: 47134
URL:
http://svn.reactos.org/svn/reactos?rev=47134&view=rev
Log:
[WIN32K]
- Bring back support for RLE compressed bitmaps.
- Merge the decompress functions for 4bb and 8bpp bitmaps to one generic function.
- Simplify SURFMEM_bCreateDib a bit by not allowing PNG/JPEG compression at all.
See issue #5276 for more details.
Modified:
trunk/reactos/subsystems/win32/win32k/eng/surface.c
Modified: trunk/reactos/subsystems/win32/win32k/eng/surface.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/en…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/eng/surface.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/eng/surface.c [iso-8859-1] Sat May 8 20:09:45
2010
@@ -204,48 +204,59 @@
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;
+BOOL DecompressBitmap(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG
Delta, ULONG Format)
+{
+ INT x = 0;
+ INT y = Size.cy - 1;
+ INT c;
+ INT length;
+ INT width;
+ 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)
- {
+ INT shift = 0;
+
+ if (Format == BMF_4RLE)
+ shift = 1;
+ else if(Format != BMF_8RLE)
+ return FALSE;
+
+ width = ((Size.cx + shift) >> shift);
+
+ _SEH2_TRY
+ {
+ while (y >= 0)
+ {
+ length = (*bits++) >> shift;
+ 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;
+ _SEH2_YIELD(return TRUE);
case RLE_DELTA:
- x += (*bits++)/2;
- y -= (*bits++)/2;
+ x += (*bits++) >> shift;
+ y -= (*bits++) >> shift;
break;
default:
- length /= 2;
+ length = length >> shift;
while (length--)
{
c = *bits++;
@@ -260,69 +271,18 @@
{
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++;
- }
- }
- }
- }
+ }
+ }
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DPRINT1("Decoding error\n");
+ _SEH2_YIELD(return FALSE);
+ }
+ _SEH2_END;
+
+ return TRUE;
}
HBITMAP FASTCALL
@@ -362,7 +322,7 @@
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);
+ DecompressBitmap(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, pso->lDelta,
Format);
}
else if (Format == BMF_8RLE)
{
@@ -370,7 +330,7 @@
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);
+ DecompressBitmap(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, pso->lDelta,
Format);
}
else
{
@@ -467,6 +427,7 @@
PSURFACE psurf;
SIZEL LocalSize;
BOOLEAN AllocatedLocally = FALSE;
+ PVOID DecompressedBits = NULL;
/*
* First, check the format so we can get the aligned scanline width.
@@ -500,17 +461,29 @@
break;
case BMF_8RLE:
+ ScanLine = (BitmapInfo->Width + 3) & ~3;
+ Compressed = TRUE;
+ break;
case BMF_4RLE:
+ ScanLine = ((BitmapInfo->Width + 7) & ~7) >> 1;
+ Compressed = TRUE;
+ break;
+
case BMF_JPEG:
case BMF_PNG:
- Compressed = TRUE;
- break;
+ ASSERT(FALSE); // ENGDDI shouldn't be creating PNGs for drivers ;-)
+ DPRINT1("No support for JPEG and PNG formats\n");
+ return NULL;
default:
DPRINT1("Invalid bitmap format\n");
return NULL;
}
+ /* Save local bitmap size */
+ LocalSize.cy = BitmapInfo->Height;
+ LocalSize.cx = BitmapInfo->Width;
+
/* Does the device manage its own surface? */
if (!Bits)
{
@@ -519,7 +492,8 @@
{
/* Note: we should not be seeing this scenario from ENGDDI */
ASSERT(FALSE);
- Size = BitmapInfo->Size;
+ DPRINT1("RLE compressed bitmap requested with no valid bitmap
bits\n");
+ return NULL;
}
else
{
@@ -551,6 +525,22 @@
{
/* Should not have asked for user memory */
ASSERT((BitmapInfo->Flags & BMF_USERMEM) == 0);
+
+ if (Compressed)
+ {
+ DecompressedBits = EngAllocMem(FL_ZERO_MEMORY, BitmapInfo->Height *
ScanLine, TAG_DIB);
+
+ if(!DecompressedBits)
+ return NULL;
+
+ if(!DecompressBitmap(LocalSize, (BYTE *)Bits, (BYTE *)DecompressedBits,
ScanLine, BitmapInfo->Format))
+ {
+ EngFreeMem(DecompressedBits);
+ return NULL;
+ }
+
+ BitmapInfo->Format = (BitmapInfo->Format == BMF_4RLE) ? BMF_4BPP :
BMF_8BPP;
+ }
}
/* Allocate the actual surface object structure */
@@ -564,6 +554,8 @@
else
EngFreeMem(Bits);
}
+ if (DecompressedBits)
+ EngFreeMem(DecompressedBits);
return NULL;
}
@@ -584,11 +576,9 @@
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;
@@ -599,48 +589,28 @@
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;
- }
+ if(Compressed)
+ pso->pvBits = DecompressedBits;
+ else
+ pso->pvBits = Bits;
+
+ /* 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
{
- /* 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 ;-)
- }
- }
-
+ /* Otherwise we start with the end and go up */
+ pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits -
ScanLine);
+ pso->lDelta = -ScanLine;
+ }
+
/* Finally set the handle and uniq */
pso->hsurf = (HSURF)psurf->BaseObject.hHmgr;
pso->iUniq = 0;