- 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.

svn path=/trunk/; revision=47134
This commit is contained in:
Kamil Hornicek 2010-05-08 18:09:45 +00:00
parent bfe6479cf7
commit 006a12e270

View file

@ -204,81 +204,31 @@ EngCreateDeviceBitmap(IN DHSURF dhsurf,
return NewBitmap; return NewBitmap;
} }
VOID Decompress4bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta) BOOL DecompressBitmap(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta, ULONG Format)
{ {
int x = 0; INT x = 0;
int y = Size.cy - 1; INT y = Size.cy - 1;
int c; INT c;
int length; INT length;
int width = ((Size.cx+1)/2); INT width;
int height = Size.cy - 1; INT height = Size.cy - 1;
BYTE *begin = CompressedBits; BYTE *begin = CompressedBits;
BYTE *bits = CompressedBits; BYTE *bits = CompressedBits;
BYTE *temp; BYTE *temp;
while (y >= 0) INT shift = 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) if (Format == BMF_4RLE)
{ shift = 1;
int x = 0; else if(Format != BMF_8RLE)
int y = Size.cy - 1; return FALSE;
int c;
int length; width = ((Size.cx + shift) >> shift);
int width = Size.cx;
int height = Size.cy - 1; _SEH2_TRY
BYTE *begin = CompressedBits; {
BYTE *bits = CompressedBits;
BYTE *temp;
while (y >= 0) while (y >= 0)
{ {
length = *bits++; length = (*bits++) >> shift;
if (length) if (length)
{ {
c = *bits++; c = *bits++;
@ -300,12 +250,13 @@ VOID Decompress8bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LO
y--; y--;
break; break;
case RLE_END: case RLE_END:
return; _SEH2_YIELD(return TRUE);
case RLE_DELTA: case RLE_DELTA:
x += *bits++; x += (*bits++) >> shift;
y -= *bits++; y -= (*bits++) >> shift;
break; break;
default: default:
length = length >> shift;
while (length--) while (length--)
{ {
c = *bits++; c = *bits++;
@ -323,6 +274,15 @@ VOID Decompress8bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LO
} }
} }
} }
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
DPRINT1("Decoding error\n");
_SEH2_YIELD(return FALSE);
}
_SEH2_END;
return TRUE;
} }
HBITMAP FASTCALL HBITMAP FASTCALL
@ -362,7 +322,7 @@ IntCreateBitmap(IN SIZEL Size,
pso->cjBits = pso->lDelta * Size.cy; pso->cjBits = pso->lDelta * Size.cy;
UncompressedFormat = BMF_4BPP; UncompressedFormat = BMF_4BPP;
UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB); 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) else if (Format == BMF_8RLE)
{ {
@ -370,7 +330,7 @@ IntCreateBitmap(IN SIZEL Size,
pso->cjBits = pso->lDelta * Size.cy; pso->cjBits = pso->lDelta * Size.cy;
UncompressedFormat = BMF_8BPP; UncompressedFormat = BMF_8BPP;
UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB); 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 else
{ {
@ -467,6 +427,7 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
PSURFACE psurf; PSURFACE psurf;
SIZEL LocalSize; SIZEL LocalSize;
BOOLEAN AllocatedLocally = FALSE; BOOLEAN AllocatedLocally = FALSE;
PVOID DecompressedBits = NULL;
/* /*
* First, check the format so we can get the aligned scanline width. * First, check the format so we can get the aligned scanline width.
@ -500,17 +461,29 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
break; break;
case BMF_8RLE: case BMF_8RLE:
case BMF_4RLE: ScanLine = (BitmapInfo->Width + 3) & ~3;
case BMF_JPEG:
case BMF_PNG:
Compressed = TRUE; Compressed = TRUE;
break; break;
case BMF_4RLE:
ScanLine = ((BitmapInfo->Width + 7) & ~7) >> 1;
Compressed = TRUE;
break;
case BMF_JPEG:
case BMF_PNG:
ASSERT(FALSE); // ENGDDI shouldn't be creating PNGs for drivers ;-)
DPRINT1("No support for JPEG and PNG formats\n");
return NULL;
default: default:
DPRINT1("Invalid bitmap format\n"); DPRINT1("Invalid bitmap format\n");
return NULL; return NULL;
} }
/* Save local bitmap size */
LocalSize.cy = BitmapInfo->Height;
LocalSize.cx = BitmapInfo->Width;
/* Does the device manage its own surface? */ /* Does the device manage its own surface? */
if (!Bits) if (!Bits)
{ {
@ -519,7 +492,8 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
{ {
/* Note: we should not be seeing this scenario from ENGDDI */ /* Note: we should not be seeing this scenario from ENGDDI */
ASSERT(FALSE); ASSERT(FALSE);
Size = BitmapInfo->Size; DPRINT1("RLE compressed bitmap requested with no valid bitmap bits\n");
return NULL;
} }
else else
{ {
@ -551,6 +525,22 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
{ {
/* Should not have asked for user memory */ /* Should not have asked for user memory */
ASSERT((BitmapInfo->Flags & BMF_USERMEM) == 0); 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 */ /* Allocate the actual surface object structure */
@ -564,6 +554,8 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
else else
EngFreeMem(Bits); EngFreeMem(Bits);
} }
if (DecompressedBits)
EngFreeMem(DecompressedBits);
return NULL; return NULL;
} }
@ -584,8 +576,6 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
pso->fjBitmap = BitmapInfo->Flags & (BMF_TOPDOWN | BMF_UMPDMEM | BMF_USERMEM); pso->fjBitmap = BitmapInfo->Flags & (BMF_TOPDOWN | BMF_UMPDMEM | BMF_USERMEM);
/* Save size and type */ /* Save size and type */
LocalSize.cy = BitmapInfo->Height;
LocalSize.cx = BitmapInfo->Width;
pso->sizlBitmap = LocalSize; pso->sizlBitmap = LocalSize;
pso->iType = STYPE_BITMAP; pso->iType = STYPE_BITMAP;
@ -601,11 +591,11 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
psurf->flHooks = 0; psurf->flHooks = 0;
/* Set bits */ /* Set bits */
if(Compressed)
pso->pvBits = DecompressedBits;
else
pso->pvBits = Bits; pso->pvBits = Bits;
/* Check for bitmap type */
if (!Compressed)
{
/* Number of bits is based on the height times the scanline */ /* Number of bits is based on the height times the scanline */
pso->cjBits = BitmapInfo->Height * ScanLine; pso->cjBits = BitmapInfo->Height * ScanLine;
if (BitmapInfo->Flags & BMF_TOPDOWN) if (BitmapInfo->Flags & BMF_TOPDOWN)
@ -620,26 +610,6 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ScanLine); pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ScanLine);
pso->lDelta = -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 */ /* Finally set the handle and uniq */
pso->hsurf = (HSURF)psurf->BaseObject.hHmgr; pso->hsurf = (HSURF)psurf->BaseObject.hHmgr;