migrate substitution keywords to SVN
[reactos.git] / reactos / subsys / 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 #include <w32k.h>
34
35 enum Rle_EscapeCodes
36 {
37 RLE_EOL = 0, /* End of line */
38 RLE_END = 1, /* End of bitmap */
39 RLE_DELTA = 2 /* Delta */
40 };
41
42 INT FASTCALL BitsPerFormat(ULONG Format)
43 {
44 switch(Format)
45 {
46 case BMF_1BPP: return 1;
47 case BMF_4BPP:
48 case BMF_4RLE: return 4;
49 case BMF_8BPP:
50 case BMF_8RLE: return 8;
51 case BMF_16BPP: return 16;
52 case BMF_24BPP: return 24;
53 case BMF_32BPP: return 32;
54 default: return 0;
55 }
56 }
57
58 ULONG FASTCALL BitmapFormat(WORD Bits, DWORD Compression)
59 {
60 switch(Compression)
61 {
62 case BI_RGB:
63 case BI_BITFIELDS:
64 switch(Bits)
65 {
66 case 1: return BMF_1BPP;
67 case 4: return BMF_4BPP;
68 case 8: return BMF_8BPP;
69 case 16: return BMF_16BPP;
70 case 24: return BMF_24BPP;
71 case 32: return BMF_32BPP;
72 }
73 return 0;
74
75 case BI_RLE4: return BMF_4RLE;
76 case BI_RLE8: return BMF_8RLE;
77
78 default: return 0;
79 }
80 }
81
82 /*
83 * @implemented
84 */
85 HBITMAP STDCALL
86 EngCreateDeviceBitmap(IN DHSURF dhsurf,
87 IN SIZEL Size,
88 IN ULONG Format)
89 {
90 HBITMAP NewBitmap;
91 SURFOBJ *SurfObj;
92
93 NewBitmap = EngCreateBitmap(Size, DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format)), Format, 0, NULL);
94 SurfObj = EngLockSurface((HSURF)NewBitmap);
95 SurfObj->dhsurf = dhsurf;
96 EngUnlockSurface(SurfObj);
97
98 return NewBitmap;
99 }
100
101 VOID Decompress4bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta)
102 {
103 int x = 0;
104 int y = Size.cy - 1;
105 int c;
106 int length;
107 int width = ((Size.cx+1)/2);
108 int height = Size.cy - 1;
109 BYTE *begin = CompressedBits;
110 BYTE *bits = CompressedBits;
111 BYTE *temp;
112 while (y >= 0)
113 {
114 length = *bits++ / 2;
115 if (length)
116 {
117 c = *bits++;
118 while (length--)
119 {
120 if (x >= width) break;
121 temp = UncompressedBits + (((height - y) * Delta) + x);
122 x++;
123 *temp = c;
124 }
125 } else {
126 length = *bits++;
127 switch (length)
128 {
129 case RLE_EOL:
130 x = 0;
131 y--;
132 break;
133 case RLE_END:
134 return;
135 case RLE_DELTA:
136 x += (*bits++)/2;
137 y -= (*bits++)/2;
138 break;
139 default:
140 length /= 2;
141 while (length--)
142 {
143 c = *bits++;
144 if (x < width)
145 {
146 temp = UncompressedBits + (((height - y) * Delta) + x);
147 x++;
148 *temp = c;
149 }
150 }
151 if ((bits - begin) & 1)
152 bits++;
153 }
154 }
155 }
156 }
157
158 VOID Decompress8bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta)
159 {
160 int x = 0;
161 int y = Size.cy - 1;
162 int c;
163 int length;
164 int width = Size.cx;
165 int height = Size.cy - 1;
166 BYTE *begin = CompressedBits;
167 BYTE *bits = CompressedBits;
168 BYTE *temp;
169 while (y >= 0)
170 {
171 length = *bits++;
172 if (length)
173 {
174 c = *bits++;
175 while (length--)
176 {
177 if (x >= width) break;
178 temp = UncompressedBits + (((height - y) * Delta) + x);
179 x++;
180 *temp = c;
181 }
182 } else {
183 length = *bits++;
184 switch (length)
185 {
186 case RLE_EOL:
187 x = 0;
188 y--;
189 break;
190 case RLE_END:
191 return;
192 case RLE_DELTA:
193 x += *bits++;
194 y -= *bits++;
195 break;
196 default:
197 while (length--)
198 {
199 c = *bits++;
200 if (x < width)
201 {
202 temp = UncompressedBits + (((height - y) * Delta) + x);
203 x++;
204 *temp = c;
205 }
206 }
207 if ((bits - begin) & 1)
208 bits++;
209 }
210 }
211 }
212 }
213
214 HBITMAP FASTCALL
215 IntCreateBitmap(IN SIZEL Size,
216 IN LONG Width,
217 IN ULONG Format,
218 IN ULONG Flags,
219 IN PVOID Bits)
220 {
221 HBITMAP NewBitmap;
222 SURFOBJ *SurfObj;
223 BITMAPOBJ *BitmapObj;
224 PVOID UncompressedBits;
225 ULONG UncompressedFormat;
226
227 if (Format == 0)
228 return 0;
229
230 NewBitmap = BITMAPOBJ_AllocBitmap();
231 if (NewBitmap == NULL)
232 return 0;
233
234 BitmapObj = BITMAPOBJ_LockBitmap(NewBitmap);
235 SurfObj = &BitmapObj->SurfObj;
236
237 if (Format == BMF_4RLE)
238 {
239 SurfObj->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_4BPP));
240 SurfObj->cjBits = SurfObj->lDelta * Size.cy;
241 UncompressedFormat = BMF_4BPP;
242 UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, SurfObj->cjBits, 0);
243 Decompress4bpp(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, SurfObj->lDelta);
244 }
245 else if (Format == BMF_8RLE)
246 {
247 SurfObj->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_8BPP));
248 SurfObj->cjBits = SurfObj->lDelta * Size.cy;
249 UncompressedFormat = BMF_8BPP;
250 UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, SurfObj->cjBits, 0);
251 Decompress8bpp(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, SurfObj->lDelta);
252 }
253 else
254 {
255 SurfObj->lDelta = abs(Width);
256 SurfObj->cjBits = SurfObj->lDelta * Size.cy;
257 UncompressedBits = Bits;
258 UncompressedFormat = Format;
259 }
260
261 if (UncompressedBits != NULL)
262 {
263 SurfObj->pvBits = UncompressedBits;
264 }
265 else
266 {
267 if (SurfObj->cjBits == 0)
268 {
269 SurfObj->pvBits = NULL;
270 }
271 else
272 {
273 if (0 != (Flags & BMF_USERMEM))
274 {
275 SurfObj->pvBits = EngAllocUserMem(SurfObj->cjBits, 0);
276 }
277 else
278 {
279 SurfObj->pvBits = EngAllocMem(0 != (Flags & BMF_NOZEROINIT) ? 0 : FL_ZERO_MEMORY,
280 SurfObj->cjBits, 0);
281 }
282 if (SurfObj->pvBits == NULL)
283 {
284 BITMAPOBJ_UnlockBitmap(NewBitmap);
285 BITMAPOBJ_FreeBitmap(NewBitmap);
286 return 0;
287 }
288 }
289 }
290
291
292 if (0 == (Flags & BMF_TOPDOWN))
293 {
294 SurfObj->pvScan0 = (PVOID) ((ULONG_PTR) SurfObj->pvBits + SurfObj->cjBits - SurfObj->lDelta);
295 SurfObj->lDelta = - SurfObj->lDelta;
296 }
297 else
298 {
299 SurfObj->pvScan0 = SurfObj->pvBits;
300 }
301
302 SurfObj->dhsurf = 0; /* device managed surface */
303 SurfObj->hsurf = (HSURF)NewBitmap;
304 SurfObj->dhpdev = NULL;
305 SurfObj->hdev = NULL;
306 SurfObj->sizlBitmap = Size;
307 SurfObj->iBitmapFormat = UncompressedFormat;
308 SurfObj->iType = STYPE_BITMAP;
309 SurfObj->fjBitmap = Flags & (BMF_TOPDOWN | BMF_NOZEROINIT);
310 SurfObj->iUniq = 0;
311
312 BitmapObj->flHooks = 0;
313 BitmapObj->flFlags = 0;
314 BitmapObj->dimension.cx = 0;
315 BitmapObj->dimension.cy = 0;
316 BitmapObj->dib = NULL;
317
318 BITMAPOBJ_UnlockBitmap(NewBitmap);
319
320 return NewBitmap;
321 }
322
323 /*
324 * @implemented
325 */
326 HBITMAP STDCALL
327 EngCreateBitmap(IN SIZEL Size,
328 IN LONG Width,
329 IN ULONG Format,
330 IN ULONG Flags,
331 IN PVOID Bits)
332 {
333 HBITMAP NewBitmap;
334
335 NewBitmap = IntCreateBitmap(Size, Width, Format, Flags, Bits);
336 if ( !NewBitmap )
337 return 0;
338
339 GDIOBJ_SetOwnership(NewBitmap, NULL);
340
341 return NewBitmap;
342 }
343
344 /*
345 * @unimplemented
346 */
347 HSURF STDCALL
348 EngCreateDeviceSurface(IN DHSURF dhsurf,
349 IN SIZEL Size,
350 IN ULONG Format)
351 {
352 HSURF NewSurface;
353 SURFOBJ *SurfObj;
354 BITMAPOBJ *BitmapObj;
355
356 NewSurface = (HSURF)BITMAPOBJ_AllocBitmap();
357 if (NewSurface == NULL)
358 return 0;
359
360 GDIOBJ_SetOwnership(NewSurface, NULL);
361
362 BitmapObj = BITMAPOBJ_LockBitmap(NewSurface);
363 SurfObj = &BitmapObj->SurfObj;
364
365 SurfObj->dhsurf = dhsurf;
366 SurfObj->hsurf = NewSurface;
367 SurfObj->sizlBitmap = Size;
368 SurfObj->iBitmapFormat = Format;
369 SurfObj->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format));
370 SurfObj->iType = STYPE_DEVICE;
371 SurfObj->iUniq = 0;
372
373 BitmapObj->flHooks = 0;
374
375 BITMAPOBJ_UnlockBitmap(NewSurface);
376
377 return NewSurface;
378 }
379
380 PFN FASTCALL DriverFunction(DRVENABLEDATA *DED, ULONG DriverFunc)
381 {
382 ULONG i;
383
384 for(i=0; i<DED->c; i++)
385 {
386 if(DED->pdrvfn[i].iFunc == DriverFunc)
387 return DED->pdrvfn[i].pfn;
388 }
389 return NULL;
390 }
391
392 /*
393 * @implemented
394 */
395 BOOL STDCALL
396 EngAssociateSurface(IN HSURF Surface,
397 IN HDEV Dev,
398 IN ULONG Hooks)
399 {
400 SURFOBJ *SurfObj;
401 BITMAPOBJ *BitmapObj;
402 GDIDEVICE* Device;
403
404 Device = (GDIDEVICE*)Dev;
405
406 BitmapObj = BITMAPOBJ_LockBitmap(Surface);
407 ASSERT(BitmapObj);
408 SurfObj = &BitmapObj->SurfObj;
409
410 /* Associate the hdev */
411 SurfObj->hdev = Dev;
412 SurfObj->dhpdev = Device->PDev;
413
414 /* Hook up specified functions */
415 BitmapObj->flHooks = Hooks;
416
417 BITMAPOBJ_UnlockBitmap(Surface);
418
419 return TRUE;
420 }
421
422 /*
423 * @implemented
424 */
425 BOOL STDCALL
426 EngModifySurface(
427 IN HSURF hsurf,
428 IN HDEV hdev,
429 IN FLONG flHooks,
430 IN FLONG flSurface,
431 IN DHSURF dhsurf,
432 OUT VOID *pvScan0,
433 IN LONG lDelta,
434 IN VOID *pvReserved)
435 {
436 SURFOBJ *pso;
437
438 pso = EngLockSurface(hsurf);
439 if (pso == NULL)
440 {
441 return FALSE;
442 }
443
444 if (!EngAssociateSurface(hsurf, hdev, flHooks))
445 {
446 EngUnlockSurface(pso);
447
448 return FALSE;
449 }
450
451 pso->dhsurf = dhsurf;
452 pso->lDelta = lDelta;
453 pso->pvScan0 = pvScan0;
454
455 EngUnlockSurface(pso);
456
457 return TRUE;
458 }
459
460 /*
461 * @implemented
462 */
463 BOOL STDCALL
464 EngDeleteSurface(IN HSURF Surface)
465 {
466 GDIOBJ_SetOwnership(Surface, PsGetCurrentProcess());
467 BITMAPOBJ_FreeBitmap(Surface);
468 return TRUE;
469 }
470
471 /*
472 * @implemented
473 */
474 BOOL STDCALL
475 EngEraseSurface(SURFOBJ *Surface,
476 RECTL *Rect,
477 ULONG iColor)
478 {
479 ASSERT(Surface);
480 ASSERT(Rect);
481 return FillSolid(Surface, Rect, iColor);
482 }
483
484 /*
485 * @implemented
486 */
487 SURFOBJ * STDCALL
488 EngLockSurface(IN HSURF Surface)
489 {
490 BITMAPOBJ *bmp = (BITMAPOBJ*)BITMAPOBJ_LockBitmap(Surface);
491 if(bmp != NULL)
492 {
493 return &bmp->SurfObj;
494 }
495
496 return NULL;
497 }
498
499 /*
500 * @implemented
501 */
502 VOID STDCALL
503 EngUnlockSurface(IN SURFOBJ *Surface)
504 {
505 ASSERT (Surface);
506 BITMAPOBJ_UnlockBitmap (Surface->hsurf);
507 }
508 /* EOF */