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