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
);
138 PALETTE_ShareUnlockPalette(psurf
->ppal
);
148 EngCreateDeviceBitmap(IN DHSURF dhsurf
,
155 NewBitmap
= EngCreateBitmap(Size
, DIB_GetDIBWidthBytes(Size
.cx
, BitsPerFormat(Format
)), Format
, 0, NULL
);
158 DPRINT1("EngCreateBitmap failed\n");
162 pso
= EngLockSurface((HSURF
)NewBitmap
);
165 DPRINT1("EngLockSurface failed on newly created bitmap!\n");
166 GreDeleteObject(NewBitmap
);
170 pso
->dhsurf
= dhsurf
;
171 EngUnlockSurface(pso
);
176 VOID
Decompress4bpp(SIZEL Size
, BYTE
*CompressedBits
, BYTE
*UncompressedBits
, LONG Delta
)
182 int width
= ((Size
.cx
+1)/2);
183 int height
= Size
.cy
- 1;
184 BYTE
*begin
= CompressedBits
;
185 BYTE
*bits
= CompressedBits
;
189 length
= *bits
++ / 2;
195 if (x
>= width
) break;
196 temp
= UncompressedBits
+ (((height
- y
) * Delta
) + x
);
223 temp
= UncompressedBits
+ (((height
- y
) * Delta
) + x
);
228 if ((bits
- begin
) & 1)
237 VOID
Decompress8bpp(SIZEL Size
, BYTE
*CompressedBits
, BYTE
*UncompressedBits
, LONG Delta
)
244 int height
= Size
.cy
- 1;
245 BYTE
*begin
= CompressedBits
;
246 BYTE
*bits
= CompressedBits
;
256 if (x
>= width
) break;
257 temp
= UncompressedBits
+ (((height
- y
) * Delta
) + x
);
283 temp
= UncompressedBits
+ (((height
- y
) * Delta
) + x
);
288 if ((bits
- begin
) & 1)
298 IntCreateBitmap(IN SIZEL Size
,
307 PVOID UncompressedBits
;
308 ULONG UncompressedFormat
;
313 psurf
= SURFACE_AllocSurfaceWithHandle();
318 hbmp
= psurf
->BaseObject
.hHmgr
;
320 pso
= &psurf
->SurfObj
;
322 if (Format
== BMF_4RLE
)
324 pso
->lDelta
= DIB_GetDIBWidthBytes(Size
.cx
, BitsPerFormat(BMF_4BPP
));
325 pso
->cjBits
= pso
->lDelta
* Size
.cy
;
326 UncompressedFormat
= BMF_4BPP
;
327 UncompressedBits
= EngAllocMem(FL_ZERO_MEMORY
, pso
->cjBits
, TAG_DIB
);
328 Decompress4bpp(Size
, (BYTE
*)Bits
, (BYTE
*)UncompressedBits
, pso
->lDelta
);
330 else if (Format
== BMF_8RLE
)
332 pso
->lDelta
= DIB_GetDIBWidthBytes(Size
.cx
, BitsPerFormat(BMF_8BPP
));
333 pso
->cjBits
= pso
->lDelta
* Size
.cy
;
334 UncompressedFormat
= BMF_8BPP
;
335 UncompressedBits
= EngAllocMem(FL_ZERO_MEMORY
, pso
->cjBits
, TAG_DIB
);
336 Decompress8bpp(Size
, (BYTE
*)Bits
, (BYTE
*)UncompressedBits
, pso
->lDelta
);
340 pso
->lDelta
= abs(Width
);
341 pso
->cjBits
= pso
->lDelta
* Size
.cy
;
342 UncompressedBits
= Bits
;
343 UncompressedFormat
= Format
;
346 if (UncompressedBits
!= NULL
)
348 pso
->pvBits
= UncompressedBits
;
352 if (pso
->cjBits
== 0)
358 if (0 != (Flags
& BMF_USERMEM
))
360 pso
->pvBits
= EngAllocUserMem(pso
->cjBits
, 0);
364 pso
->pvBits
= EngAllocMem(0 != (Flags
& BMF_NOZEROINIT
) ?
366 pso
->cjBits
, TAG_DIB
);
368 if (pso
->pvBits
== NULL
)
370 SURFACE_UnlockSurface(psurf
);
371 SURFACE_FreeSurfaceByHandle(hbmp
);
372 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
378 if (0 == (Flags
& BMF_TOPDOWN
))
380 pso
->pvScan0
= (PVOID
)((ULONG_PTR
)pso
->pvBits
+ pso
->cjBits
- pso
->lDelta
);
381 pso
->lDelta
= - pso
->lDelta
;
385 pso
->pvScan0
= pso
->pvBits
;
388 pso
->dhsurf
= 0; /* device managed surface */
389 pso
->hsurf
= (HSURF
)hbmp
;
392 pso
->sizlBitmap
= Size
;
393 pso
->iBitmapFormat
= UncompressedFormat
;
394 pso
->iType
= STYPE_BITMAP
;
395 pso
->fjBitmap
= Flags
& (BMF_TOPDOWN
| BMF_NOZEROINIT
);
400 psurf
->dimension
.cx
= 0;
401 psurf
->dimension
.cy
= 0;
403 psurf
->hSecure
= NULL
;
404 psurf
->hDIBSection
= NULL
;
406 SURFACE_UnlockSurface(psurf
);
411 /* Name gleaned from C++ symbol information for SURFMEM::bInitDIB */
412 typedef struct _DEVBITMAPINFO
419 } DEVBITMAPINFO
, *PDEVBITMAPINFO
;
423 SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo
,
426 BOOLEAN Compressed
= FALSE
;
427 ULONG ScanLine
= 0; // Compiler is dumb
432 BOOLEAN AllocatedLocally
= FALSE
;
435 * First, check the format so we can get the aligned scanline width.
436 * RLE and the newer fancy-smanshy JPG/PNG support do NOT have scanlines
437 * since they are compressed surfaces!
439 switch (BitmapInfo
->Format
)
442 ScanLine
= ((BitmapInfo
->Width
+ 31) & ~31) >> 3;
446 ScanLine
= ((BitmapInfo
->Width
+ 7) & ~7) >> 1;
450 ScanLine
= (BitmapInfo
->Width
+ 3) & ~3;
454 ScanLine
= ((BitmapInfo
->Width
+ 1) & ~1) << 1;
458 ScanLine
= ((BitmapInfo
->Width
* 3) + 3) & ~3;
462 ScanLine
= BitmapInfo
->Width
<< 2;
473 DPRINT1("Invalid bitmap format\n");
477 /* Does the device manage its own surface? */
480 /* We need to allocate bits for the caller, figure out the size */
483 /* Note: we should not be seeing this scenario from ENGDDI */
485 Size
= BitmapInfo
->Size
;
489 /* The height times the bytes for each scanline */
490 Size
= BitmapInfo
->Height
* ScanLine
;
495 /* Check for allocation flag */
496 if (BitmapInfo
->Flags
& BMF_USERMEM
)
498 /* Get the bits from user-mode memory */
499 Bits
= EngAllocUserMem(Size
, 'mbuG');
503 /* Get kernel bits (zeroed out if requested) */
504 Bits
= EngAllocMem((BitmapInfo
->Flags
& BMF_NOZEROINIT
) ? 0 : FL_ZERO_MEMORY
,
508 AllocatedLocally
= TRUE
;
509 /* Bail out if that failed */
510 if (!Bits
) return NULL
;
515 /* Should not have asked for user memory */
516 ASSERT((BitmapInfo
->Flags
& BMF_USERMEM
) == 0);
519 /* Allocate the actual surface object structure */
520 psurf
= SURFACE_AllocSurfaceWithHandle();
523 if(Bits
&& AllocatedLocally
)
525 if(BitmapInfo
->Flags
& BMF_USERMEM
)
526 EngFreeUserMem(Bits
);
533 /* We should now have our surface object */
534 pso
= &psurf
->SurfObj
;
536 /* Save format and flags */
537 pso
->iBitmapFormat
= BitmapInfo
->Format
;
538 pso
->fjBitmap
= BitmapInfo
->Flags
& (BMF_TOPDOWN
| BMF_UMPDMEM
| BMF_USERMEM
);
540 /* Save size and type */
541 LocalSize
.cy
= BitmapInfo
->Height
;
542 LocalSize
.cx
= BitmapInfo
->Width
;
543 pso
->sizlBitmap
= LocalSize
;
544 pso
->iType
= STYPE_BITMAP
;
546 /* Device-managed surface, no flags or dimension */
551 psurf
->dimension
.cx
= 0;
552 psurf
->dimension
.cy
= 0;
553 psurf
->hSecure
= NULL
;
554 psurf
->hDIBSection
= NULL
;
560 /* Check for bitmap type */
563 /* Number of bits is based on the height times the scanline */
564 pso
->cjBits
= BitmapInfo
->Height
* ScanLine
;
565 if (BitmapInfo
->Flags
& BMF_TOPDOWN
)
567 /* For topdown, the base address starts with the bits */
568 pso
->pvScan0
= pso
->pvBits
;
569 pso
->lDelta
= ScanLine
;
573 /* Otherwise we start with the end and go up */
574 pso
->pvScan0
= (PVOID
)((ULONG_PTR
)pso
->pvBits
+ pso
->cjBits
- ScanLine
);
575 pso
->lDelta
= -ScanLine
;
580 /* Compressed surfaces don't have scanlines! */
582 pso
->cjBits
= BitmapInfo
->Size
;
584 /* Check for JPG or PNG */
585 if ((BitmapInfo
->Format
!= BMF_JPEG
) && (BitmapInfo
->Format
!= BMF_PNG
))
587 /* Wherever the bit data is */
588 pso
->pvScan0
= pso
->pvBits
;
592 /* Fancy formats don't use a base address */
594 ASSERT(FALSE
); // ENGDDI shouldn't be creating PNGs for drivers ;-)
598 /* Finally set the handle and uniq */
599 pso
->hsurf
= (HSURF
)psurf
->BaseObject
.hHmgr
;
602 /* Unlock and return the surface */
603 SURFACE_UnlockSurface(psurf
);
612 EngCreateBitmap(IN SIZEL Size
,
619 DEVBITMAPINFO BitmapInfo
;
621 /* Capture the parameters */
622 BitmapInfo
.Format
= Format
;
623 BitmapInfo
.Width
= Size
.cx
;
624 BitmapInfo
.Height
= Size
.cy
;
625 BitmapInfo
.Flags
= Flags
;
628 * If the display driver supports framebuffer access, use the scanline width
629 * to determine the actual width of the bitmap, and convert it to pels instead
632 if ((Bits
) && (Width
))
634 switch (BitmapInfo
.Format
)
636 /* Do the conversion for each bit depth we support */
638 BitmapInfo
.Width
= Width
* 8;
641 BitmapInfo
.Width
= Width
* 2;
644 BitmapInfo
.Width
= Width
;
647 BitmapInfo
.Width
= Width
/ 2;
650 BitmapInfo
.Width
= Width
/ 3;
653 BitmapInfo
.Width
= Width
/ 4;
658 /* Now create the surface */
659 Surface
= SURFMEM_bCreateDib(&BitmapInfo
, Bits
);
660 if (!Surface
) return 0;
662 /* Set public ownership and reutrn the handle */
663 GDIOBJ_SetOwnership(Surface
->hsurf
, NULL
);
664 return Surface
->hsurf
;
671 EngCreateDeviceSurface(IN DHSURF dhsurf
,
679 psurf
= SURFACE_AllocSurfaceWithHandle();
685 hsurf
= psurf
->BaseObject
.hHmgr
;
686 GDIOBJ_SetOwnership(hsurf
, NULL
);
688 pso
= &psurf
->SurfObj
;
690 pso
->dhsurf
= dhsurf
;
692 pso
->sizlBitmap
= Size
;
693 pso
->iBitmapFormat
= Format
;
694 pso
->lDelta
= DIB_GetDIBWidthBytes(Size
.cx
, BitsPerFormat(Format
));
695 pso
->iType
= STYPE_DEVICE
;
700 SURFACE_UnlockSurface(psurf
);
719 ppdev
= (PDEVOBJ
*)hdev
;
721 /* Lock the surface */
722 psurf
= SURFACE_LockSurface(hsurf
);
727 pso
= &psurf
->SurfObj
;
729 /* Associate the hdev */
731 pso
->dhpdev
= ppdev
->dhpdev
;
733 /* Hook up specified functions */
734 psurf
->flHooks
= flHooks
;
737 psurf
->ppal
= PALETTE_ShareLockPalette(ppdev
->devinfo
.hpalDefault
);
739 SURFACE_UnlockSurface(psurf
);
762 psurf
= SURFACE_LockSurface(hsurf
);
768 ppdev
= (PDEVOBJ
*)hdev
;
769 pso
= &psurf
->SurfObj
;
770 pso
->dhsurf
= dhsurf
;
771 pso
->lDelta
= lDelta
;
772 pso
->pvScan0
= pvScan0
;
774 /* Associate the hdev */
776 pso
->dhpdev
= ppdev
->dhpdev
;
778 /* Hook up specified functions */
779 psurf
->flHooks
= flHooks
;
782 psurf
->ppal
= PALETTE_ShareLockPalette(ppdev
->devinfo
.hpalDefault
);
784 SURFACE_UnlockSurface(psurf
);
793 EngDeleteSurface(IN HSURF hsurf
)
795 GDIOBJ_SetOwnership(hsurf
, PsGetCurrentProcess());
796 SURFACE_FreeSurfaceByHandle(hsurf
);
804 EngEraseSurface(SURFOBJ
*pso
,
810 return FillSolid(pso
, Rect
, iColor
);
817 NtGdiEngLockSurface(IN HSURF hsurf
)
819 return EngLockSurface(hsurf
);
827 EngLockSurface(IN HSURF hsurf
)
829 SURFACE
*psurf
= GDIOBJ_ShareLockObj(hsurf
, GDI_OBJECT_TYPE_BITMAP
);
832 return &psurf
->SurfObj
;
842 NtGdiEngUnlockSurface(IN SURFOBJ
*pso
)
844 EngUnlockSurface(pso
);
851 EngUnlockSurface(IN SURFOBJ
*pso
)
855 SURFACE
*psurf
= CONTAINING_RECORD(pso
, SURFACE
, SurfObj
);
856 GDIOBJ_ShareUnlockObjByPtr((POBJ
)psurf
);