Rename NtGdiDeleteObject to GreDeleteObject
[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 pso->dhsurf = dhsurf;
195 EngUnlockSurface(pso);
196
197 return NewBitmap;
198 }
199
200 VOID Decompress4bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta)
201 {
202 int x = 0;
203 int y = Size.cy - 1;
204 int c;
205 int length;
206 int width = ((Size.cx+1)/2);
207 int height = Size.cy - 1;
208 BYTE *begin = CompressedBits;
209 BYTE *bits = CompressedBits;
210 BYTE *temp;
211 while (y >= 0)
212 {
213 length = *bits++ / 2;
214 if (length)
215 {
216 c = *bits++;
217 while (length--)
218 {
219 if (x >= width) break;
220 temp = UncompressedBits + (((height - y) * Delta) + x);
221 x++;
222 *temp = c;
223 }
224 }
225 else
226 {
227 length = *bits++;
228 switch (length)
229 {
230 case RLE_EOL:
231 x = 0;
232 y--;
233 break;
234 case RLE_END:
235 return;
236 case RLE_DELTA:
237 x += (*bits++)/2;
238 y -= (*bits++)/2;
239 break;
240 default:
241 length /= 2;
242 while (length--)
243 {
244 c = *bits++;
245 if (x < width)
246 {
247 temp = UncompressedBits + (((height - y) * Delta) + x);
248 x++;
249 *temp = c;
250 }
251 }
252 if ((bits - begin) & 1)
253 {
254 bits++;
255 }
256 }
257 }
258 }
259 }
260
261 VOID Decompress8bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta)
262 {
263 int x = 0;
264 int y = Size.cy - 1;
265 int c;
266 int length;
267 int width = Size.cx;
268 int height = Size.cy - 1;
269 BYTE *begin = CompressedBits;
270 BYTE *bits = CompressedBits;
271 BYTE *temp;
272 while (y >= 0)
273 {
274 length = *bits++;
275 if (length)
276 {
277 c = *bits++;
278 while (length--)
279 {
280 if (x >= width) break;
281 temp = UncompressedBits + (((height - y) * Delta) + x);
282 x++;
283 *temp = c;
284 }
285 }
286 else
287 {
288 length = *bits++;
289 switch (length)
290 {
291 case RLE_EOL:
292 x = 0;
293 y--;
294 break;
295 case RLE_END:
296 return;
297 case RLE_DELTA:
298 x += *bits++;
299 y -= *bits++;
300 break;
301 default:
302 while (length--)
303 {
304 c = *bits++;
305 if (x < width)
306 {
307 temp = UncompressedBits + (((height - y) * Delta) + x);
308 x++;
309 *temp = c;
310 }
311 }
312 if ((bits - begin) & 1)
313 {
314 bits++;
315 }
316 }
317 }
318 }
319 }
320
321 HBITMAP FASTCALL
322 IntCreateBitmap(IN SIZEL Size,
323 IN LONG Width,
324 IN ULONG Format,
325 IN ULONG Flags,
326 IN PVOID Bits)
327 {
328 HBITMAP hbmp;
329 SURFOBJ *pso;
330 PSURFACE psurf;
331 PVOID UncompressedBits;
332 ULONG UncompressedFormat;
333
334 if (Format == 0)
335 return 0;
336
337 psurf = SURFACE_AllocSurfaceWithHandle();
338 if (psurf == NULL)
339 {
340 return 0;
341 }
342 hbmp = psurf->BaseObject.hHmgr;
343
344 if (! SURFACE_InitBitsLock(psurf))
345 {
346 SURFACE_UnlockSurface(psurf);
347 SURFACE_FreeSurfaceByHandle(hbmp);
348 return 0;
349 }
350 pso = &psurf->SurfObj;
351
352 if (Format == BMF_4RLE)
353 {
354 pso->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_4BPP));
355 pso->cjBits = pso->lDelta * Size.cy;
356 UncompressedFormat = BMF_4BPP;
357 UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
358 Decompress4bpp(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, pso->lDelta);
359 }
360 else if (Format == BMF_8RLE)
361 {
362 pso->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_8BPP));
363 pso->cjBits = pso->lDelta * Size.cy;
364 UncompressedFormat = BMF_8BPP;
365 UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
366 Decompress8bpp(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, pso->lDelta);
367 }
368 else
369 {
370 pso->lDelta = abs(Width);
371 pso->cjBits = pso->lDelta * Size.cy;
372 UncompressedBits = Bits;
373 UncompressedFormat = Format;
374 }
375
376 if (UncompressedBits != NULL)
377 {
378 pso->pvBits = UncompressedBits;
379 }
380 else
381 {
382 if (pso->cjBits == 0)
383 {
384 pso->pvBits = NULL;
385 }
386 else
387 {
388 if (0 != (Flags & BMF_USERMEM))
389 {
390 pso->pvBits = EngAllocUserMem(pso->cjBits, 0);
391 }
392 else
393 {
394 pso->pvBits = EngAllocMem(0 != (Flags & BMF_NOZEROINIT) ?
395 0 : FL_ZERO_MEMORY,
396 pso->cjBits, TAG_DIB);
397 }
398 if (pso->pvBits == NULL)
399 {
400 SURFACE_UnlockSurface(psurf);
401 SURFACE_FreeSurfaceByHandle(hbmp);
402 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
403 return 0;
404 }
405 }
406 }
407
408 if (0 == (Flags & BMF_TOPDOWN))
409 {
410 pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - pso->lDelta);
411 pso->lDelta = - pso->lDelta;
412 }
413 else
414 {
415 pso->pvScan0 = pso->pvBits;
416 }
417
418 pso->dhsurf = 0; /* device managed surface */
419 pso->hsurf = (HSURF)hbmp;
420 pso->dhpdev = NULL;
421 pso->hdev = NULL;
422 pso->sizlBitmap = Size;
423 pso->iBitmapFormat = UncompressedFormat;
424 pso->iType = STYPE_BITMAP;
425 pso->fjBitmap = Flags & (BMF_TOPDOWN | BMF_NOZEROINIT);
426 pso->iUniq = 0;
427
428 psurf->flHooks = 0;
429 psurf->flFlags = 0;
430 psurf->dimension.cx = 0;
431 psurf->dimension.cy = 0;
432
433 psurf->hSecure = NULL;
434 psurf->hDIBSection = NULL;
435
436 SURFACE_UnlockSurface(psurf);
437
438 return hbmp;
439 }
440
441 /*
442 * @implemented
443 */
444 HBITMAP APIENTRY
445 EngCreateBitmap(IN SIZEL Size,
446 IN LONG Width,
447 IN ULONG Format,
448 IN ULONG Flags,
449 IN PVOID Bits)
450 {
451 HBITMAP hNewBitmap;
452
453 hNewBitmap = IntCreateBitmap(Size, Width, Format, Flags, Bits);
454 if ( !hNewBitmap )
455 return 0;
456
457 GDIOBJ_SetOwnership(hNewBitmap, NULL);
458
459 return hNewBitmap;
460 }
461
462 /*
463 * @unimplemented
464 */
465 HSURF APIENTRY
466 EngCreateDeviceSurface(IN DHSURF dhsurf,
467 IN SIZEL Size,
468 IN ULONG Format)
469 {
470 HSURF hsurf;
471 SURFOBJ *pso;
472 PSURFACE psurf;
473
474 psurf = SURFACE_AllocSurfaceWithHandle();
475 if (!psurf)
476 {
477 return 0;
478 }
479
480 hsurf = psurf->BaseObject.hHmgr;
481 GDIOBJ_SetOwnership(hsurf, NULL);
482
483 if (!SURFACE_InitBitsLock(psurf))
484 {
485 SURFACE_UnlockSurface(psurf);
486 SURFACE_FreeSurfaceByHandle(hsurf);
487 return 0;
488 }
489 pso = &psurf->SurfObj;
490
491 pso->dhsurf = dhsurf;
492 pso->hsurf = hsurf;
493 pso->sizlBitmap = Size;
494 pso->iBitmapFormat = Format;
495 pso->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format));
496 pso->iType = STYPE_DEVICE;
497 pso->iUniq = 0;
498
499 psurf->flHooks = 0;
500
501 SURFACE_UnlockSurface(psurf);
502
503 return hsurf;
504 }
505
506 /*
507 * @implemented
508 */
509 BOOL
510 APIENTRY
511 EngAssociateSurface(
512 IN HSURF hsurf,
513 IN HDEV hdev,
514 IN FLONG flHooks)
515 {
516 SURFOBJ *pso;
517 PSURFACE psurf;
518 PDEVOBJ* ppdev;
519
520 ppdev = (PDEVOBJ*)hdev;
521
522 /* Lock the surface */
523 psurf = SURFACE_LockSurface(hsurf);
524 if (!psurf)
525 {
526 return FALSE;
527 }
528 pso = &psurf->SurfObj;
529
530 /* Associate the hdev */
531 pso->hdev = hdev;
532 pso->dhpdev = ppdev->hPDev;
533
534 /* Hook up specified functions */
535 psurf->flHooks = flHooks;
536
537 SURFACE_UnlockSurface(psurf);
538
539 return TRUE;
540 }
541
542 /*
543 * @implemented
544 */
545 BOOL APIENTRY
546 EngModifySurface(
547 IN HSURF hsurf,
548 IN HDEV hdev,
549 IN FLONG flHooks,
550 IN FLONG flSurface,
551 IN DHSURF dhsurf,
552 OUT VOID *pvScan0,
553 IN LONG lDelta,
554 IN VOID *pvReserved)
555 {
556 SURFOBJ *pso;
557 PSURFACE psurf;
558 PDEVOBJ* ppdev;
559
560 psurf = SURFACE_LockSurface(hsurf);
561 if (psurf == NULL)
562 {
563 return FALSE;
564 }
565
566 ppdev = (PDEVOBJ*)hdev;
567 pso = &psurf->SurfObj;
568 pso->dhsurf = dhsurf;
569 pso->lDelta = lDelta;
570 pso->pvScan0 = pvScan0;
571
572 /* Associate the hdev */
573 pso->hdev = hdev;
574 pso->dhpdev = ppdev->hPDev;
575
576 /* Hook up specified functions */
577 psurf->flHooks = flHooks;
578
579 SURFACE_UnlockSurface(psurf);
580
581 return TRUE;
582 }
583
584 /*
585 * @implemented
586 */
587 BOOL APIENTRY
588 EngDeleteSurface(IN HSURF hsurf)
589 {
590 GDIOBJ_SetOwnership(hsurf, PsGetCurrentProcess());
591 SURFACE_FreeSurfaceByHandle(hsurf);
592 return TRUE;
593 }
594
595 /*
596 * @implemented
597 */
598 BOOL APIENTRY
599 EngEraseSurface(SURFOBJ *pso,
600 RECTL *Rect,
601 ULONG iColor)
602 {
603 ASSERT(pso);
604 ASSERT(Rect);
605 return FillSolid(pso, Rect, iColor);
606 }
607
608 /*
609 * @implemented
610 */
611 SURFOBJ * APIENTRY
612 NtGdiEngLockSurface(IN HSURF hsurf)
613 {
614 return EngLockSurface(hsurf);
615 }
616
617
618 /*
619 * @implemented
620 */
621 SURFOBJ * APIENTRY
622 EngLockSurface(IN HSURF hsurf)
623 {
624 SURFACE *psurf = GDIOBJ_ShareLockObj(hsurf, GDI_OBJECT_TYPE_BITMAP);
625
626 if (psurf != NULL)
627 return &psurf->SurfObj;
628
629 return NULL;
630 }
631
632
633 /*
634 * @implemented
635 */
636 VOID APIENTRY
637 NtGdiEngUnlockSurface(IN SURFOBJ *pso)
638 {
639 EngUnlockSurface(pso);
640 }
641
642 /*
643 * @implemented
644 */
645 VOID APIENTRY
646 EngUnlockSurface(IN SURFOBJ *pso)
647 {
648 if (pso != NULL)
649 {
650 SURFACE *psurf = CONTAINING_RECORD(pso, SURFACE, SurfObj);
651 GDIOBJ_ShareUnlockObjByPtr((POBJ)psurf);
652 }
653 }
654
655
656 /* EOF */