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