Forum: PC-Programmierung SDL2: Flackern unter Windows 10


von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,

ich habe eine kleine LCD-Emulation in SDL2 geschrieben, um eine schnelle 
Ansicht der Grafik an meinem Mikrocontroller zu haben - zu Testzwecken 
und für die Bilder in der Doku.

Auf meinem PC, der leider mit Windows 10 läuft, ist die Ansicht auf in 
Ordnung. Auf einem anderen PC, auch mit Windows 10, flackert der 
Fensterinhalt heftig.

Es sieht so aus, als schriebe jeder Aufruf der eigentlichen 
Zeichenroutinen in ein anderes Halbbild.

Seit wann? Das kann ich nicht sagen. Die Display-Emulation ist schon 
uralt, und wurde schon recht lange nicht mehr an besagtem Rechner 
getestet.

Die eigentlichen Zeichen-Routinen sind unglaublich banal:
1
    /* Variablen und Konstanten fuer Display-Emulation */
2
    const char headline[] = "TFT ILI9341 Emulation";
3
    SDL_Window   * pWindow;
4
    SDL_Renderer * pRenderer;
5
    SDL_Texture * pTexture;
6
7
8
    /* Grafik-Teil des Mockups mit SDL initialisieren */
9
    exit_t tft_sdl_init(void)
10
    {
11
        SDL_Init(SDL_INIT_VIDEO);
12
13
        int ret = SDL_InitSubSystem(SDL_INIT_VIDEO);
14
        assert( ret == 0 );
15
16
        pWindow = SDL_CreateWindow(headline,
17
                SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
18
                LCD_EMULATION_SCALE*TFT_WIDTH_PX,
19
                LCD_EMULATION_SCALE*TFT_HEIGHT_PX,
20
                0);
21
22
        pRenderer = SDL_CreateRenderer(pWindow, -1, 0);
23
        SDL_RenderSetScale(pRenderer, 1.0 * LCD_EMULATION_SCALE, 1.0 * LCD_EMULATION_SCALE);
24
25
        uint32_t pixelformat = SDL_PIXELFORMAT_RGB565;
26
27
        pTexture = SDL_CreateTexture(pRenderer,
28
                pixelformat, SDL_TEXTUREACCESS_STATIC,
29
                TFT_WIDTH_PX,
30
                TFT_HEIGHT_PX);
31
32
        return EXIT_SUCCESS;
33
    }
34
35
36
37
    /* Vorschriftsmaessige Beendigung vorbereiten */
38
    void tft_sdl_deinit(void)
39
    {
40
        SDL_DestroyTexture(pTexture);
41
        SDL_DestroyRenderer(pRenderer);
42
        SDL_DestroyWindow(pWindow);
43
        SDL_QuitSubSystem(SDL_INIT_VIDEO);
44
    }
45
46
47
    /* Rechteck-Koordinaten umwandeln */
48
    static inline SDL_Rect rect2sdl(Rect_t R)
49
    {
50
        SDL_Rect S;
51
        S.x = R.x;
52
        S.y = R.y;
53
        S.w = R.w;
54
        S.h = R.h;
55
        return S;
56
    }
57
58
59
    /* Gefuelltes Rechteck zeichnen
60
     *  return: Anzahl der gezeichneten Pixel
61
     *  Die Pruefung, ob das gezeichnete Rechteck noch im erlauben Bereich liegt, erfolgt in der 
62
     *  aufrufenden static_inline Funktion tft_drawRect() */
63
    // FIXME: Jeder Aufruf dieser Funktion scheint in ein anderes Halbbild zu zeichnen
64
    ufast24_t tft_sdl_drawRectF_noclip(Rect_t R, uint16_t color)
65
    {
66
        //tft_clipkoord(&Pos, &Size); clipping wird von static-inline-Funktion vorgenommen
67
68
        SDL_Rect Rect = rect2sdl(R);
69
70
        Rgb24_t Rgb = color_rgb16to24_s(color);
71
72
        #if 1 
73
            // FIXME: REMOVEME abschaltbar, um sicherzustellen, dass wirklich alle Zeichenfunktionen
74
            // ueber diese Funktion zeichnen
75
            SDL_SetRenderDrawColor(pRenderer, Rgb.r, Rgb.g, Rgb.b, SDL_ALPHA_OPAQUE );
76
            SDL_RenderFillRect(pRenderer, &Rect);
77
            SDL_RenderPresent(pRenderer);
78
            // SDL_Delay(10); // Macht das Ergebnis nicht besser, nur langsamer
79
        #endif
80
81
        return (uint_fast24_t) R.w * R.h;
82
    }

Dass die Zeichen-Funktionen uralt sind, heisst ja nicht, dass sie 
korrekt sind. Screenshots des Fehlerbildes kann ich gerade nicht machen, 
weil ich am anderen Rechner bin. Aber es ist kein einfacher dynamischer 
Effekt wie tearing - die abwechselnden Halbbilder sind auch in 
Screenshots vorhanden.

Hat jemand einen Tipp für mich?

: Bearbeitet durch User
von Walter T. (nicolas)


Angehängte Dateien:

Lesenswert?

Hier sind mal Screenshots, damit man weiss, was ich mit "Halbbilder" 
meine:

Das erste Testbild soll mehrere Farbverlaufsbalken, darüber gezeichnet 
zwei konzentrische Kreise mit 1px Breite und vier Diagonalen darstellen. 
Jeder horizontale Balken des Farbverlaufs und jedes Einzelpixel bei den 
Linien ist eine Schreiboperation, die mit SDL_RenderPresent() 
abgeschlossen wird (letztendlich jeweils ein einziger Aufruf von 
tft_sdl_drawRectF_noclip()).

Das zweite Testbild ist ein textlastiges Testbild. Der dunkelgraue 
Hintergrund wird in einer einzelnen Schreiboperation geschrieben. Jeder 
Buchstabe ist auch eine einzelne Schreiboperation. Die farbigen 
Piktogramme bestehen meistens aus etlichen unterschiedlich großen 
Schreiboperationen. Ausnahme sind nur das Schloß rechts und die Klemme 
links, die in nur einer Operation geschrieben werden.

Es sieht also so aus, als landeten Schreiboperationen alternierend auf 
unterschiedlichen Fensterebenen - oder wenn man es so nennen mag: In 
unterschiedlichen Doppelpufferhälften.

Insofern ist "Flackern" auch nicht unbedingt der richtige Ausdruck. 
Solange kein Update des Fensterinhalts erfolgt, steht das jeweilige 
Halbbild still.


Alle mir bekannten Kompatibilitätseinstellungen unter Windows für die 
Ausführung der *.exe-Datei habe ich natürlich schon ausprobiert.

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

So. Ich habe jetzt mehrere Windows-10-Rechner ausprobiert, und der 
meinige ist der einzige, der diese Grafikfehler anzeigt.

Außerdem zeigt er diese Grafikfehler jetzt auch in einer alten Version, 
des Programms, die damals fehlerfrei angezeigt wurde.

Da muß jetzt nicht heißen, dass von einem der letzten Windows-Updates 
etwas vermurkst wurde - vielleicht hat es nur einen 
Implementierungsfehler meinerseits aufgedeckt.

Aber das heisst auch, dass der Fehler -wenn er auf meiner Seite ist- 
sehr schwer zu finden sein wird, weil er auf anderen Rechnern nicht 
nachvollziehbar ist. Höchstens durch Code-Audit, und das wird wohl 
keiner machen.

Schade.

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

Nachtrag: Das Problem ist verschwunden. Ich habe einen neuen 
NVidia-Treiber installiert und das Problem ist verschwunden.

Irgendwie ist das peinlich, nicht vorher auf die Idee zu kommen. Und 
irgendwie erschreckend, dass bei einer popeligen 
2D-Fenster-Pixel-Ansicht der Grafikkartentreiber immer noch in die Suppe 
spucken kann.

Für mich ist das Problem erledigt. Möge mein Monolog jemandem, der auf 
ein ähnliches Problem stößt, hilfreich sein.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.