[WIN32K]
[reactos.git] / subsystems / win32 / win32k / eng / surface.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI Driver Surace Functions
5 * FILE: subsys/win32k/eng/surface.c
6 * PROGRAMERS: Jason Filby
7 * Timo Kreuzer
8 * REVISION HISTORY:
9 * 3/7/1999: Created
10 * 9/11/2000: Updated to handle real pixel packed bitmaps (UPDATE TO DATE COMPLETED)
11 * TESTING TO BE DONE:
12 * - Create a GDI bitmap with all formats, perform all drawing operations on them, render to VGA surface
13 * refer to \test\microwin\src\engine\devdraw.c for info on correct pixel plotting for various formats
14 */
15
16 #include <win32k.h>
17
18 #define NDEBUG
19 #include <debug.h>
20
21 ULONG giUniqueSurface = 0;
22
23 UCHAR
24 gajBitsPerFormat[11] =
25 {
26 0, /* 0: unused */
27 1, /* 1: BMF_1BPP */
28 4, /* 2: BMF_4BPP */
29 8, /* 3: BMF_8BPP */
30 16, /* 4: BMF_16BPP */
31 24, /* 5: BMF_24BPP */
32 32, /* 6: BMF_32BPP */
33 4, /* 7: BMF_4RLE */
34 8, /* 8: BMF_8RLE */
35 0, /* 9: BMF_JPEG */
36 0, /* 10: BMF_PNG */
37 };
38
39
40 ULONG FASTCALL BitmapFormat(WORD Bits, DWORD Compression)
41 {
42 switch (Compression)
43 {
44 case BI_RGB:
45 /* Fall through */
46 case BI_BITFIELDS:
47 switch (Bits)
48 {
49 case 1:
50 return BMF_1BPP;
51 case 4:
52 return BMF_4BPP;
53 case 8:
54 return BMF_8BPP;
55 case 16:
56 return BMF_16BPP;
57 case 24:
58 return BMF_24BPP;
59 case 32:
60 return BMF_32BPP;
61 }
62 return 0;
63
64 case BI_RLE4:
65 return BMF_4RLE;
66
67 case BI_RLE8:
68 return BMF_8RLE;
69
70 default:
71 return 0;
72 }
73 }
74
75 BOOL
76 INTERNAL_CALL
77 SURFACE_Cleanup(PVOID ObjectBody)
78 {
79 PSURFACE psurf = (PSURFACE)ObjectBody;
80 PVOID pvBits = psurf->SurfObj.pvBits;
81 NTSTATUS Status;
82
83 /* Check if the surface has bits */
84 if (pvBits)
85 {
86 /* Only bitmaps can have bits */
87 ASSERT(psurf->SurfObj.iType == STYPE_BITMAP);
88
89 /* Check if it is a DIB section */
90 if (psurf->hDIBSection)
91 {
92 /* Unsecure the memory */
93 EngUnsecureMem(psurf->hSecure);
94
95 /* Calculate the real start of the section */
96 pvBits = (PVOID)((ULONG_PTR)pvBits - psurf->dwOffset);
97
98 /* Unmap the section */
99 Status = MmUnmapViewOfSection(PsGetCurrentProcess(), pvBits);
100 if (!NT_SUCCESS(Status))
101 {
102 DPRINT1("Could not unmap section view!\n");
103 // Should we BugCheck here?
104 ASSERT(FALSE);
105 }
106 }
107 else if (psurf->SurfObj.fjBitmap & BMF_USERMEM)
108 {
109 /* Bitmap was allocated from usermode memory */
110 EngFreeUserMem(pvBits);
111 }
112 else if (psurf->SurfObj.fjBitmap & BMF_KMSECTION)
113 {
114 /* Bitmap was allocated from a kernel section */
115 if (!EngFreeSectionMem(NULL, pvBits))
116 {
117 DPRINT1("EngFreeSectionMem failed for %p!\n", pvBits);
118 // Should we BugCheck here?
119 ASSERT(FALSE);
120 }
121 }
122 else if (psurf->SurfObj.fjBitmap & BMF_RLE_HACK)
123 {
124 /* HACK: Free RLE decompressed bits */
125 EngFreeMem(pvBits);
126 }
127 else
128 {
129 /* There should be nothing to free */
130 ASSERT(psurf->SurfObj.fjBitmap & BMF_DONT_FREE);
131 }
132 }
133
134 /* Free palette */
135 if(psurf->ppal)
136 {
137 PALETTE_ShareUnlockPalette(psurf->ppal);
138 }
139
140 return TRUE;
141 }
142
143
144 PSURFACE
145 NTAPI
146 SURFACE_AllocSurface(
147 IN ULONG iType,
148 IN ULONG cx,
149 IN ULONG cy,
150 IN ULONG iFormat)
151 {
152 PSURFACE psurf;
153 SURFOBJ *pso;
154
155 /* Verify format */
156 if (iFormat < BMF_1BPP || iFormat > BMF_PNG)
157 {
158 DPRINT1("Invalid bitmap format: %ld\n", iFormat);
159 return NULL;
160 }
161
162 /* Allocate a SURFACE object */
163 psurf = (PSURFACE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP);
164
165 if (psurf)
166 {
167 /* Initialize the basic fields */
168 pso = &psurf->SurfObj;
169 pso->hsurf = psurf->BaseObject.hHmgr;
170 pso->sizlBitmap.cx = cx;
171 pso->sizlBitmap.cy = cy;
172 pso->iBitmapFormat = iFormat;
173 pso->iType = iType;
174 pso->iUniq = InterlockedIncrement((PLONG)&giUniqueSurface);
175
176 /* Assign a default palette amd increment its reference count */
177 psurf->ppal = appalSurfaceDefault[iFormat];
178 GDIOBJ_IncrementShareCount(&psurf->ppal->BaseObject);
179 }
180
181 return psurf;
182 }
183
184 BOOL
185 NTAPI
186 SURFACE_bSetBitmapBits(
187 IN PSURFACE psurf,
188 IN USHORT fjBitmap,
189 IN ULONG ulWidth,
190 IN PVOID pvBits OPTIONAL)
191 {
192 SURFOBJ *pso = &psurf->SurfObj;
193 PVOID pvSection;
194 UCHAR cBitsPixel;
195
196 /* Only bitmaps can have bits */
197 ASSERT(psurf->SurfObj.iType == STYPE_BITMAP);
198
199 /* Get bits per pixel from the format */
200 cBitsPixel = gajBitsPerFormat[pso->iBitmapFormat];
201
202 /* Is a width in bytes given? */
203 if (!ulWidth)
204 {
205 /* Calculate width from the bitmap width in pixels */
206 ulWidth = DIB_GetDIBWidthBytes(psurf->SurfObj.sizlBitmap.cx, cBitsPixel);
207 }
208 else
209 {
210 /* Align the width (windows compatibility, drivers expect that) */
211 ulWidth = ((((ulWidth << 3) / cBitsPixel) * cBitsPixel + 31) & ~31) >> 3;
212 }
213
214
215 /* Calculate the bitmap size in bytes */
216 pso->cjBits = ulWidth * pso->sizlBitmap.cy;
217
218 /* Did the caller provide bits? */
219 if (pvBits)
220 {
221 /* Yes, so let him free it */
222 fjBitmap |= BMF_DONT_FREE;
223 }
224 else if (pso->cjBits)
225 {
226 /* We must allocate memory, check what kind */
227 if (fjBitmap & BMF_USERMEM)
228 {
229 /* User mode memory was requested */
230 pvBits = EngAllocUserMem(pso->cjBits, 0);
231 }
232 else
233 {
234 /* Use a kernel mode section */
235 fjBitmap |= BMF_KMSECTION;
236 pvBits = EngAllocSectionMem(&pvSection,
237 (fjBitmap & BMF_NOZEROINIT) ?
238 0 : FL_ZERO_MEMORY,
239 pso->cjBits, TAG_DIB);
240
241 /* Free the section already, but keep the mapping */
242 if (pvBits) EngFreeSectionMem(pvSection, NULL);
243 }
244
245 /* Check for failure */
246 if (!pvBits) return FALSE;
247 }
248
249 /* Set pvBits, pvScan0 and lDelta */
250 pso->pvBits = pvBits;
251 if (fjBitmap & BMF_TOPDOWN)
252 {
253 /* Topdown is the normal way */
254 pso->pvScan0 = pso->pvBits;
255 pso->lDelta = ulWidth;
256 }
257 else
258 {
259 /* Inversed bitmap (bottom up) */
260 pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ulWidth);
261 pso->lDelta = -ulWidth;
262 }
263
264 pso->fjBitmap = fjBitmap;
265
266 /* Success */
267 return TRUE;
268 }
269
270 HBITMAP
271 APIENTRY
272 EngCreateBitmap(
273 IN SIZEL sizl,
274 IN LONG lWidth,
275 IN ULONG iFormat,
276 IN ULONG fl,
277 IN PVOID pvBits)
278 {
279 PSURFACE psurf;
280 HBITMAP hbmp;
281
282 /* Allocate a surface */
283 psurf = SURFACE_AllocSurface(STYPE_BITMAP, sizl.cx, sizl.cy, iFormat);
284 if (!psurf)
285 {
286 DPRINT1("SURFACE_AllocSurface failed.\n");
287 return NULL;
288 }
289
290 /* Get the handle for the bitmap */
291 hbmp = (HBITMAP)psurf->SurfObj.hsurf;
292
293 /* Set the bitmap bits */
294 if (!SURFACE_bSetBitmapBits(psurf, fl, lWidth, pvBits))
295 {
296 /* Bail out if that failed */
297 DPRINT1("SURFACE_bSetBitmapBits failed.\n");
298 SURFACE_FreeSurfaceByHandle(hbmp);
299 return NULL;
300 }
301
302 /* Set public ownership */
303 GDIOBJ_SetOwnership(hbmp, NULL);
304
305 /* Unlock the surface and return */
306 SURFACE_UnlockSurface(psurf);
307 return hbmp;
308 }
309
310 /*
311 * @implemented
312 */
313 HBITMAP
314 APIENTRY
315 EngCreateDeviceBitmap(
316 IN DHSURF dhsurf,
317 IN SIZEL sizl,
318 IN ULONG iFormat)
319 {
320 PSURFACE psurf;
321 HBITMAP hbmp;
322
323 /* Allocate a surface */
324 psurf = SURFACE_AllocSurface(STYPE_DEVBITMAP, sizl.cx, sizl.cy, iFormat);
325 if (!psurf)
326 {
327 return 0;
328 }
329
330 /* Set the device handle */
331 psurf->SurfObj.dhsurf = dhsurf;
332
333 /* Get the handle for the bitmap */
334 hbmp = (HBITMAP)psurf->SurfObj.hsurf;
335
336 /* Set public ownership */
337 GDIOBJ_SetOwnership(hbmp, NULL);
338
339 /* Unlock the surface and return */
340 SURFACE_UnlockSurface(psurf);
341 return hbmp;
342 }
343
344 HSURF
345 APIENTRY
346 EngCreateDeviceSurface(
347 IN DHSURF dhsurf,
348 IN SIZEL sizl,
349 IN ULONG iFormat)
350 {
351 PSURFACE psurf;
352 HSURF hsurf;
353
354 /* Allocate a surface */
355 psurf = SURFACE_AllocSurface(STYPE_DEVICE, sizl.cx, sizl.cy, iFormat);
356 if (!psurf)
357 {
358 return 0;
359 }
360
361 /* Set the device handle */
362 psurf->SurfObj.dhsurf = dhsurf;
363
364 /* Get the handle for the surface */
365 hsurf = psurf->SurfObj.hsurf;
366
367 /* Set public ownership */
368 GDIOBJ_SetOwnership(hsurf, NULL);
369
370 /* Unlock the surface and return */
371 SURFACE_UnlockSurface(psurf);
372 return hsurf;
373 }
374
375 BOOL
376 APIENTRY
377 EngAssociateSurface(
378 IN HSURF hsurf,
379 IN HDEV hdev,
380 IN FLONG flHooks)
381 {
382 SURFOBJ *pso;
383 PSURFACE psurf;
384 PDEVOBJ* ppdev;
385
386 ppdev = (PDEVOBJ*)hdev;
387
388 /* Lock the surface */
389 psurf = SURFACE_LockSurface(hsurf);
390 if (!psurf)
391 {
392 return FALSE;
393 }
394 pso = &psurf->SurfObj;
395
396 /* Associate the hdev */
397 pso->hdev = hdev;
398 pso->dhpdev = ppdev->dhpdev;
399
400 /* Hook up specified functions */
401 psurf->flags &= ~HOOK_FLAGS;
402 psurf->flags |= (flHooks & HOOK_FLAGS);
403
404 /* Get palette */
405 psurf->ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault);
406
407 SURFACE_UnlockSurface(psurf);
408
409 return TRUE;
410 }
411
412 BOOL
413 APIENTRY
414 EngModifySurface(
415 IN HSURF hsurf,
416 IN HDEV hdev,
417 IN FLONG flHooks,
418 IN FLONG flSurface,
419 IN DHSURF dhsurf,
420 OUT VOID *pvScan0,
421 IN LONG lDelta,
422 IN VOID *pvReserved)
423 {
424 SURFOBJ *pso;
425 PSURFACE psurf;
426 PDEVOBJ* ppdev;
427
428 psurf = SURFACE_LockSurface(hsurf);
429 if (psurf == NULL)
430 {
431 return FALSE;
432 }
433
434 ppdev = (PDEVOBJ*)hdev;
435 pso = &psurf->SurfObj;
436 pso->dhsurf = dhsurf;
437 pso->lDelta = lDelta;
438 pso->pvScan0 = pvScan0;
439
440 /* Associate the hdev */
441 pso->hdev = hdev;
442 pso->dhpdev = ppdev->dhpdev;
443
444 /* Hook up specified functions */
445 psurf->flags &= ~HOOK_FLAGS;
446 psurf->flags |= (flHooks & HOOK_FLAGS);
447
448 /* Get palette */
449 psurf->ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault);
450
451 SURFACE_UnlockSurface(psurf);
452
453 return TRUE;
454 }
455
456
457 BOOL
458 APIENTRY
459 EngDeleteSurface(IN HSURF hsurf)
460 {
461 GDIOBJ_SetOwnership(hsurf, PsGetCurrentProcess());
462 SURFACE_FreeSurfaceByHandle(hsurf);
463 return TRUE;
464 }
465
466 BOOL
467 APIENTRY
468 EngEraseSurface(
469 SURFOBJ *pso,
470 RECTL *prcl,
471 ULONG iColor)
472 {
473 ASSERT(pso);
474 ASSERT(prcl);
475 return FillSolid(pso, prcl, iColor);
476 }
477
478 /*
479 * @implemented
480 */
481 SURFOBJ * APIENTRY
482 NtGdiEngLockSurface(IN HSURF hsurf)
483 {
484 return EngLockSurface(hsurf);
485 }
486
487
488 SURFOBJ *
489 APIENTRY
490 EngLockSurface(IN HSURF hsurf)
491 {
492 SURFACE *psurf = GDIOBJ_ShareLockObj(hsurf, GDI_OBJECT_TYPE_BITMAP);
493
494 if (psurf != NULL)
495 return &psurf->SurfObj;
496
497 return NULL;
498 }
499
500 VOID
501 APIENTRY
502 NtGdiEngUnlockSurface(IN SURFOBJ *pso)
503 {
504 EngUnlockSurface(pso);
505 }
506
507 VOID
508 APIENTRY
509 EngUnlockSurface(IN SURFOBJ *pso)
510 {
511 if (pso != NULL)
512 {
513 SURFACE *psurf = CONTAINING_RECORD(pso, SURFACE, SurfObj);
514 GDIOBJ_ShareUnlockObjByPtr((POBJ)psurf);
515 }
516 }
517
518 /* EOF */