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