a33cf6f01573070514f55d6e24ca80dc2ff5838a
[reactos.git] / reactos / subsystems / win32 / win32k / eng / surface.c
1 /*
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
7 * REVISION HISTORY:
8 * 3/7/1999: Created
9 * 9/11/2000: Updated to handle real pixel packed bitmaps (UPDATE TO DATE COMPLETED)
10 * TESTING TO BE DONE:
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
13 */
14
15 #include <w32k.h>
16
17 #define NDEBUG
18 #include <debug.h>
19
20 enum Rle_EscapeCodes
21 {
22 RLE_EOL = 0, /* End of line */
23 RLE_END = 1, /* End of bitmap */
24 RLE_DELTA = 2 /* Delta */
25 };
26
27 INT FASTCALL BitsPerFormat(ULONG Format)
28 {
29 switch (Format)
30 {
31 case BMF_1BPP:
32 return 1;
33
34 case BMF_4BPP:
35 /* Fall through */
36 case BMF_4RLE:
37 return 4;
38
39 case BMF_8BPP:
40 /* Fall through */
41 case BMF_8RLE:
42 return 8;
43
44 case BMF_16BPP:
45 return 16;
46
47 case BMF_24BPP:
48 return 24;
49
50 case BMF_32BPP:
51 return 32;
52
53 default:
54 return 0;
55 }
56 }
57
58 ULONG FASTCALL BitmapFormat(WORD Bits, DWORD Compression)
59 {
60 switch (Compression)
61 {
62 case BI_RGB:
63 /* Fall through */
64 case BI_BITFIELDS:
65 switch (Bits)
66 {
67 case 1:
68 return BMF_1BPP;
69 case 4:
70 return BMF_4BPP;
71 case 8:
72 return BMF_8BPP;
73 case 16:
74 return BMF_16BPP;
75 case 24:
76 return BMF_24BPP;
77 case 32:
78 return BMF_32BPP;
79 }
80 return 0;
81
82 case BI_RLE4:
83 return BMF_4RLE;
84
85 case BI_RLE8:
86 return BMF_8RLE;
87
88 default:
89 return 0;
90 }
91 }
92
93 BOOL INTERNAL_CALL
94 SURFACE_Cleanup(PVOID ObjectBody)
95 {
96 PSURFACE psurf = (PSURFACE)ObjectBody;
97 PVOID pvBits = psurf->SurfObj.pvBits;
98
99 /* If this is an API bitmap, free the bits */
100 if (pvBits != NULL &&
101 (psurf->flFlags & BITMAPOBJ_IS_APIBITMAP))
102 {
103 /* Check if we have a DIB section */
104 if (psurf->hSecure)
105 {
106 // FIXME: IMPLEMENT ME!
107 // MmUnsecureVirtualMemory(psurf->hSecure);
108 if (psurf->hDIBSection)
109 {
110 /* DIB was created from a section */
111 NTSTATUS Status;
112
113 pvBits = (PVOID)((ULONG_PTR)pvBits - psurf->dwOffset);
114 Status = ZwUnmapViewOfSection(NtCurrentProcess(), pvBits);
115 if (!NT_SUCCESS(Status))
116 {
117 DPRINT1("Could not unmap section view!\n");
118 // Should we BugCheck here?
119 }
120 }
121 else
122 {
123 /* DIB was allocated */
124 EngFreeUserMem(pvBits);
125 }
126 }
127 else
128 {
129 // FIXME: use TAG
130 ExFreePool(psurf->SurfObj.pvBits);
131 }
132
133 if (psurf->hDIBPalette != NULL)
134 {
135 GreDeleteObject(psurf->hDIBPalette);
136 }
137 }
138
139 if (NULL != psurf->BitsLock)
140 {
141 ExFreePoolWithTag(psurf->BitsLock, TAG_SURFACE);
142 psurf->BitsLock = NULL;
143 }
144
145 return TRUE;
146 }
147
148 BOOL INTERNAL_CALL
149 SURFACE_InitBitsLock(PSURFACE psurf)
150 {
151 psurf->BitsLock = ExAllocatePoolWithTag(NonPagedPool,
152 sizeof(FAST_MUTEX),
153 TAG_SURFACE);
154 if (NULL == psurf->BitsLock)
155 {
156 return FALSE;
157 }
158
159 ExInitializeFastMutex(psurf->BitsLock);
160
161 return TRUE;
162 }
163
164 void INTERNAL_CALL
165 SURFACE_CleanupBitsLock(PSURFACE psurf)
166 {
167 if (NULL != psurf->BitsLock)
168 {
169 ExFreePoolWithTag(psurf->BitsLock, TAG_SURFACE);
170 psurf->BitsLock = NULL;
171 }
172 }
173
174
175 /*
176 * @implemented
177 */
178 HBITMAP APIENTRY
179 EngCreateDeviceBitmap(IN DHSURF dhsurf,
180 IN SIZEL Size,
181 IN ULONG Format)
182 {
183 HBITMAP NewBitmap;
184 SURFOBJ *pso;
185
186 NewBitmap = EngCreateBitmap(Size, DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format)), Format, 0, NULL);
187 if (!NewBitmap)
188 {
189 DPRINT1("EngCreateBitmap failed\n");
190 return 0;
191 }
192
193 pso = EngLockSurface((HSURF)NewBitmap);
194 if (!pso)
195 {
196 DPRINT1("EngLockSurface failed on newly created bitmap!\n");
197 GreDeleteObject(NewBitmap);
198 return NULL;
199 }
200
201 pso->dhsurf = dhsurf;
202 EngUnlockSurface(pso);
203
204 return NewBitmap;
205 }
206
207 VOID Decompress4bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta)
208 {
209 int x = 0;
210 int y = Size.cy - 1;
211 int c;
212 int length;
213 int width = ((Size.cx+1)/2);
214 int height = Size.cy - 1;
215 BYTE *begin = CompressedBits;
216 BYTE *bits = CompressedBits;
217 BYTE *temp;
218 while (y >= 0)
219 {
220 length = *bits++ / 2;
221 if (length)
222 {
223 c = *bits++;
224 while (length--)
225 {
226 if (x >= width) break;
227 temp = UncompressedBits + (((height - y) * Delta) + x);
228 x++;
229 *temp = c;
230 }
231 }
232 else
233 {
234 length = *bits++;
235 switch (length)
236 {
237 case RLE_EOL:
238 x = 0;
239 y--;
240 break;
241 case RLE_END:
242 return;
243 case RLE_DELTA:
244 x += (*bits++)/2;
245 y -= (*bits++)/2;
246 break;
247 default:
248 length /= 2;
249 while (length--)
250 {
251 c = *bits++;
252 if (x < width)
253 {
254 temp = UncompressedBits + (((height - y) * Delta) + x);
255 x++;
256 *temp = c;
257 }
258 }
259 if ((bits - begin) & 1)
260 {
261 bits++;
262 }
263 }
264 }
265 }
266 }
267
268 VOID Decompress8bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta)
269 {
270 int x = 0;
271 int y = Size.cy - 1;
272 int c;
273 int length;
274 int width = Size.cx;
275 int height = Size.cy - 1;
276 BYTE *begin = CompressedBits;
277 BYTE *bits = CompressedBits;
278 BYTE *temp;
279 while (y >= 0)
280 {
281 length = *bits++;
282 if (length)
283 {
284 c = *bits++;
285 while (length--)
286 {
287 if (x >= width) break;
288 temp = UncompressedBits + (((height - y) * Delta) + x);
289 x++;
290 *temp = c;
291 }
292 }
293 else
294 {
295 length = *bits++;
296 switch (length)
297 {
298 case RLE_EOL:
299 x = 0;
300 y--;
301 break;
302 case RLE_END:
303 return;
304 case RLE_DELTA:
305 x += *bits++;
306 y -= *bits++;
307 break;
308 default:
309 while (length--)
310 {
311 c = *bits++;
312 if (x < width)
313 {
314 temp = UncompressedBits + (((height - y) * Delta) + x);
315 x++;
316 *temp = c;
317 }
318 }
319 if ((bits - begin) & 1)
320 {
321 bits++;
322 }
323 }
324 }
325 }
326 }
327
328 HBITMAP FASTCALL
329 IntCreateBitmap(IN SIZEL Size,
330 IN LONG Width,
331 IN ULONG Format,
332 IN ULONG Flags,
333 IN PVOID Bits)
334 {
335 SURFOBJ *pso;
336 PSURFACE psurf;
337 SIZEL LocalSize;
338 ULONG ScanLine = 0; // Compiler is dumb
339 ULONG BitsSize;
340
341 ScanLine = abs(Width);
342
343 /* Does the device manage its own surface? */
344 if (!Bits)
345 {
346 /* The height times the bytes for each scanline */
347 BitsSize = Size.cy * ScanLine;
348 if (BitsSize)
349 {
350 /* Check for allocation flag */
351 if (Flags & BMF_USERMEM)
352 {
353 /* Get the bits from user-mode memory */
354 Bits = EngAllocUserMem(BitsSize, 'mbuG');
355 }
356 else
357 {
358 /* Get kernel bits (zeroed out if requested) */
359 Bits = EngAllocMem((Flags & BMF_NOZEROINIT) ? 0 : FL_ZERO_MEMORY,
360 BitsSize,
361 TAG_DIB);
362 }
363
364 /* Bail out if that failed */
365 if (!Bits) return NULL;
366 }
367 }
368 else
369 {
370 /* Should not have asked for user memory */
371 // ASSERT((Flags & BMF_USERMEM) == 0);
372 }
373
374 /* Allocate the actual surface object structure */
375 psurf = SURFACE_AllocSurfaceWithHandle();
376 if (!psurf) return NULL;
377
378 /* Lock down the surface */
379 if (!SURFACE_InitBitsLock(psurf))
380 {
381 /* Bail out if that failed */
382 SURFACE_UnlockSurface(psurf);
383 SURFACE_FreeSurface(psurf);
384 return NULL;
385 }
386
387 /* We should now have our surface object */
388 pso = &psurf->SurfObj;
389
390 /* Set bits */
391 pso->pvBits = Bits;
392
393 /* Number of bits is based on the height times the scanline */
394 pso->cjBits = Size.cy * ScanLine;
395 if (Flags & BMF_TOPDOWN)
396 {
397 /* For topdown, the base address starts with the bits */
398 pso->pvScan0 = pso->pvBits;
399 pso->lDelta = ScanLine;
400 }
401 else
402 {
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;
406 }
407
408 /* Save format and flags */
409 pso->iBitmapFormat = Format;
410 pso->fjBitmap = Flags & (BMF_TOPDOWN | BMF_UMPDMEM | BMF_USERMEM);
411
412 /* Save size and type */
413 LocalSize.cx = Size.cx;
414 LocalSize.cy = Size.cy;
415 pso->sizlBitmap = Size;
416 pso->iType = STYPE_BITMAP;
417
418 /* Device-managed surface, no flags or dimension */
419 pso->dhsurf = 0;
420 pso->dhpdev = NULL;
421 pso->hdev = NULL;
422 psurf->flFlags = 0;
423 psurf->dimension.cx = 0;
424 psurf->dimension.cy = 0;
425 psurf->hSecure = NULL;
426 psurf->hDIBSection = NULL;
427 psurf->flHooks = 0;
428
429
430 /* Finally set the handle and uniq */
431 pso->hsurf = (HSURF)psurf->BaseObject.hHmgr;
432 pso->iUniq = 0;
433
434 /* Unlock and return the surface */
435 SURFACE_UnlockSurface(psurf);
436 return pso->hsurf;
437 }
438
439 /* Name gleaned from C++ symbol information for SURFMEM::bInitDIB */
440 typedef struct _DEVBITMAPINFO
441 {
442 ULONG Format;
443 ULONG Width;
444 ULONG Height;
445 ULONG Flags;
446 ULONG Size;
447 } DEVBITMAPINFO, *PDEVBITMAPINFO;
448
449 SURFOBJ*
450 FASTCALL
451 SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
452 IN PVOID Bits)
453 {
454 BOOLEAN Compressed = FALSE;
455 ULONG ScanLine = 0; // Compiler is dumb
456 ULONG Size;
457 SURFOBJ *pso;
458 PSURFACE psurf;
459 SIZEL LocalSize;
460
461 /*
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!
465 */
466 switch (BitmapInfo->Format)
467 {
468 case BMF_1BPP:
469 //ScanLine = ((BitmapInfo->Width + 31) & ~31) / 8;
470 break;
471
472 case BMF_4BPP:
473 //ScanLine = ((BitmapInfo->Width + 7) & ~7) / 2;
474 break;
475
476 case BMF_8BPP:
477 //ScanLine = ((BitmapInfo->Width + 3) & ~3);
478 break;
479
480 case BMF_16BPP:
481 //ScanLine = ((BitmapInfo->Width + 1) & ~1) * 2;
482 break;
483
484 case BMF_24BPP:
485 //ScanLine = ((BitmapInfo->Width * 3) + 3) & ~3;
486 break;
487
488 case BMF_32BPP:
489 // ScanLine = BitmapInfo->Width * 4;
490 break;
491
492 case BMF_8RLE:
493 case BMF_4RLE:
494 case BMF_JPEG:
495 case BMF_PNG:
496 Compressed = TRUE;
497 break;
498
499 default:
500 DPRINT1("Invalid bitmap format\n");
501 return NULL;
502 }
503
504 ScanLine = BitmapInfo->Width;
505
506 /* Does the device manage its own surface? */
507 if (!Bits)
508 {
509 /* We need to allocate bits for the caller, figure out the size */
510 if (Compressed)
511 {
512 /* Note: we should not be seeing this scenario from ENGDDI */
513 ASSERT(FALSE);
514 Size = BitmapInfo->Size;
515 }
516 else
517 {
518 /* The height times the bytes for each scanline */
519 Size = BitmapInfo->Height * ScanLine;
520 }
521
522 if (Size)
523 {
524 /* Check for allocation flag */
525 if (BitmapInfo->Flags & BMF_USERMEM)
526 {
527 /* Get the bits from user-mode memory */
528 Bits = EngAllocUserMem(Size, 'mbuG');
529 }
530 else
531 {
532 /* Get kernel bits (zeroed out if requested) */
533 Bits = EngAllocMem((BitmapInfo->Flags & BMF_NOZEROINIT) ? 0 : FL_ZERO_MEMORY,
534 Size,
535 TAG_DIB);
536 }
537
538 /* Bail out if that failed */
539 if (!Bits) return NULL;
540 }
541 }
542 else
543 {
544 /* Should not have asked for user memory */
545 ASSERT((BitmapInfo->Flags & BMF_USERMEM) == 0);
546 }
547
548 /* Allocate the actual surface object structure */
549 psurf = SURFACE_AllocSurfaceWithHandle();
550 if (!psurf) return NULL;
551
552 /* Lock down the surface */
553 if (!SURFACE_InitBitsLock(psurf))
554 {
555 /* Bail out if that failed */
556 SURFACE_UnlockSurface(psurf);
557 SURFACE_FreeSurface(psurf);
558 return NULL;
559 }
560
561 /* We should now have our surface object */
562 pso = &psurf->SurfObj;
563
564 /* Save format and flags */
565 pso->iBitmapFormat = BitmapInfo->Format;
566 pso->fjBitmap = BitmapInfo->Flags & (BMF_TOPDOWN | BMF_UMPDMEM | BMF_USERMEM);
567
568 /* Save size and type */
569 LocalSize.cy = BitmapInfo->Height;
570 LocalSize.cx = BitmapInfo->Width;
571 pso->sizlBitmap = LocalSize;
572 pso->iType = STYPE_BITMAP;
573
574 /* Device-managed surface, no flags or dimension */
575 pso->dhsurf = 0;
576 pso->dhpdev = NULL;
577 pso->hdev = NULL;
578 psurf->flFlags = 0;
579 psurf->dimension.cx = 0;
580 psurf->dimension.cy = 0;
581 psurf->hSecure = NULL;
582 psurf->hDIBSection = NULL;
583 psurf->flHooks = 0;
584
585 /* Set bits */
586 pso->pvBits = Bits;
587
588 /* Check for bitmap type */
589 if (!Compressed)
590 {
591 /* Number of bits is based on the height times the scanline */
592 pso->cjBits = BitmapInfo->Height * ScanLine;
593 if (BitmapInfo->Flags & BMF_TOPDOWN)
594 {
595 /* For topdown, the base address starts with the bits */
596 pso->pvScan0 = pso->pvBits;
597 pso->lDelta = ScanLine;
598 }
599 else
600 {
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;
604 }
605 }
606 else
607 {
608 /* Compressed surfaces don't have scanlines! */
609 ASSERT(FALSE); // Should not get here on ENGDDI
610 pso->lDelta = 0;
611 pso->cjBits = BitmapInfo->Size;
612
613 /* Check for JPG or PNG */
614 if ((BitmapInfo->Format != BMF_JPEG) && (BitmapInfo->Format != BMF_PNG))
615 {
616 /* Wherever the bit data is */
617 pso->pvScan0 = pso->pvBits;
618 }
619 else
620 {
621 /* Fancy formats don't use a base address */
622 pso->pvScan0 = NULL;
623 ASSERT(FALSE); // ENGDDI shouldn't be creating PNGs for drivers ;-)
624 }
625 }
626
627 /* Finally set the handle and uniq */
628 pso->hsurf = (HSURF)psurf->BaseObject.hHmgr;
629 pso->iUniq = 0;
630
631 /* Unlock and return the surface */
632 SURFACE_UnlockSurface(psurf);
633 return pso;
634 }
635
636 /*
637 * @implemented
638 */
639 HBITMAP
640 APIENTRY
641 EngCreateBitmap(IN SIZEL Size,
642 IN LONG Width,
643 IN ULONG Format,
644 IN ULONG Flags,
645 IN PVOID Bits)
646 {
647 SURFOBJ* Surface;
648 DEVBITMAPINFO BitmapInfo;
649
650 /* Capture the parameters */
651 BitmapInfo.Format = Format;
652 BitmapInfo.Width = Size.cx;
653 BitmapInfo.Height = Size.cy;
654 BitmapInfo.Flags = Flags;
655
656 /*
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
659 * of bytes.
660 */
661 if ((Bits) && (Width))
662 {
663 #if 0
664 switch (BitmapInfo.Format)
665 {
666 /* Do the conversion for each bit depth we support */
667 case BMF_1BPP:
668 BitmapInfo.Width = Width * 8;
669 break;
670 case BMF_4BPP:
671 BitmapInfo.Width = Width * 2;
672 break;
673 case BMF_8BPP:
674 BitmapInfo.Width = Width;
675 break;
676 case BMF_16BPP:
677 BitmapInfo.Width = Width / 2;
678 break;
679 case BMF_24BPP:
680 BitmapInfo.Width = Width / 3;
681 break;
682 case BMF_32BPP:
683 BitmapInfo.Width = Width / 4;
684 break;
685 }
686 #endif
687 BitmapInfo.Width = Width;
688
689 }
690
691 /* Now create the surface */
692 Surface = SURFMEM_bCreateDib(&BitmapInfo, Bits);
693 if (!Surface) return 0;
694
695 /* Set public ownership and reutrn the handle */
696 GDIOBJ_SetOwnership(Surface->hsurf, NULL);
697 return Surface->hsurf;
698 }
699
700 /*
701 * @unimplemented
702 */
703 HSURF APIENTRY
704 EngCreateDeviceSurface(IN DHSURF dhsurf,
705 IN SIZEL Size,
706 IN ULONG Format)
707 {
708 HSURF hsurf;
709 SURFOBJ *pso;
710 PSURFACE psurf;
711
712 psurf = SURFACE_AllocSurfaceWithHandle();
713 if (!psurf)
714 {
715 return 0;
716 }
717
718 hsurf = psurf->BaseObject.hHmgr;
719 GDIOBJ_SetOwnership(hsurf, NULL);
720
721 if (!SURFACE_InitBitsLock(psurf))
722 {
723 SURFACE_UnlockSurface(psurf);
724 SURFACE_FreeSurfaceByHandle(hsurf);
725 return 0;
726 }
727 pso = &psurf->SurfObj;
728
729 pso->dhsurf = dhsurf;
730 pso->hsurf = hsurf;
731 pso->sizlBitmap = Size;
732 pso->iBitmapFormat = Format;
733 pso->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format));
734 pso->iType = STYPE_DEVICE;
735 pso->iUniq = 0;
736
737 psurf->flHooks = 0;
738
739 SURFACE_UnlockSurface(psurf);
740
741 return hsurf;
742 }
743
744 /*
745 * @implemented
746 */
747 BOOL
748 APIENTRY
749 EngAssociateSurface(
750 IN HSURF hsurf,
751 IN HDEV hdev,
752 IN FLONG flHooks)
753 {
754 SURFOBJ *pso;
755 PSURFACE psurf;
756 PDEVOBJ* ppdev;
757
758 ppdev = (PDEVOBJ*)hdev;
759
760 /* Lock the surface */
761 psurf = SURFACE_LockSurface(hsurf);
762 if (!psurf)
763 {
764 return FALSE;
765 }
766 pso = &psurf->SurfObj;
767
768 /* Associate the hdev */
769 pso->hdev = hdev;
770 pso->dhpdev = ppdev->dhpdev;
771
772 /* Hook up specified functions */
773 psurf->flHooks = flHooks;
774
775 SURFACE_UnlockSurface(psurf);
776
777 return TRUE;
778 }
779
780 /*
781 * @implemented
782 */
783 BOOL APIENTRY
784 EngModifySurface(
785 IN HSURF hsurf,
786 IN HDEV hdev,
787 IN FLONG flHooks,
788 IN FLONG flSurface,
789 IN DHSURF dhsurf,
790 OUT VOID *pvScan0,
791 IN LONG lDelta,
792 IN VOID *pvReserved)
793 {
794 SURFOBJ *pso;
795 PSURFACE psurf;
796 PDEVOBJ* ppdev;
797
798 psurf = SURFACE_LockSurface(hsurf);
799 if (psurf == NULL)
800 {
801 return FALSE;
802 }
803
804 ppdev = (PDEVOBJ*)hdev;
805 pso = &psurf->SurfObj;
806 pso->dhsurf = dhsurf;
807 pso->lDelta = lDelta;
808 pso->pvScan0 = pvScan0;
809
810 /* Associate the hdev */
811 pso->hdev = hdev;
812 pso->dhpdev = ppdev->dhpdev;
813
814 /* Hook up specified functions */
815 psurf->flHooks = flHooks;
816
817 SURFACE_UnlockSurface(psurf);
818
819 return TRUE;
820 }
821
822 /*
823 * @implemented
824 */
825 BOOL APIENTRY
826 EngDeleteSurface(IN HSURF hsurf)
827 {
828 GDIOBJ_SetOwnership(hsurf, PsGetCurrentProcess());
829 SURFACE_FreeSurfaceByHandle(hsurf);
830 return TRUE;
831 }
832
833 /*
834 * @implemented
835 */
836 BOOL APIENTRY
837 EngEraseSurface(SURFOBJ *pso,
838 RECTL *Rect,
839 ULONG iColor)
840 {
841 ASSERT(pso);
842 ASSERT(Rect);
843 return FillSolid(pso, Rect, iColor);
844 }
845
846 /*
847 * @implemented
848 */
849 SURFOBJ * APIENTRY
850 NtGdiEngLockSurface(IN HSURF hsurf)
851 {
852 return EngLockSurface(hsurf);
853 }
854
855
856 /*
857 * @implemented
858 */
859 SURFOBJ * APIENTRY
860 EngLockSurface(IN HSURF hsurf)
861 {
862 SURFACE *psurf = GDIOBJ_ShareLockObj(hsurf, GDI_OBJECT_TYPE_BITMAP);
863
864 if (psurf != NULL)
865 return &psurf->SurfObj;
866
867 return NULL;
868 }
869
870
871 /*
872 * @implemented
873 */
874 VOID APIENTRY
875 NtGdiEngUnlockSurface(IN SURFOBJ *pso)
876 {
877 EngUnlockSurface(pso);
878 }
879
880 /*
881 * @implemented
882 */
883 VOID APIENTRY
884 EngUnlockSurface(IN SURFOBJ *pso)
885 {
886 if (pso != NULL)
887 {
888 SURFACE *psurf = CONTAINING_RECORD(pso, SURFACE, SurfObj);
889 GDIOBJ_ShareUnlockObjByPtr((POBJ)psurf);
890 }
891 }
892
893
894 /* EOF */