Merged most of the recent changes from the Wine edit control.
[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.46 2004/12/14 04:55:43 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 GDIOBJ_SetOwnership(NewBitmap, NULL);
336
337 return NewBitmap;
338 }
339
340 /*
341 * @unimplemented
342 */
343 HSURF STDCALL
344 EngCreateDeviceSurface(IN DHSURF dhsurf,
345 IN SIZEL Size,
346 IN ULONG Format)
347 {
348 HSURF NewSurface;
349 SURFOBJ *SurfObj;
350 BITMAPOBJ *BitmapObj;
351
352 NewSurface = (HSURF)BITMAPOBJ_AllocBitmap();
353 if (NewSurface == NULL)
354 return 0;
355
356 GDIOBJ_SetOwnership(NewSurface, NULL);
357
358 BitmapObj = BITMAPOBJ_LockBitmap(NewSurface);
359 SurfObj = &BitmapObj->SurfObj;
360
361 SurfObj->dhsurf = dhsurf;
362 SurfObj->hsurf = NewSurface;
363 SurfObj->sizlBitmap = Size;
364 SurfObj->iBitmapFormat = Format;
365 SurfObj->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format));
366 SurfObj->iType = STYPE_DEVICE;
367 SurfObj->iUniq = 0;
368
369 BitmapObj->flHooks = 0;
370
371 BITMAPOBJ_UnlockBitmap(NewSurface);
372
373 return NewSurface;
374 }
375
376 PFN FASTCALL DriverFunction(DRVENABLEDATA *DED, ULONG DriverFunc)
377 {
378 ULONG i;
379
380 for(i=0; i<DED->c; i++)
381 {
382 if(DED->pdrvfn[i].iFunc == DriverFunc)
383 return DED->pdrvfn[i].pfn;
384 }
385 return NULL;
386 }
387
388 /*
389 * @implemented
390 */
391 BOOL STDCALL
392 EngAssociateSurface(IN HSURF Surface,
393 IN HDEV Dev,
394 IN ULONG Hooks)
395 {
396 SURFOBJ *SurfObj;
397 BITMAPOBJ *BitmapObj;
398 GDIDEVICE* Device;
399
400 Device = (GDIDEVICE*)Dev;
401
402 BitmapObj = BITMAPOBJ_LockBitmap(Surface);
403 ASSERT(BitmapObj);
404 SurfObj = &BitmapObj->SurfObj;
405
406 /* Associate the hdev */
407 SurfObj->hdev = Dev;
408 SurfObj->dhpdev = Device->PDev;
409
410 /* Hook up specified functions */
411 BitmapObj->flHooks = Hooks;
412
413 BITMAPOBJ_UnlockBitmap(Surface);
414
415 return TRUE;
416 }
417
418 /*
419 * @implemented
420 */
421 BOOL STDCALL
422 EngModifySurface(
423 IN HSURF hsurf,
424 IN HDEV hdev,
425 IN FLONG flHooks,
426 IN FLONG flSurface,
427 IN DHSURF dhsurf,
428 OUT VOID *pvScan0,
429 IN LONG lDelta,
430 IN VOID *pvReserved)
431 {
432 SURFOBJ *pso;
433
434 pso = EngLockSurface(hsurf);
435 if (pso == NULL)
436 {
437 return FALSE;
438 }
439
440 if (!EngAssociateSurface(hsurf, hdev, flHooks))
441 {
442 EngUnlockSurface(pso);
443
444 return FALSE;
445 }
446
447 pso->dhsurf = dhsurf;
448 pso->lDelta = lDelta;
449 pso->pvScan0 = pvScan0;
450
451 EngUnlockSurface(pso);
452
453 return TRUE;
454 }
455
456 /*
457 * @implemented
458 */
459 BOOL STDCALL
460 EngDeleteSurface(IN HSURF Surface)
461 {
462 GDIOBJ_SetOwnership(Surface, PsGetCurrentProcess());
463 BITMAPOBJ_FreeBitmap(Surface);
464 return TRUE;
465 }
466
467 /*
468 * @implemented
469 */
470 BOOL STDCALL
471 EngEraseSurface(SURFOBJ *Surface,
472 RECTL *Rect,
473 ULONG iColor)
474 {
475 ASSERT(Surface);
476 ASSERT(Rect);
477 return FillSolid(Surface, Rect, iColor);
478 }
479
480 /*
481 * @implemented
482 */
483 SURFOBJ * STDCALL
484 EngLockSurface(IN HSURF Surface)
485 {
486 BITMAPOBJ *bmp = (BITMAPOBJ*)BITMAPOBJ_LockBitmap(Surface);
487 if(bmp != NULL)
488 {
489 return &bmp->SurfObj;
490 }
491
492 return NULL;
493 }
494
495 /*
496 * @implemented
497 */
498 VOID STDCALL
499 EngUnlockSurface(IN SURFOBJ *Surface)
500 {
501 ASSERT (Surface);
502 BITMAPOBJ_UnlockBitmap (Surface->hsurf);
503 }
504 /* EOF */