flat assembler
Message board for the users of flat assembler.

Index > Windows > GDI vs GDI+

Author
Thread Post new topic Reply to topic
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 22 Aug 2008, 17:45
Anyone has a serious speed comparison about this? (On platforms not older than WinXP).

And yes revolution, I already checked your website but lots of .Net pages with not very well made benchmarks and lots of Command&Conquer links in some searches Laughing

I was using IDApro a little but it is somewhat hard to follow and seems that any call using integers parameters is forwarded to the float parameters version (in the case of DrawLineI it does DrawLineI>DrawLine(floats)>DrawLines>DrawPath>RenderPath).

It is somewhat easier to use than GDI (no more SelectObject/DeleteObject annoyance), but is it really faster even on video cards with hardware acceleration like GeForce?
Post 22 Aug 2008, 17:45
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 19869
Location: In your JS exploiting you and your system
revolution 22 Aug 2008, 18:05
LocoDelAssembly wrote:
Anyone has a serious speed comparison about this? (On platforms not older than WinXP).
My limited testing with graphics has shown me that the GDI is very slow. I found that rolling my own animation routines and just sending a bitmap to the GDI engine produced much lower CPU usage (and more time for other things). However I have not yet had need to use GDI+.
LocoDelAssembly wrote:
And yes revolution, I already checked your website but lots of .Net pages with not very well made benchmarks and lots of Command&Conquer links in some searches Laughing
Hehe, perhaps you were using the wrong search terms Wink But actually I would not have considered referring anyone to google for matters like this. Searching for basic information and facts is easy, but comparisons and good quality experience is hard to find so I am not surprised you can't find what you need.
LocoDelAssembly wrote:
I was using IDApro a little but it is somewhat hard to follow and seems that any call using integers parameters is forwarded to the float parameters version (in the case of DrawLineI it does DrawLineI>DrawLine(floats)>DrawLines>DrawPath>RenderPath).

It is somewhat easier to use than GDI (no more SelectObject/DeleteObject annoyance), but is it really faster even on video cards with hardware acceleration like GeForce?
If you can find the root function then I expect that it will always be faster to roll your own routines and limit your use to just the most primitive API provided by the OS. It can mean more work for you but if performance is a key goal then you might not have any other option.
Post 22 Aug 2008, 18:05
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 22 Aug 2008, 19:48
Quote:

I found that rolling my own animation routines and just sending a bitmap to the GDI engine produced much lower CPU usage

Using DIBSection over a CompatibleDC? I had a bad experience with that approach, if the bit depth of the DIBSection didn't match that of the current display mode the CPU usage was a constant 100 % without being able to BitBlt one frame per Hz, setting the display bit depth to the one used in the DIBSection throttled down the CPU usage by about 50 % and one frame per Hz was possible, but the minimum CPU usage was using a CompatibleBitmap, having a hard to measure CPU usage. All this on an AMD Athlon 750 MHz with a GeForce FX 5200 and Windows Server 2003. What I've forgot to try was blitting the DIBSection to a DC with a CompatibleBitmap selected first and then from the latter DC to the window DC. I believe that using CompatibleBitmap MUST BE faster in average since the operations should be easy to perform by the driver (and hardware) than a DIB.

BTW, I was tracing GdiplusDrawLineI on Olly and I don't know how many times I pressed F7 but after 15 minutes of doing that EIP still don't get back to my executable!! I'm starting to think that GDI+ has from few to none chances at all to be faster than plain GDI (apart of the fact that many functions seems to be built on top of plain GDI).

I think I better abandon GDI+ and try to find how to do anti-aliasing on GDI instead...

Thanks for answering revolution Smile

[edit]Setting a breakpoint to the list of functions below the debugger never stops. I wonder if this call is REALLY built on top of GDI Confused

CreateDIBitmap, PlgBlt, StretchDIBits, StrokePath, PolyDraw, GetPixel, SetPixelV, SetPixel, GetDIBits, SetDIBits, SelectObject, CreateDIBSection, PatBlt, LineTo, BitBlt.

Code:
; Template for program using standard Win32 headers

format PE GUI 4.0
entry start

include 'win32ax.inc'
struct GdiplusStartupInput
  GdiplusVersion dd ?
  DebugEventCallback dd ?
  SuppressBackgroundThread dd ?
  SuppressExternalCodecs dd ?
ends

section '.data' data readable writeable

  _class TCHAR 'FASMWIN32',0
  _title TCHAR 'Win32 program template',0
  _error TCHAR 'Startup failed.',0

  wc WNDCLASS 0,WindowProc,0,0,NULL,NULL,NULL,COLOR_BTNFACE+1,NULL,_class

  msg MSG
  input GdiplusStartupInput 1 ; GdiplusVersion = 1
  token dd ?

section '.code' code readable executable

  start:

        invoke  GetModuleHandle,0
        mov     [wc.hInstance],eax
        invoke  LoadIcon,0,IDI_APPLICATION
        mov     [wc.hIcon],eax
        invoke  LoadCursor,0,IDC_ARROW
        mov     [wc.hCursor],eax
        invoke  RegisterClass,wc
        test    eax,eax
        jz      error

        invoke  GdiplusStartup, token, input, NULL
        test    eax, eax
        jnz     error

        invoke  CreateWindowEx,0,_class,_title,WS_VISIBLE+WS_DLGFRAME+WS_SYSMENU,128,128,256*3,192*3,NULL,NULL,[wc.hInstance],NULL
        test    eax,eax
        jz      error

  msg_loop:
        invoke  GetMessage,msg,NULL,0,0
        cmp     eax,1
        jb      end_loop
        jne     msg_loop
        invoke  TranslateMessage,msg
        invoke  DispatchMessage,msg
        jmp     msg_loop

  error:
        invoke  MessageBox,NULL,_error,NULL,MB_ICONERROR+MB_OK

  end_loop:
        invoke  GdiplusShutdown, [token]
        invoke  ExitProcess,[msg.wParam]

proc WindowProc hwnd,wmsg,wparam,lparam
local ps:PAINTSTRUCT

        push    ebx esi edi

        cmp     [wmsg],WM_DESTROY
        je      .wmdestroy

        cmp     [wmsg], WM_PAINT
        je      .wmpaint

  .defwndproc:
        invoke  DefWindowProc,[hwnd],[wmsg],[wparam],[lparam]
        jmp     .finish

  .wmpaint:
        invoke  BeginPaint, [hwnd], addr ps
        stdcall draw, eax
        invoke  EndPaint, [hwnd], addr ps
        jmp     .finish_ret_0

  .wmdestroy:
        invoke  PostQuitMessage,0

  .finish_ret_0:
        xor     eax,eax

  .finish:
        pop     edi esi ebx
        ret
endp

proc drawNode x, y, node

  ret
endp

proc draw hdc
local pGraphics:DWORD, pPen:DWORD

  invoke  GdipCreateFromHDC, [hdc], addr pGraphics
  invoke  GdipCreatePen1, $FF000000, 3.0, 0, addr pPen

  push    ebx
  mov     ebx, 10

  invoke  GdipSetSmoothingMode, [pGraphics], 2

.loop:
  invoke  GdipDrawLineI, [pGraphics], [pPen], addr 0+ebx*8, addr 100+ebx*8, addr 500+ebx*8, addr 200+ebx*8
  dec     ebx
  jns     .loop

  pop     ebx

  invoke  GdipDeleteGraphics, [pGraphics]
  invoke  GdipDeletePen, [pPen]
  ret
endp

section '.idata' import data readable writeable

  library gdi, 'GDI.DLL',\
          gdiplus, 'GDIPLUS.DLL',\
          kernel32,'KERNEL32.DLL',\
          user32,'USER32.DLL'

  include 'api\gdi32.inc'

  import  gdiplus,\
                  GdiplusShutdown, 'GdiplusShutdown',\
                  GdipCreateFromHDC, 'GdipCreateFromHDC',\
                  GdipCreatePen1, 'GdipCreatePen1',\
                  GdipDeleteGraphics, 'GdipDeleteGraphics',\
                  GdipDeletePen, 'GdipDeletePen',\
                  GdipDrawLineI, 'GdipDrawLineI',\
                  GdipSetSmoothingMode, 'GdipSetSmoothingMode',\
                  GdiplusStartup, 'GdiplusStartup'

  include 'api\kernel32.inc'
  include 'api\user32.inc'    
Post 22 Aug 2008, 19:48
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 19869
Location: In your JS exploiting you and your system
revolution 22 Aug 2008, 20:19
Oh, you absolutely need to match your BMP to the display capabilities. I only made two versions of my code, 16BPP and 24BPP(32BPP). I had no need to support 8BPP so I never implemented it, but such ancient systems would probably not have been usable anyhow so it didn't matter.
Post 22 Aug 2008, 20:19
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 22 Aug 2008, 21:08
Something I forgot to mention, the CPU usage was also much higher when a window was on top of some portion of the window I was painting, however this performance hit was not perceived when using a CompatibleBitmap. In my box, blitting performance was seriously limited compared to compatible bitmaps BUT, I was doing very little work (very few pixels changed between blittings and there was no operation that needed GetPixel/SetPixel), so maybe in a more intensive graphics processing bitmaps compensate the lower blitting performance (not considering the obvious case of low-level operations where GetPixel/SetPixel would be the only high-level operations usable and for sure much more expensive than DIBSections).
Post 22 Aug 2008, 21:08
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 3884
Location: vpcmipstrm
bitRAKE 23 Aug 2008, 03:28
AntiGrain (C++) has really high-quality output. (Haven't used the newer Pascal version (AggPas).)

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 23 Aug 2008, 03:28
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 23 Aug 2008, 04:37
Awesome bitRAKE!!! And it works flicker free also even though it uses SetDIBitsToDevice instead of BitBlt of a CompatibleDC with a CompatibleBitmap. Additionally it also has a test that proofs that GDI+ is slower than AntiGrain and it is even bugged.

Thank you very much!!
Post 23 Aug 2008, 04:37
View user's profile Send private message Reply with quote
slovach



Joined: 14 May 2007
Posts: 4
slovach 24 Aug 2008, 08:36
Hi, you will surely find Get/SetPixel to be horrendously slow, I'm also sure that you will find GDI+ to infact be slower than GDI in most cases as well. Wink

As far as I know, the fastest way to draw in GDI is to create a DIB and draw on it by setting the bits. This probably gets the benefit of being accelerated by your graphics hardware on more modern hardware / drivers.

Anyway, it's very simple to do actually, but information on it is definitely scarce.

(sorry, it's going to be in C, I'm not experienced enough in ASM to convert it myself yet)
The first issue for drawing is the bitmap padding. This can be simply worked around by doing something like:
Code:
(y * SCREEN_WIDTH + x) << 2)    


From then on, you basically set your pixels by doing this, then blitting it.

Code:
bits[padding + 2] = red;
bits[padding + 1] = green;
bits[padding      ] = blue;    


If you need to load pictures, you can also convert your images to byte arrays and go from there, pixel by pixel straight to your DIB. It should be pretty simple to keep the number of BitBlit calls extremely minimal.

BitBlt may also be faster than SetDIBitsToDevice.

I wrote a simple retro 2d starfield a while back. While it's in C, and might have some possible speed ups from ASM, it's still pretty fast. The drawing is very cheap compared to the actual calculations for the starfield.
Post 24 Aug 2008, 08:36
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2023, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.