canvas/source/directx/dx_vcltools.cxx |    6 -
 vcl/inc/win/salbmp.h                  |   13 +-
 vcl/win/gdi/salbmp.cxx                |  165 ++++++++++++++++------------------
 3 files changed, 92 insertions(+), 92 deletions(-)

New commits:
commit 087b82633eaa393cbe2bad55783af3894f85425f
Author:     Noel Grandin <noelgran...@gmail.com>
AuthorDate: Tue Jun 10 22:19:52 2025 +0200
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Wed Jun 11 17:10:25 2025 +0200

    tdf#166932 no need to use GlobalAlloc in BitmapEx
    
    which consumes a GDI handle for each bitmap, and can consequently
    sometimes use up a lot of handles.
    Just use the regular malloc/free.
    
    Change-Id: I19782ac16ff195644b4feb62848c1a95acf08021
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186342
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Tested-by: Noel Grandin <noel.gran...@collabora.co.uk>
    (cherry picked from commit 41ce88c0dc01211e2cc319890a069d04360c76eb)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186361
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/canvas/source/directx/dx_vcltools.cxx 
b/canvas/source/directx/dx_vcltools.cxx
index 83978830e0d6..8e1201ae692f 100644
--- a/canvas/source/directx/dx_vcltools.cxx
+++ b/canvas/source/directx/dx_vcltools.cxx
@@ -63,11 +63,11 @@ namespace dxcanvas::tools
 
             /// Draw DI bits to given Graphics
             bool drawDIBits( const std::shared_ptr< Gdiplus::Graphics >& 
rGraphics,
-                             const void*                                     
hDIB )
+                             void*                                       pDIB )
             {
                 bool            bRet( false );
 
-                const BITMAPINFO* pBI = static_cast<BITMAPINFO*>(GlobalLock( 
const_cast<void *>(hDIB) ));
+                const BITMAPINFO* pBI = static_cast<BITMAPINFO*>(pDIB);
 
                 if( pBI )
                 {
@@ -77,8 +77,6 @@ namespace dxcanvas::tools
                     // forward to outsourced GDI+ rendering method
                     // (header clashes)
                     bRet = tools::drawDIBits( rGraphics, *pBI, pBits );
-
-                    GlobalUnlock( const_cast<void *>(hDIB) );
                 }
 
                 return bRet;
diff --git a/vcl/inc/win/salbmp.h b/vcl/inc/win/salbmp.h
index 8ff069153d12..685c0ffae73a 100644
--- a/vcl/inc/win/salbmp.h
+++ b/vcl/inc/win/salbmp.h
@@ -36,7 +36,8 @@ class WinSalBitmap final: public SalBitmap
 {
 private:
     Size                maSize;
-    HGLOBAL             mhDIB;
+    void*               mpDIB;
+    sal_Int32           mnDIBSize { 0 };
     HBITMAP             mhDDB;
 
     sal_uInt16          mnBitCount;
@@ -46,14 +47,16 @@ private:
 
 public:
 
-    HGLOBAL             ImplGethDIB() const { return mhDIB; }
+    void*               ImplGethDIB() const { return mpDIB; }
     HBITMAP             ImplGethDDB() const { return mhDDB; }
 
     std::shared_ptr< Gdiplus::Bitmap > ImplGetGdiPlusBitmap(const 
WinSalBitmap* pAlphaSource = nullptr) const;
 
-    static HGLOBAL      ImplCreateDIB( const Size& rSize, vcl::PixelFormat 
ePixelFormat, const BitmapPalette& rPal );
-    static HANDLE       ImplCopyDIBOrDDB( HANDLE hHdl, bool bDIB );
-    static sal_uInt16   ImplGetDIBColorCount( HGLOBAL hDIB );
+    static void         ImplCreateDIB( const Size& rSize, vcl::PixelFormat 
ePixelFormat, const BitmapPalette& rPal,
+                                       void*& rpDIB, sal_Int32 &rnDIBSize );
+    static HBITMAP      ImplCopyDDB( HBITMAP hHdl );
+    static void*        ImplCopyDIB( void* pDIB, sal_Int32 nDIBSize );
+    static sal_uInt16   ImplGetDIBColorCount( void* pDIB );
 
 public:
 
diff --git a/vcl/win/gdi/salbmp.cxx b/vcl/win/gdi/salbmp.cxx
index e33ca5e03950..f65cd869e277 100644
--- a/vcl/win/gdi/salbmp.cxx
+++ b/vcl/win/gdi/salbmp.cxx
@@ -46,7 +46,7 @@
 WinSalBitmap::WinSalBitmap()
 :   SalBitmap(),
     maSize(),
-    mhDIB(nullptr),
+    mpDIB(nullptr),
     mhDDB(nullptr),
     mnBitCount(0)
 {
@@ -59,8 +59,8 @@ WinSalBitmap::~WinSalBitmap()
 
 void WinSalBitmap::Destroy()
 {
-    if( mhDIB )
-        GlobalFree( mhDIB );
+    if( mpDIB )
+        free( mpDIB );
     else if( mhDDB )
         DeleteObject( mhDDB );
 
@@ -430,7 +430,7 @@ std::shared_ptr<Gdiplus::Bitmap> 
WinSalBitmap::ImplCreateGdiPlusBitmap(const Win
 bool WinSalBitmap::Create( HBITMAP hBitmap )
 {
     assert(hBitmap);
-    assert(!mhDIB && "already created");
+    assert(!mpDIB && "already created");
     assert(!mhDDB && "already created");
 
     BITMAP  aDDBInfo;
@@ -446,15 +446,18 @@ bool WinSalBitmap::Create( HBITMAP hBitmap )
 
 bool WinSalBitmap::Create(const Size& rSize, vcl::PixelFormat ePixelFormat, 
const BitmapPalette& rPal)
 {
-    assert(!mhDIB && "already created");
+    assert(!mpDIB && "already created");
     assert(!mhDDB && "already created");
 
-    HGLOBAL hDIB = ImplCreateDIB(rSize, ePixelFormat, rPal);
+    void* pDIB = nullptr;
+    sal_Int32 nDIBSize = 0;
+    ImplCreateDIB(rSize, ePixelFormat, rPal, pDIB, nDIBSize);
 
-    if( !hDIB )
+    if( !pDIB )
         return false;
 
-    mhDIB = hDIB;
+    mpDIB = pDIB;
+    mnDIBSize = nDIBSize;
     maSize = rSize;
     mnBitCount = vcl::pixelFormatBitCount(ePixelFormat);
 
@@ -463,41 +466,50 @@ bool WinSalBitmap::Create(const Size& rSize, 
vcl::PixelFormat ePixelFormat, cons
 
 bool WinSalBitmap::Create( const SalBitmap& rSSalBitmap )
 {
-    assert(!mhDIB && "already created");
+    assert(!mpDIB && "already created");
     assert(!mhDDB && "already created");
 
     const WinSalBitmap& rSalBitmap = static_cast<const 
WinSalBitmap&>(rSSalBitmap);
 
-    if ( !rSalBitmap.mhDIB && !rSalBitmap.mhDDB )
-        return false;
-
-    HANDLE hNewHdl = ImplCopyDIBOrDDB( rSalBitmap.mhDIB ? rSalBitmap.mhDIB : 
rSalBitmap.mhDDB,
-                                       rSalBitmap.mhDIB != nullptr );
+    if (rSalBitmap.mpDIB)
+    {
+        void* pNew = ImplCopyDIB( rSalBitmap.mpDIB, rSalBitmap.mnDIBSize );
+        if ( !pNew )
+            return false;
 
-    if ( !hNewHdl )
-        return false;
+        mpDIB = pNew;
+        mnDIBSize = rSalBitmap.mnDIBSize;
+        maSize = rSalBitmap.maSize;
+        mnBitCount = rSalBitmap.mnBitCount;
 
-    if( rSalBitmap.mhDIB )
-        mhDIB = static_cast<HGLOBAL>(hNewHdl);
-    else if( rSalBitmap.mhDDB )
-        mhDDB = static_cast<HBITMAP>(hNewHdl);
+        return true;
+    }
+    else if (rSalBitmap.mhDDB)
+    {
+        HBITMAP hNewHdl = ImplCopyDDB( rSalBitmap.mhDDB );
+        if ( !hNewHdl )
+            return false;
 
-    maSize = rSalBitmap.maSize;
-    mnBitCount = rSalBitmap.mnBitCount;
+        mhDDB = hNewHdl;
+        maSize = rSalBitmap.maSize;
+        mnBitCount = rSalBitmap.mnBitCount;
 
-    return true;
+        return true;
+    }
+    else
+        return false;
 }
 
 bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, SalGraphics* pSGraphics )
 {
-    assert(!mhDIB && "already created");
+    assert(!mpDIB && "already created");
     assert(!mhDDB && "already created");
 
     const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp);
-    if(!rSalBmp.mhDIB)
+    if(!rSalBmp.mpDIB)
         return false;
 
-    PBITMAPINFO pBI = static_cast<PBITMAPINFO>(GlobalLock( rSalBmp.mhDIB ));
+    PBITMAPINFO pBI = static_cast<PBITMAPINFO>(mpDIB);
     if (!pBI)
         return false;
 
@@ -507,11 +519,9 @@ bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, 
SalGraphics* pSGraphics )
     HDC                 hDC  = pGraphics->getHDC();
     BITMAP              aDDBInfo;
     PBYTE               pBits = reinterpret_cast<PBYTE>(pBI) + 
pBI->bmiHeader.biSize +
-                                ImplGetDIBColorCount( rSalBmp.mhDIB ) * 
sizeof( RGBQUAD );
+                                ImplGetDIBColorCount( rSalBmp.mpDIB ) * 
sizeof( RGBQUAD );
     HBITMAP hNewDDB = CreateDIBitmap( hDC, &pBI->bmiHeader, CBM_INIT, pBits, 
pBI, DIB_RGB_COLORS );
 
-    GlobalUnlock( rSalBmp.mhDIB );
-
     if( hNewDDB && GetObjectW( hNewDDB, sizeof( aDDBInfo ), &aDDBInfo ) )
     {
         mhDDB = hNewDDB;
@@ -528,7 +538,7 @@ bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, 
SalGraphics* pSGraphics )
 
 bool WinSalBitmap::Create(const SalBitmap& rSSalBmp, vcl::PixelFormat 
eNewPixelFormat)
 {
-    assert(!mhDIB && "already created");
+    assert(!mpDIB && "already created");
     assert(!mhDDB && "already created");
 
     const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp);
@@ -538,12 +548,12 @@ bool WinSalBitmap::Create(const SalBitmap& rSSalBmp, 
vcl::PixelFormat eNewPixelF
     if( !rSalBmp.mhDDB )
         return false;
 
-    mhDIB = ImplCreateDIB( rSalBmp.maSize, eNewPixelFormat, BitmapPalette() );
+    ImplCreateDIB( rSalBmp.maSize, eNewPixelFormat, BitmapPalette(), mpDIB, 
mnDIBSize );
 
-    if( !mhDIB )
+    if( !mpDIB )
         return false;
 
-    PBITMAPINFO pBI = static_cast<PBITMAPINFO>(GlobalLock( mhDIB ));
+    PBITMAPINFO pBI = static_cast<PBITMAPINFO>(mpDIB);
     if (!pBI)
         return false;
 
@@ -551,20 +561,18 @@ bool WinSalBitmap::Create(const SalBitmap& rSSalBmp, 
vcl::PixelFormat eNewPixelF
     const int   nLines = static_cast<int>(rSalBmp.maSize.Height());
     HDC         hDC = GetDC( nullptr );
     PBYTE       pBits = reinterpret_cast<PBYTE>(pBI) + pBI->bmiHeader.biSize +
-                        ImplGetDIBColorCount( mhDIB ) * sizeof( RGBQUAD );
+                        ImplGetDIBColorCount( mpDIB ) * sizeof( RGBQUAD );
 
     if( GetDIBits( hDC, rSalBmp.mhDDB, 0, nLines, pBits, pBI, DIB_RGB_COLORS ) 
== nLines )
     {
-        GlobalUnlock( mhDIB );
         maSize = rSalBmp.maSize;
         mnBitCount = vcl::pixelFormatBitCount(eNewPixelFormat);
         bRet = true;
     }
     else
     {
-        GlobalUnlock( mhDIB );
-        GlobalFree( mhDIB );
-        mhDIB = nullptr;
+        free( mpDIB );
+        mpDIB = nullptr;
     }
 
     ReleaseDC( nullptr, hDC );
@@ -620,12 +628,13 @@ sal_uInt16 WinSalBitmap::ImplGetDIBColorCount( HGLOBAL 
hDIB )
     return nColors;
 }
 
-HGLOBAL WinSalBitmap::ImplCreateDIB(const Size& rSize, vcl::PixelFormat 
ePixelFormat, const BitmapPalette& rPal)
+void WinSalBitmap::ImplCreateDIB(const Size& rSize, vcl::PixelFormat 
ePixelFormat, const BitmapPalette& rPal,
+                                    void*& rpDIB, sal_Int32 &rnDIBSize)
 {
-    HGLOBAL hDIB = nullptr;
+    rpDIB = nullptr;
 
     if( rSize.IsEmpty() )
-        return hDIB;
+        return;
 
     const auto nBits = vcl::pixelFormatBitCount(ePixelFormat);
 
@@ -634,7 +643,7 @@ HGLOBAL WinSalBitmap::ImplCreateDIB(const Size& rSize, 
vcl::PixelFormat ePixelFo
     const sal_uLong nImageSize = nAlignedWidth4Bytes * rSize.Height();
     bool bOverflow = (nImageSize / nAlignedWidth4Bytes) != 
static_cast<sal_uLong>(rSize.Height());
     if( bOverflow )
-        return hDIB;
+        return;
 
     // allocate bitmap memory including header and palette
     sal_uInt16 nColors = 0;
@@ -644,16 +653,14 @@ HGLOBAL WinSalBitmap::ImplCreateDIB(const Size& rSize, 
vcl::PixelFormat ePixelFo
     const sal_uLong nHeaderSize = sizeof( BITMAPINFOHEADER ) + nColors * 
sizeof( RGBQUAD );
     bOverflow = (nHeaderSize + nImageSize) < nImageSize;
     if( bOverflow )
-        return hDIB;
-
-    hDIB = GlobalAlloc( GHND, nHeaderSize + nImageSize );
-    if( !hDIB )
-        return hDIB;
+        return;
 
-    PBITMAPINFO pBI = static_cast<PBITMAPINFO>( GlobalLock( hDIB ) );
-    if (!pBI)
-        return hDIB;
+    rpDIB = malloc( nHeaderSize + nImageSize );
+    if( !rpDIB )
+        return;
+    rnDIBSize = nHeaderSize + nImageSize;
 
+    PBITMAPINFO pBI = static_cast<PBITMAPINFO>( rpDIB );
     PBITMAPINFOHEADER pBIH = reinterpret_cast<PBITMAPINFOHEADER>( pBI );
 
     pBIH->biSize = sizeof( BITMAPINFOHEADER );
@@ -675,29 +682,13 @@ HGLOBAL WinSalBitmap::ImplCreateDIB(const Size& rSize, 
vcl::PixelFormat ePixelFo
         if( nMinCount )
             memcpy( pBI->bmiColors, rPal.ImplGetColorBuffer(), nMinCount * 
sizeof(RGBQUAD) );
     }
-
-    GlobalUnlock( hDIB );
-
-    return hDIB;
 }
 
-HANDLE WinSalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl, bool bDIB )
+HBITMAP WinSalBitmap::ImplCopyDDB( HBITMAP hHdl )
 {
-    HANDLE  hCopy = nullptr;
+    HBITMAP  hCopy = nullptr;
 
-    if ( bDIB && hHdl )
-    {
-        const sal_uLong nSize = GlobalSize( hHdl );
-
-        if ( (hCopy = GlobalAlloc( GHND, nSize  )) != nullptr )
-        {
-            memcpy( GlobalLock( hCopy ), GlobalLock( hHdl ), nSize );
-
-            GlobalUnlock( hCopy );
-            GlobalUnlock( hHdl );
-        }
-    }
-    else if ( hHdl )
+    if ( hHdl )
     {
         BITMAP aBmp;
 
@@ -725,12 +716,26 @@ HANDLE WinSalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl, bool 
bDIB )
     return hCopy;
 }
 
+void* WinSalBitmap::ImplCopyDIB( void* pDIB, sal_Int32 nSize )
+{
+    void*  pCopy = nullptr;
+
+    if ( pDIB )
+    {
+        pCopy = malloc(nSize);
+        if ( pCopy )
+            memcpy( pCopy, pDIB, nSize );
+    }
+
+    return pCopy;
+}
+
 BitmapBuffer* WinSalBitmap::AcquireBuffer( BitmapAccessMode /*nMode*/ )
 {
-    if (!mhDIB)
+    if (!mpDIB)
         return nullptr;
 
-    PBITMAPINFO pBI = static_cast<PBITMAPINFO>(GlobalLock( mhDIB ));
+    PBITMAPINFO pBI = static_cast<PBITMAPINFO>(mpDIB);
     if (!pBI)
         return nullptr;
 
@@ -756,7 +761,7 @@ BitmapBuffer* WinSalBitmap::AcquireBuffer( BitmapAccessMode 
/*nMode*/ )
 
             if( pBuffer->mnBitCount <= 8 )
             {
-                const sal_uInt16 nPalCount = ImplGetDIBColorCount( mhDIB );
+                const sal_uInt16 nPalCount = ImplGetDIBColorCount( mpDIB );
 
                 pBuffer->maPalette.SetEntryCount( nPalCount );
                 memcpy( pBuffer->maPalette.ImplGetColorBuffer(), 
pBI->bmiColors, nPalCount * sizeof( RGBQUAD ) );
@@ -767,12 +772,9 @@ BitmapBuffer* WinSalBitmap::AcquireBuffer( 
BitmapAccessMode /*nMode*/ )
         }
         else
         {
-            GlobalUnlock( mhDIB );
             pBuffer.reset();
         }
     }
-    else
-        GlobalUnlock( mhDIB );
 
     return pBuffer.release();
 }
@@ -781,20 +783,17 @@ void WinSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, 
BitmapAccessMode nMode
 {
     if( pBuffer )
     {
-        if( mhDIB )
+        if( mpDIB )
         {
             if( nMode == BitmapAccessMode::Write && !!pBuffer->maPalette )
             {
-                if (PBITMAPINFO pBI = static_cast<PBITMAPINFO>(GlobalLock( 
mhDIB )))
+                if (PBITMAPINFO pBI = static_cast<PBITMAPINFO>(mpDIB))
                 {
                     const sal_uInt16    nCount = 
pBuffer->maPalette.GetEntryCount();
-                    const sal_uInt16    nDIBColorCount = ImplGetDIBColorCount( 
mhDIB );
+                    const sal_uInt16    nDIBColorCount = ImplGetDIBColorCount( 
mpDIB );
                     memcpy( pBI->bmiColors, 
pBuffer->maPalette.ImplGetColorBuffer(), std::min( nDIBColorCount, nCount ) * 
sizeof( RGBQUAD ) );
-                    GlobalUnlock( mhDIB );
                 }
             }
-
-            GlobalUnlock( mhDIB );
         }
 
         delete pBuffer;
@@ -806,10 +805,10 @@ void WinSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, 
BitmapAccessMode nMode
 bool WinSalBitmap::GetSystemData( BitmapSystemData& rData )
 {
     bool bRet = false;
-    if( mhDIB || mhDDB )
+    if( mpDIB || mhDDB )
     {
         bRet = true;
-        rData.pDIB = mhDIB;
+        rData.pDIB = mpDIB;
         const Size& rSize = GetSize ();
         rData.mnWidth = rSize.Width();
         rData.mnHeight = rSize.Height();

Reply via email to