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. (STYPE_BITMAP, sizl.cx=%ld, sizl.cy=%ld, iFormat=%lu, fl=%lu, lWidth=%ld, pvBits=0x%p)\n",
328 sizl
.cx
, sizl
.cy
, iFormat
, fl
, lWidth
, pvBits
);
332 /* Get the handle for the bitmap */
333 hbmp
= (HBITMAP
)psurf
->SurfObj
.hsurf
;
335 /* Set public ownership */
336 GDIOBJ_vSetObjectOwner(&psurf
->BaseObject
, GDI_OBJ_HMGR_PUBLIC
);
338 /* Unlock the surface and return */
339 SURFACE_UnlockSurface(psurf
);
348 EngCreateDeviceBitmap(
356 /* Allocate a surface */
357 psurf
= SURFACE_AllocSurface(STYPE_DEVBITMAP
,
367 DPRINT1("SURFACE_AllocSurface failed. (STYPE_DEVBITMAP, sizl.cx=%ld, sizl.cy=%ld, iFormat=%lu)\n",
368 sizl
.cx
, sizl
.cy
, iFormat
);
372 /* Set the device handle */
373 psurf
->SurfObj
.dhsurf
= dhsurf
;
375 /* Set public ownership */
376 GDIOBJ_vSetObjectOwner(&psurf
->BaseObject
, GDI_OBJ_HMGR_PUBLIC
);
378 /* Get the handle for the bitmap */
379 hbmp
= (HBITMAP
)psurf
->SurfObj
.hsurf
;
381 /* Unlock the surface and return */
382 SURFACE_UnlockSurface(psurf
);
388 EngCreateDeviceSurface(
396 /* Allocate a surface */
397 psurf
= SURFACE_AllocSurface(STYPE_DEVICE
,
407 DPRINT1("SURFACE_AllocSurface failed. (STYPE_DEVICE, sizl.cx=%ld, sizl.cy=%ld, iFormat=%lu)\n",
408 sizl
.cx
, sizl
.cy
, iFormat
);
412 /* Set the device handle */
413 psurf
->SurfObj
.dhsurf
= dhsurf
;
415 /* Set public ownership */
416 GDIOBJ_vSetObjectOwner(&psurf
->BaseObject
, GDI_OBJ_HMGR_PUBLIC
);
418 /* Get the handle for the surface */
419 hsurf
= psurf
->SurfObj
.hsurf
;
421 /* Unlock the surface and return */
422 SURFACE_UnlockSurface(psurf
);
438 ppdev
= (PDEVOBJ
*)hdev
;
440 /* Lock the surface */
441 psurf
= SURFACE_ShareLockSurface(hsurf
);
446 pso
= &psurf
->SurfObj
;
448 /* Associate the hdev */
450 pso
->dhpdev
= ppdev
->dhpdev
;
452 /* Hook up specified functions */
453 psurf
->flags
&= ~HOOK_FLAGS
;
454 psurf
->flags
|= (flHooks
& HOOK_FLAGS
);
456 /* Assign the PDEV's palette */
457 ppal
= PALETTE_ShareLockPalette(ppdev
->devinfo
.hpalDefault
);
458 SURFACE_vSetPalette(psurf
, ppal
);
459 PALETTE_ShareUnlockPalette(ppal
);
461 SURFACE_ShareUnlockSurface(psurf
);
472 _In_ FLONG flSurface
,
476 _Reserved_ PVOID pvReserved
)
483 /* Lock the surface */
484 psurf
= SURFACE_ShareLockSurface(hsurf
);
487 DPRINT1("Failed to reference surface %p\n", hsurf
);
491 ppdev
= (PDEVOBJ
*)hdev
;
492 pso
= &psurf
->SurfObj
;
493 pso
->dhsurf
= dhsurf
;
495 /* Associate the hdev */
497 pso
->dhpdev
= ppdev
->dhpdev
;
499 /* Hook up specified functions */
500 psurf
->flags
&= ~HOOK_FLAGS
;
501 psurf
->flags
|= (flHooks
& HOOK_FLAGS
);
503 /* Assign the PDEV's palette */
504 ppal
= PALETTE_ShareLockPalette(ppdev
->devinfo
.hpalDefault
);
505 SURFACE_vSetPalette(psurf
, ppal
);
506 PALETTE_ShareUnlockPalette(ppal
);
508 /* Update surface flags */
509 if (flSurface
& MS_NOTSYSTEMMEMORY
)
510 pso
->fjBitmap
|= BMF_NOTSYSMEM
;
512 pso
->fjBitmap
&= ~BMF_NOTSYSMEM
;
513 if (flSurface
& MS_SHAREDACCESS
)
514 psurf
->flags
|= SHAREACCESS_SURFACE
;
516 psurf
->flags
&= ~SHAREACCESS_SURFACE
;
518 /* Check if the caller passed bitmap bits */
519 if ((pvScan0
!= NULL
) && (lDelta
!= 0))
521 /* Update the fields */
522 pso
->pvScan0
= pvScan0
;
523 pso
->lDelta
= lDelta
;
525 /* This is a bitmap now! */
526 pso
->iType
= STYPE_BITMAP
;
528 /* Check memory layout */
531 /* Topdown is the normal way */
532 pso
->cjBits
= lDelta
* pso
->sizlBitmap
.cy
;
533 pso
->pvBits
= pso
->pvScan0
;
534 pso
->fjBitmap
|= BMF_TOPDOWN
;
538 /* Inversed bitmap (bottom up) */
539 pso
->cjBits
= (-lDelta
) * pso
->sizlBitmap
.cy
;
540 pso
->pvBits
= (PCHAR
)pso
->pvScan0
- pso
->cjBits
- lDelta
;
541 pso
->fjBitmap
&= ~BMF_TOPDOWN
;
546 /* Set bits to NULL */
551 /* Set appropriate surface type */
552 if (pso
->iType
!= STYPE_DEVICE
)
553 pso
->iType
= STYPE_DEVBITMAP
;
556 SURFACE_ShareUnlockSurface(psurf
);
565 _In_ _Post_ptr_invalid_ HSURF hsurf
)
569 psurf
= SURFACE_ShareLockSurface(hsurf
);
572 DPRINT1("Could not reference surface %p to delete\n", hsurf
);
576 GDIOBJ_vDeleteObject(&psurf
->BaseObject
);
589 return FillSolid(pso
, prcl
, iColor
);
596 NtGdiEngLockSurface(IN HSURF hsurf
)
598 return EngLockSurface(hsurf
);
607 SURFACE
*psurf
= SURFACE_ShareLockSurface(hsurf
);
609 return psurf
? &psurf
->SurfObj
: NULL
;
615 NtGdiEngUnlockSurface(
620 return STATUS_NOT_IMPLEMENTED
;
626 _In_ _Post_ptr_invalid_ SURFOBJ
*pso
)
630 SURFACE
*psurf
= CONTAINING_RECORD(pso
, SURFACE
, SurfObj
);
631 SURFACE_ShareUnlockSurface(psurf
);