Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Nopea putpixel (SDL)

Sivun loppuun

Burton [01.02.2007 18:43:51]

#

Moi. Olen etsimässä nopeaa putpixel-toimintoa C+SDL -yhdistelmälle. Useimmat erillisessä funktiossa olevat ovat todella hitaita koko ruudun täyttämiseen. Onko teillä suoria ehdotuksia? Muistan joskus lukeneeni memset-tyylisestä putpixelistä, mutta en enää muista sen toimintaa.

Kiitos :-)
-Burton

Legu [01.02.2007 19:06:04]

#

Tällä koodilla saa kaikki bytet samoiksi (= vain harmaasävy)

// Näyttö lukkoon jos tarvitsee
memset(naytto->pixels, /* arvo väliltä 0-255 (0 = musta, 255 valkoinen) */ 0, naytto->w * naytto->h * naytto->format>BytesPerPixel);
// Pois lukosta

EDIT: Niin tietysti tällä saa täytettyä koko ruudun mihin väriin tahansa

//                                                    R  B   G
SDL_FillRect(naytto, NULL, SDL_MapRGB(naytto->format, 0, 0, 255));

Burton [01.02.2007 19:19:17]

#

Mutta ajatuksena oli, että pystyisi piirtämään vaikka koko ruudun täyteen spritejä putpixelin avulla. Olen huomannut, että tämä on todella hidasta ja siksi joudun käyttämään SDL:n valmiita funktioita ja sijoittamaan kuvia ruudulle.

Metabolix [01.02.2007 19:29:31]

#

Inline-funktiolla tuo onnistuu juuri niin nopeasti kuin funktiolla yleensä on mahdollista. Putpixel ei tosiaan ole oikea väline koko ruudun piirtämiseen uusiksi, jos resoluutio on vähänkään isompi. Yksi mahdollisesti jopa melkein merkittävä nopeutuskonsti on se, että varmistat pinnan olevan tietyssä formaatissa, jolloin voit optimoida koodin juuri sille formaatille. Myös sopivassa paikassa olevat const-määreet ja vastaavat kikat voivat nopeuttaa ihmeesti, kuten myös turhien muistiosoitusten karsiminen. Muistathan optimointilipun -O2.

Burton [01.02.2007 19:46:10]

#

Mitä tämä -O2 -lippu tekee? Olen kyllä käyttänyt gcc:llä kääntäessäni lippua -O1, mutta luulin tämän vain pienentävän ulos tulevan tiedoston kokoa.

edit. tämä koodi:

#include <SDL/SDL.h>
#define PITCH naytto->pitch
SDL_Surface *naytto;

int main(int aaaaa,char *bbbbb[]) {
    SDL_Init(SDL_INIT_VIDEO);
    naytto = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);
    Uint8 *p = (Uint8 *)naytto->pixels;
    int y , x, b;
    long hidastea = SDL_GetTicks();
    fprintf(stderr, "%i\n", hidastea);
    for (b = 0; b < 1000; b = b + 1) {
        for (y = 0; y < 600; y = y + 1) {
            for (x = 0; x < 800; x = x + 1) {
                *(Uint32 *)(p + y * PITCH + (x << 2)) = 255;
            }
        } SDL_UpdateRect(naytto, 0, 0, 800, 600);
    }
    hidastea=SDL_GetTicks();
    fprintf(stderr,"%i\n",hidastea);
    SDL_Quit(); return 0;
}

suoriutui 7432 millisekunnissa. Eli minusta se on aika nopea, jos kerran tuhat kertaa täytetään 800*600 -kokoinen näyttö.

Lahha [01.02.2007 20:29:24]

#

O1 pienentää binäärin kokoa ja O2 lisää nopeutta.

Burton [01.02.2007 20:36:24]

#

Voiko niitä käyttää yhdessä? GCC tekee hirveän isoja tiedostoja muuten...

Metabolix [01.02.2007 20:39:10]

#

Lahha kirjoitti:

O1 pienentää binäärin kokoa ja O2 lisää nopeutta.

No ei nyt aivan noinkaan. O1 optimoi vähän, O2 optimoi enemmän. Os panostaa kokoon. Vain yhtä tällaista optimointilippua voi käyttää kerralla. O2 sisältää myös kaikki O1:n optimoinnit. Koon pienentyminen tulee perusoptimoinnissa kaupan päälle, kun turhaa koodia poistetaan ja asiat tehdään tehokkaammin. Kokoon auttaa vielä paljon enemmän -s (pienellä, ei isolla).

Burton [01.02.2007 20:39:56]

#

Onko sitten olemassa O3-lipuke?

Metabolix [01.02.2007 20:41:57]

#

Toki, mutta se ei läheskään aina ole kakkosta parempi (joskus jopa huomattavasti huonompikin) ja se voi jo joissakin tapauksissa merkittävästi suurentaa binaaria. Sitä isompia ei sitten olekaan.

Burton [02.02.2007 13:17:26]

#

Tein koodin:

#include <SDL/SDL.h>
    #define PITCH naytto->pitch
    SDL_Surface *naytto;
int main(int aaaa,char *bbbb[]) {
    if (SDL_Init(SDL_INIT_VIDEO)<0) {
        fprintf(stderr,"SDL-Virhe: %s\n",SDL_GetError());
        exit(1);
    }
    naytto = SDL_SetVideoMode(320, 200, 32, SDL_SWSURFACE|SDL_FULLSCREEN );
    SDL_Event t;
    Uint8 *p = (Uint8 *)naytto->pixels;
    while (1) {
        SDL_PollEvent(&t);
        if (t.type == SDL_QUIT)
            break;
        else
            if (t.type == SDL_KEYDOWN)
                if (t.key.keysym.sym == SDLK_ESCAPE)
                    break;

        *(Uint32 *)(p + 100 * PITCH + (100 << 2))= 255;
        SDL_UpdateRect(naytto, 0, 0, 320, 200);

        SDL_Delay(1)
    } SDL_Quit(); return 0;
}

Ja tuo ei toiminut, mutta jos jätän SDL_FULLSCREEN:n pois koodi toimii!
Koodin pitäisi tulostaa ruudulle pikseli.

zacura [02.02.2007 16:27:42]

#

Pitääköhän pinta lukita SDL_LockSurfacella ennen pixelien käpälöintiä, ja vapauttaa sen jälkeen SDL_UnlockSurfacella. SDL:n dokumenteissa on lisää aiheesta.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta