Schlechte GDI+ Performance auf WinXP

  • Das ganze nun bunt! :P

    Wenn jeder Pixel bunt sein soll, dann einfach Zeile 87 auskommentieren und entsprechend Zeile 94 aktivieren!


    Gruß,
    UEZ

    PS: In Zeile 47 _GDIPlus_GraphicsClear($backbuffer, 0xA0000000) auf _GDIPlus_GraphicsClear($backbuffer, 0xFF000000) setzen oder den Workaround von Bitboy anwenden, falls das oben beschriebene Problem auftritt!

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    Einmal editiert, zuletzt von UEZ (1. Juli 2009 um 11:32)

  • Ich glaube, dass ganze hängt an nicht am Alpha Channel, sondern eher an _GDIPlus_GraphicsDrawImageRect($graphics, $bitmap, 0, 0, $width, $height)!

    Ich habe mal eine andere Variante benutzt und es funzt ohne Probleme, auch mit aktivem Alpha Channel -> _GDIPlus_GraphicsClear($backbuffer, 0x9A000000)

    Keine Ahnung, warum GDIPlus_GraphicsDrawImageRect($graphics, $bitmap, 0, 0, $width, $height) auf WinXP Kisten Probleme bereitet!

    Gruß,
    UEZ

    PS: mmmhhhh, es sieht so aus, als ob kein Alpha Channel mit der neuen Methode möglich ist! :huh: , denn wenn der Wert für den Alpha Channel sich ändert, dann passiert nichts! :thumbdown: Und ich habe mich gefreut einen Workaround gefunden zu haben :(

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    2 Mal editiert, zuletzt von UEZ (3. Juli 2009 um 22:20)

  • Also, mit der neueren Treiberversion 6.14.11.8618 (10.06.2009) funzt jetzt auch unter WinXP!

    Scheint wohl ein Treiberproblem gewesen zu sein; wollte ich nur mal erwähnen!

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Ich hab da was ganz seltsames entdeckt!

    Und zwar, wenn man vor _GDIPlus_GraphicsCreateFromHWND die Zeile

    [autoit]

    WinSetTrans($hWnd,"",255)

    [/autoit]

    einfügt, dann läuft das Script auch unter WinXP flüssig

    UEZ´s Script aus dem ersten Post:

    Spoiler anzeigen
    [autoit]

    #AutoIt3Wrapper_Run_Obfuscator=y
    #Obfuscator_Parameters=/so
    #AutoIt3Wrapper_Res_SaveSource=n
    #AutoIt3Wrapper_UseUpx=n
    #AutoIt3Wrapper_Run_After=upx.exe --best "%out%"
    #AutoIt3Wrapper_Run_After=del /f /q "Explosions (from AutoIteroids)_Obfuscated.au3"
    #include <GuiConstantsEx.au3>
    #include <GDIPlus.au3>
    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    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)
    WinSetTrans($hWnd,"",255)
    _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()

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    ; Clean up resources
    _GDIPlus_PenDispose($pen)
    _GDIPlus_BitmapDispose($bitmap)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_GraphicsDispose($backbuffer)
    _GDIPlus_Shutdown()

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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 ;==>_Random

    [/autoit] [autoit][/autoit] [autoit][/autoit]

    Drehende Dreiecke von H2112:

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Opt("GUIOnEventMode", 1); Setzt das Script in den OnEventModus

    [/autoit] [autoit][/autoit] [autoit]

    Global $hGraphic, $bitmap, $backbuffer, $Pen, $brush
    Global $rotation1 = 0, $rotation2 = 0, $rotation3 = 0, $rotation4 = 0, $rotation5 = 0
    Global $Pi = 3.14159

    [/autoit] [autoit][/autoit] [autoit]

    $hwnd = GUICreate("GDI+ Beispiel: Drehende Dreiecke", 450, 450, -1, -1); Erstellt ein Fenster
    GUISetBkColor(0x000000); Setzt die Hintergrundfarbe der GUI auf schwarz
    GUISetOnEvent(-3, "_Close"); Die Funktion '_Close' wird ausgeführt, wenn das Fenster geschlossen wird
    GUISetState(@SW_SHOW, $hwnd); Macht das Fenster sichtbar
    WinSetTrans($hwnd,"",255)

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_Startup(); Ladet die GDI+ dll
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hwnd) ; Erstelle GDI+ Objekt von der GUI (Grafik)
    $bitmap = _GDIPlus_BitmapCreateFromGraphics(450, 450, $hGraphic) ; Erstelle Bitmap von der Grafik
    $backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap) ; Erstelle Grafik Kontext von der Bitmap (dient für die Doppeltbufferung der Grafik, damit die Bewegungen flüssiger aussehen
    $pen = _GDIPlus_PenCreate(0, 1) ; Erstelle Stift mit der Stärke 1 Pixels
    _GDIPlus_PenSetColor($Pen, 0xFF00FF00) ; Setze Stiftfarbe
    $brush = _GDIPlus_BrushCreateSolid(0x10000000); Erstellt ein vollfarbiges Pinselobjekt

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    _GDIPlus_GraphicsFillRect($backbuffer, 0, 0, 450, 450, $brush); Überzeichnet den Buffer mit einem transparentem schwarz
    ; Ab hier werden die Dreiecke im Buffer gezeichnet und berechnet
    $rotation1 += $Pi / 200
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation1 + $Pi / 2) * 200 + 450 / 2, Sin($rotation1 + $Pi / 2) * 200 + 450 / 2, Cos($rotation1 + $Pi / 2 + (2 * $Pi) / 3) * 200 + 450 / 2, Sin($rotation1 + $Pi / 2 + (2 * $Pi) / 3) * 200 + 450 / 2, $pen)
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation1 + $Pi / 2 + (2 * $Pi) / 3) * 200 + 450 / 2, Sin($rotation1 + $Pi / 2 + (2 * $Pi) / 3) * 200 + 450 / 2, Cos($rotation1 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 200 + 450 / 2, Sin($rotation1 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 200 + 450 / 2, $pen)
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation1 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 200 + 450 / 2, Sin($rotation1 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 200 + 450 / 2, Cos($rotation1 + $Pi / 2) * 200 + 450 / 2, Sin($rotation1 + $Pi / 2) * 200 + 450 / 2, $pen)
    $rotation2 -= $Pi / 100
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation2 + $Pi / 2) * 100 + 450 / 2, Sin($rotation2 + $Pi / 2) * 100 + 450 / 2, Cos($rotation2 + $Pi / 2 + (2 * $Pi) / 3) * 100 + 450 / 2, Sin($rotation2 + $Pi / 2 + (2 * $Pi) / 3) * 100 + 450 / 2, $pen)
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation2 + $Pi / 2 + (2 * $Pi) / 3) * 100 + 450 / 2, Sin($rotation2 + $Pi / 2 + (2 * $Pi) / 3) * 100 + 450 / 2, Cos($rotation2 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 100 + 450 / 2, Sin($rotation2 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 100 + 450 / 2, $pen)
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation2 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 100 + 450 / 2, Sin($rotation2 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 100 + 450 / 2, Cos($rotation2 + $Pi / 2) * 100 + 450 / 2, Sin($rotation2 + $Pi / 2) * 100 + 450 / 2, $pen)
    $rotation3 += $Pi / 50
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation3 + $Pi / 2) * 50 + 450 / 2, Sin($rotation3 + $Pi / 2) * 50 + 450 / 2, Cos($rotation3 + $Pi / 2 + (2 * $Pi) / 3) * 50 + 450 / 2, Sin($rotation3 + $Pi / 2 + (2 * $Pi) / 3) * 50 + 450 / 2, $pen)
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation3 + $Pi / 2 + (2 * $Pi) / 3) * 50 + 450 / 2, Sin($rotation3 + $Pi / 2 + (2 * $Pi) / 3) * 50 + 450 / 2, Cos($rotation3 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 50 + 450 / 2, Sin($rotation3 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 50 + 450 / 2, $pen)
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation3 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 50 + 450 / 2, Sin($rotation3 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 50 + 450 / 2, Cos($rotation3 + $Pi / 2) * 50 + 450 / 2, Sin($rotation3 + $Pi / 2) * 50 + 450 / 2, $pen)
    $rotation4 -= $Pi / 25
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation4 + $Pi / 2) * 25 + 450 / 2, Sin($rotation4 + $Pi / 2) * 25 + 450 / 2, Cos($rotation4 + $Pi / 2 + (2 * $Pi) / 3) * 25 + 450 / 2, Sin($rotation4 + $Pi / 2 + (2 * $Pi) / 3) * 25 + 450 / 2, $pen)
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation4 + $Pi / 2 + (2 * $Pi) / 3) * 25 + 450 / 2, Sin($rotation4 + $Pi / 2 + (2 * $Pi) / 3) * 25 + 450 / 2, Cos($rotation4 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 25 + 450 / 2, Sin($rotation4 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 25 + 450 / 2, $pen)
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation4 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 25 + 450 / 2, Sin($rotation4 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 25 + 450 / 2, Cos($rotation4 + $Pi / 2) * 25 + 450 / 2, Sin($rotation4 + $Pi / 2) * 25 + 450 / 2, $pen)
    $rotation5 += $Pi / 12.5
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation5 + $Pi / 2) * 12.5 + 450 / 2, Sin($rotation5 + $Pi / 2) * 12.5 + 450 / 2, Cos($rotation5 + $Pi / 2 + (2 * $Pi) / 3) * 12.5 + 450 / 2, Sin($rotation5 + $Pi / 2 + (2 * $Pi) / 3) * 12.5 + 450 / 2, $pen)
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation5 + $Pi / 2 + (2 * $Pi) / 3) * 12.5 + 450 / 2, Sin($rotation5 + $Pi / 2 + (2 * $Pi) / 3) * 12.5 + 450 / 2, Cos($rotation5 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 12.5 + 450 / 2, Sin($rotation5 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 12.5 + 450 / 2, $pen)
    _GDIPlus_GraphicsDrawLine($backbuffer, Cos($rotation5 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 12.5 + 450 / 2, Sin($rotation5 + $Pi / 2 + ((2 * $Pi) / 3) * 2) * 12.5 + 450 / 2, Cos($rotation5 + $Pi / 2) * 12.5 + 450 / 2, Sin($rotation5 + $Pi / 2) * 12.5 + 450 / 2, $pen)
    ; Ende der Zeichnungen und Berechnungen
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $bitmap, 0, 0, 450, 450) ; Das Zeichnen hat im Buffer stattgefunden. Damit das Ganze sichtbar wird, wird das Ganze in die Graphik kopiert
    Sleep(10)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _Close()
    _GDIPlus_BrushDispose($brush); Löst das Pinselobjekt auf
    _GDIPlus_PenDispose($pen); Löst den Pinsel auf
    _GDIPlus_GraphicsDispose($backbuffer); Löst den Buffer auf
    _GDIPlus_BitmapDispose($bitmap); Löst die Bitmap auf
    _GDIPlus_GraphicsDispose($hGraphic); Löst die Graphic auf
    _GDIPlus_Shutdown(); Schließt die GDI+ dll
    WinClose($hwnd); Schließt das Fenster
    Exit; Beendet das Script
    EndFunc

    [/autoit]

    Zum Vergleich einfach WinSetTrans in Zeile 14 bzw. 13 auskommentieren

    Kann das jemand bestätigen?
    Das wäre dann ein richtig einfacher Workaround :thumbup:

    E

  • Werde ich mal heute Abend auf meiner Kiste testen, wobei bei mir das allerdings schon einigermaßen sauber läuft (ab und zu flackert's mal kurz)! In der VM gab es so wie so keine Probleme!

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯