[Windows] Layered windows with per-pixel alpha + Max2D
BlitzMax Forums/BlitzMax Programming/[Windows] Layered windows with per-pixel alpha + Max2D
| ||
Building on the previous sample Layered windows with per-pixel alpha, this uses Max2D for rendering. This sample uses UpdateLayeredWindow and the result from Max2D+D3D9/GL rendering to only show what is drawn on screen. For D3D9, it copies from the render target into a surface, then copies that into a bitmap and then it draws the image to the screen with proper transparency. For GL it copies it directly to a buffer and then to a bitmap, and finally to the screen. The bitmap is needed by UpdateLayeredWindow for per-pixel transparency. This sample uses a Desktop sized window, which isnt really needed unless you need to draw all over the screen. If all you need is some movable region to draw to, a smaller window will be faster. I use MaxGUI for this, but it should work with Graphics windows too. D3D9: GL: |
| ||
Hi, I'm getting some really bad fps on Windows 7. I'll test again when I'm home. -Henri |
| ||
Thats weird, i get 60+ with Windows 10. This was the fastest method i found of grabbing the rendered output. But i do grab the entire screen though, so depending on screen resolution and cpu power it probably eats a lot. The grabbing uses practically the same technique as GrabPixmap() so shouldt be THAT slow. Maybe Windows 7 just sucks with UpdateLayeredWindow, or the window is too big for it... EDIT: I added some error checking, it should print an error if any of the APIs complain. |
| ||
Heres a version with performance monitoring of various parts of the source. If anyone wants to check why its so slow on Windows 7, run it and see what it spits out on exit. EDIT: Heres the numbers i get, Windows 10 64-bit, Skylake 6700K 4Ghz, AMD R390 8GB. EVENT_GADGETPAINT: time=15 avg=15 count=1499 Flip;Cls: time=7 avg=7 count=1499 UpdateBitmapFromDeviceSurface: time=8 avg=7 count=1499 GetRenderTarget: time=0 avg=0 count=1499 BitBlt: time=6 avg=5 count=1499 LockRect: time=0 avg=0 count=1499 Transform Alpha: time=1 avg=0 count=1499 SetDIBits: time=1 avg=1 count=1499 UpdateLayeredWindow: time=2 avg=1 count=1501 EDIT2: Lowering the timer frequency to 30 should help too btw. Seeing as i get roughly 16ms per frame i can keep it at 60fps. |
| ||
Cool, thanks grable. |
| ||
Some dedicated debugging there :-) Here are the results: EVENT_GADGETPAINT: time=905 avg=684 count=14 Flip;Cls: time=0 avg=0 count=14 UpdateBitmapFromDeviceSurface: time=905 avg=684 count=14 GetRenderTarget: time=0 avg=0 count=14 BitBlt: time=902 avg=681 count=14 LockRect: time=0 avg=0 count=14 Transform Alpha: time=2 avg=1 count=14 SetDIBits: time=1 avg=1 count=14 UpdateLayeredWindow: time=1 avg=1 count=15 Frequency isn't the issue, it almost seems like it's not hardware excelerated. -Henri |
| ||
@Dan Hope you find a use for it, most of what i see are crap bloatware and mmo launchers using this lol Hmmm.. BitBlt is not supposed to be that slow, its one of the fastest blitting functions in windows! Thanks for checking it out for me :) |
| ||
. |
| ||
After lots of testing the fix was embarrassingly simple :( It would seem that BitBlt does not have an optimized path involving D3D9 Surfaces on Windows 7. The fix was using another primitive, GetRenderTargetData which copies between surfaces instead. This was the same speed on Windows 10, and fast enough on Windows 7 that im using that one instead now. All posts updated, im leaving the performance monitored version up if anyone encounters similar trouble in the future (XP maybe? :p) This makes me want to see if changing GrabPixmap() is possible as well, since it also uses BitBlt. |
| ||
Added OpenGL version to top post, even using glReadPixels is fast enough it seems :) |
| ||
Nicely catched. I have a feeling that I've heard people say GrapPixmap is slow so maybe you got something there. One final thing. Not sure if it's a bug, but the image stops following after you press left mouse button. Anyway, cool stuff :-) -Henri |
| ||
One final thing. Not sure if it's a bug, but the image stops following after you press left mouse button. Thats because it loses focus. Since the mouse is not over the window, whatever is behind gets focus instead. So not a bug ;) I have a feeling that I've heard people say GrapPixmap is slow so maybe you got something there I looked at GrabPixmap some more. But it cant use GetRenderTargetData, since it requires the surfaces have specific types and only copies the whole surface :/But there are optimization opportunities though, i think it would help to not allocate a new surface and pixmap every time for one. Thanks. I have no idea what im gonna use it for, but it is cool :) |