- Merge aicom-network-fixes up to r36740
[reactos.git] / reactos / subsystems / win32 / win32k / eng / surface.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * PURPOSE: GDI Driver Surace Functions
23 * FILE: subsys/win32k/eng/surface.c
24 * PROGRAMER: Jason Filby
25 * REVISION HISTORY:
26 * 3/7/1999: Created
27 * 9/11/2000: Updated to handle real pixel packed bitmaps (UPDATE TO DATE COMPLETED)
28 * TESTING TO BE DONE:
29 * - Create a GDI bitmap with all formats, perform all drawing operations on them, render to VGA surface
30 * refer to \test\microwin\src\engine\devdraw.c for info on correct pixel plotting for various formats
31 */
32
33 #include <w32k.h>
34
35 #define NDEBUG
36 #include <debug.h>
37
38 enum Rle_EscapeCodes
39 {
40 RLE_EOL = 0, /* End of line */
41 RLE_END = 1, /* End of bitmap */
42 RLE_DELTA = 2 /* Delta */
43 };
44
45 INT FASTCALL BitsPerFormat(ULONG Format)
46 {
47 switch (Format)
48 {
49 case BMF_1BPP:
50 return 1;
51
52 case BMF_4BPP:
53 /* Fall through */
54 case BMF_4RLE:
55 return 4;
56
57 case BMF_8BPP:
58 /* Fall through */
59 case BMF_8RLE:
60 return 8;
61
62 case BMF_16BPP:
63 return 16;
64
65 case BMF_24BPP:
66 return 24;
67
68 case BMF_32BPP:
69 return 32;
70
71 default:
72 return 0;
73 }
74 }
75
76 ULONG FASTCALL BitmapFormat(WORD Bits, DWORD Compression)
77 {
78 switch (Compression)
79 {
80 case BI_RGB:
81 /* Fall through */
82 case BI_BITFIELDS:
83 switch (Bits)
84 {
85 case 1:
86 return BMF_1BPP;
87 case 4:
88 return BMF_4BPP;
89 case 8:
90 return BMF_8BPP;
91 case 16:
92 return BMF_16BPP;
93 case 24:
94 return BMF_24BPP;
95 case 32:
96 return BMF_32BPP;
97 }
98 return 0;
99
100 case BI_RLE4:
101 return BMF_4RLE;
102
103 case BI_RLE8:
104 return BMF_8RLE;
105
106 default:
107 return 0;
108 }
109 }
110
111 BOOL INTERNAL_CALL
112 BITMAPOBJ_InitBitsLock(BITMAPOBJ *BitmapObj)
113 {
114 BitmapObj->BitsLock = ExAllocatePoolWithTag(NonPagedPool,
115 sizeof(FAST_MUTEX),
116 TAG_BITMAPOBJ);
117 if (NULL == BitmapObj->BitsLock)
118 {
119 return FALSE;
120 }
121
122 ExInitializeFastMutex(BitmapObj->BitsLock);
123
124 return TRUE;
125 }
126
127 void INTERNAL_CALL
128 BITMAPOBJ_CleanupBitsLock(BITMAPOBJ *BitmapObj)
129 {
130 if (NULL != BitmapObj->BitsLock)
131 {
132 ExFreePoolWithTag(BitmapObj->BitsLock, TAG_BITMAPOBJ);
133 BitmapObj->BitsLock = NULL;
134 }
135 }
136
137
138 /*
139 * @implemented
140 */
141 HBITMAP STDCALL
142 EngCreateDeviceBitmap(IN DHSURF dhsurf,
143 IN SIZEL Size,
144 IN ULONG Format)
145 {
146 HBITMAP NewBitmap;
147 SURFOBJ *SurfObj;
148
149 NewBitmap = EngCreateBitmap(Size, DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format)), Format, 0, NULL);
150 if (!NewBitmap)
151 {
152 DPRINT1("EngCreateBitmap failed\n");
153 return 0;
154 }
155
156 SurfObj = EngLockSurface((HSURF)NewBitmap);
157 SurfObj->dhsurf = dhsurf;
158 EngUnlockSurface(SurfObj);
159
160 return NewBitmap;
161 }
162
163 VOID Decompress4bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta)
164 {
165 int x = 0;
166 int y = Size.cy - 1;
167 int c;
168 int length;
169 int width = ((Size.cx+1)/2);
170 int height = Size.cy - 1;
171 BYTE *begin = CompressedBits;
172 BYTE *bits = CompressedBits;
173 BYTE *temp;
174 while (y >= 0)
175 {
176 length = *bits++ / 2;
177 if (length)
178 {
179 c = *bits++;
180 while (length--)
181 {
182 if (x >= width) break;
183 temp = UncompressedBits + (((height - y) * Delta) + x);
184 x++;
185 *temp = c;
186 }
187 }
188 else
189 {
190 length = *bits++;
191 switch (length)
192 {
193 case RLE_EOL:
194 x = 0;
195 y--;
196 break;
197 case RLE_END:
198 return;
199 case RLE_DELTA:
200 x += (*bits++)/2;
201 y -= (*bits++)/2;
202 break;
203 default:
204 length /= 2;
205 while (length--)
206 {
207 c = *bits++;
208 if (x < width)
209 {
210 temp = UncompressedBits + (((height - y) * Delta) + x);
211 x++;
212 *temp = c;
213 }
214 }
215 if ((bits - begin) & 1)
216 {
217 bits++;
218 }
219 }
220 }
221 }
222 }
223
224 VOID Decompress8bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta)
225 {
226 int x = 0;
227 int y = Size.cy - 1;
228 int c;
229 int length;
230 int width = Size.cx;
231 int height = Size.cy - 1;
232 BYTE *begin = CompressedBits;
233 BYTE *bits = CompressedBits;
234 BYTE *temp;
235 while (y >= 0)
236 {
237 length = *bits++;
238 if (length)
239 {
240 c = *bits++;
241 while (length--)
242 {
243 if (x >= width) break;
244 temp = UncompressedBits + (((height - y) * Delta) + x);
245 x++;
246 *temp = c;
247 }
248 }
249 else
250 {
251 length = *bits++;
252 switch (length)
253 {
254 case RLE_EOL:
255 x = 0;
256 y--;
257 break;
258 case RLE_END:
259 return;
260 case RLE_DELTA:
261 x += *bits++;
262 y -= *bits++;
263 break;
264 default:
265 while (length--)
266 {
267 c = *bits++;
268 if (x < width)
269 {
270 temp = UncompressedBits + (((height - y) * Delta) + x);
271 x++;
272 *temp = c;
273 }
274 }
275 if ((bits - begin) & 1)
276 {
277 bits++;
278 }
279 }
280 }
281 }
282 }
283
284 HBITMAP FASTCALL
285 IntCreateBitmap(IN SIZEL Size,
286 IN LONG Width,
287 IN ULONG Format,
288 IN ULONG Flags,
289 IN PVOID Bits)
290 {
291 HBITMAP NewBitmap;
292 SURFOBJ *SurfObj;
293 BITMAPOBJ *BitmapObj;
294 PVOID UncompressedBits;
295 ULONG UncompressedFormat;
296
297 if (Format == 0)
298 return 0;
299
300 BitmapObj = BITMAPOBJ_AllocBitmapWithHandle();
301 if (BitmapObj == NULL)
302 {
303 return 0;
304 }
305 NewBitmap = BitmapObj->BaseObject.hHmgr;
306
307 if (! BITMAPOBJ_InitBitsLock(BitmapObj))
308 {
309 BITMAPOBJ_UnlockBitmap(BitmapObj);
310 BITMAPOBJ_FreeBitmapByHandle(NewBitmap);
311 return 0;
312 }
313 SurfObj = &BitmapObj->SurfObj;
314
315 if (Format == BMF_4RLE)
316 {
317 SurfObj->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_4BPP));
318 SurfObj->cjBits = SurfObj->lDelta * Size.cy;
319 UncompressedFormat = BMF_4BPP;
320 UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, SurfObj->cjBits, TAG_DIB);
321 Decompress4bpp(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, SurfObj->lDelta);
322 }
323 else if (Format == BMF_8RLE)
324 {
325 SurfObj->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_8BPP));
326 SurfObj->cjBits = SurfObj->lDelta * Size.cy;
327 UncompressedFormat = BMF_8BPP;
328 UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, SurfObj->cjBits, TAG_DIB);
329 Decompress8bpp(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, SurfObj->lDelta);
330 }
331 else
332 {
333 SurfObj->lDelta = abs(Width);
334 SurfObj->cjBits = SurfObj->lDelta * Size.cy;
335 UncompressedBits = Bits;
336 UncompressedFormat = Format;
337 }
338
339 if (UncompressedBits != NULL)
340 {
341 SurfObj->pvBits = UncompressedBits;
342 }
343 else
344 {
345 if (SurfObj->cjBits == 0)
346 {
347 SurfObj->pvBits = NULL;
348 }
349 else
350 {
351 if (0 != (Flags & BMF_USERMEM))
352 {
353 SurfObj->pvBits = EngAllocUserMem(SurfObj->cjBits, 0);
354 }
355 else
356 {
357 SurfObj->pvBits = EngAllocMem(0 != (Flags & BMF_NOZEROINIT) ?
358 0 : FL_ZERO_MEMORY,
359 SurfObj->cjBits, TAG_DIB);
360 }
361 if (SurfObj->pvBits == NULL)
362 {
363 BITMAPOBJ_UnlockBitmap(BitmapObj);
364 BITMAPOBJ_FreeBitmapByHandle(NewBitmap);
365 return 0;
366 }
367 }
368 }
369
370 if (0 == (Flags & BMF_TOPDOWN))
371 {
372 SurfObj->pvScan0 = (PVOID) ((ULONG_PTR) SurfObj->pvBits + SurfObj->cjBits - SurfObj->lDelta);
373 SurfObj->lDelta = - SurfObj->lDelta;
374 }
375 else
376 {
377 SurfObj->pvScan0 = SurfObj->pvBits;
378 }
379
380 SurfObj->dhsurf = 0; /* device managed surface */
381 SurfObj->hsurf = (HSURF)NewBitmap;
382 SurfObj->dhpdev = NULL;
383 SurfObj->hdev = NULL;
384 SurfObj->sizlBitmap = Size;
385 SurfObj->iBitmapFormat = UncompressedFormat;
386 SurfObj->iType = STYPE_BITMAP;
387 SurfObj->fjBitmap = Flags & (BMF_TOPDOWN | BMF_NOZEROINIT);
388 SurfObj->iUniq = 0;
389
390 BitmapObj->flHooks = 0;
391 BitmapObj->flFlags = 0;
392 BitmapObj->dimension.cx = 0;
393 BitmapObj->dimension.cy = 0;
394 BitmapObj->dib = NULL;
395
396 BITMAPOBJ_UnlockBitmap(BitmapObj);
397
398 return NewBitmap;
399 }
400
401 /*
402 * @implemented
403 */
404 HBITMAP STDCALL
405 EngCreateBitmap(IN SIZEL Size,
406 IN LONG Width,
407 IN ULONG Format,
408 IN ULONG Flags,
409 IN PVOID Bits)
410 {
411 HBITMAP NewBitmap;
412
413 NewBitmap = IntCreateBitmap(Size, Width, Format, Flags, Bits);
414 if ( !NewBitmap )
415 return 0;
416
417 GDIOBJ_SetOwnership(NewBitmap, NULL);
418
419 return NewBitmap;
420 }
421
422 /*
423 * @unimplemented
424 */
425 HSURF STDCALL
426 EngCreateDeviceSurface(IN DHSURF dhsurf,
427 IN SIZEL Size,
428 IN ULONG Format)
429 {
430 HSURF NewSurface;
431 SURFOBJ *SurfObj;
432 BITMAPOBJ *BitmapObj;
433
434 BitmapObj = BITMAPOBJ_AllocBitmapWithHandle();
435 if (!BitmapObj)
436 {
437 return 0;
438 }
439
440 NewSurface = BitmapObj->BaseObject.hHmgr;
441 GDIOBJ_SetOwnership(NewSurface, NULL);
442
443 if (!BITMAPOBJ_InitBitsLock(BitmapObj))
444 {
445 BITMAPOBJ_UnlockBitmap(BitmapObj);
446 BITMAPOBJ_FreeBitmapByHandle(NewSurface);
447 return 0;
448 }
449 SurfObj = &BitmapObj->SurfObj;
450
451 SurfObj->dhsurf = dhsurf;
452 SurfObj->hsurf = NewSurface;
453 SurfObj->sizlBitmap = Size;
454 SurfObj->iBitmapFormat = Format;
455 SurfObj->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format));
456 SurfObj->iType = STYPE_DEVICE;
457 SurfObj->iUniq = 0;
458
459 BitmapObj->flHooks = 0;
460
461 BITMAPOBJ_UnlockBitmap(BitmapObj);
462
463 return NewSurface;
464 }
465
466 PFN FASTCALL DriverFunction(DRVENABLEDATA *DED, ULONG DriverFunc)
467 {
468 ULONG i;
469
470 for (i=0; i<DED->c; i++)
471 {
472 if (DED->pdrvfn[i].iFunc == DriverFunc)
473 {
474 return DED->pdrvfn[i].pfn;
475 }
476 }
477 return NULL;
478 }
479
480 /*
481 * @implemented
482 */
483 BOOL STDCALL
484 EngAssociateSurface(IN HSURF Surface,
485 IN HDEV Dev,
486 IN ULONG Hooks)
487 {
488 SURFOBJ *SurfObj;
489 BITMAPOBJ *BitmapObj;
490 GDIDEVICE* Device;
491
492 Device = (GDIDEVICE*)Dev;
493
494 BitmapObj = BITMAPOBJ_LockBitmap(Surface);
495 ASSERT(BitmapObj);
496 SurfObj = &BitmapObj->SurfObj;
497
498 /* Associate the hdev */
499 SurfObj->hdev = Dev;
500 SurfObj->dhpdev = Device->hPDev;
501
502 /* Hook up specified functions */
503 BitmapObj->flHooks = Hooks;
504
505 BITMAPOBJ_UnlockBitmap(BitmapObj);
506
507 return TRUE;
508 }
509
510 /*
511 * @implemented
512 */
513 BOOL STDCALL
514 EngModifySurface(
515 IN HSURF hsurf,
516 IN HDEV hdev,
517 IN FLONG flHooks,
518 IN FLONG flSurface,
519 IN DHSURF dhsurf,
520 OUT VOID *pvScan0,
521 IN LONG lDelta,
522 IN VOID *pvReserved)
523 {
524 SURFOBJ *pso;
525
526 pso = EngLockSurface(hsurf);
527 if (pso == NULL)
528 {
529 return FALSE;
530 }
531
532 if (!EngAssociateSurface(hsurf, hdev, flHooks))
533 {
534 EngUnlockSurface(pso);
535
536 return FALSE;
537 }
538
539 pso->dhsurf = dhsurf;
540 pso->lDelta = lDelta;
541 pso->pvScan0 = pvScan0;
542
543 EngUnlockSurface(pso);
544
545 return TRUE;
546 }
547
548 /*
549 * @implemented
550 */
551 BOOL STDCALL
552 EngDeleteSurface(IN HSURF Surface)
553 {
554 GDIOBJ_SetOwnership(Surface, PsGetCurrentProcess());
555 BITMAPOBJ_FreeBitmapByHandle(Surface);
556 return TRUE;
557 }
558
559 /*
560 * @implemented
561 */
562 BOOL STDCALL
563 EngEraseSurface(SURFOBJ *Surface,
564 RECTL *Rect,
565 ULONG iColor)
566 {
567 ASSERT(Surface);
568 ASSERT(Rect);
569 return FillSolid(Surface, Rect, iColor);
570 }
571
572 #define GDIBdyToHdr(body) \
573 ((PGDIOBJHDR)(body) - 1)
574
575
576 /*
577 * @implemented
578 */
579 SURFOBJ * STDCALL
580 NtGdiEngLockSurface(IN HSURF Surface)
581 {
582 return EngLockSurface(Surface);
583 }
584
585
586 /*
587 * @implemented
588 */
589 SURFOBJ * STDCALL
590 EngLockSurface(IN HSURF Surface)
591 {
592 BITMAPOBJ *bmp = GDIOBJ_ShareLockObj(Surface, GDI_OBJECT_TYPE_BITMAP);
593
594 if (bmp != NULL)
595 return &bmp->SurfObj;
596
597 return NULL;
598 }
599
600
601 /*
602 * @implemented
603 */
604 VOID STDCALL
605 NtGdiEngUnlockSurface(IN SURFOBJ *Surface)
606 {
607 EngUnlockSurface(Surface);
608 }
609
610 /*
611 * @implemented
612 */
613 VOID STDCALL
614 EngUnlockSurface(IN SURFOBJ *Surface)
615 {
616 if (Surface != NULL)
617 {
618 BITMAPOBJ *bmp = CONTAINING_RECORD(Surface, BITMAPOBJ, SurfObj);
619 GDIOBJ_ShareUnlockObjByPtr((POBJ)bmp);
620 }
621 }
622
623
624 /* EOF */