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