/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * PURPOSE: GDI Driver Surace Functions * FILE: subsys/win32k/eng/surface.c * PROGRAMERS: Jason Filby * Timo Kreuzer * REVISION HISTORY: * 3/7/1999: Created * 9/11/2000: Updated to handle real pixel packed bitmaps (UPDATE TO DATE COMPLETED) * TESTING TO BE DONE: * - Create a GDI bitmap with all formats, perform all drawing operations on them, render to VGA surface * refer to \test\microwin\src\engine\devdraw.c for info on correct pixel plotting for various formats */ #include #define NDEBUG #include ULONG giUniqueSurface = 0; UCHAR gajBitsPerFormat[11] = { 0, /* 0: unused */ 1, /* 1: BMF_1BPP */ 4, /* 2: BMF_4BPP */ 8, /* 3: BMF_8BPP */ 16, /* 4: BMF_16BPP */ 24, /* 5: BMF_24BPP */ 32, /* 6: BMF_32BPP */ 4, /* 7: BMF_4RLE */ 8, /* 8: BMF_8RLE */ 0, /* 9: BMF_JPEG */ 0, /* 10: BMF_PNG */ }; ULONG FASTCALL BitmapFormat(WORD Bits, DWORD Compression) { switch (Compression) { case BI_RGB: /* Fall through */ case BI_BITFIELDS: switch (Bits) { case 1: return BMF_1BPP; case 4: return BMF_4BPP; case 8: return BMF_8BPP; case 16: return BMF_16BPP; case 24: return BMF_24BPP; case 32: return BMF_32BPP; } return 0; case BI_RLE4: return BMF_4RLE; case BI_RLE8: return BMF_8RLE; default: return 0; } } BOOL INTERNAL_CALL SURFACE_Cleanup(PVOID ObjectBody) { PSURFACE psurf = (PSURFACE)ObjectBody; PVOID pvBits = psurf->SurfObj.pvBits; NTSTATUS Status; /* Check if the surface has bits */ if (pvBits) { /* Only bitmaps can have bits */ ASSERT(psurf->SurfObj.iType == STYPE_BITMAP); /* Check if it is a DIB section */ if (psurf->hDIBSection) { /* Unsecure the memory */ EngUnsecureMem(psurf->hSecure); /* Calculate the real start of the section */ pvBits = (PVOID)((ULONG_PTR)pvBits - psurf->dwOffset); /* Unmap the section */ Status = MmUnmapViewOfSection(PsGetCurrentProcess(), pvBits); if (!NT_SUCCESS(Status)) { DPRINT1("Could not unmap section view!\n"); // Should we BugCheck here? ASSERT(FALSE); } } else if (psurf->SurfObj.fjBitmap & BMF_USERMEM) { /* Bitmap was allocated from usermode memory */ EngFreeUserMem(pvBits); } else if (psurf->SurfObj.fjBitmap & BMF_KMSECTION) { /* Bitmap was allocated from a kernel section */ if (!EngFreeSectionMem(NULL, pvBits)) { DPRINT1("EngFreeSectionMem failed for %p!\n", pvBits); // Should we BugCheck here? ASSERT(FALSE); } } else if (psurf->SurfObj.fjBitmap & BMF_RLE_HACK) { /* HACK: Free RLE decompressed bits */ EngFreeMem(pvBits); } else { /* There should be nothing to free */ ASSERT(psurf->SurfObj.fjBitmap & BMF_DONT_FREE); } } /* Free palette */ if(psurf->ppal) { PALETTE_ShareUnlockPalette(psurf->ppal); } return TRUE; } PSURFACE NTAPI SURFACE_AllocSurface( IN ULONG iType, IN ULONG cx, IN ULONG cy, IN ULONG iFormat) { PSURFACE psurf; SURFOBJ *pso; /* Verify format */ if (iFormat < BMF_1BPP || iFormat > BMF_PNG) { DPRINT1("Invalid bitmap format: %ld\n", iFormat); return NULL; } /* Allocate a SURFACE object */ psurf = (PSURFACE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP); if (psurf) { /* Initialize the basic fields */ pso = &psurf->SurfObj; pso->hsurf = psurf->BaseObject.hHmgr; pso->sizlBitmap.cx = cx; pso->sizlBitmap.cy = cy; pso->iBitmapFormat = iFormat; pso->iType = iType; pso->iUniq = InterlockedIncrement((PLONG)&giUniqueSurface); /* Assign a default palette and increment its reference count */ psurf->ppal = appalSurfaceDefault[iFormat]; GDIOBJ_IncrementShareCount(&psurf->ppal->BaseObject); } return psurf; } BOOL NTAPI SURFACE_bSetBitmapBits( IN PSURFACE psurf, IN USHORT fjBitmap, IN ULONG ulWidth, IN PVOID pvBits OPTIONAL) { SURFOBJ *pso = &psurf->SurfObj; PVOID pvSection; UCHAR cBitsPixel; /* Only bitmaps can have bits */ ASSERT(psurf->SurfObj.iType == STYPE_BITMAP); /* Get bits per pixel from the format */ cBitsPixel = gajBitsPerFormat[pso->iBitmapFormat]; /* Is a width in bytes given? */ if (ulWidth) { /* Align the width (Windows compatibility, drivers expect that) */ ulWidth = WIDTH_BYTES_ALIGN32((ulWidth << 3) / cBitsPixel, cBitsPixel); } else { /* Calculate width from the bitmap width in pixels */ ulWidth = WIDTH_BYTES_ALIGN32(pso->sizlBitmap.cx, cBitsPixel); } /* Calculate the bitmap size in bytes */ pso->cjBits = ulWidth * pso->sizlBitmap.cy; /* Did the caller provide bits? */ if (pvBits) { /* Yes, so let him free it */ fjBitmap |= BMF_DONT_FREE; } else if (pso->cjBits) { /* We must allocate memory, check what kind */ if (fjBitmap & BMF_USERMEM) { /* User mode memory was requested */ pvBits = EngAllocUserMem(pso->cjBits, 0); } else { /* Use a kernel mode section */ fjBitmap |= BMF_KMSECTION; pvBits = EngAllocSectionMem(&pvSection, (fjBitmap & BMF_NOZEROINIT) ? 0 : FL_ZERO_MEMORY, pso->cjBits, TAG_DIB); /* Free the section already, but keep the mapping */ if (pvBits) EngFreeSectionMem(pvSection, NULL); } /* Check for failure */ if (!pvBits) return FALSE; } /* Set pvBits, pvScan0 and lDelta */ pso->pvBits = pvBits; if (fjBitmap & BMF_TOPDOWN) { /* Topdown is the normal way */ pso->pvScan0 = pso->pvBits; pso->lDelta = ulWidth; } else { /* Inversed bitmap (bottom up) */ pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ulWidth); pso->lDelta = -ulWidth; } pso->fjBitmap = fjBitmap; /* Success */ return TRUE; } HBITMAP APIENTRY EngCreateBitmap( IN SIZEL sizl, IN LONG lWidth, IN ULONG iFormat, IN ULONG fl, IN PVOID pvBits) { PSURFACE psurf; HBITMAP hbmp; /* Allocate a surface */ psurf = SURFACE_AllocSurface(STYPE_BITMAP, sizl.cx, sizl.cy, iFormat); if (!psurf) { DPRINT1("SURFACE_AllocSurface failed.\n"); return NULL; } /* Get the handle for the bitmap */ hbmp = (HBITMAP)psurf->SurfObj.hsurf; /* Set the bitmap bits */ if (!SURFACE_bSetBitmapBits(psurf, fl, lWidth, pvBits)) { /* Bail out if that failed */ DPRINT1("SURFACE_bSetBitmapBits failed.\n"); SURFACE_FreeSurfaceByHandle(hbmp); return NULL; } /* Set public ownership */ GDIOBJ_SetOwnership(hbmp, NULL); /* Unlock the surface and return */ SURFACE_UnlockSurface(psurf); return hbmp; } /* * @implemented */ HBITMAP APIENTRY EngCreateDeviceBitmap( IN DHSURF dhsurf, IN SIZEL sizl, IN ULONG iFormat) { PSURFACE psurf; HBITMAP hbmp; /* Allocate a surface */ psurf = SURFACE_AllocSurface(STYPE_DEVBITMAP, sizl.cx, sizl.cy, iFormat); if (!psurf) { return 0; } /* Set the device handle */ psurf->SurfObj.dhsurf = dhsurf; /* Get the handle for the bitmap */ hbmp = (HBITMAP)psurf->SurfObj.hsurf; /* Set public ownership */ GDIOBJ_SetOwnership(hbmp, NULL); /* Unlock the surface and return */ SURFACE_UnlockSurface(psurf); return hbmp; } HSURF APIENTRY EngCreateDeviceSurface( IN DHSURF dhsurf, IN SIZEL sizl, IN ULONG iFormat) { PSURFACE psurf; HSURF hsurf; /* Allocate a surface */ psurf = SURFACE_AllocSurface(STYPE_DEVICE, sizl.cx, sizl.cy, iFormat); if (!psurf) { return 0; } /* Set the device handle */ psurf->SurfObj.dhsurf = dhsurf; /* Get the handle for the surface */ hsurf = psurf->SurfObj.hsurf; /* Set public ownership */ GDIOBJ_SetOwnership(hsurf, NULL); /* Unlock the surface and return */ SURFACE_UnlockSurface(psurf); return hsurf; } BOOL APIENTRY EngAssociateSurface( IN HSURF hsurf, IN HDEV hdev, IN FLONG flHooks) { SURFOBJ *pso; PSURFACE psurf; PDEVOBJ* ppdev; ppdev = (PDEVOBJ*)hdev; /* Lock the surface */ psurf = SURFACE_LockSurface(hsurf); if (!psurf) { return FALSE; } pso = &psurf->SurfObj; /* Associate the hdev */ pso->hdev = hdev; pso->dhpdev = ppdev->dhpdev; /* Hook up specified functions */ psurf->flags &= ~HOOK_FLAGS; psurf->flags |= (flHooks & HOOK_FLAGS); /* Get palette */ psurf->ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault); SURFACE_UnlockSurface(psurf); return TRUE; } BOOL APIENTRY EngModifySurface( IN HSURF hsurf, IN HDEV hdev, IN FLONG flHooks, IN FLONG flSurface, IN DHSURF dhsurf, OUT VOID *pvScan0, IN LONG lDelta, IN VOID *pvReserved) { SURFOBJ *pso; PSURFACE psurf; PDEVOBJ* ppdev; psurf = SURFACE_LockSurface(hsurf); if (psurf == NULL) { return FALSE; } ppdev = (PDEVOBJ*)hdev; pso = &psurf->SurfObj; pso->dhsurf = dhsurf; pso->lDelta = lDelta; pso->pvScan0 = pvScan0; /* Associate the hdev */ pso->hdev = hdev; pso->dhpdev = ppdev->dhpdev; /* Hook up specified functions */ psurf->flags &= ~HOOK_FLAGS; psurf->flags |= (flHooks & HOOK_FLAGS); /* Get palette */ psurf->ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault); SURFACE_UnlockSurface(psurf); return TRUE; } BOOL APIENTRY EngDeleteSurface(IN HSURF hsurf) { GDIOBJ_SetOwnership(hsurf, PsGetCurrentProcess()); SURFACE_FreeSurfaceByHandle(hsurf); return TRUE; } BOOL APIENTRY EngEraseSurface( SURFOBJ *pso, RECTL *prcl, ULONG iColor) { ASSERT(pso); ASSERT(prcl); return FillSolid(pso, prcl, iColor); } /* * @implemented */ SURFOBJ * APIENTRY NtGdiEngLockSurface(IN HSURF hsurf) { return EngLockSurface(hsurf); } SURFOBJ * APIENTRY EngLockSurface(IN HSURF hsurf) { SURFACE *psurf = GDIOBJ_ShareLockObj(hsurf, GDI_OBJECT_TYPE_BITMAP); if (psurf != NULL) return &psurf->SurfObj; return NULL; } VOID APIENTRY NtGdiEngUnlockSurface(IN SURFOBJ *pso) { EngUnlockSurface(pso); } VOID APIENTRY EngUnlockSurface(IN SURFOBJ *pso) { if (pso != NULL) { SURFACE *psurf = CONTAINING_RECORD(pso, SURFACE, SurfObj); GDIOBJ_ShareUnlockObjByPtr((POBJ)psurf); } } /* EOF */