Autor Thema: GUI LowLevel  (Gelesen 30774 mal)

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« am: 27. September 2011, 14:32 »
Ich wollte mich gedanklich mal mit den LowLevel Konzepten einer GUI vertraut machen.

Erstmal was ich unter LowLevel verstehe. Damit meine ich wie was wann gezeichnet wird.

Hat wer dazu ein paar interessante Links/Papers die man lesen kann/sollte?

Ich "kenne" bisher folgende Konzepte:

Es wird direkt ein Bild im Grafikkartenspeicher erzeugt, sprich die einzelnen Programme haben keinen eigenen Buffer (sofern sie sich selbst keinen Anlegen), sondern bekommen von der GUI gesagt das sie doch bitte neuzeichnen sollen und welchen Bereich. Dort sollte doch der Buffer in den sie schreiben, auch mit übergeben werden und nicht so dass das Programm in einen eigenen Buffer schreibt und den dann an die GUI schickt, oder?
Das sollte so die "alte" Variante sein und vorallem die am wenigsten Speicher verbraucht, weil ja immer nur direkt in den Framebuffer geschrieben wird. Allerdings verbraucht dies auch mehr CPU Zeit.

Zu dieser Variante hätte ich gleich mal Fragen.

Ist das die Variante wie sie unter alten GUIs verwendet wurde (z.B. Windows 3.11)? Wenn ja, wie haben die Auflösungen wie 1024x768x32bit hinbekommen? Damit meine ich das wenn man davon ausgeht, dass das gesamte Bild neugezeichnet werden muss und von einem PCI-Bus ausgeht (was ja nicht unbedingt sein musste), wie konnten die 60Hz (FPS) und mehr erreichen? Das geht doch schon aus Bandbreitengründen nicht. Bei einem ISA-Bus und 640x480x32bit sollte das ja eigentlich auch nicht gehen.
Oder wurde früher einfach nur 16bit oder sogar nur 256 Farben verwendet?

Die andere Variante die ich dann kenne, nennt sich wohl Compositing (??).

Dort hat jedes Programm einen Buffer von seinem Fenster(n) und wenn die GUI ein neues Bild zeichnen möchte (und sich etwas in diesem Fenster geändert hat), erstellt das Programm nen neuen Buffer, zeichnet dort rein und schickt den Buffer an die GUI.
Vorteil ist hier das weniger CPU Zeit, aber dafür wesentlich mehr Speicher verbraucht wird.
Soweit richtig?

Was mich jetzt, insbesondere wenn ich dann irgendwann mal ne GUI designen möchte, interessiert, wie kann man dort Theming umsetzen bzw. wie wird es gemacht das jedes Fenster und die Komponenten gleich aussehen?

Ich stelle mir das so vor, dass man OS Libs nutzt um die Fenster und Elemente zu zeichnen und nicht nur in das eigentliche Fenster (ohne Rahmen, Menüleiste und sowas), sondern immer das gesamte Fenster (halt mir Rahmen, Menüleiste und sowas) zeichnet.
Theming würde dann so funktionieren, dass sich die Libs halt die Daten aus irgendwelchen Dateien holen, wie nun die Titelleiste aussehen soll, wie der Rahmen aussehen soll usw.
Ist das auch soweit richtig?

Dann, auch wenn es eigentlich außerhalb dessen liegt was ich je erreichen werde, wie läuft das mit 2D Hardwarebeschleunigung? Soweit ich es verstanden habe, gibt es die nur soweit das man Blitting in irgendeiner Weise hardwarebeschleunigt zur Verfügung hat.
Allerdings entsinne ich mich mal was gelesen zu haben, dass früher auch primitive Objekte (ala Rechteck und sowas) per Grafikkartenbefehl gezeichnet wurden?! Kann es sein, dass so höhere Auflösungen und Bittiefen möglich waren?


Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 27. September 2011, 18:22 »
Ist das die Variante wie sie unter alten GUIs verwendet wurde (z.B. Windows 3.11)? Wenn ja, wie haben die Auflösungen wie 1024x768x32bit hinbekommen?
Grafikkarte entsprechend programmieren. Ganz einfach. :-P

Damit meine ich das wenn man davon ausgeht, dass das gesamte Bild neugezeichnet werden muss und von einem PCI-Bus ausgeht (was ja nicht unbedingt sein musste), wie konnten die 60Hz (FPS) und mehr erreichen? Das geht doch schon aus Bandbreitengründen nicht. Bei einem ISA-Bus und 640x480x32bit sollte das ja eigentlich auch nicht gehen.
Oder wurde früher einfach nur 16bit oder sogar nur 256 Farben verwendet?
Richtig in allen Punkten. Mit einer ISA-Grafikkarte kannst du - selbst wenn du 800x600 in HighColor hinkriegst - keine Vollbildvideos mit 25fps anzeigen, weil du keine 24 MB/s durch den ISA-Bus schaufeln kannst. Bei einfachen PCI-Grafikkarten ist das ähnlich.

Die 60 Hz erzeugt die Grafikkarte selbst aus ihrem Framebuffer. Selbst, wenn der bei dir in den Adressraum gemappt ist, ist das physisch auf der Grafikkarte vorhandener Speicher und der ist schnell genug, um eine gewisse Auflösung, Bildwiederholrate und Farbtiefe anzuzeigen, sonst kann die Grafikkarte den Modus nicht erzeugen. Du kannst halt nicht mit 60 Hz das Bild ändern. Damit es trotzdem hinreichend schnell ist, versucht man, Redraws möglichst zu vermeiden:

Jedes Steuerelement zeichnet sich selbst auf Anforderung neu. Es wird nur neugezeichnet, was vorher verdeckt war (wenn du z.B. ein Fenster in den Vordergrund bringst) und nicht das gesamte Fenster. Beim Verschieben verschiebst du nicht das Fenster, sondern es wird nur ein Rahmen gezeichnet, bis die Endposition feststeht. Videos werden im kleinen Fenster bei niedrigen Bildraten dargestellt. Sowas in der Art halt.

Um Bandbreite zu sparen, kann man dann auf Hardwarebeschleunigung zugreifen, z.B. BitBlit oder Hardware-Overlays (du sendest ein Video z.B. als 320x240 im YUV-Format und die Hardware plottet das auf 640x480 hochskaliert in einen mit Chroma-Keying markierten Bereich). Zu Windows 3.1-Zeiten hatte man üblicherweise nur 640x480@8, mein erster Rechner (Win95, P133) hatte 800x600@16; der eine oder andere Videoplayer konnte je nach Video auch die Auflösung automatisch runterschalten. :-)

Dort hat jedes Programm einen Buffer von seinem Fenster(n) und wenn die GUI ein neues Bild zeichnen möchte (und sich etwas in diesem Fenster geändert hat), erstellt das Programm nen neuen Buffer, zeichnet dort rein und schickt den Buffer an die GUI.
Vorteil ist hier das weniger CPU Zeit, aber dafür wesentlich mehr Speicher verbraucht wird.
Soweit richtig?
Kann man so machen. Ich würde vorschlagen, jedes Fenster kriegt einen eigenen Buffer von der GUI zugeteilt und wenn sich darin etwas geändert hat, wird die GUI über den geänderten Bereich informiert. Wie die das zeichnet, ist für die Anwendung egal (im einfachsten Fall wird dann im Framebuffer der entsprechende Bereich geändert, sofern der Fensterausschnitt überhaupt sichtbar war).

Schnell und CPU-sparsam wird das nur, wenn du genug Grafikspeicher hast, um diese Buffer dort zu lagern (du die also nicht über den Bus schicken musst) und du in der Lage bist, die Grafikkarte die Buffer selbst zeichnen zu lassen, also genug Overlays vorhanden sind. Wirklich gegeben ist das eigentlich nur bei 3D-Beschleunigung, ansonsten hast du meist nur wenige Overlays, die nicht auf jedem Head gleichzeitig sein können und nur komische Farbformate unterstützen. Für das Vordergrundfenster mag es die Trickserei wert sein, ich denke aber eher nicht.

Was mich jetzt, insbesondere wenn ich dann irgendwann mal ne GUI designen möchte, interessiert, wie kann man dort Theming umsetzen bzw. wie wird es gemacht das jedes Fenster und die Komponenten gleich aussehen?
Eine gemeinsame Grafikbibliothek benutzen. Steuerelemente und Dekorationen sind Anwendungssache (es sei denn, du lässt die Titelleiste vom Window Manager zeichnen), die sehen also immer dann unterschiedlich aus, wenn die Anwendungen sie auf verschiedenen Wegen zeichnen. Dagegen kannst du nichts machen. Portier lieber GTK oder Qt, statt ne eigene Lib dafür zu schreiben. Theming unterstützen die auch.

Dann, auch wenn es eigentlich außerhalb dessen liegt was ich je erreichen werde, wie läuft das mit 2D Hardwarebeschleunigung? Soweit ich es verstanden habe, gibt es die nur soweit das man Blitting in irgendeiner Weise hardwarebeschleunigt zur Verfügung hat.
Ja. Neben BitBlit gibt es aber noch Muster, Linien, Kreise, Ellipsen usw. die hardwarebeschleunigt sein können.

Allerdings entsinne ich mich mal was gelesen zu haben, dass früher auch primitive Objekte (ala Rechteck und sowas) per Grafikkartenbefehl gezeichnet wurden?! Kann es sein, dass so höhere Auflösungen und Bittiefen möglich waren?
Nein. Die Objekte müssen in den Grafikspeicher passen, du arbeitest mit Bitmap-basierten Systemen. Vektorgrafik ist schon seeehr lange out. ;-)

Gruß,
Svenska

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 27. September 2011, 19:11 »
Zitat von: svenska
Ich würde vorschlagen, jedes Fenster kriegt einen eigenen Buffer von der GUI zugeteilt und wenn sich darin etwas geändert hat, wird die GUI über den geänderten Bereich informiert.
Ich dachte da, in meiner naiven Art ;), daran asynchron zu zeichen. Soll heißen dass das Programm etwas neu zeichnen möchte und das sagt sie der GUI (mit dem entsprechendem Bereich) und die GUI entscheidet dann ob der Bereich sichtbar ist oder nicht und wenn er sichtbar ist, wird eine Nachricht an die Anwendung geschickt, dass sie einen bestimmten Bereich neu zeichnen soll. Das hätte halt den Vorteil, das wirklich nur gezeichnet wird, wenn das auch nötig ist.
Die Frage ist jetzt, kann das überhaupt so funktionieren?

Zitat von: svenska
Schnell und CPU-sparsam wird das nur, wenn du genug Grafikspeicher hast, um diese Buffer dort zu lagern (du die also nicht über den Bus schicken musst)
Das verstehe ich nicht ganz, da die Anwendung den Buffer ja mit Daten füllen muss, muss ja auf jeden Fall was über den Bus geschickt werden. Zumal gilt nicht noch immer dass das Schreiben in den Grafikspeicher nicht alzu schnell ist, sprich das es sich lohnt bei Doublebuffering einen Buffer (das fertige Bild) im Systemspeicher zu haben und diesen Buffer dann per BitBlt (oder halt kopieren) an die Grafikkarte zu schicken?

Zitat von: svenska
Steuerelemente und Dekorationen sind Anwendungssache
Naja, ich dachte da dann schon an eine Lib die so die Standardsteuerelemente (was meinst du mit Dekorationen?) beinhaltet.

Zitat von: svenska
(es sei denn, du lässt die Titelleiste vom Window Manager zeichnen)
Soll heißen, die Anwendung "sieht" die Titelleiste gar nicht in ihrem Buffer? Mal davon abgesehen, das ich die Idee verlockend finde (würde das was mir vorschwebt bestimmt einfacher machen), wie wird dort dann Theming umgesetzt, da das ja dann an zwei unterschiedlichen Stellen stattfinden müsste?

Zitat von: svenska
Neben BitBlit gibt es aber noch Muster, Linien, Kreise, Ellipsen usw. die hardwarebeschleunigt sein können.
Das war eigentlich das was ich meinte, mit das man der Grafikkarte sagen konnte, das man ein Rechteck zeichnen möchte.

Wie verhält es sich eigentlich mit FreeForm Windows und dem Feststellen was neu gezeichnet werden muss? Da kann ich ja schlecht nen Recheck für nehmen und jedes Mal zeichnen lassen (wenn man jetzt mal davon ausgeht, das es keine Buffer pro Fenster gibt) nur um festzustellen dass das Fenster dort nix zeichnet, ist ja auch doof. Geht das nur halbwegs effektiv mit nem Buffer pro Fenster (so dass man nen Farbwert festlegt, wo dann kein Zeichenbereich ist)?

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 27. September 2011, 19:52 »
Unter Windows greifen Anwendungen in der Regel nicht direkt auf den Buffer zu, sondern nutzen einen sogenannten Device Context. Das ist im Prinzip nur ein Handle, das die Zeichenfläche identifiziert. Man kann auch einen Device Context für das Fenster inklusive Titelleiste, Menu und Rahmen oder sogar den gesamten Bildschirm anfordern.

Ich dachte da, in meiner naiven Art ;), daran asynchron zu zeichen. Soll heißen dass das Programm etwas neu zeichnen möchte und das sagt sie der GUI (mit dem entsprechendem Bereich) und die GUI entscheidet dann ob der Bereich sichtbar ist oder nicht und wenn er sichtbar ist, wird eine Nachricht an die Anwendung geschickt, dass sie einen bestimmten Bereich neu zeichnen soll. Das hätte halt den Vorteil, das wirklich nur gezeichnet wird, wenn das auch nötig ist.
Die Frage ist jetzt, kann das überhaupt so funktionieren?

Funktioniert unter Windows mehr oder weniger so, wie du beschrieben hast. Die Anwendung ruft z.B. die Methode InvalidateRect auf, um anzukündigen, das sie was neuzeichnen will. Das System schickt dann eine Nachricht (WM_PAINT) an die Anwendung. Bei der Verarbeitung fordert die Anwendung den Device Context (mit BeginPaint) an und nutzt ihn um zu Zeichnen. Die Anwendung setzt dann eine Reihe von Operationen auf dem Device Context ab (BitBlt, Rectangle, etc ...) Die Begrenzung auf den sichtbaren Bereich wird mit Hilfe des Device Contexts realisiert, der die entsprechenden Informationen enthält. Der Grafiktreiber hat dann die Möglichkeit nach Abschluss der Zeichenoperation (EndPaint) die einzelnen Befehle zu optimieren und in der Hardware zu beschleunigen.

Zitat von: svenska
(es sei denn, du lässt die Titelleiste vom Window Manager zeichnen)
Soll heißen, die Anwendung "sieht" die Titelleiste gar nicht in ihrem Buffer? Mal davon abgesehen, das ich die Idee verlockend finde (würde das was mir vorschwebt bestimmt einfacher machen), wie wird dort dann Theming umgesetzt, da das ja dann an zwei unterschiedlichen Stellen stattfinden müsste?
Für den Fall, dass der Window Manager das nicht macht: Unter Windows wird der Anwendung eine andere Nachricht (WM_NCPAINT, NC = Non-Client Area) geschickt, wenn der Rahmen, usw. neugezeichnet werden muss. Die Anwendung kann dann einen anderen Device Context anfordern, mit dem sie außer halb des Fensters rummalen kann.
Dieser Text wird unter jedem Beitrag angezeigt.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 27. September 2011, 20:24 »
Zitat von: porkchicken
Funktioniert unter Windows mehr oder weniger so, wie du beschrieben hast. ...
Interessant das es unter Windows so gemacht wird, nur wird es dann nicht wirklich asynchron umgesetzt. Denn wenn eine Anwendung durch irgendeinen CPU intensiven Prozess blockiert ist, wird die GUI nicht neu gezeichnet und nimmt auch keine Befehle mehr entgegen. Das wollte ich halt voneinander trennen, so dass sowas nicht passieren kann.

Zitat von: porkchicken
Unter Windows wird der Anwendung eine andere Nachricht (WM_NCPAINT, NC = Non-Client Area) geschickt, wenn der Rahmen, usw. neugezeichnet werden muss. Die Anwendung kann dann einen anderen Device Context anfordern, mit dem sie außer halb des Fensters rummalen kann.
Also ich würde das nicht so zulassen. Wenn die Anwendung wirklich alles (inkl. Titelleiste und Rahmen) selbst zeichnen will, dann sollte sie das schon von Anfang an wissen und dem entsprechend ein Fenster ohne Titelleiste und Rahmen erzeugen.

Welchen Grund hat ein Programm außerhalb des eigenen Fensters zu zeichnen?

Das man unter Windows einen Device Context anfordern muss (was ich jetzt mal mit nem Buffer gleichsetze) wäre in meinem Design auch von Vorteil. Ich überlege nämlich noch, ob ich einmal die Variante des direkten Schreibens in den Framebuffer und des jedes Fenster seinen eigenen Buffer hat unterstütze, so dass auf Systemen mit zu wenig Speicher (keine Ahnung woran ich das dann festmachen würde) die GUI trotzdem laufen würde. Ist wie mit dem Caching, wenn genug Speicher vorhanden ist wird dieser fürs Caching genutzt.
Dadurch dass das Fenster nen Buffer vom GUI bekommt, merkt das Fenster den Unterschied auch gar nicht.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 27. September 2011, 20:36 »
Interessant das es unter Windows so gemacht wird, nur wird es dann nicht wirklich asynchron umgesetzt.
Es ist auch möglich außerhalb dieser WM_PAINT-Nachricht zu zeichnen.

Also ich würde das nicht so zulassen. Wenn die Anwendung wirklich alles (inkl. Titelleiste und Rahmen) selbst zeichnen will, dann sollte sie das schon von Anfang an wissen und dem entsprechend ein Fenster ohne Titelleiste und Rahmen erzeugen.
Im Prinzip ist das auch so. Die Zeichenfläche ist begrenzt, und wird von der Anwendung vor dem Zeichnen festgelegt. Nur besteht die Möglichkeit das zur Laufzeit zu ändern.
« Letzte Änderung: 27. September 2011, 20:42 von PorkChicken »
Dieser Text wird unter jedem Beitrag angezeigt.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 27. September 2011, 23:37 »
Zitat von: svenska
Schnell und CPU-sparsam wird das nur, wenn du genug Grafikspeicher hast, um diese Buffer dort zu lagern (du die also nicht über den Bus schicken musst)
Das verstehe ich nicht ganz, da die Anwendung den Buffer ja mit Daten füllen muss, muss ja auf jeden Fall was über den Bus geschickt werden. Zumal gilt nicht noch immer dass das Schreiben in den Grafikspeicher nicht alzu schnell ist, sprich das es sich lohnt bei Doublebuffering einen Buffer (das fertige Bild) im Systemspeicher zu haben und diesen Buffer dann per BitBlt (oder halt kopieren) an die Grafikkarte zu schicken?
Du verwürfelst da zwei Dinge. Wenn ich das gesamte Fenster in einem eigenen, vorgerenderten Buffer in der Grafikkarte lagere, dann brauche ich für die Zusammenstellung des Desktops nur noch Befehle in der Art "dieses Teilrechteck an folgende Position", muss die Fensterdaten selbst also nicht mehr übertragen. Und auch wenn die Anwendung etwas ändern will, muss sie nur die Änderungen in die Grafikkarte kopieren, nicht das gesamte Fenster.

Das zweite ist, dass ein Zugriff auf den Grafikspeicher nicht besonders teuer ist, weil du den ja eh machen musst. Wenn du aber nur einen einzigen Bildschirm im Grafikspeicher lagern kannst (z.B. weil nur 4 MB Grafikspeicher), dann musst du für jedes Pixel, was du ändern möchtest, den alten Pixelwert lesen, ihn ändern, neu in die Grafikkarte kopieren. Das ist langsam. Wenn du aber jedes Fenster unabhängig vom Bildschirminhalt schon in der Grafikkarte hast, stört das nicht - die Anwendung kann ihren Fensterinhalt selbst reproduzieren und das "Compositing" braucht die fertigen Buffer nur (Hardwarebeschleunigt) übereinander zeichnen. Die Daten müssen dazu nicht durch die CPU.

quote="svenska"]Steuerelemente und Dekorationen sind Anwendungssache
Naja, ich dachte da dann schon an eine Lib die so die Standardsteuerelemente (was meinst du mit Dekorationen?) beinhaltet.[/quote]Dekoration sind Titelleiste, Schließen-Knopf, Systemmenü und sowas. Wenn eine Anwendung fürs Fensterzeichnen eine Lib benutzt, dann tut das nicht das GUI-System. Darum "Anwendungssache".

Soll heißen, die Anwendung "sieht" die Titelleiste gar nicht in ihrem Buffer? Mal davon abgesehen, das ich die Idee verlockend finde (würde das was mir vorschwebt bestimmt einfacher machen), wie wird dort dann Theming umgesetzt, da das ja dann an zwei unterschiedlichen Stellen stattfinden müsste?
Ist ne Designfrage. Beide Ansätze sind möglich. Und ja, du hättest Theming dann einmal in der Lib und einmal im Window Manager.

Wie verhält es sich eigentlich mit FreeForm Windows und dem Feststellen was neu gezeichnet werden muss?
Keine Ahnung. Ich würde sowas als Rechteck mit Transparenz betrachten. Da, wo das Fenster durchsichtig ist, muss ich nur neuzeichnen, wenn ich das Fenster gerade verschoben habe.

Geht das nur halbwegs effektiv mit nem Buffer pro Fenster (so dass man nen Farbwert festlegt, wo dann kein Zeichenbereich ist)?
Vierter Farbwert "Transparenz". Geht aber nur, wenn die Grafikkarte das unterstützt, bei 4/8/16/24 Bit Farbtiefe garnicht; du müsstest also Double-Buffering betreiben. (Solltest du ohnehin, wenn du nichts hardwarebeschleunigst. Aber nicht jedesmal den ganzen Framebuffer übertragen, sondern nur den Teil, der sich geändert hat.)

Interessant das es unter Windows so gemacht wird, nur wird es dann nicht wirklich asynchron umgesetzt. Denn wenn eine Anwendung durch irgendeinen CPU intensiven Prozess blockiert ist, wird die GUI nicht neu gezeichnet und nimmt auch keine Befehle mehr entgegen. Das wollte ich halt voneinander trennen, so dass sowas nicht passieren kann.
Der einfachste Fall ist, dass dein GUI-System von jedem Fenster einen Snapshot hat und wenn das Programm nicht antwortet, wird einfach der gezeichnet (Windows neuer als XP kann das).

Bei Wayland geht die Diskussion dahin, dass eine Anwendung das Rechteck angeben kann, wo der "Schließen"-Knopf im Fenster ist (i.d.R. in der Titelleiste rechts), damit Wayland auch bei nicht reagierender Anwendung herausfinden kann, dass der Anwender die Anwendung killen möchte. Viel mehr kannst du nicht garantieren, wenn du das Zeichnen der Anwendung selbst überlässt. Die Alternative - indirektes Rendering - ist nicht schön.

Welchen Grund hat ein Programm außerhalb des eigenen Fensters zu zeichnen?
Das hängt von der Definition der des Nullpunkts ab. Bei OS/2 ist er unten links, bei Windows und X11 ist er oben links unterhalb der Titelleiste. Die befindet sich dann außerhalb des Fensters, kann aber vom Programm selbst gezeichnet werden (wobei niemand ein Programm daran hindert, die Titelleiste "in" das Programm zu zeichnen).

Gruß,
Svenska

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 28. September 2011, 20:07 »
Hallo,


also mir persönlich gefällt das Konzept wo die Anwendung dazu aufgefordert wird Teile oder alles ihrer Fenster neu zu zeichnen absolut gar nicht. Ich finde es sehr viel besser wenn die Anwendung einfach immer dann wenn sie der Meinung ist das tun zu müssen ihren Fensterinhalt aktualisiert. Das kann asynchron (also ohne ein Kopplung an bestimmte Frames) geschehen oder auch synchron (also mit Kopplung an bestimmte Frames), letzteres ist z.B. für einen Video-Player von Interesse, der könnte einfach schon mal die nächsten 20 Bilder komplett im RAM entpacken und dann der GUI sagen zu welchen Zeitpunkten welches Bild sichtbar sein soll (das würde sogar funktionieren wenn die Bildwiederholrate des Videos nicht mit der Bildwiederholrate des Monitors übereinstimmt, es kommt dann eben nur zu leichtem Jitter wenn es da nicht zumindest ein glattes Verhältnis gibt). Der einzigste Nachteil dieser Methode ist der erhebliche Speicherverbrauch weil ja alle Fenster komplett vorliegen müssen, selbst wenn sie gar nicht sichtbar sind, nur bei verkleinerten Fenstern (also in die Task-Leiste zugeklappt) würde ich da eventuell ne Ausnahme machen und dann bei "wiederherstellen" eben auch die Anwendung antriggern. Es wäre aber auch eine Option selbst die Fenster immer komplett zu haben, auf diese Art wäre die GUI niemals von den Anwendungen abhängig und der User könnte alle Fenster nach belieben verschieben oder in die Task-Leiste zuklappen. Nur wenn die sichtbare Größe des Fensters verändert wird ist eine Reaktion der Anwendung erforderlich aber auch hier könnte die GUI erst mal einfach mit irgendeiner Default-Farbe vorbelegen und irgendwann füllt die Anwendung das dann mit echtem Inhalt (oder eben auch nicht, aber die GUI bliebe trotzdem voll funktionsfähig).

Die Fenster-Dekoration, sowas wie der anfassbare Rahmen oder die Titel-Leiste, sollte aber normalerweise schon von der GUI kommen (dann ist die Fläche für die die Anwendung selber zuständig ist ein wenig kleiner als die Fläche die vom Fenster insgesamt belegt wird und die Anwandung kann auch nur innerhalb des Fester-Innerem frei zeichnen, die GUI sollte bei Ausbruchsversuchen auch zuverlässig clippen), solange es trotzdem auch noch die Option gibt ein Fenster komplett ohne jegliche Dekoration zu erstellen (hier wäre dann die gesamte Fensterfläche für die Anwendung frei verfügbar, clipping sollte aber trotzdem vorhanden sein damit die Anwendung nicht woanders hin malt). Wenn die Fensterdekoration von der GUI kommt hat das auch den Vorteil das der Anwender ein Fenster verschieben oder auch einklappen/aufklappen kann ohne das die GUI von den Anwendungen abhängig wäre.

Meiner persönlichen Meinung nach ist es extrem wichtig das die GUI immer voll funktionsfähig ist egal ob die Anwendungen reagieren oder nicht. Eine GUI die das nicht gewährleisten kann ist aus meiner Sicht nicht akzeptabel. Ja ich weiß das ich jeden Tag vor genau solchen GUIs sitze, weder Windows noch der KDE oder Gnome können das.

Mit Wayland wird allem Anschein nach mehr Funktionalität in die Software verlagert obwohl die Anwendungen versuchen mehr Funktionalität in die Hardware zu verlagern (z.B. HW-beschleunigter Flash-Player im Firefox-Fenster). Auch das bei Wayland die Fensterdekoration und das Zusammenstellen des gesamten Desktops (IMHO das was man unter "Compositing" versteht) mehr in die Software verlagert wird empfinde ich persönlich als großen Rückschritt. Ich würde lieber möglichst fiele Funktionen die die Qt-Library anbietet direkt in HW realisieren (so das die Anwendung nur die Zeichenbefehle als Metadaten an die HW gibt und diese innerhalb ihres eigenen Speichers den jeweiligen Fensterinhalt in einem separatem Bereich zeichnet) um so eine möglichst hohe Performance und möglichst geringe CPU-Belastung zu erreichen. Gerade das periodische händische Umkopieren des gesamten Framebuffers von einem SW-Buffer im normalen RAM in den Video-Speicher der Grafikkarte ist deutlich aufwendiger als wenn die Grafikkarte sich die Bilddaten selber per Busmastering aus dem Speicher holt. Wenn man das Zeichnen der HW überlässt könnte man sogar bei asynchroner Darstellung absolut flicker-free erreichen indem die HW dafür sorgt das ein Zeichenbefehl entweder noch komplett ins nächste Frame kommt oder erst mit dem übernächsten Frame sichtbar wird.

Wohin sich die heutigen Plattformen bezüglich ihrer Grafikarchitektur bewegen werden wir wohl innerhalb der nächsten paar Jahre erfahren, es ist derzeit in diesem Bereich zumindest ein Umbruch im Gange.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 28. September 2011, 20:25 »
Zitat von: erik
also mir persönlich gefällt das Konzept wo die Anwendung dazu aufgefordert wird Teile oder alles ihrer Fenster neu zu zeichnen absolut gar nicht.
Warum nicht?

Ich will das vorallem deswegen machen, weil es schön zu der Art und Weise des IPC passt. Denn es wird ja pro IPC Nachricht ein Thread erstellt, sprich der Thread ist nur vorhanden wenn auch wirklich was gemacht werden muss.
Zumal ich so ja erreichen will, dass die Anwendung auch wirklich nur aktiv wird, wenn sie was zeichnen muss (was sie ja nicht muss, wenn sie eh komplett verdeckt ist oder sich der geänderte Bereich in einem verdeckten Bereich befindet).

Zitat von: erik
Ich finde es sehr viel besser wenn die Anwendung einfach immer dann wenn sie der Meinung ist das tun zu müssen ihren Fensterinhalt aktualisiert.
Kann sie ja, wie oben beschrieben, machen. Sie muss nur einfach eine Nachricht mit dem Bereich an die GUI schicken und diese entscheidet ob das auch wirklich nötig ist oder auf einen späteren Zeitpunkt verschoben werden kann.

Zitat von: erik
Gerade das periodische händische Umkopieren des gesamten Framebuffers von einem SW-Buffer im normalen RAM in den Video-Speicher der Grafikkarte ist deutlich aufwendiger als wenn die Grafikkarte sich die Bilddaten selber per Busmastering aus dem Speicher holt.
Also man kopiert ja meistens nicht den gesamten Framebuffer (das will man ja gerade vermeiden), sondern nur das was sich geändert hat und dazu muss man auch lesen und das ist aus dem Grakaspeicher sehr langsam. Hat man Hardwarebeschleunigung nutzt man doch genau dafür BitBlt (das vergleicht doch und kopiert nur das was sich geänder hat, oder?).

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 28. September 2011, 22:25 »
Hallo,


Zitat von: erik
also mir persönlich gefällt das Konzept wo die Anwendung dazu aufgefordert wird Teile oder alles ihrer Fenster neu zu zeichnen absolut gar nicht.
Warum nicht?
Abhängigkeit! Und Flexibilität.

Dass das Antriggern seht gut zu der Art von IPC passt stimmt natürlich auch wieder, aber das trifft auch auf periodische Events u.ä. zu (zumindest bei der Art wie ich die implementieren möchte) so das ich das nur begrenzt als Argument betrachte. Außerdem ist ja auch beim IPC der Caller-Thread, vom GUI-Prozess, so lange blockiert bis das IPC eine Antwort (den neuen Fensterinhalt) zurück liefert. Der Punkt ist einfach dass das angetriggerte Zeichnen unbekannt lange dauert und damit für eine GUI die der User jetzt bedienen möchte eigentlich nicht tragbar ist.

Das eine Anwendung wissen können sollte ob ihr Fenster überhaupt sichtbar ist ist aber auch wieder richtig. Sie könnte der GUI ja sagen das sie benachrichtigt werden möchte wenn ihr Fenster wieder sichtbar ist (selbst wenn nur zum Teil), solange bleibt einfach der Fenster-Buffer unverändert so das die GUI zumindest irgendetwas darstellen kann wenn der User das Fester plötzlich wieder vorholt. Wenn die Anwendung dann schnell ihren Fensterinhalt aktualisiert merkt der User eventuell nichts von dem alten Inhalt und wenn die Anwendung erst mal wieder von der Swap-Datei in den RAM gekratzt werden muss so ist das Fenster zumindest nicht leer und der Anwender kann die GUI auch normal bedienen. Hier wäre es noch cool wenn die Anwendung das erneute Zustellen von Bedien-Events erst wieder freischalten muss und vorher sämtliche Mausklicks und Tastendrücke einfach nur ins leere gehen damit zumindest nicht veraltete Bedienelemente (die jetzt eventuell gar keinen Sinn mehr machen) bedient werden können, aber es gibt auch Situationen wo es von Vorteil ist wenn die GUI die Bedien-Events sammelt (wenn die Anwendung gerade anderweitig beschäftigt ist) und diese von der Anwendung später bearbeitet werden können.

Ich hab bis jetzt noch nicht allzu viel Erfahrung beim programmieren von graphischen Programmen gesammelt, ich hab da nur ein paar Java-Programme mit Swing-GUI vorzuweisen, aber so wie ich mir das vorstelle (und es bei Swing auch ist) wird ein Fenster immer irgendwie in Rechtecke unterteilt, so das jedes Pixel im Fenster genau einem Rechteck zugeordnet ist, so ein Rechteck kann aber auch wieder in weitere Rechtecke unterteilt sein. Echten Inhalt gibt es aber nur bei Leaf-Nodes, ein Rechteck kann seine Fläche entweder komplett an Unter-Rechtecke weitergeben oder eben echten Inhalt darstellen. Letztendlich bleibt es dabei das jedes Pixel von genau einem Rechteck mit Farbe gefüllt wird. Wenn diese Struktur nicht nur innerhalb der Anwendung bleibt sondern die GUI das bekommt hat die Anwendung immer noch die Möglichkeit jedes Rechteck individuell mit Inhalt zu beschicken aber es besteht auch die Option in so ein Rechteck ein GIF zu legen und die GUI kann das entweder selber in Software immer wieder neu zeichnen oder lässt sich von der Hardware tatkräftig unterstützen. So ein Rechteck könnte aber auch von einem Flash-Player belegt sein der dazu noch nicht einmal im Kontext der Anwendung laufen muss sondern als externer Prozess läuft und einfach nur wie ein Plug-In in das Fenster der Applikation irgendetwas rein malt oder dafür auch Hardware-Beschleunigung in Anspruch nimmt (ohne das sich die Applikation dafür interessieren müsste). All das geht aber eben nur mit einem flexiblen Konzept das IMHO auch bedingt das nicht die GUI die Anwendungen antriggert ihre Fenster zu aktualisieren sondern das die Anwendungen das nur tun wenn es tatsächlich echte Events gibt.

Zitat von: erik
Ich finde es sehr viel besser wenn die Anwendung einfach immer dann wenn sie der Meinung ist das tun zu müssen ihren Fensterinhalt aktualisiert.
Kann sie ja, wie oben beschrieben, machen. Sie muss nur einfach eine Nachricht mit dem Bereich an die GUI schicken und diese entscheidet ob das auch wirklich nötig ist oder auf einen späteren Zeitpunkt verschoben werden kann.
Das erscheint mir irgendwie umständlich. Stell Dir einfach mal ein animiertes GIF vor (um z.B. eine kleine Fortschrittsanimation anzuzeigen), da könnte doch die Anwendung sich immer per Event antriggern lassen wenn mal wieder ein neues Bild gezeichnet werden muss (die Zeitabstände müssen bei GIF nicht immer gleich sein so das hier flexiblere Events erforderlich sein können) und die Anwendung dann eben einfach ein kleines Rechteck im Fenster mit einem neuen Bild füllen lässt. Wenn alle Bilder des GIFs bereits im Grafikspeicher liegen dann muss der GUI-Treiber nur noch immer einen Pointer austauschen, das würde ich als effizient bezeichnen. Von händischem Zeichnen halte ich auch nicht sehr viel.

Hat man Hardwarebeschleunigung nutzt man doch genau dafür BitBlt (das vergleicht doch und kopiert nur das was sich geänder hat, oder?).
Vergleichen bedeutet aber auch Lesen also kann die Grafikkarte auch gleich den gesamten SW-Frame-Buffer aus dem normalen RAM einlesen und fertig.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 29. September 2011, 00:57 »
Hat man Hardwarebeschleunigung nutzt man doch genau dafür BitBlt (das vergleicht doch und kopiert nur das was sich geänder hat, oder?).
Nein, BitBlt ist im Prinzip nur ein Kopieren mittels DMA.
Dieser Text wird unter jedem Beitrag angezeigt.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 29. September 2011, 01:22 »
Hallo,

also mir persönlich gefällt das Konzept wo die Anwendung dazu aufgefordert wird Teile oder alles ihrer Fenster neu zu zeichnen absolut gar nicht.
Naja, wenn ich ein Fenster verschiebe, dann muss das Fenster, was da vorher (teilweise) hinter gelegen hat, davon erfahren und den Teil, der gerade freigelegt wurde, neu zeichnen. Das ist zwingend notwendig, wenn du kein Compositing betreibst. Denn dann hat das Fenstersystem einen kompletten Puffer der Anwendung und kann selbst neu zeichnen.

letzteres ist z.B. für einen Video-Player von Interesse
Eher weniger, weil die Videodarstellung in der Regel hardwarebeschleunigt gemacht wird. Wenn nicht, ist die Darstellung für vernünftiges Video ohnehin zu langsam. Übrigens: Die GUI triggert das Neuzeichnen, die Anwendung zeichnet neu und informiert die GUI über den neu gezeichneten Bereich. Das heißt nicht, dass die Anwendung das nicht aus sich selbst heraus könnte (sonst würden sich Fensterinhalte ohne externe Ereignisse nie ändern können).

Was du vorschlägst, ist Compositing.

Meiner persönlichen Meinung nach ist es extrem wichtig das die GUI immer voll funktionsfähig ist egal ob die Anwendungen reagieren oder nicht.
Die Idee, dass die Anwendung dem GUI-System mitteilt, wo die entsprechenden Buttons sitzen, finde ich garnicht so abwegig. Fakt ist, dass Anwendungen eigentlich alles über eine Library zeichnen, die entsprechende Funktionalität für Titelleisten usw. muss man nicht nochmal extra im GUI-System duplizieren. Theming ist ein Grund dafür, direktes Rendering auch - und insbesondere Spiele und Vollbildanwendungen wollen keine GUI-eigenen Titelleisten, sondern was eigenes.

Mit Wayland wird allem Anschein nach mehr Funktionalität in die Software verlagert obwohl die Anwendungen versuchen mehr Funktionalität in die Hardware zu verlagern
Guck dir das X11-Protokoll an und sage mir, ob du das gut findest. :-)
Effektiv wird ein Großteil des heute irrelevanten Desktops weggelassen und soweit zurechtgestutzt, dass der Grafiktreiber eine Menge beschleunigen kann. Das setzt aber immer einen modernen Grafiktreiber voraus, VESA ist da nicht geeignet. Die Art und Weise, wie Windows 3.1x arbeitet, ist für solch primitive Hardware optimal - aber Theming, Compositing und große Buffer sind damit nicht sinnvoll möglich.

Eine Anwendung, die mit GTK oder Qt geschrieben ist, braucht die Funktionalität, die GTK oder Qt bieten, nicht nochmal extra aus dem GUI-System benutzen. Von daher sehe ich keinen wirklichen Rückschritt.

Ich würde lieber möglichst fiele Funktionen die die Qt-Library anbietet direkt in HW realisieren
Ein Grafiktreiber und/oder ein GUI-System, das nur Qt anbietet, halte ich für ungeeignet. Die Idee, Compositing vorauszusetzen, finde ich gut - auch, wenn das bei primitiven Grafikchipsätzen heißt, dass das Bild im System-RAM zusammengesetzt und dann an die Grafikkarte geschickt werden muss.

Bei vorhandener 3D-Unterstützung sind alle Fenster nur Texturen, die man zusammenbauen kann und liegen im Grafikspeicher vor. Selbst mittelgroße Embedded Devices können das.

Hat man Hardwarebeschleunigung nutzt man doch genau dafür BitBlt (das vergleicht doch und kopiert nur das was sich geänder hat, oder?).
Nicht wirklich. Um Veränderungen feststellen zu können, brauchst du beide Daten, müsstest also allein dafür schon das ganze Bild über den Bus schieben. ;-)
Was sich geändert hat, weiß das GUI-System (und kann ein Redraw für den betroffenen Bereich anfordern) oder die Anwendung (muss nur den betroffenen Bereich neu zeichnen und die GUI informieren). Daraus ergibt sich, welche Teile überhaupt kopiert werden müssen.

Außerdem ist ja auch beim IPC der Caller-Thread, vom GUI-Prozess, so lange blockiert bis das IPC eine Antwort (den neuen Fensterinhalt) zurück liefert. Der Punkt ist einfach dass das angetriggerte Zeichnen unbekannt lange dauert und damit für eine GUI die der User jetzt bedienen möchte eigentlich nicht tragbar ist.
Das muss nicht sein. Die Antwort auf ein "bitte jetzt [32:48] bis [128:96] neu zeichnen" muss nicht mit einem Bildschirminhalt beantwortet werden. Die Antwort kommt per asynchronem Event "ich bin fertig". Das GUI-System muss dann den neuen Inhalt übertragen.

Wer redet denn von synchronem IPC? Grafische Nutzeroberflächen sind asynchron. ;-)

Das eine Anwendung wissen können sollte ob ihr Fenster überhaupt sichtbar ist ist aber auch wieder richtig.
Warum muss das die Anwendung wissen? Wenn sie keine Redraw-Events bekommt, muss sie auch nicht neu zeichnen. Die wenigsten Anwendungen müssen ihren Bildschirminhalt ständig neu aktualisieren (und Video-Player nutzen lieber eine spezielle Schnittstelle dafür).

Hier wäre es noch cool wenn die Anwendung das erneute Zustellen von Bedien-Events erst wieder freischalten muss und vorher sämtliche Mausklicks und Tastendrücke einfach nur ins leere gehen
Dagegen. Events vom Benutzer wegwerfen ist immer falsch. Wenn ich ein Fenster anklicke, was gerade beschäftigt ist, dann will ich nicht, dass ich ignoriert werde.

All das geht aber eben nur mit einem flexiblen Konzept das IMHO auch bedingt das nicht die GUI die Anwendungen antriggert ihre Fenster zu aktualisieren sondern das die Anwendungen das nur tun wenn es tatsächlich echte Events gibt.
Erstmal schließt das eine das andere ja nicht aus und zum zweiten ist der Flash-Player im Browser höchstwahrscheinlich ein Subfenster des Browsers. Selbst, wenn der Flash-Player in einem anderen Anwendungskontext läuft! Ein Redraw-Event für den betroffenen Bereich muss der Browser also einfach nur an seine Subfenster weiterleiten.

In Windows sind die meisten Steuerelemente als Fenster realisiert, sie sehen nur nicht so aus.

Stell Dir einfach mal ein animiertes GIF vor (um z.B. eine kleine Fortschrittsanimation anzuzeigen), da könnte doch die Anwendung sich immer per Event antriggern lassen
Das betrachte ich als vom Design her kaputt. Das GUI-System hat sich nicht dafür zu interessieren, was die Anwendung darstellen möchte. Spezialfälle wie Animationen kann die Anwendung selbst erledigen - entweder durch Pixelschubsen oder eine spezielle Video-API. Die Anwendung zeichnet einfach neu, was neu gezeichnet werden muss und informiert die GUI darüber. Ob das auch real auf dem Bildschirm erscheint, ist der Anwendung egal. Alles andere verlagert überflüssige Komplexität in die Anwendungen und sorgt dafür, dass alternative Darstellungsmechanismen nicht möglich sind. Der Zustand "minimiert" hat auf einem Tablet ohne Taskleiste keine Bedeutung, ebenso wie "überlappt sich mit einem anderen Fenster" bei einem Tiling Window Manager eher unmöglich ist. Warum soll die Anwendung sich darum kümmern müssen?

Nein, BitBlt ist im Prinzip nur ein Kopieren mittels DMA.
Wobei je nach Hardware auch eine Bitoperation gemacht werden kann (z.B. XOR beim Cursor).

Gruß,
Svenska

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 29. September 2011, 08:42 »
Zitat von: erik
Stell Dir einfach mal ein animiertes GIF vor (um z.B. eine kleine Fortschrittsanimation anzuzeigen), da könnte doch die Anwendung sich immer per Event antriggern lassen wenn mal wieder ein neues Bild gezeichnet werden muss (die Zeitabstände müssen bei GIF nicht immer gleich sein so das hier flexiblere Events erforderlich sein können) und die Anwendung dann eben einfach ein kleines Rechteck im Fenster mit einem neuen Bild füllen lässt. Wenn alle Bilder des GIFs bereits im Grafikspeicher liegen dann muss der GUI-Treiber nur noch immer einen Pointer austauschen, das würde ich als effizient bezeichnen. Von händischem Zeichnen halte ich auch nicht sehr viel.
Also irgendwann mussten ja die einzelnen Bilder des GIFs mal händisch gezeichnet werden um die Buffer anzulegen. Dann kommt noch hinzu, dass das was du beschreibst doch auch möglich ist, wenn die GUI die Anwendung antriggert. Denn es bleibt dabei, warum sollte man Buffer austauschen, wenn das Fenster gar nicht sichtbar ist.
Die Anwendung erstellt halt einfach ihre Buffer, speichert die meinetwegen in einer Liste, mit Zeitwerten und die Anwendung sendet zu jeder Zeit (wo sich der Inhalt ändert) eine Nachricht an die GUI, das sich was verändert hat und setzt den Zeiger auf das nächste Element in der Liste. Die GUI entscheidet jetzt aber, ob es Sinn macht einen neuen Buffer von der Anwendung anzufordern und nur dann wird auch ein Buffer übertragen. Das nenne ich effizient ;)

Zitat von: svenska
Die Idee, dass die Anwendung dem GUI-System mitteilt, wo die entsprechenden Buttons sitzen, finde ich garnicht so abwegig.
Welchen Vorteil hätte das? Ich sehe da nur mehr Aufwand in der GUI, der sonst in der Anwendung wäre.

Zitat von: svenska
Fakt ist, dass Anwendungen eigentlich alles über eine Library zeichnen, die entsprechende Funktionalität für Titelleisten usw. muss man nicht nochmal extra im GUI-System duplizieren. Theming ist ein Grund dafür, direktes Rendering auch - und insbesondere Spiele und Vollbildanwendungen wollen keine GUI-eigenen Titelleisten, sondern was eigenes.
Ich habe mich noch nicht mit solchen Libs beschäftigt, aber wie setzt man es dann um das alle Anwendungen gleich aussehen? Ich möchte eigentlich nicht, dass jede Anwendung ne andere Titelleiste (und damit wahrscheinlich auch noch andere Position der Buttons hat (schließen und sowas)) und andere Bedienelemente hat. Das sollte schon alles einheitlich sein.
Oder erreicht man das durch Theming?

Zitat von: svenska
Effektiv wird ein Großteil des heute irrelevanten Desktops weggelassen und soweit zurechtgestutzt, dass der Grafiktreiber eine Menge beschleunigen kann. Das setzt aber immer einen modernen Grafiktreiber voraus, VESA ist da nicht geeignet. Die Art und Weise, wie Windows 3.1x arbeitet, ist für solch primitive Hardware optimal - aber Theming, Compositing und große Buffer sind damit nicht sinnvoll möglich.
Naja, seien wir mal ehrlich, wer von uns rechnet schon damit, dass er nen hardwarebeschleunigten Grafiktreiber haben wird? Man wird immer irgendwie auf VESA zurück greifen müssen.
Deswegen wollte ich ja auch beide Varianten unterstützen.

Zitat von: svenska
Was sich geändert hat, weiß das GUI-System
Da bin ich mir gerade nicht so sicher. Sagen wir mal es wird ein Button gedrückt (und der Button wird dann gedrückt dargestellt), dann wird die GUI, von der Anwendung, zwar benachrichtigt dass sich der Bereich um den Button geändert hat, aber das heißt nicht, dass alle Pixel ne andere Farbe bekommen. Das bekommt man nur durch vergleichen heraus. In nem anderen Forum (osdev.org) wird halt empfohlen zu vergleichen (im Systemram) und nur die wirklich geänderten Werte an die Graka zu schicken, weil es sonst zu langsam ist.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 29. September 2011, 14:55 »
Hallo,

Zitat von: svenska
Die Idee, dass die Anwendung dem GUI-System mitteilt, wo die entsprechenden Buttons sitzen, finde ich garnicht so abwegig.
Welchen Vorteil hätte das? Ich sehe da nur mehr Aufwand in der GUI, der sonst in der Anwendung wäre.
Wenn die Titelleiste von der Anwendung gezeichnet wird und die Anwendung nicht auf Ereignisse reagiert, dann weiß die GUI wenigstens, wenn der Nutzer die Anwendung schließen möchte und kann sie z.B. töten.

Ich habe mich noch nicht mit solchen Libs beschäftigt, aber wie setzt man es dann um das alle Anwendungen gleich aussehen?
Indem alle Anwendungen die gleiche Lib verwenden. Effektiv gibt es zwei große Bibliotheken (GTK und Qt) und durch Theming kann man die gleich aussehen lassen.

Die zweite Möglichkeit ist die Apple-Variante: Es gibt Design-Richtlinien und Programme, die die nicht erfüllen, werden nicht zertifiziert. :-) Das garantiert "überall gleiches Aussehen", ist aber für ein Hobby-OS ungeeignet.

Ich möchte eigentlich nicht, dass jede Anwendung ne andere Titelleiste (und damit wahrscheinlich auch noch andere Position der Buttons hat (schließen und sowas)) und andere Bedienelemente hat. Das sollte schon alles einheitlich sein.
Es gibt Programme, für die ein anderes Aussehen durchaus sinnvoll ist (z.B. Spiele, die haben keine Titelleiste und der Schließen-Button ist im Hauptmenü).

Alle Programme, die eine bestimmte Lib nutzen, kannst du über die Einstellungen dieser Lib themen und dann sehen sie gleich aus.

Naja, seien wir mal ehrlich, wer von uns rechnet schon damit, dass er nen hardwarebeschleunigten Grafiktreiber haben wird? Man wird immer irgendwie auf VESA zurück greifen müssen.
Nicht unbedingt, aber wenn du ein modernes GUI-System haben willst, dann wird VESA nur suboptimal laufen und wenn du ein VESA-optimiertes GUI-System willst, dann kannst du Compositing direkt vergessen. Du hast die Wahl.

Zitat von: svenska
Was sich geändert hat, weiß das GUI-System
Da bin ich mir gerade nicht so sicher. Sagen wir mal es wird ein Button gedrückt (und der Button wird dann gedrückt dargestellt), dann wird die GUI, von der Anwendung, zwar benachrichtigt dass sich der Bereich um den Button geändert hat, aber das heißt nicht, dass alle Pixel ne andere Farbe bekommen.
Wenn du einen Button drückst, dann sagt der Button seinem übergeordnetem Fenster "Ich muss mich jetzt neu zeichnen." Das macht die Library, die die Widgets zur Verfügung stellt. Das übergeordnete Fenster wartet dann ab, bis der Button sich neu gezeichnet hat und sagt dem GUI-System "Hier, folgendes Rechteck wurde neu gezeichnet." Das GUI-System guckt dann nach, ob der Teilbereich überhaupt sichtbar ist und zeichnet das - falls notwendig - auf den Bildschirm. Da wird nicht verglichen.

Jedes Steuerelement weiß selbst, wie es sich zeichnet. Die GUI ist nur dafür verantwortlich, das auch in den Framebuffer zu kopieren, falls das notwendig ist.

Das bekommt man nur durch vergleichen heraus. In nem anderen Forum (osdev.org) wird halt empfohlen zu vergleichen (im Systemram) und nur die wirklich geänderten Werte an die Graka zu schicken, weil es sonst zu langsam ist.
Wozu vergleichen? Die Anwendung sagt dem GUI-System doch, was sich geändert hat. Die wird's schon wissen, nochmal extra einen Vergleichsschritt drüberzuwerfen ist überflüssig.

Gruß,
Svenska

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 29. September 2011, 15:19 »
Zitat von: svenska
Wenn die Titelleiste von der Anwendung gezeichnet wird und die Anwendung nicht auf Ereignisse reagiert, dann weiß die GUI wenigstens, wenn der Nutzer die Anwendung schließen möchte und kann sie z.B. töten.
Ich weiß gerade nicht wie Windows das macht, aber funktioniert das ja auch, wenn die Anwendung nicht reagiert, stellt Windows das irgendwie fest (vorallem wenn man dann ein paar Mal klickt) und fragt ob das Programm beendet werden soll.

Bei Theming kann man ja auch die Lage der Titelleistebuttons (schließen und sowas) ändern. Von daher wäre es eventuell ausreichend, wenn man Lage und Größe der 4 (unter Windows) Buttons (Systemmenü, Minimieren, Maximieren und Schließen) der GUI mitteilt.
Dann würde ich es aber so machen, dass es Grundsätzlich nur Fenster ohne Titelleiste und Rahmen gibt und dass das alles die Anwendung machen muss.

Zitat von: svenska
Es gibt Programme, für die ein anderes Aussehen durchaus sinnvoll ist (z.B. Spiele, die haben keine Titelleiste und der Schließen-Button ist im Hauptmenü).
Naja, dafür würde es dann doch 2 Typen von Fenster geben, einmal mit Rahmen und Titelleiste und einmal ohne Rahmen und Titelleiste.

Zitat von: svenska
Nicht unbedingt, aber wenn du ein modernes GUI-System haben willst, dann wird VESA nur suboptimal laufen und wenn du ein VESA-optimiertes GUI-System willst, dann kannst du Compositing direkt vergessen. Du hast die Wahl.
Windows und Linux haben auch noch VESA Treiber und beide nutzen Compositing. Zumal ich deswegen ja mit dem Gedanken spiele die GUI so zu entwerfen, dass zur Laufzeit entschieden wird, welche Variante (immer neuzeichnen direkt in den Framebuffer oder Compositing) genutzt wird.

Zitat von: svenska
Wozu vergleichen? Die Anwendung sagt dem GUI-System doch, was sich geändert hat. Die wird's schon wissen, nochmal extra einen Vergleichsschritt drüberzuwerfen ist überflüssig.
Es ging darum, dass das Schreiben in den Grakaspeicher nicht besonders schnell ist und das man deswegen so wenig Daten wie möglich zur Graka schicken sollte. Deswegen kam das mit dem Vergleichen und wirklich nur die Pixel senden die sich geändert haben.
Mit meinem Bsp. wollte ich darauf hinaus, das nur weil sich der Bereich des Buttons geändert hat, es noch lange nicht heißt das sich wirklich alle Pixel in dem Bereich geändert haben.

Anderes Bsp. du scrollst eine Webpage (z.B. das Forum) und das gesamte Fenster muss neugezeichnet werden. Bei den großen Flächen mit der gleichen Farbe, kannst du einiges an Bandbreite einsparen, indem du nur die Pixel schreibst, wo sich die Farbe auch verändert hat und bei diesem Bsp. wären das ne Menge Pixel die man nicht ändern müsste.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 29. September 2011, 15:45 »
Bei Theming kann man ja auch die Lage der Titelleistebuttons (schließen und sowas) ändern. Von daher wäre es eventuell ausreichend, wenn man Lage und Größe der 4 (unter Windows) Buttons (Systemmenü, Minimieren, Maximieren und Schließen) der GUI mitteilt.
Dann würde ich es aber so machen, dass es Grundsätzlich nur Fenster ohne Titelleiste und Rahmen gibt und dass das alles die Anwendung machen muss.
Davon rede ich die ganze Zeit.

Windows und Linux haben auch noch VESA Treiber und beide nutzen Compositing. Zumal ich deswegen ja mit dem Gedanken spiele die GUI so zu entwerfen, dass zur Laufzeit entschieden wird, welche Variante (immer neuzeichnen direkt in den Framebuffer oder Compositing) genutzt wird.
Nein, beide Systeme haben kein Compositing, wenn der VESA-Treiber verwendet wird...

Es ging darum, dass das Schreiben in den Grakaspeicher nicht besonders schnell ist und das man deswegen so wenig Daten wie möglich zur Graka schicken sollte. Deswegen kam das mit dem Vergleichen und wirklich nur die Pixel senden die sich geändert haben.
Bringt meiner Meinung nach wenig, zumindest kenne ich keinen Fall, wo man das wirklich tut.

Anderes Bsp. du scrollst eine Webpage (z.B. das Forum) und das gesamte Fenster muss neugezeichnet werden. Bei den großen Flächen mit der gleichen Farbe, kannst du einiges an Bandbreite einsparen, indem du nur die Pixel schreibst, wo sich die Farbe auch verändert hat und bei diesem Bsp. wären das ne Menge Pixel die man nicht ändern müsste.
Es ist aber nicht Aufgabe des GUI-Systems, das nachträglich festzustellen, sondern Aufgabe der Anwendung, nur die entsprechenden Rechtecke zu übertragen. Ist jedenfalls meine Meinung.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 29. September 2011, 16:13 »
Zitat von: svenska
Davon rede ich die ganze Zeit.
Schön das wir uns verstehen :D

Ist es beim Theming auch möglich die Form der Fenster festzulegen? Oder anders, wie Schwierig wäre das, so schwierig das es sich wieder lohnen würde, die Anwendungen nur direkt ins Fenster zeichnen zu lassen und Rahmen und Titelleiste der GUI zu überlassen?

Zitat von: svenska
Nein, beide Systeme haben kein Compositing, wenn der VESA-Treiber verwendet wird...
Also können beide Compositing und die alte Variante (so wie ich es eigentlich auch geplant habe)?!

Zitat von: svenska
Es ist aber nicht Aufgabe des GUI-Systems, das nachträglich festzustellen, sondern Aufgabe der Anwendung, nur die entsprechenden Rechtecke zu übertragen. Ist jedenfalls meine Meinung.
Da hast du schon recht.

Man könnte das ja im VESA-Treiber machen. Der hat dann immer 2 Buffer mit dem Bildinhalt, einmal den mit dem vorherigen Bild und einmal den mit dem neuen Bild. So kann er dann vergleichen und nur das schreiben was sich wirklich geändert hat.

Solch eine Variante sollte man eigentlich sogar grundsätzlich machen, weil man will bestimmt nicht jedes Mal den Bereich vom Mauszeiger neuzeichnen lassen, indem man sich die Daten wieder von den Anwendungen holt, sondern dass man den Mauszeiger immer als letztes überträgt, aber nicht mit in den Buffern speichert.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 29. September 2011, 17:53 »
Ist es beim Theming auch möglich die Form der Fenster festzulegen? Oder anders, wie Schwierig wäre das, so schwierig das es sich wieder lohnen würde, die Anwendungen nur direkt ins Fenster zeichnen zu lassen und Rahmen und Titelleiste der GUI zu überlassen?
Wie wäre es, wenn du einfach alle Dekorationen den Anwendungen überlässt? Wenn die vorhandene Farbtiefe einen Alphakanal unterstützt (bei 32 Bit ist das möglich, sonst nicht), dann kann die Anwendung einen Teil ihres Fensters transparent machen und das Problem ist gelöst. :-)

Ansonsten bin ich grundsätzlich eher gegen Freiform-Fenster.

Zitat von: svenska
Nein, beide Systeme haben kein Compositing, wenn der VESA-Treiber verwendet wird...
Also können beide Compositing und die alte Variante (so wie ich es eigentlich auch geplant habe)?!
Ja. Aber zwei Systeme parallel zu unterstützen wäre mir zuviel Aufwand. Ich würde wahrscheinlich ausschließlich Compositing unterstützen, der VESA-Treiber hätte dann halt Pech und wäre etwas langsamer als notwendig.

weil man will bestimmt nicht jedes Mal den Bereich vom Mauszeiger neuzeichnen lassen, indem man sich die Daten wieder von den Anwendungen holt, sondern dass man den Mauszeiger immer als letztes überträgt, aber nicht mit in den Buffern speichert.
Naja, du kannst den Mauszeiger mit XOR drüberzeichnen und wenn er sich wegbewegt nochmal - dann sollte das ursprüngliche Bild wieder rauskommen. Jede Grafikkarte mit ein bisschen 2D unterstützt Hardware-Cursor, allerdings hat zumindest X11 damit öfter mal Probleme gehabt. :-)

Gruß,
Svenska

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 29. September 2011, 18:12 »
Zitat von: svenska
Wenn die vorhandene Farbtiefe einen Alphakanal unterstützt (bei 32 Bit ist das möglich, sonst nicht), dann kann die Anwendung einen Teil ihres Fensters transparent machen und das Problem ist gelöst.
Problem ist, ich kann mir nicht vorstellen, das man das halbwegs effizient lösen kann. Denn dann müsste ich das oberste Fenster fragen, ob da wo sich die Maus befindet (und am besten gerade geklickt hat), das Fenster richtig ist oder nicht und wenn nicht, müsste ich zum nächst tieferen Fenster gehen usw.

Das muss sich doch auch anders lösen lassen.

Zitat von: svenska
Ansonsten bin ich grundsätzlich eher gegen Freiform-Fenster.
Naja, ich bin ja auch der Meinung nen Fenster kann ruhig ne rechteckige Form haben, aber da ich von dem BeOS/Haiku Design angetan bin (und das auch so umsetzen wollte), bräuchte ich halt sowas und da bietet sich dann an, dass die Anwendung nix mit Rahmen und Titelleiste zu tun hat.

Wenn ich mal die Lust dazu habe, versuche ich mal im Haiku-Source den Code dafür zu finden.

Zitat von: svenska
Ja. Aber zwei Systeme parallel zu unterstützen wäre mir zuviel Aufwand. Ich würde wahrscheinlich ausschließlich Compositing unterstützen, der VESA-Treiber hätte dann halt Pech und wäre etwas langsamer als notwendig.
Problem hierbei ist, würdest du dich wirklich damit abgeben, dass deine GUI dann auf den meisten System wahrscheinlich langsam bis zu langsam wäre (keine Ahnung wie groß der Unterschied ist)? Denn genügend Treiber wirst du wohl nicht zusammen bekommen, es sei denn du schaffst dir nen Layer, so dass du z.B. Linuxtreiber kompilieren und dann nutzen kannst (wie heißt die neue Schnittstelle für Grafiktreiber doch gleich, ich komm gerade nicht drauf?).

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 29. September 2011, 18:37 »
Naja, ich bin ja auch der Meinung nen Fenster kann ruhig ne rechteckige Form haben, aber da ich von dem BeOS/Haiku Design angetan bin (und das auch so umsetzen wollte), bräuchte ich halt sowas und da bietet sich dann an, dass die Anwendung nix mit Rahmen und Titelleiste zu tun hat.
Oder die GUI-Lib erzeugt einfach ein eigenes Fenster für die Titelleiste, die nur gemeinsam verschoben werden, dann ist das Problem auch beseitigt. Ein Fenster muss nicht ein Rechteck mit Rahmen und Titelleiste sein - effektiv ist ein Fenster etwas, was ein Fenster-Handle anbieten kann. GTK kann das selbst, das muss die GUI nicht anbieten.

(wie heißt die neue Schnittstelle für Grafiktreiber doch gleich, ich komm gerade nicht drauf?).
Gallium3D.

Fakt ist, mit dem VESA-Treiber machst du keinen Anwender glücklich. Entweder, du baust dir einen modernen Desktop - oder du lässt es sein. Eine Mischung ist in jedem Fall Mist, und zwei Codepfade pflegen halte ich für unsinnig. Besonders bei so komplexem Zeug wie GUI und einem Hobby-OS.

Gruß,
Svenska

 

Einloggen