wxAutoBufferedPaintDC can cause very slow rendering if drawing bitmaps with alpha on MSW (Issue #23841)

33 views
Skip to first unread message

VZ

unread,
Aug 31, 2023, 9:17:12 AM8/31/23
to wx-...@googlegroups.com, Subscribed

wxAutoBufferedPaintDC can cause very slow rendering if drawing bitmaps with alpha on MSW.

The reason is that the backing store bitmap used by wxAutoBufferedPaintDC is a DDB and not a DIB. If you draw an alpha bitmap onto the DC then AlphaBlt will use wxAlphaPixelData which when not using a DIB will make a copy of the whole backing store. It does this for each bitmap draw (can be pretty bad on wxAuiToolBar).
I've worked around it by making my own double buffering solution that uses this:

            // Convert to DIB.  This way, if transparent images are drawn then 
            // you do not get a DDB=>DIB=>DDB conversion via temporary
            // expensive resource allocations!
            store.ConvertToDIB();

Thats meant I have to derive wxAuiToolBar and re-implement OnPaint. Would be nice to be able to avoid doing that.

Originally posted by @petebannister in #23585 (comment)


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23841@github.com>

VZ

unread,
Sep 7, 2023, 5:38:13 PM9/7/23
to wx-...@googlegroups.com, Subscribed

For the record, this is probably the same problem as alluded to here:

https://github.com/wxWidgets/wxWidgets/blob/3861ad6b6d9b202dcb0f1cb56bcd52a7c375290a/src/richtext/richtextctrl.cpp#L3025-L3029

Except that using depth of 24 doesn't work when alpha is effectively used, of course. OTOH fixing this would allow to remove the workaround in the code above.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23841/1710800681@github.com>

dsa-t

unread,
May 25, 2024, 1:29:45 AMMay 25
to wx-...@googlegroups.com, Subscribed

KiCad also spends 90% of time drawing bitmaps while resizing

image.png (view on web)


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23841/2130786121@github.com>

dsa-t

unread,
May 25, 2024, 4:23:19 PMMay 25
to wx-...@googlegroups.com, Subscribed

After updating from 3.2.4 to 3.2.5, aDc.GetAsBitmap().ConvertToDIB(); causes a (recursive) assert
"deleting bitmap still selected into wxMemoryDC"


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23841/2131427873@github.com>

VZ

unread,
May 25, 2024, 5:04:16 PMMay 25
to wx-...@googlegroups.com, Subscribed

It's normal that destroying a bitmap selected into a memory DC results in an assert, this really shouldn't be done.

The question is whether we should be always creating the backing store bitmap as a DIB or not and I am still not sure about the answer here. I think that in general using DIB should be faster because it is a better target for drawing into, which is done many times while composing it, and then it's only blitted to the screen once, but it's not at all impossible that there might be some situations in which drawing to it is fast anyhow but blitting it to screen is faster with DDB. I don't have any benchmarks to check it, however, and even if we had/I wrote one, there are so many different combinations of Windows version, display depth, video driver etc that it seems impossible to test all of them.

I think we could experiment with always using a DIB here in master, but I'm really not sure about doing this in 3.2.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23841/2131452803@github.com>

VZ

unread,
May 25, 2024, 5:12:04 PMMay 25
to wx-...@googlegroups.com, Subscribed

BTW, I forgot to mention, but the change needed to always create DIPs is trivial:

diff --git a/src/common/dcbufcmn.cpp b/src/common/dcbufcmn.cpp
index ba31002c1d..74710fe561 100644
--- a/src/common/dcbufcmn.cpp
+++ b/src/common/dcbufcmn.cpp
@@ -84,7 +84,7 @@ private:
 
         // we must always return a valid bitmap but creating a bitmap of
         // size 0 would fail, so create a 1*1 bitmap in this case
-        buffer->CreateWithLogicalSize(wxMax(w, 1), wxMax(h, 1), scale);
+        buffer->CreateWithLogicalSize(wxMax(w, 1), wxMax(h, 1), scale, 32);
 
         return buffer;
     }

so it's not at all a problem to do it, the problem is to determine whether it's really a good idea.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23841/2131458849@github.com>

Reply all
Reply to author
Forward
0 new messages