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