Author: tkreuzer Date: Tue May 1 12:14:10 2012 New Revision: 56460
URL: http://svn.reactos.org/svn/reactos?rev=56460&view=rev Log: [WIN32K] Rewrite SURFACE_AllocSurface(), which now does the part of the former SURFACE_bSetBitmapBits() as well. This is to allocate the bits for a bitmap directly with the SURFACE object in one allocation. Also don't use kernel mode sections anymore by default, but paged pool memory.
Modified: trunk/reactos/win32ss/gdi/eng/surface.c trunk/reactos/win32ss/gdi/eng/surface.h trunk/reactos/win32ss/gdi/ntgdi/bitblt.c trunk/reactos/win32ss/gdi/ntgdi/bitmaps.c
Modified: trunk/reactos/win32ss/gdi/eng/surface.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/eng/surface.c?r... ============================================================================== --- trunk/reactos/win32ss/gdi/eng/surface.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/eng/surface.c [iso-8859-1] Tue May 1 12:14:10 2012 @@ -15,7 +15,7 @@ #define NDEBUG #include <debug.h>
-ULONG giUniqueSurface = 0; +LONG giUniqueSurface = 0;
UCHAR gajBitsPerFormat[11] = @@ -34,7 +34,9 @@ };
-ULONG FASTCALL BitmapFormat(ULONG cBits, ULONG iCompression) +ULONG +FASTCALL +BitmapFormat(ULONG cBits, ULONG iCompression) { switch (iCompression) { @@ -107,15 +109,10 @@ 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); + else if (psurf->SurfObj.fjBitmap & BMF_POOLALLOC) + { + /* Free a pool allocation */ + ExFreePool(pvBits); } }
@@ -132,126 +129,162 @@ PSURFACE NTAPI SURFACE_AllocSurface( - IN USHORT iType, - IN ULONG cx, - IN ULONG cy, - IN ULONG iFormat) -{ + _In_ USHORT iType, + _In_ ULONG cx, + _In_ ULONG cy, + _In_ ULONG iFormat, + _In_ ULONG fjBitmap, + _In_opt_ ULONG cjWidth, + _In_opt_ PVOID pvBits) +{ + ULONG cBitsPixel, cjBits, cjObject; PSURFACE psurf; SURFOBJ *pso; + PVOID pvSection; + + ASSERT(!pvBits || (iType == STYPE_BITMAP)); + ASSERT(pvBits || !(fjBitmap & BMF_DONT_FREE)); + ASSERT(!pvBits || !(fjBitmap & BMF_SINGLEALLOC));
/* Verify format */ - if (iFormat < BMF_1BPP || iFormat > BMF_PNG) + if ((iFormat < BMF_1BPP) || (iFormat > BMF_PNG)) { DPRINT1("Invalid bitmap format: %ld\n", iFormat); return NULL; }
+ /* Get bits per pixel from the format */ + cBitsPixel = gajBitsPerFormat[iFormat]; + + /* Are bits and a width in bytes given? */ + if (pvBits && cjWidth) + { + /* Align the width (Windows compatibility, drivers expect that) */ + cjWidth = WIDTH_BYTES_ALIGN32((cjWidth << 3) / cBitsPixel, cBitsPixel); + } + else + { + /* Calculate width from the bitmap width in pixels */ + cjWidth = WIDTH_BYTES_ALIGN32(cx, cBitsPixel); + } + + /* Calculate the bitmap size in bytes */ + cjBits = cjWidth * cy; + + /* Check if we need an extra large object */ + if ((iType == STYPE_BITMAP) && (pvBits == NULL) && + !(fjBitmap & BMF_USERMEM) && !(fjBitmap & BMF_KMSECTION)) + { + /* Allocate an object large enough to hold the bits */ + cjObject = sizeof(SURFACE) + cjBits; + } + else + { + /* Otherwise just allocate the SURFACE structure */ + cjObject = sizeof(SURFACE); + } + + /* Check for arithmetic overflow */ + if ((cjBits < cjWidth) || (cjObject < sizeof(SURFACE))) + { + /* Fail! */ + return NULL; + } + /* Allocate a SURFACE object */ - psurf = (PSURFACE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP, sizeof(SURFACE)); - - 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_vReferenceObjectByPointer(&psurf->ppal->BaseObject); - } - - return psurf; -} - -BOOL -NTAPI -SURFACE_bSetBitmapBits( - IN PSURFACE psurf, - IN ULONG 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) + psurf = (PSURFACE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP, cjObject); + if (!psurf) + { + return NULL; + } + + /* 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->fjBitmap = (USHORT)fjBitmap; + pso->iUniq = InterlockedIncrement(&giUniqueSurface); + pso->cjBits = cjBits; + + /* Check if we need a bitmap buffer */ + if (iType == STYPE_BITMAP) + { + /* Check if we got one or if we need to allocate one */ + if (pvBits != NULL) + { + /* Use the caller provided buffer */ + pso->pvBits = pvBits; + } + else if (fjBitmap & BMF_USERMEM) { /* User mode memory was requested */ - pvBits = EngAllocUserMem(pso->cjBits, 0); + pso->pvBits = EngAllocUserMem(cjBits, 0); + + /* Check for failure */ + if (!pso->pvBits) + { + GDIOBJ_vDeleteObject(&psurf->BaseObject); + return NULL; + } + } + else if (fjBitmap & BMF_KMSECTION) + { + /* Use a kernel mode section */ + pso->pvBits = EngAllocSectionMem(&pvSection, + (fjBitmap & BMF_NOZEROINIT) ? + 0 : FL_ZERO_MEMORY, + cjBits, TAG_DIB); + + /* Check for failure */ + if (!pso->pvBits) + { + GDIOBJ_vDeleteObject(&psurf->BaseObject); + return NULL; + } + + /* Free the section already, but keep the mapping */ + EngFreeSectionMem(pvSection, NULL); } 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; + /* Buffer is after the object */ + pso->pvBits = psurf + 1; + + /* Zero the buffer, except requested otherwise */ + if (!(fjBitmap & BMF_NOZEROINIT)) + { + RtlZeroMemory(pso->pvBits, cjBits); + } + } + } + else + { + /* There are no bitmap bits */ + pso->pvBits = NULL; + } + + /* Set pvScan0 and lDelta */ if (fjBitmap & BMF_TOPDOWN) { /* Topdown is the normal way */ pso->pvScan0 = pso->pvBits; - pso->lDelta = ulWidth; + pso->lDelta = cjWidth; } else { /* Inversed bitmap (bottom up) */ - pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ulWidth); - pso->lDelta = -(LONG)ulWidth; - } - - pso->fjBitmap = (USHORT)fjBitmap; - - /* Success */ - return TRUE; + pso->pvScan0 = ((PCHAR)pso->pvBits + pso->cjBits - cjWidth); + pso->lDelta = -(LONG)cjWidth; + } + + /* Assign a default palette and increment its reference count */ + psurf->ppal = appalSurfaceDefault[iFormat]; + GDIOBJ_vReferenceObjectByPointer(&psurf->ppal->BaseObject); + + return psurf; }
HBITMAP @@ -267,7 +300,13 @@ HBITMAP hbmp;
/* Allocate a surface */ - psurf = SURFACE_AllocSurface(STYPE_BITMAP, sizl.cx, sizl.cy, iFormat); + psurf = SURFACE_AllocSurface(STYPE_BITMAP, + sizl.cx, + sizl.cy, + iFormat, + fl, + lWidth, + pvBits); if (!psurf) { DPRINT1("SURFACE_AllocSurface failed.\n"); @@ -276,15 +315,6 @@
/* 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"); - GDIOBJ_vDeleteObject(&psurf->BaseObject); - return NULL; - }
/* Set public ownership */ GDIOBJ_vSetObjectOwner(&psurf->BaseObject, GDI_OBJ_HMGR_PUBLIC); @@ -308,10 +338,17 @@ HBITMAP hbmp;
/* Allocate a surface */ - psurf = SURFACE_AllocSurface(STYPE_DEVBITMAP, sizl.cx, sizl.cy, iFormat); + psurf = SURFACE_AllocSurface(STYPE_DEVBITMAP, + sizl.cx, + sizl.cy, + iFormat, + 0, + 0, + NULL); if (!psurf) { - return 0; + DPRINT1("SURFACE_AllocSurface failed.\n"); + return NULL; }
/* Set the device handle */ @@ -339,10 +376,17 @@ HSURF hsurf;
/* Allocate a surface */ - psurf = SURFACE_AllocSurface(STYPE_DEVICE, sizl.cx, sizl.cy, iFormat); + psurf = SURFACE_AllocSurface(STYPE_DEVICE, + sizl.cx, + sizl.cy, + iFormat, + 0, + 0, + NULL); if (!psurf) { - return 0; + DPRINT1("SURFACE_AllocSurface failed.\n"); + return NULL; }
/* Set the device handle */
Modified: trunk/reactos/win32ss/gdi/eng/surface.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/eng/surface.h?r... ============================================================================== --- trunk/reactos/win32ss/gdi/eng/surface.h [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/eng/surface.h [iso-8859-1] Tue May 1 12:14:10 2012 @@ -83,7 +83,8 @@
#define BMF_DONT_FREE 0x100 #define BMF_RLE_HACK 0x200 - +#define BMF_SINGLEALLOC 0x400 +#define BMF_POOLALLOC 0x800
/* Internal interface */
@@ -99,31 +100,30 @@ #define SURFACE_ShareUnlockSurface(pBMObj) \ GDIOBJ_vDereferenceObject ((POBJ)pBMObj)
-BOOL NTAPI SURFACE_Cleanup(PVOID ObjectBody); - -PSURFACE -NTAPI -SURFACE_AllocSurface( - IN USHORT iType, - IN ULONG cx, - IN ULONG cy, - IN ULONG iFormat); - -BOOL -NTAPI -SURFACE_bSetBitmapBits( - IN PSURFACE psurf, - IN ULONG fjBitmap, - IN ULONG ulWidth, - IN PVOID pvBits OPTIONAL); - #define GDIDEV(SurfObj) ((PDEVOBJ *)((SurfObj)->hdev)) #define GDIDEVFUNCS(SurfObj) ((PDEVOBJ *)((SurfObj)->hdev))->DriverFunctions
-ULONG FASTCALL BitmapFormat(ULONG cBits, ULONG iCompression); extern UCHAR gajBitsPerFormat[]; #define BitsPerFormat(Format) gajBitsPerFormat[Format]
#define WIDTH_BYTES_ALIGN32(cx, bpp) ((((cx) * (bpp) + 31) & ~31) >> 3) #define WIDTH_BYTES_ALIGN16(cx, bpp) ((((cx) * (bpp) + 15) & ~15) >> 3)
+ULONG +FASTCALL +BitmapFormat(ULONG cBits, ULONG iCompression); + +BOOL +NTAPI +SURFACE_Cleanup(PVOID ObjectBody); + +PSURFACE +NTAPI +SURFACE_AllocSurface( + _In_ USHORT iType, + _In_ ULONG cx, + _In_ ULONG cy, + _In_ ULONG iFormat, + _In_ ULONG fjBitmap, + _In_opt_ ULONG cjWidth, + _In_opt_ PVOID pvBits);
Modified: trunk/reactos/win32ss/gdi/ntgdi/bitblt.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/bitblt.c?... ============================================================================== --- trunk/reactos/win32ss/gdi/ntgdi/bitblt.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/ntgdi/bitblt.c [iso-8859-1] Tue May 1 12:14:10 2012 @@ -1160,34 +1160,36 @@ }
/* Allocate a surface */ - psurfDest = SURFACE_AllocSurface(STYPE_BITMAP, 1, 1, BMF_32BPP); + psurfDest = SURFACE_AllocSurface(STYPE_BITMAP, + 1, + 1, + BMF_32BPP, + BMF_DONT_FREE, + 0, + &ulRGBColor); if (psurfDest) { - /* Set the bitmap bits */ - if (SURFACE_bSetBitmapBits(psurfDest, 0, 0, &ulRGBColor)) - { - RECTL rclDest = {0, 0, 1, 1}; - EXLATEOBJ exlo; - - /* Translate from the source palette to RGB color */ - EXLATEOBJ_vInitialize(&exlo, - psurfSrc->ppal, - &gpalRGB, - 0, - RGB(0xff,0xff,0xff), - RGB(0,0,0)); - - /* Call the copy bits function */ - EngCopyBits(&psurfDest->SurfObj, - &psurfSrc->SurfObj, - NULL, - &exlo.xlo, - &rclDest, - &ptlSrc); - - /* Cleanup the XLATEOBJ */ - EXLATEOBJ_vCleanup(&exlo); - } + RECTL rclDest = {0, 0, 1, 1}; + EXLATEOBJ exlo; + + /* Translate from the source palette to RGB color */ + EXLATEOBJ_vInitialize(&exlo, + psurfSrc->ppal, + &gpalRGB, + 0, + RGB(0xff,0xff,0xff), + RGB(0,0,0)); + + /* Call the copy bits function */ + EngCopyBits(&psurfDest->SurfObj, + &psurfSrc->SurfObj, + NULL, + &exlo.xlo, + &rclDest, + &ptlSrc); + + /* Cleanup the XLATEOBJ */ + EXLATEOBJ_vCleanup(&exlo);
/* Delete the surface */ GDIOBJ_vDeleteObject(&psurfDest->BaseObject);
Modified: trunk/reactos/win32ss/gdi/ntgdi/bitmaps.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/bitmaps.c... ============================================================================== --- trunk/reactos/win32ss/gdi/ntgdi/bitmaps.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/ntgdi/bitmaps.c [iso-8859-1] Tue May 1 12:14:10 2012 @@ -56,25 +56,36 @@ { PSURFACE psurf; HBITMAP hbmp; + PVOID pvCompressedBits;
/* Verify format */ if (iFormat < BMF_1BPP || iFormat > BMF_PNG) return NULL;
+ /* The infamous RLE hack */ + if ((iFormat == BMF_4RLE) || (iFormat == BMF_8RLE)) + { + pvCompressedBits = pvBits; + pvBits = NULL; + iFormat = (iFormat == BMF_4RLE) ? BMF_4BPP : BMF_8BPP; + } + /* Allocate a surface */ - psurf = SURFACE_AllocSurface(STYPE_BITMAP, nWidth, nHeight, iFormat); + psurf = SURFACE_AllocSurface(STYPE_BITMAP, + nWidth, + nHeight, + iFormat, + fjBitmap, + cjWidthBytes, + pvBits); if (!psurf) { DPRINT1("SURFACE_AllocSurface failed.\n"); return NULL; }
- /* Get the handle for the bitmap */ - hbmp = (HBITMAP)psurf->SurfObj.hsurf; - /* The infamous RLE hack */ - if (iFormat == BMF_4RLE || iFormat == BMF_8RLE) - { - PVOID pvCompressedBits; + if ((iFormat == BMF_4RLE) || (iFormat == BMF_8RLE)) + { SIZEL sizl; LONG lDelta;
@@ -82,33 +93,16 @@ sizl.cy = nHeight; lDelta = WIDTH_BYTES_ALIGN32(nWidth, gajBitsPerFormat[iFormat]);
- pvCompressedBits = pvBits; - pvBits = EngAllocMem(FL_ZERO_MEMORY, lDelta * nHeight, TAG_DIB); - if (!pvBits) - { - EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); - GDIOBJ_vDeleteObject(&psurf->BaseObject); - return NULL; - } + pvBits = psurf->SurfObj.pvBits; DecompressBitmap(sizl, pvCompressedBits, pvBits, lDelta, iFormat); - fjBitmap |= BMF_RLE_HACK; - - iFormat = iFormat == BMF_4RLE ? BMF_4BPP : BMF_8BPP; - psurf->SurfObj.iBitmapFormat = iFormat; - } + psurf->SurfObj.fjBitmap |= BMF_RLE_HACK; + } + + /* Get the handle for the bitmap */ + hbmp = (HBITMAP)psurf->SurfObj.hsurf;
/* Mark as API bitmap */ psurf->flags |= (flags | API_BITMAP); - - /* Set the bitmap bits */ - if (!SURFACE_bSetBitmapBits(psurf, fjBitmap, cjWidthBytes, pvBits)) - { - /* Bail out if that failed */ - DPRINT1("SURFACE_bSetBitmapBits failed.\n"); - EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); - GDIOBJ_vDeleteObject(&psurf->BaseObject); - return NULL; - }
/* Unlock the surface and return */ SURFACE_UnlockSurface(psurf); @@ -149,8 +143,9 @@ IN OPTIONAL LPBYTE pUnsafeBits) { HBITMAP hbmp; - ULONG cRealBpp, cjWidthBytes, iFormat; + ULONG cRealBpp, cjWidthBytes, iFormat, fjBitmap; ULONGLONG cjSize; + PSURFACE psurf;
/* Calculate bitmap format and real bits per pixel. */ iFormat = BitmapFormat(cBitsPixel * cPlanes, BI_RGB); @@ -170,12 +165,27 @@ return NULL; }
- /* Call internal function. */ - hbmp = GreCreateBitmapEx(nWidth, nHeight, 0, iFormat, 0, 0, NULL, DDB_SURFACE); - - if (pUnsafeBits && hbmp) - { - PSURFACE psurf = SURFACE_ShareLockSurface(hbmp); + /* Allocate the surface (but don't set the bits) */ + psurf = SURFACE_AllocSurface(STYPE_BITMAP, + nWidth, + nHeight, + iFormat, + fjBitmap, + 0, + NULL); + if (!psurf) + { + DPRINT1("SURFACE_AllocSurface failed.\n"); + return NULL; + } + + /* Mark as API and DDB bitmap */ + psurf->flags |= (API_BITMAP | DDB_SURFACE); + + /* Check if we have bits to set */ + if (pUnsafeBits) + { + /* Protect with SEH and copy the bits */ _SEH2_TRY { ProbeForRead(pUnsafeBits, (SIZE_T)cjSize, 1); @@ -187,9 +197,18 @@ _SEH2_YIELD(return NULL;) } _SEH2_END - - SURFACE_ShareUnlockSurface(psurf); - } + } + else + { + /* Zero the bits */ + RtlZeroMemory(psurf->SurfObj.pvBits, psurf->SurfObj.cjBits); + } + + /* Get the handle for the bitmap */ + hbmp = (HBITMAP)psurf->SurfObj.hsurf; + + /* Unlock the surface */ + SURFACE_UnlockSurface(psurf);
return hbmp; } @@ -324,7 +343,8 @@ HBITMAP Bmp; PDC Dc;
- if (Width <= 0 || Height <= 0 || (Width * Height) > 0x3FFFFFFF) + /* Check parameters */ + if ((Width <= 0) || (Height <= 0) || ((Width * Height) > 0x3FFFFFFF)) { EngSetLastError(ERROR_INVALID_PARAMETER); return NULL; @@ -351,17 +371,19 @@ return Bmp; }
-BOOL APIENTRY +BOOL +APIENTRY NtGdiGetBitmapDimension( HBITMAP hBitmap, - LPSIZE Dimension) + LPSIZE psizDim) { PSURFACE psurfBmp; - BOOL Ret = TRUE; + BOOL bResult = TRUE;
if (hBitmap == NULL) return FALSE;
+ /* Lock the bitmap */ psurfBmp = SURFACE_ShareLockSurface(hBitmap); if (psurfBmp == NULL) { @@ -369,20 +391,22 @@ return FALSE; }
+ /* Use SEH to copy the data to the caller */ _SEH2_TRY { - ProbeForWrite(Dimension, sizeof(SIZE), 1); - *Dimension = psurfBmp->sizlDim; + ProbeForWrite(psizDim, sizeof(SIZE), 1); + *psizDim = psurfBmp->sizlDim; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - Ret = FALSE; + bResult = FALSE; } _SEH2_END
+ /* Unlock the bitmap */ SURFACE_ShareUnlockSurface(psurfBmp);
- return Ret; + return bResult; }
@@ -580,7 +604,7 @@ psurfSrc->SurfObj.sizlBitmap.cy, abs(psurfSrc->SurfObj.lDelta), psurfSrc->SurfObj.iBitmapFormat, - psurfSrc->SurfObj.fjBitmap, + psurfSrc->SurfObj.fjBitmap & BMF_TOPDOWN, psurfSrc->SurfObj.cjBits, NULL, psurfSrc->flags);