UEZ Posted June 27, 2009 Share Posted June 27, 2009 (edited) Hi,why is e.g. _GDIPlus_GraphicsClear($backbuffer, 0x9A000000) in the example below extremly slow on some machines?expandcollapse popup#include <GuiConstantsEx.au3> #include <GDIPlus.au3> #include <Array.au3> Opt('MustDeclareVars', 1) Global $hGUI, $hWnd, $hGraphic, $width, $height $width = @DesktopWidth * 0.75 $height = @DesktopHeight * 0.75 Global Const $explosion_step = 6, $explosion_length = ($width + $height) / 8, $explosion_max_amount = 20, $explosion_max_particle = 20 Global $explosion_coordinate[$explosion_max_particle][6 * $explosion_max_amount] ; on/off, x, y, vx, vy, v Global $explosion_amount = 0 ; Create GUI $hGUI = GUICreate("Explosions (from AUTOITEROIDS) using GDI+ by UEZ 2009!", $width, $height) $hWnd = WinGetHandle($hGUI) _GDIPlus_Startup() Global $graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd) Global $bitmap = _GDIPlus_BitmapCreateFromGraphics($width, $height, $graphics) Global $backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap) _GDIPlus_GraphicsClear($backbuffer) _GDIPlus_GraphicsSetSmoothingMode($backbuffer, 4) Global $pen_size = 1 Global $pen_color = 0xAFFF8070 Global $pen = _GDIPlus_PenCreate($pen_color, $pen_size) GUISetState() Do _GDIPlus_GraphicsClear($backbuffer, 0x9A000000) If Mod(Random(1, 10, 1), 9) >= 5 Then ; Explosion_Init(Random(50, $width - 50, 1), Random(50, $height - 50, 1)) EndIf Explosion() _GDIPlus_GraphicsDrawImageRect($graphics, $bitmap, 0, 0, $width, $height) Until Not Sleep(30) Or GUIGetMsg() = $GUI_EVENT_CLOSE ; Clean up resources _GDIPlus_PenDispose($pen) _GDIPlus_BitmapDispose($bitmap) _GDIPlus_GraphicsDispose($graphics) _GDIPlus_GraphicsDispose($backbuffer) _GDIPlus_Shutdown() Func Explosion_Init($ex, $ey) ;initialise explosion For $o = 0 To $explosion_step * ($explosion_max_amount - 1) Step $explosion_step ;fill array with coordinate of hit object If $explosion_coordinate[0][$o] <> 1 Then $explosion_coordinate[0][$o] = 1 $explosion_coordinate[0][$o + 1] = $ex ;save x coordinate $explosion_coordinate[0][$o + 2] = $ey ;save x coordinate For $n = 0 To $explosion_max_particle - 1 $explosion_coordinate[$n][$o + 1] = $explosion_coordinate[0][$o + 1] ;duplicate x start position of all explosion particles $explosion_coordinate[$n][$o + 2] = $explosion_coordinate[0][$o + 2] ;duplicate y start position of all explosion particles $explosion_coordinate[$n][$o + 3] = _Random(-7, 7, 1) ;create random x vector (explosion particle speed) $explosion_coordinate[$n][$o + 4] = _Random(-7, 7, 1) ;create random y vector (explosion particle speed) $explosion_coordinate[$n][$o + 5] = Abs($explosion_coordinate[$n][3 + $o]) + Abs($explosion_coordinate[$n][4 + $o]) ;add absolute distance of vectors x and y Next ExitLoop EndIf Next EndFunc ;==>Explosion_Init Func Explosion() ;draw explosions coordinates Local $q, $k $explosion_amount = 0 For $k = 0 To $explosion_step * ($explosion_max_amount - 1) Step $explosion_step If $explosion_coordinate[0][$k] = 1 Then ;only draw active explosions $explosion_amount += 1 For $q = 0 To $explosion_max_particle - 1 $explosion_coordinate[$q][$k + 1] += $explosion_coordinate[$q][$k + 3] ;draw new x coordinate of a particle $explosion_coordinate[$q][$k + 2] += $explosion_coordinate[$q][$k + 4] ;draw new y coordinate of a particle $explosion_coordinate[$q][$k + 5] += Abs($explosion_coordinate[$q][$k + 3]) + Abs($explosion_coordinate[$q][$k + 4]) If $explosion_coordinate[$q][$k + 5] <= $explosion_length Then ;draw until max. distance has been reached _GDIPlus_GraphicsDrawEllipse($backbuffer, $explosion_coordinate[$q][$k + 1], $explosion_coordinate[$q][$k + 2], 2, 2, $pen) Else ;when max. distance has been reached then set x vector and y vector to 0 $explosion_coordinate[0][$k] = 0 EndIf Next EndIf Next ConsoleWrite($explosion_amount & @CRLF) EndFunc ;==>Explosion Func _Random($w1, $w2, $w3 = 0) ;just to avoid 0 as random number Local $x = 0, $l1 = 0.50 While $x = 0 $x = Random($w1, $w2, $w3) If $x < $l1 And $x >= 0 Then $x += $l1 If $x > -$l1 And $x <= 0 Then $x -= $l1 WEnd Return $x EndFunc ;==>_RandomIf I'm using _GDIPlus_GraphicsClear($backbuffer, 0xFF000000) is running as expected!Further, if it is extremly slow and you click (lmb) and hold it pressed on another window then it is running properly until you release the lmb again!Is this a bug?I discovered it coincidentally on my desktop pc (WinXP SP3). It is working properly on my both notebooks (Vista SP2 x32)!I cannot see the reason why it is working properly on some machines and on the others not!Thanks,UEZ Edited June 27, 2009 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
cppman Posted June 27, 2009 Share Posted June 27, 2009 (edited) First of all, GDI+ is not hardware accelerated, so everything is done on the CPU. I'm going to make an assumption here and say that it is slow simply because when you have the alpha channel below 255, you're "enabling" alpha blending. Since this isn't hardware accelerated, the CPU has to go through each pixel and perform an equation (on each pixel) to get the right color.Edit: try running it on a Vista+ desktop. This should also run just fine. Vista+ is based on Direct3D, so GDI+ will indirectly be hardware accelerated.Edit: just tested it on a Vista desktop and it works just fine. However, on XP or lower it is very slow - so, my theory stands. Edited July 10, 2009 by cppman Miva OS Project Link to comment Share on other sites More sharing options...
UEZ Posted June 27, 2009 Author Share Posted June 27, 2009 (edited) First of all, GDI+ is not hardware accelerated, so everything is done on the CPU. I'm going to make an assumption here and say that it is slow simply because when you have the alpha channel below 255, you're "enabling" alpha blending. Since this isn't hardware accelerated, the CPU has to go through each pixel and perform an equation (on each pixel) to get the right color.Edit: try running it on a Vista+ desktop. This should also run just fine. Vista+ is based on Direct3D, so GDI+ will indirectly be hardware accelerated.Edit: just tested it on a Vista desktop and it works just fine. However, on XP or lower it is very slow - so, my theory stands. Why it is working properly on WinXP when you click and hold lmb on a different window?Maybe it is a problem with gdi+ dll on WinXP!?!UEZ Edited June 27, 2009 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
cppman Posted June 27, 2009 Share Posted June 27, 2009 Why it is working properly on WinXP when you click and hold lmb on a different window?Maybe it is a problem with gdi+ dll on WinXP!?!UEZThat's odd. Maybe it's something about how Windows works prior to Vista. Other than that, I have no clue. Miva OS Project Link to comment Share on other sites More sharing options...
UEZ Posted July 3, 2009 Author Share Posted July 3, 2009 (edited) It seems to be a problem with _GDIPlus_GraphicsDrawImageRect() when alpha channel is < 0xff on WinXP (in a vm it worked properly!) because when I use this method it is working properly!expandcollapse popup#include <GuiConstantsEx.au3> ;Coded by UEZ 2009 #AutoIt3Wrapper_Run_Obfuscator=y #Obfuscator_Parameters=/sf /sv /om /cs=0 /cn=0 #AutoIt3Wrapper_Res_SaveSource=n #AutoIt3Wrapper_UseUpx=n ;~ #AutoIt3Wrapper_Run_After=upx.exe --best "%out%" #AutoIt3Wrapper_Run_After=upx.exe --ultra-brute "%out%" #AutoIt3Wrapper_Run_After=del /f /q "Particle Explosions (from AUTOITEROIDS) old_Obfuscated.au3" #include <GuiConstantsEx.au3> #include <GDIPlus.au3> #include <Array.au3> Opt('MustDeclareVars', 1) Opt("GUIOnEventMode", 1) Global $fps = 0, $fps_diff, $fps_maintimer, $fps_timer Global $hWnd, $hGraphic, $width, $height, $win_title = "GDI+: Particle Explosions (from AUTOITEROIDS modified) by UEZ 2009!" $width = @DesktopWidth * 0.75 $height = @DesktopHeight * 0.75 Global Const $explosion_step = 8, $explosion_length = ($width + $height) / 7, $explosion_max_amount = 20, $explosion_max_particle = 15 Global $explosion_coordinate[$explosion_max_particle][$explosion_step * $explosion_max_amount] ; on/off, x, y, vx, vy, v, brush, color Global $explosion_amount = 0 ; Create GUI $hWnd = GUICreate($win_title, $width, $height) WinSetTrans($hWnd,"", 255); workaround for WinXP machines _GDIPlus_Startup() Global $graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd) Global $bitmap = _GDIPlus_BitmapCreateFromGraphics($width, $height, $graphics) Global $backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap) _GDIPlus_GraphicsClear($backbuffer) _GDIPlus_GraphicsSetSmoothingMode($backbuffer, 2) ;~ Global $pen_size = 1 ;~ Global $pen_color = 0xAFFF8070 ;~ Global $pen = _GDIPlus_PenCreate($pen_color, $pen_size) Global $brush_color Global $x_min = $explosion_length * 0.75, $x_max = $width - $x_min, $y_min = $explosion_length * 0.75, $y_max = $height - $y_min For $o = 0 To $explosion_step * ($explosion_max_amount - 1) Step $explosion_step $brush_color = 0; 0xFF000000 + Random(0x400000, 0xFFFFFF, 1) For $n = 0 To $explosion_max_particle - 1 ;~ $brush_color = 0; 0xFF000000 + Random(0x400000, 0xFFFFFF, 1) $explosion_coordinate[$n][$o + 6] = _GDIPlus_BrushCreateSolid($brush_color) Next Next GUISetState() GUISetOnEvent($GUI_EVENT_CLOSE, "Close") $fps_maintimer = TimerInit() Do $fps_timer = TimerInit() _GDIPlus_GraphicsClear($backbuffer, 0xA0000000) If Mod(Random(1, 10, 1), 9) >= 4 Then Explosion_Init(Random($x_min, $x_max, 1), Random($y_min, $y_max, 1)) EndIf Explosion() _GDIPlus_GraphicsDrawImageRect($graphics, $bitmap, 0, 0, $width, $height) $fps_diff = TimerDiff($fps_timer) If TimerDiff($fps_maintimer) > 1000 Then $fps = Round(1000 / $fps_diff, 2) $fps_maintimer = TimerInit() EndIf WinSetTitle($hwnd, "", $win_title & " (fps: " & $fps & @TAB & ", #explosions: " & $explosion_amount & @TAB & ", #particles: " & $explosion_amount * $explosion_max_particle & ")") Until Not Sleep(20) Func Close() ; Clean up resources For $o = 0 To $explosion_step * ($explosion_max_amount - 1) Step $explosion_step For $n = 0 To $explosion_max_particle - 1 _GDIPlus_BrushDispose($explosion_coordinate[$n][$o + 6]) Next Next ;~ _GDIPlus_PenDispose($pen) _GDIPlus_BitmapDispose($bitmap) _GDIPlus_GraphicsDispose($graphics) _GDIPlus_GraphicsDispose($backbuffer) _GDIPlus_Shutdown() WinClose($hwnd) Exit EndFunc Func Explosion_Init($ex, $ey) ;initialise explosion For $o = 0 To $explosion_step * ($explosion_max_amount - 1) Step $explosion_step ;fill array with coordinate of hit object If $explosion_coordinate[0][$o] <> 1 Then $explosion_coordinate[0][$o] = 1 $explosion_coordinate[0][$o + 1] = $ex ;save x coordinate $explosion_coordinate[0][$o + 2] = $ey ;save y coordinate $brush_color = 0xFF000000 + Random(0xF0F0F0, 0xFFFFFF, 1) For $n = 0 To $explosion_max_particle - 1 $explosion_coordinate[$n][$o + 1] = $explosion_coordinate[0][$o + 1] ;duplicate x start position of all explosion particles $explosion_coordinate[$n][$o + 2] = $explosion_coordinate[0][$o + 2] ;duplicate y start position of all explosion particles $explosion_coordinate[$n][$o + 3] = _Random(-7, 7, 1) ;create random x vector (explosion particle speed) $explosion_coordinate[$n][$o + 4] = _Random(-7, 7, 1) ;create random y vector (explosion particle speed) $explosion_coordinate[$n][$o + 5] = Abs($explosion_coordinate[$n][3 + $o]) + Abs($explosion_coordinate[$n][4 + $o]) ;add absolute distance of vectors x and y ;~ $brush_color = 0xFF000000 + Random(0xF0F0F0, 0xFFFFFF, 1) ;each particle gets another color $explosion_coordinate[$n][$o + 7] = $brush_color _GDIPlus_BrushSetSolidColor($explosion_coordinate[$n][$o + 6], $explosion_coordinate[$n][$o + 7]) Next ExitLoop EndIf Next EndFunc ;==>Explosion_Init Func Explosion() ;draw explosions coordinates Local $q, $k, $r, $g, $b $explosion_amount = 0 For $k = 0 To $explosion_step * ($explosion_max_amount - 1) Step $explosion_step If $explosion_coordinate[0][$k] = 1 Then ;only draw active explosions $explosion_amount += 1 For $q = 0 To $explosion_max_particle - 1 $explosion_coordinate[$q][$k + 1] += $explosion_coordinate[$q][$k + 3] ;draw new x coordinate of a particle $explosion_coordinate[$q][$k + 2] += $explosion_coordinate[$q][$k + 4] ;draw new y coordinate of a particle $explosion_coordinate[$q][$k + 5] += Abs($explosion_coordinate[$q][$k + 3]) + Abs($explosion_coordinate[$q][$k + 4]) ;absolute vector length If $explosion_coordinate[$q][$k + 5] <= $explosion_length Then ;draw until max. distance has been reached ;~ _GDIPlus_GraphicsDrawEllipse($backbuffer, $explosion_coordinate[$q][$k + 1], $explosion_coordinate[$q][$k + 2], 2, 2, $pen) _GDIPlus_GraphicsFillEllipse($backbuffer, $explosion_coordinate[$q][$k + 1], $explosion_coordinate[$q][$k + 2], 3, 3, $explosion_coordinate[$q][$k + 6]) ;fade out colors $r = BitAND($explosion_coordinate[$q][$k + 7], 0x00FF0000) / 0x10000 * 0.91 ;decrease red channel $g = BitAND($explosion_coordinate[$q][$k + 7], 0x0000FF00) / 0x100 * 0.91 ;decrease green channel $b = BitAND($explosion_coordinate[$q][$k + 7], 0x000000FF) * 0.91 ;decrease blue channel $explosion_coordinate[$q][$k + 7] = "0xFF" & Hex($r, 2) & Hex($g, 2) & Hex($b, 2) _GDIPlus_BrushSetSolidColor($explosion_coordinate[$q][$k + 6], $explosion_coordinate[$q][$k + 7]) ;set new color Else ;when max. distance has been reached then set x vector and y vector to 0 $explosion_coordinate[0][$k] = 0 EndIf Next EndIf Next EndFunc ;==>Explosion Func _Random($w1, $w2, $w3 = 0) ;just to avoid 0 as random number Local $x = 0, $l1 = 0.50 While $x = 0 $x = Random($w1, $w2, $w3) If $x < $l1 And $x >= 0 Then $x += $l1 If $x > -$l1 And $x <= 0 Then $x -= $l1 WEnd Return $x EndFunc ;==>_RandomI have no idea why! UEZEdit: seems to be working because value for alpha channel in function _GDIPlus_GraphicsClear() is not working or I made a mistake Edit2: a workaround seems to be to use WinSetTrans(). Thanks to eukalyptus for the hint Edited February 22, 2010 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now