2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI Driver Surace Functions
5 * FILE: subsys/win32k/eng/surface.c
6 * PROGRAMER: Jason Filby
9 * 9/11/2000: Updated to handle real pixel packed bitmaps (UPDATE TO DATE COMPLETED)
11 * - Create a GDI bitmap with all formats, perform all drawing operations on them, render to VGA surface
12 * refer to \test\microwin\src\engine\devdraw.c for info on correct pixel plotting for various formats
22 RLE_EOL
= 0, /* End of line */
23 RLE_END
= 1, /* End of bitmap */
24 RLE_DELTA
= 2 /* Delta */
27 INT FASTCALL
BitsPerFormat(ULONG Format
)
58 ULONG FASTCALL
BitmapFormat(WORD Bits
, DWORD Compression
)
94 SURFACE_Cleanup(PVOID ObjectBody
)
96 PSURFACE psurf
= (PSURFACE
)ObjectBody
;
97 PVOID pvBits
= psurf
->SurfObj
.pvBits
;
99 /* If this is an API bitmap, free the bits */
100 if (pvBits
!= NULL
&&
101 (psurf
->flFlags
& BITMAPOBJ_IS_APIBITMAP
))
103 /* Check if we have a DIB section */
106 // FIXME: IMPLEMENT ME!
107 // MmUnsecureVirtualMemory(psurf->hSecure);
108 if (psurf
->hDIBSection
)
110 /* DIB was created from a section */
113 pvBits
= (PVOID
)((ULONG_PTR
)pvBits
- psurf
->dwOffset
);
114 Status
= ZwUnmapViewOfSection(NtCurrentProcess(), pvBits
);
115 if (!NT_SUCCESS(Status
))
117 DPRINT1("Could not unmap section view!\n");
118 // Should we BugCheck here?
123 /* DIB was allocated */
124 EngFreeUserMem(pvBits
);
130 ExFreePool(psurf
->SurfObj
.pvBits
);
133 if (psurf
->hDIBPalette
!= NULL
)
135 GreDeleteObject(psurf
->hDIBPalette
);
139 if (NULL
!= psurf
->BitsLock
)
141 ExFreePoolWithTag(psurf
->BitsLock
, TAG_SURFACE
);
142 psurf
->BitsLock
= NULL
;
149 SURFACE_InitBitsLock(PSURFACE psurf
)
151 psurf
->BitsLock
= ExAllocatePoolWithTag(NonPagedPool
,
154 if (NULL
== psurf
->BitsLock
)
159 ExInitializeFastMutex(psurf
->BitsLock
);
165 SURFACE_CleanupBitsLock(PSURFACE psurf
)
167 if (NULL
!= psurf
->BitsLock
)
169 ExFreePoolWithTag(psurf
->BitsLock
, TAG_SURFACE
);
170 psurf
->BitsLock
= NULL
;
179 EngCreateDeviceBitmap(IN DHSURF dhsurf
,
186 NewBitmap
= EngCreateBitmap(Size
, DIB_GetDIBWidthBytes(Size
.cx
, BitsPerFormat(Format
)), Format
, 0, NULL
);
189 DPRINT1("EngCreateBitmap failed\n");
193 pso
= EngLockSurface((HSURF
)NewBitmap
);
196 DPRINT1("EngLockSurface failed on newly created bitmap!\n");
197 GreDeleteObject(NewBitmap
);
201 pso
->dhsurf
= dhsurf
;
202 EngUnlockSurface(pso
);
207 VOID
Decompress4bpp(SIZEL Size
, BYTE
*CompressedBits
, BYTE
*UncompressedBits
, LONG Delta
)
213 int width
= ((Size
.cx
+1)/2);
214 int height
= Size
.cy
- 1;
215 BYTE
*begin
= CompressedBits
;
216 BYTE
*bits
= CompressedBits
;
220 length
= *bits
++ / 2;
226 if (x
>= width
) break;
227 temp
= UncompressedBits
+ (((height
- y
) * Delta
) + x
);
254 temp
= UncompressedBits
+ (((height
- y
) * Delta
) + x
);
259 if ((bits
- begin
) & 1)
268 VOID
Decompress8bpp(SIZEL Size
, BYTE
*CompressedBits
, BYTE
*UncompressedBits
, LONG Delta
)
275 int height
= Size
.cy
- 1;
276 BYTE
*begin
= CompressedBits
;
277 BYTE
*bits
= CompressedBits
;
287 if (x
>= width
) break;
288 temp
= UncompressedBits
+ (((height
- y
) * Delta
) + x
);
314 temp
= UncompressedBits
+ (((height
- y
) * Delta
) + x
);
319 if ((bits
- begin
) & 1)
329 IntCreateBitmap(IN SIZEL Size
,
338 ULONG ScanLine
= 0; // Compiler is dumb
341 ScanLine
= abs(Width
);
343 /* Does the device manage its own surface? */
346 /* The height times the bytes for each scanline */
347 BitsSize
= Size
.cy
* ScanLine
;
350 /* Check for allocation flag */
351 if (Flags
& BMF_USERMEM
)
353 /* Get the bits from user-mode memory */
354 Bits
= EngAllocUserMem(BitsSize
, 'mbuG');
358 /* Get kernel bits (zeroed out if requested) */
359 Bits
= EngAllocMem((Flags
& BMF_NOZEROINIT
) ? 0 : FL_ZERO_MEMORY
,
364 /* Bail out if that failed */
365 if (!Bits
) return NULL
;
370 /* Should not have asked for user memory */
371 // ASSERT((Flags & BMF_USERMEM) == 0);
374 /* Allocate the actual surface object structure */
375 psurf
= SURFACE_AllocSurfaceWithHandle();
376 if (!psurf
) return NULL
;
378 /* Lock down the surface */
379 if (!SURFACE_InitBitsLock(psurf
))
381 /* Bail out if that failed */
382 SURFACE_UnlockSurface(psurf
);
383 SURFACE_FreeSurface(psurf
);
387 /* We should now have our surface object */
388 pso
= &psurf
->SurfObj
;
393 /* Number of bits is based on the height times the scanline */
394 pso
->cjBits
= Size
.cy
* ScanLine
;
395 if (Flags
& BMF_TOPDOWN
)
397 /* For topdown, the base address starts with the bits */
398 pso
->pvScan0
= pso
->pvBits
;
399 pso
->lDelta
= ScanLine
;
403 /* Otherwise we start with the end and go up */
404 pso
->pvScan0
= (PVOID
)((ULONG_PTR
)pso
->pvBits
+ pso
->cjBits
- ScanLine
);
405 pso
->lDelta
= -ScanLine
;
408 /* Save format and flags */
409 pso
->iBitmapFormat
= Format
;
410 pso
->fjBitmap
= Flags
& (BMF_TOPDOWN
| BMF_UMPDMEM
| BMF_USERMEM
);
412 /* Save size and type */
413 LocalSize
.cx
= Size
.cx
;
414 LocalSize
.cy
= Size
.cy
;
415 pso
->sizlBitmap
= Size
;
416 pso
->iType
= STYPE_BITMAP
;
418 /* Device-managed surface, no flags or dimension */
423 psurf
->dimension
.cx
= 0;
424 psurf
->dimension
.cy
= 0;
425 psurf
->hSecure
= NULL
;
426 psurf
->hDIBSection
= NULL
;
430 /* Finally set the handle and uniq */
431 pso
->hsurf
= (HSURF
)psurf
->BaseObject
.hHmgr
;
434 /* Unlock and return the surface */
435 SURFACE_UnlockSurface(psurf
);
439 /* Name gleaned from C++ symbol information for SURFMEM::bInitDIB */
440 typedef struct _DEVBITMAPINFO
447 } DEVBITMAPINFO
, *PDEVBITMAPINFO
;
451 SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo
,
454 BOOLEAN Compressed
= FALSE
;
455 ULONG ScanLine
= 0; // Compiler is dumb
462 * First, check the format so we can get the aligned scanline width.
463 * RLE and the newer fancy-smanshy JPG/PNG support do NOT have scanlines
464 * since they are compressed surfaces!
466 switch (BitmapInfo
->Format
)
469 //ScanLine = ((BitmapInfo->Width + 31) & ~31) / 8;
473 //ScanLine = ((BitmapInfo->Width + 7) & ~7) / 2;
477 //ScanLine = ((BitmapInfo->Width + 3) & ~3);
481 //ScanLine = ((BitmapInfo->Width + 1) & ~1) * 2;
485 //ScanLine = ((BitmapInfo->Width * 3) + 3) & ~3;
489 // ScanLine = BitmapInfo->Width * 4;
500 DPRINT1("Invalid bitmap format\n");
504 ScanLine
= BitmapInfo
->Width
;
506 /* Does the device manage its own surface? */
509 /* We need to allocate bits for the caller, figure out the size */
512 /* Note: we should not be seeing this scenario from ENGDDI */
514 Size
= BitmapInfo
->Size
;
518 /* The height times the bytes for each scanline */
519 Size
= BitmapInfo
->Height
* ScanLine
;
524 /* Check for allocation flag */
525 if (BitmapInfo
->Flags
& BMF_USERMEM
)
527 /* Get the bits from user-mode memory */
528 Bits
= EngAllocUserMem(Size
, 'mbuG');
532 /* Get kernel bits (zeroed out if requested) */
533 Bits
= EngAllocMem((BitmapInfo
->Flags
& BMF_NOZEROINIT
) ? 0 : FL_ZERO_MEMORY
,
538 /* Bail out if that failed */
539 if (!Bits
) return NULL
;
544 /* Should not have asked for user memory */
545 ASSERT((BitmapInfo
->Flags
& BMF_USERMEM
) == 0);
548 /* Allocate the actual surface object structure */
549 psurf
= SURFACE_AllocSurfaceWithHandle();
550 if (!psurf
) return NULL
;
552 /* Lock down the surface */
553 if (!SURFACE_InitBitsLock(psurf
))
555 /* Bail out if that failed */
556 SURFACE_UnlockSurface(psurf
);
557 SURFACE_FreeSurface(psurf
);
561 /* We should now have our surface object */
562 pso
= &psurf
->SurfObj
;
564 /* Save format and flags */
565 pso
->iBitmapFormat
= BitmapInfo
->Format
;
566 pso
->fjBitmap
= BitmapInfo
->Flags
& (BMF_TOPDOWN
| BMF_UMPDMEM
| BMF_USERMEM
);
568 /* Save size and type */
569 LocalSize
.cy
= BitmapInfo
->Height
;
570 LocalSize
.cx
= BitmapInfo
->Width
;
571 pso
->sizlBitmap
= LocalSize
;
572 pso
->iType
= STYPE_BITMAP
;
574 /* Device-managed surface, no flags or dimension */
579 psurf
->dimension
.cx
= 0;
580 psurf
->dimension
.cy
= 0;
581 psurf
->hSecure
= NULL
;
582 psurf
->hDIBSection
= NULL
;
588 /* Check for bitmap type */
591 /* Number of bits is based on the height times the scanline */
592 pso
->cjBits
= BitmapInfo
->Height
* ScanLine
;
593 if (BitmapInfo
->Flags
& BMF_TOPDOWN
)
595 /* For topdown, the base address starts with the bits */
596 pso
->pvScan0
= pso
->pvBits
;
597 pso
->lDelta
= ScanLine
;
601 /* Otherwise we start with the end and go up */
602 pso
->pvScan0
= (PVOID
)((ULONG_PTR
)pso
->pvBits
+ pso
->cjBits
- ScanLine
);
603 pso
->lDelta
= -ScanLine
;
608 /* Compressed surfaces don't have scanlines! */
609 ASSERT(FALSE
); // Should not get here on ENGDDI
611 pso
->cjBits
= BitmapInfo
->Size
;
613 /* Check for JPG or PNG */
614 if ((BitmapInfo
->Format
!= BMF_JPEG
) && (BitmapInfo
->Format
!= BMF_PNG
))
616 /* Wherever the bit data is */
617 pso
->pvScan0
= pso
->pvBits
;
621 /* Fancy formats don't use a base address */
623 ASSERT(FALSE
); // ENGDDI shouldn't be creating PNGs for drivers ;-)
627 /* Finally set the handle and uniq */
628 pso
->hsurf
= (HSURF
)psurf
->BaseObject
.hHmgr
;
631 /* Unlock and return the surface */
632 SURFACE_UnlockSurface(psurf
);
641 EngCreateBitmap(IN SIZEL Size
,
648 DEVBITMAPINFO BitmapInfo
;
650 /* Capture the parameters */
651 BitmapInfo
.Format
= Format
;
652 BitmapInfo
.Width
= Size
.cx
;
653 BitmapInfo
.Height
= Size
.cy
;
654 BitmapInfo
.Flags
= Flags
;
657 * If the display driver supports framebuffer access, use the scanline width
658 * to determine the actual width of the bitmap, and convert it to pels instead
661 if ((Bits
) && (Width
))
664 switch (BitmapInfo
.Format
)
666 /* Do the conversion for each bit depth we support */
668 BitmapInfo
.Width
= Width
* 8;
671 BitmapInfo
.Width
= Width
* 2;
674 BitmapInfo
.Width
= Width
;
677 BitmapInfo
.Width
= Width
/ 2;
680 BitmapInfo
.Width
= Width
/ 3;
683 BitmapInfo
.Width
= Width
/ 4;
687 BitmapInfo
.Width
= Width
;
691 /* Now create the surface */
692 Surface
= SURFMEM_bCreateDib(&BitmapInfo
, Bits
);
693 if (!Surface
) return 0;
695 /* Set public ownership and reutrn the handle */
696 GDIOBJ_SetOwnership(Surface
->hsurf
, NULL
);
697 return Surface
->hsurf
;
704 EngCreateDeviceSurface(IN DHSURF dhsurf
,
712 psurf
= SURFACE_AllocSurfaceWithHandle();
718 hsurf
= psurf
->BaseObject
.hHmgr
;
719 GDIOBJ_SetOwnership(hsurf
, NULL
);
721 if (!SURFACE_InitBitsLock(psurf
))
723 SURFACE_UnlockSurface(psurf
);
724 SURFACE_FreeSurfaceByHandle(hsurf
);
727 pso
= &psurf
->SurfObj
;
729 pso
->dhsurf
= dhsurf
;
731 pso
->sizlBitmap
= Size
;
732 pso
->iBitmapFormat
= Format
;
733 pso
->lDelta
= DIB_GetDIBWidthBytes(Size
.cx
, BitsPerFormat(Format
));
734 pso
->iType
= STYPE_DEVICE
;
739 SURFACE_UnlockSurface(psurf
);
758 ppdev
= (PDEVOBJ
*)hdev
;
760 /* Lock the surface */
761 psurf
= SURFACE_LockSurface(hsurf
);
766 pso
= &psurf
->SurfObj
;
768 /* Associate the hdev */
770 pso
->dhpdev
= ppdev
->dhpdev
;
772 /* Hook up specified functions */
773 psurf
->flHooks
= flHooks
;
775 SURFACE_UnlockSurface(psurf
);
798 psurf
= SURFACE_LockSurface(hsurf
);
804 ppdev
= (PDEVOBJ
*)hdev
;
805 pso
= &psurf
->SurfObj
;
806 pso
->dhsurf
= dhsurf
;
807 pso
->lDelta
= lDelta
;
808 pso
->pvScan0
= pvScan0
;
810 /* Associate the hdev */
812 pso
->dhpdev
= ppdev
->dhpdev
;
814 /* Hook up specified functions */
815 psurf
->flHooks
= flHooks
;
817 SURFACE_UnlockSurface(psurf
);
826 EngDeleteSurface(IN HSURF hsurf
)
828 GDIOBJ_SetOwnership(hsurf
, PsGetCurrentProcess());
829 SURFACE_FreeSurfaceByHandle(hsurf
);
837 EngEraseSurface(SURFOBJ
*pso
,
843 return FillSolid(pso
, Rect
, iColor
);
850 NtGdiEngLockSurface(IN HSURF hsurf
)
852 return EngLockSurface(hsurf
);
860 EngLockSurface(IN HSURF hsurf
)
862 SURFACE
*psurf
= GDIOBJ_ShareLockObj(hsurf
, GDI_OBJECT_TYPE_BITMAP
);
865 return &psurf
->SurfObj
;
875 NtGdiEngUnlockSurface(IN SURFOBJ
*pso
)
877 EngUnlockSurface(pso
);
884 EngUnlockSurface(IN SURFOBJ
*pso
)
888 SURFACE
*psurf
= CONTAINING_RECORD(pso
, SURFACE
, SurfObj
);
889 GDIOBJ_ShareUnlockObjByPtr((POBJ
)psurf
);