2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI Driver Surace Functions
5 * FILE: win32ss/gdi/eng/surface.c
6 * PROGRAMERS: Jason Filby
9 * - Create a GDI bitmap with all formats, perform all drawing operations on them, render to VGA surface
10 * refer to \test\microwin\src\engine\devdraw.c for info on correct pixel plotting for various formats
18 LONG giUniqueSurface
= 0;
21 gajBitsPerFormat
[11] =
27 16, /* 4: BMF_16BPP */
28 24, /* 5: BMF_24BPP */
29 32, /* 6: BMF_32BPP */
39 BitmapFormat(ULONG cBits
, ULONG iCompression
)
46 if (cBits
<= 1) return BMF_1BPP
;
47 if (cBits
<= 4) return BMF_4BPP
;
48 if (cBits
<= 8) return BMF_8BPP
;
49 if (cBits
<= 16) return BMF_16BPP
;
50 if (cBits
<= 24) return BMF_24BPP
;
51 if (cBits
<= 32) return BMF_32BPP
;
67 SURFACE_vCleanup(PVOID ObjectBody
)
69 PSURFACE psurf
= (PSURFACE
)ObjectBody
;
70 PVOID pvBits
= psurf
->SurfObj
.pvBits
;
72 /* Check if the surface has bits */
75 /* Only bitmaps can have bits */
76 ASSERT(psurf
->SurfObj
.iType
== STYPE_BITMAP
);
78 /* Check if it is a DIB section */
79 if (psurf
->hDIBSection
)
81 /* Unmap the section view */
82 EngUnmapSectionView(pvBits
, psurf
->dwOffset
, psurf
->hSecure
);
84 else if (psurf
->SurfObj
.fjBitmap
& BMF_USERMEM
)
86 /* Bitmap was allocated from usermode memory */
87 EngFreeUserMem(pvBits
);
89 else if (psurf
->SurfObj
.fjBitmap
& BMF_KMSECTION
)
91 /* Bitmap was allocated from a kernel section */
92 if (!EngFreeSectionMem(NULL
, pvBits
))
94 DPRINT1("EngFreeSectionMem failed for %p!\n", pvBits
);
95 // Should we BugCheck here?
99 else if (psurf
->SurfObj
.fjBitmap
& BMF_POOLALLOC
)
101 /* Free a pool allocation */
109 PALETTE_ShareUnlockPalette(psurf
->ppal
);
116 SURFACE_AllocSurface(
122 _In_opt_ ULONG cjWidth
,
123 _In_opt_ ULONG cjBufSize
,
124 _In_opt_ PVOID pvBits
)
126 ULONG cBitsPixel
, cjBits
, cjObject
;
131 NT_ASSERT(!pvBits
|| (iType
== STYPE_BITMAP
));
132 NT_ASSERT((iFormat
<= BMF_32BPP
) || (cjBufSize
!= 0));
133 NT_ASSERT((LONG
)cy
> 0);
136 if ((iFormat
< BMF_1BPP
) || (iFormat
> BMF_PNG
))
138 DPRINT1("Invalid bitmap format: %lu\n", iFormat
);
142 /* Get bits per pixel from the format */
143 cBitsPixel
= gajBitsPerFormat
[iFormat
];
145 /* Are bits and a width in bytes given? */
146 if (pvBits
&& cjWidth
)
148 /* Align the width (Windows compatibility, drivers expect that) */
149 cjWidth
= WIDTH_BYTES_ALIGN32((cjWidth
<< 3) / cBitsPixel
, cBitsPixel
);
153 /* Calculate width from the bitmap width in pixels */
154 cjWidth
= WIDTH_BYTES_ALIGN32(cx
, cBitsPixel
);
157 /* Is this an uncompressed format? */
158 if (iFormat
<= BMF_32BPP
)
160 /* Calculate the correct bitmap size in bytes */
161 if (!NT_SUCCESS(RtlULongMult(cjWidth
, cy
, &cjBits
)))
163 DPRINT1("Overflow calculating size: cjWidth %lu, cy %lu\n",
168 /* Did we get a buffer and size? */
169 if ((pvBits
!= NULL
) && (cjBufSize
!= 0))
171 /* Make sure the buffer is large enough */
172 if (cjBufSize
< cjBits
)
174 DPRINT1("Buffer is too small, required: %lu, got %lu\n",
182 /* Compressed format, use the provided size */
183 NT_ASSERT(cjBufSize
!= 0);
187 /* Check if we need an extra large object */
188 if ((iType
== STYPE_BITMAP
) && (pvBits
== NULL
) &&
189 !(fjBitmap
& BMF_USERMEM
) && !(fjBitmap
& BMF_KMSECTION
))
191 /* Allocate an object large enough to hold the bits */
192 cjObject
= sizeof(SURFACE
) + cjBits
;
196 /* Otherwise just allocate the SURFACE structure */
197 cjObject
= sizeof(SURFACE
);
200 /* Check for arithmetic overflow */
201 if (cjObject
< sizeof(SURFACE
))
204 DPRINT1("Overflow calculating cjObject: cjBits %lu\n", cjBits
);
208 /* Allocate a SURFACE object */
209 psurf
= (PSURFACE
)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP
, cjObject
);
215 /* Initialize the basic fields */
216 pso
= &psurf
->SurfObj
;
217 pso
->hsurf
= psurf
->BaseObject
.hHmgr
;
218 pso
->sizlBitmap
.cx
= cx
;
219 pso
->sizlBitmap
.cy
= cy
;
220 pso
->iBitmapFormat
= iFormat
;
222 pso
->fjBitmap
= (USHORT
)fjBitmap
;
223 pso
->iUniq
= InterlockedIncrement(&giUniqueSurface
);
224 pso
->cjBits
= cjBits
;
226 /* Check if we need a bitmap buffer */
227 if (iType
== STYPE_BITMAP
)
229 /* Check if we got one or if we need to allocate one */
232 /* Use the caller provided buffer */
233 pso
->pvBits
= pvBits
;
235 else if (fjBitmap
& BMF_USERMEM
)
237 /* User mode memory was requested */
238 pso
->pvBits
= EngAllocUserMem(cjBits
, 0);
240 /* Check for failure */
243 GDIOBJ_vDeleteObject(&psurf
->BaseObject
);
247 else if (fjBitmap
& BMF_KMSECTION
)
249 /* Use a kernel mode section */
250 pso
->pvBits
= EngAllocSectionMem(&pvSection
,
251 (fjBitmap
& BMF_NOZEROINIT
) ?
255 /* Check for failure */
258 GDIOBJ_vDeleteObject(&psurf
->BaseObject
);
262 /* Free the section already, but keep the mapping */
263 EngFreeSectionMem(pvSection
, NULL
);
267 /* Buffer is after the object */
268 pso
->pvBits
= psurf
+ 1;
270 /* Zero the buffer, except requested otherwise */
271 if (!(fjBitmap
& BMF_NOZEROINIT
))
273 RtlZeroMemory(pso
->pvBits
, cjBits
);
277 /* Set pvScan0 and lDelta */
278 if (fjBitmap
& BMF_TOPDOWN
)
280 /* Topdown is the normal way */
281 pso
->pvScan0
= pso
->pvBits
;
282 pso
->lDelta
= cjWidth
;
286 /* Inversed bitmap (bottom up) */
287 pso
->pvScan0
= ((PCHAR
)pso
->pvBits
+ pso
->cjBits
- cjWidth
);
288 pso
->lDelta
= -(LONG
)cjWidth
;
293 /* There are no bitmap bits */
294 pso
->pvScan0
= pso
->pvBits
= NULL
;
298 /* Assign a default palette and increment its reference count */
299 SURFACE_vSetPalette(psurf
, appalSurfaceDefault
[iFormat
]);
311 _In_opt_ PVOID pvBits
)
316 /* Allocate a surface */
317 psurf
= SURFACE_AllocSurface(STYPE_BITMAP
,
327 DPRINT1("SURFACE_AllocSurface failed.\n");
331 /* Get the handle for the bitmap */
332 hbmp
= (HBITMAP
)psurf
->SurfObj
.hsurf
;
334 /* Set public ownership */
335 GDIOBJ_vSetObjectOwner(&psurf
->BaseObject
, GDI_OBJ_HMGR_PUBLIC
);
337 /* Unlock the surface and return */
338 SURFACE_UnlockSurface(psurf
);
347 EngCreateDeviceBitmap(
355 /* Allocate a surface */
356 psurf
= SURFACE_AllocSurface(STYPE_DEVBITMAP
,
366 DPRINT1("SURFACE_AllocSurface failed.\n");
370 /* Set the device handle */
371 psurf
->SurfObj
.dhsurf
= dhsurf
;
373 /* Set public ownership */
374 GDIOBJ_vSetObjectOwner(&psurf
->BaseObject
, GDI_OBJ_HMGR_PUBLIC
);
376 /* Get the handle for the bitmap */
377 hbmp
= (HBITMAP
)psurf
->SurfObj
.hsurf
;
379 /* Unlock the surface and return */
380 SURFACE_UnlockSurface(psurf
);
386 EngCreateDeviceSurface(
394 /* Allocate a surface */
395 psurf
= SURFACE_AllocSurface(STYPE_DEVICE
,
405 DPRINT1("SURFACE_AllocSurface failed.\n");
409 /* Set the device handle */
410 psurf
->SurfObj
.dhsurf
= dhsurf
;
412 /* Set public ownership */
413 GDIOBJ_vSetObjectOwner(&psurf
->BaseObject
, GDI_OBJ_HMGR_PUBLIC
);
415 /* Get the handle for the surface */
416 hsurf
= psurf
->SurfObj
.hsurf
;
418 /* Unlock the surface and return */
419 SURFACE_UnlockSurface(psurf
);
435 ppdev
= (PDEVOBJ
*)hdev
;
437 /* Lock the surface */
438 psurf
= SURFACE_ShareLockSurface(hsurf
);
443 pso
= &psurf
->SurfObj
;
445 /* Associate the hdev */
447 pso
->dhpdev
= ppdev
->dhpdev
;
449 /* Hook up specified functions */
450 psurf
->flags
&= ~HOOK_FLAGS
;
451 psurf
->flags
|= (flHooks
& HOOK_FLAGS
);
453 /* Assign the PDEV's palette */
454 ppal
= PALETTE_ShareLockPalette(ppdev
->devinfo
.hpalDefault
);
455 SURFACE_vSetPalette(psurf
, ppal
);
456 PALETTE_ShareUnlockPalette(ppal
);
458 SURFACE_ShareUnlockSurface(psurf
);
469 _In_ FLONG flSurface
,
473 _Reserved_ PVOID pvReserved
)
480 /* Lock the surface */
481 psurf
= SURFACE_ShareLockSurface(hsurf
);
484 DPRINT1("Failed to reference surface %p\n", hsurf
);
488 ppdev
= (PDEVOBJ
*)hdev
;
489 pso
= &psurf
->SurfObj
;
490 pso
->dhsurf
= dhsurf
;
492 /* Associate the hdev */
494 pso
->dhpdev
= ppdev
->dhpdev
;
496 /* Hook up specified functions */
497 psurf
->flags
&= ~HOOK_FLAGS
;
498 psurf
->flags
|= (flHooks
& HOOK_FLAGS
);
500 /* Assign the PDEV's palette */
501 ppal
= PALETTE_ShareLockPalette(ppdev
->devinfo
.hpalDefault
);
502 SURFACE_vSetPalette(psurf
, ppal
);
503 PALETTE_ShareUnlockPalette(ppal
);
505 /* Update surface flags */
506 if (flSurface
& MS_NOTSYSTEMMEMORY
)
507 pso
->fjBitmap
|= BMF_NOTSYSMEM
;
509 pso
->fjBitmap
&= ~BMF_NOTSYSMEM
;
510 if (flSurface
& MS_SHAREDACCESS
)
511 psurf
->flags
|= SHAREACCESS_SURFACE
;
513 psurf
->flags
&= ~SHAREACCESS_SURFACE
;
515 /* Check if the caller passed bitmap bits */
516 if ((pvScan0
!= NULL
) && (lDelta
!= 0))
518 /* Update the fields */
519 pso
->pvScan0
= pvScan0
;
520 pso
->lDelta
= lDelta
;
522 /* This is a bitmap now! */
523 pso
->iType
= STYPE_BITMAP
;
525 /* Check memory layout */
528 /* Topdown is the normal way */
529 pso
->cjBits
= lDelta
* pso
->sizlBitmap
.cy
;
530 pso
->pvBits
= pso
->pvScan0
;
531 pso
->fjBitmap
|= BMF_TOPDOWN
;
535 /* Inversed bitmap (bottom up) */
536 pso
->cjBits
= (-lDelta
) * pso
->sizlBitmap
.cy
;
537 pso
->pvBits
= (PCHAR
)pso
->pvScan0
- pso
->cjBits
- lDelta
;
538 pso
->fjBitmap
&= ~BMF_TOPDOWN
;
543 /* Set bits to NULL */
548 /* Set appropriate surface type */
549 if (pso
->iType
!= STYPE_DEVICE
)
550 pso
->iType
= STYPE_DEVBITMAP
;
553 SURFACE_ShareUnlockSurface(psurf
);
562 _In_ _Post_ptr_invalid_ HSURF hsurf
)
566 psurf
= SURFACE_ShareLockSurface(hsurf
);
569 DPRINT1("Could not reference surface %p to delete\n", hsurf
);
573 GDIOBJ_vDeleteObject(&psurf
->BaseObject
);
586 return FillSolid(pso
, prcl
, iColor
);
593 NtGdiEngLockSurface(IN HSURF hsurf
)
595 return EngLockSurface(hsurf
);
604 SURFACE
*psurf
= SURFACE_ShareLockSurface(hsurf
);
606 return psurf
? &psurf
->SurfObj
: NULL
;
612 NtGdiEngUnlockSurface(
617 return STATUS_NOT_IMPLEMENTED
;
623 _In_ _Post_ptr_invalid_ SURFOBJ
*pso
)
627 SURFACE
*psurf
= CONTAINING_RECORD(pso
, SURFACE
, SurfObj
);
628 SURFACE_ShareUnlockSurface(psurf
);