Aplicar reescalado sin reiniciar el modo gráfico

Started by josebita, December 17, 2012, 04:52:15 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

josebita

Sería interesante para las GPUs que fallan (y probablemente para ahorrar recursos en otros sistemas) que la función gr_set_mode() no siempre eliminara las superficies que existen.
Me explico: en Android empieza a ser común que se haga un primer set_mode implícito (al cargar la libvideo) y después el usuario haga otra a mano para hacer un escalado del modo gráfico nominal al del móvil. Sería interesante que, dado que las características de la SDL_Surface que actuará de fondo de pantalla no se cambian al hacer ese set_mode, gr_set_mode fuera un poquito más inteligente y detectara que no hace falta una nueva superficir y por tanto no liberara la existente.


Sería añadir algunos if() en la función y creo que ayudaría con las GPUs que dan problemas. Como digo, en otras plataformas ahorraría el paso de liberar la superficie y volver a crear otra idéntica...

SplinterGU


igual lo tengo pensando y lo voy a hacer de otra forma... pero, en que afecta que libere y vuelva a crear?
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

josebita

Quote from: SplinterGU on December 17, 2012, 06:23:51 PM
igual lo tengo pensando y lo voy a hacer de otra forma... pero, en que afecta que libere y vuelva a crear?
Parece que ese es el problema con las GPU Adreno. Así lo esquivamos...

SplinterGU

o sea, que en los adreno no puedes cambiar la resolucion?
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

JaViS

Quote from: josebita on December 17, 2012, 06:54:26 PM
Quote from: SplinterGU on December 17, 2012, 06:23:51 PM
igual lo tengo pensando y lo voy a hacer de otra forma... pero, en que afecta que libere y vuelva a crear?
Parece que ese es el problema con las GPU Adreno. Así lo esquivamos...


Hay alguna mencion acerca de esto por parte de la gente de SLD?
Working on Anarkade. A couch multiplayer 2D shooter.

SplinterGU

igual me parece raro, no creo que sea eso, a menos que me digas que no se puede cambiar la resolucion, sino usar la que viene por default, como sea, es un tema de SDL...
si ese fuera el problema, entonces directamente hay que inhibir el set_mode y que solo haga el cambio 1 vez... pero el tema se complica, porque hay que virtualizar todas las resoluciones...

no se, seguro que ese es el tema?
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

josebita

Quote from: SplinterGU on December 17, 2012, 08:42:08 PM
igual me parece raro, no creo que sea eso, a menos que me digas que no se puede cambiar la resolucion, sino usar la que viene por default, como sea, es un tema de SDL...
si ese fuera el problema, entonces directamente hay que inhibir el set_mode y que solo haga el cambio 1 vez... pero el tema se complica, porque hay que virtualizar todas las resoluciones...

no se, seguro que ese es el tema?
El problema no es ese específicamente. En SDL2 no existe SDL_SetVideoMode dado que ahora se soportan múltiples ventanas y por tanto hay que hacerlo de otra forma. Para poder utilizar llamadas compatibles estoy usando la capa de compatibilidad que hasta cierto momento venía con SDL1.3 y que desde hace tiempo no se incluye con el código y la consideran obsoleta.
El problema parece algún tema más complejo relacionado con OpenGL ES pero el problema al final se manifiesta en que no puedo hacer más de una llamada a SDL_SetVideoMode. Lo ideal sería quitar la capa de compatibilidad y utilizar los nuevos APIs pero cuando lo intenté resultó que me daba problemas en otros puntos del código de Bennu que utilizaban las llamadas de SDL1.2. Tendré que ver que'puedo hacer...

En cualquier caso, en ningún dispositivo Android que yo conozca se puede cambiar la resolución.

panreyes

En mi Samsung Galaxy S (i9000) se puede setear a 640x480, pero el tactil no funciona bien.

SplinterGU

pero que tengas multiples ventanas no significa que no puedas setear una a fullscreen... o no se puede con la nueva SDL usar fullscreen? hablo con total ignorancia porque no conozco nada de la sdl2, pero me parece raro que no se pueda setear un fullscreen, y si se puede, no veo la diferencia entre un set_mode a fullscreen (que es lo que supongo estamos discutiendo) y una ventana (o lo que sea) a fullscreen.

como sea, tu port puede tranquilamente hacer la inicializacion al modo nativo y luego eliminas tu el cambio de set_mode y si es diferente el modo que se pide del que esta seteado, entonces forzar un scale_resolution...

entonces tambien entiendo que si haces un programa sin set_mode funciona bien? cierto? no tendras quizas algun problema con la profundidad de video? no se, cuenta mas de lo que has visto y analizado.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

josebita

Quote from: SplinterGU on December 17, 2012, 09:41:34 PM
pero que tengas multiples ventanas no significa que no puedas setear una a fullscreen... o no se puede con la nueva SDL usar fullscreen? hablo con total ignorancia porque no conozco nada de la sdl2, pero me parece raro que no se pueda setear un fullscreen, y si se puede, no veo la diferencia entre un set_mode a fullscreen (que es lo que supongo estamos discutiendo) y una ventana (o lo que sea) a fullscreen.

como sea, tu port puede tranquilamente hacer la inicializacion al modo nativo y luego eliminas tu el cambio de set_mode y si es diferente el modo que se pide del que esta seteado, entonces forzar un scale_resolution...

entonces tambien entiendo que si haces un programa sin set_mode funciona bien? cierto? no tendras quizas algun problema con la profundidad de video? no se, cuenta mas de lo que has visto y analizado.
No me estoy explicando muy bien...

Con SDL2 se puede poner en modo fullscreen, claro. Pero SDL2 introduce el -revolucionario- concepto de ventanas y pantallas. Se pueden manejar múltiples ventanas por separado. Por ejemplo se puede crear una aplicación que en un portátil con una salida VGA conectada tenga una ventana con cierto contenido en la pantalla del portátil y otra distinta en la salida VGA (y cada una a pantalla completa en su espacio). Dicho esto: la función SDL_SetVideoMode ya no existe. Ahora el proceso para establecer el tamaño de cada ventana es algo distinto y los conceptos no son los mismos, de forma que el código equivalente al que antes hacía SDL_SetVideoMode es algo así:
SDL_Surface *
SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
{
    SDL_DisplayMode desktop_mode, current_mode;
    int display = SDL_GetWindowDisplay(window);
    int window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
    int window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
    int window_w;
    int window_h;
    Uint32 window_flags;
    Uint32 surface_flags;

    if (!SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE)) {
        if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
            return NULL;
        }
    }

    // Just choose the default screen in case SDL_GetWindowDisplay failed
    display == -1 ? display = 0 : 1;
    SDL_GetDesktopDisplayMode(display, &desktop_mode);

    if (width == 0) {
        width = desktop_mode.w;
    }
    if (height == 0) {
        height = desktop_mode.h;
    }
    if (bpp == 0) {
        bpp = SDL_BITSPERPIXEL(desktop_mode.format);
    }

    /* Destroy existing window */
    g_publicsurface = NULL;
    if (g_shadowsurface) {
        g_shadowsurface->flags &= ~SDL_DONTFREE;
        SDL_FreeSurface(g_shadowsurface);
        g_shadowsurface = NULL;
    }
    if (g_videosurface) {
        g_videosurface->flags &= ~SDL_DONTFREE;
        SDL_FreeSurface(g_videosurface);
        g_videosurface = NULL;
    }
    if (window) {
        SDL_GetWindowPosition(window, &window_x, &window_y);
        SDL_DestroyWindow(window);
    }

    /* Set up the event filter */
    if (!SDL_GetEventFilter(NULL, NULL)) {
        SDL_SetEventFilter(g_eventfilter, NULL);
    }

    /* Create a new window */
    window_flags = SDL_WINDOW_SHOWN;
    if (flags & SDL_FULLSCREEN) {
        window_flags |= SDL_WINDOW_FULLSCREEN;
    }
    if (flags & SDL_OPENGL) {
        window_flags |= SDL_WINDOW_OPENGL;
    }
    if (flags & SDL_RESIZABLE) {
        window_flags |= SDL_WINDOW_RESIZABLE;
    }
    if (flags & SDL_NOFRAME) {
        window_flags |= SDL_WINDOW_BORDERLESS;
    }
    window =
        SDL_CreateWindow("", window_x, window_y, width, height,
                         window_flags);
    if (!window) {
        return NULL;
    }
    SDL_ShowWindow(window);

    window_flags = SDL_GetWindowFlags(window);
    surface_flags = 0;
    if (window_flags & SDL_WINDOW_FULLSCREEN) {
        surface_flags |= SDL_FULLSCREEN;
    }
    if ((window_flags & SDL_WINDOW_OPENGL) && (flags & SDL_OPENGL)) {
        surface_flags |= SDL_OPENGL;
    }
    if (window_flags & SDL_WINDOW_RESIZABLE) {
        surface_flags |= SDL_RESIZABLE;
    }
    if (window_flags & SDL_WINDOW_BORDERLESS) {
        surface_flags |= SDL_NOFRAME;
    }

    SDL_VideoFlags = flags;

    /* Create the screen surface */
    g_windowsurface = SDL_GetWindowSurface(window);
    if (!g_windowsurface) {
        return NULL;
    }

    /* Center the public surface in the window surface */
    SDL_GetWindowSize(window, &window_w, &window_h);
    SDL_VideoViewport.x = (window_w - width)/2;
    SDL_VideoViewport.y = (window_h - height)/2;
    SDL_VideoViewport.w = width;
    SDL_VideoViewport.h = height;

    g_videosurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
    g_videosurface->flags |= surface_flags;
    g_videosurface->flags |= SDL_DONTFREE;
    SDL_FreeFormat(g_videosurface->format);
    g_videosurface->format = g_windowsurface->format;
    g_videosurface->format->refcount++;
    g_videosurface->w = width;
    g_videosurface->h = height;
    g_videosurface->pitch = g_windowsurface->pitch;
    g_videosurface->pixels = (void *)((Uint8 *)g_windowsurface->pixels +
        SDL_VideoViewport.y * g_videosurface->pitch +
        SDL_VideoViewport.x  * g_videosurface->format->BytesPerPixel);
    SDL_SetClipRect(g_videosurface, NULL);

    /* Create a shadow surface if necessary */
    if ((bpp != g_videosurface->format->BitsPerPixel)
        && !(flags & SDL_ANYFORMAT)) {
        g_shadowsurface =
            SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
        if (!g_shadowsurface) {
            return NULL;
        }
        g_shadowsurface->flags |= surface_flags;
        g_shadowsurface->flags |= SDL_DONTFREE;

        /* 8-bit g_shadowsurface surfaces report that they have exclusive palette */
        if (g_shadowsurface->format->palette) {
            g_shadowsurface->flags |= SDL_HWPALETTE;
            SDL_DitherColors(g_shadowsurface->format->palette->colors,
                             g_shadowsurface->format->BitsPerPixel);
        }
        SDL_FillRect(g_shadowsurface, NULL,
            SDL_MapRGB(g_shadowsurface->format, 0, 0, 0));
    }
    g_publicsurface =
        (g_shadowsurface ? g_shadowsurface : g_videosurface);

    ClearVideoSurface();

    /* We're finally done! */
    return g_publicsurface;
}


Pero vamos, que esto no viene mucho a cuento.
Lo único que comentaba es que en la gr_set_mode y en algunos móviles al hacer SDL_SetVideoMode una segunda vez falla. Preguntaba si no sería posible evitar la llamada siempre y cuando la superficie que se vaya a crear sea idéntica a la que ya tengo es decir, si hago:
set_mode(640, 480, 16);
FRAME;
scale_resolution = 6400480;
set_mode(320, 240, 16);

No tiene sentido que internamente se llame a SDL_SetVideoMode la segunda vez porque me vale la SDL_Surface que tenía y la puedo reutilizar.

Yo esto lo voy a meter en el port a Android pero me preguntaba si no sería interesante meterlo en el código oficial, por eso lo sugería.

SplinterGU

esta bueno eso de las ventanas...

entiendo, pero igual aca estas intentando parchar un bug de la SDL desde fuera...

hazlo en tu port... ya vere yo cuando llegue a eso... ahora estoy en otras cosas con bennugd...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

josebita

Quote from: SplinterGU on December 18, 2012, 12:36:11 AM
esta bueno eso de las ventanas...

entiendo, pero igual aca estas intentando parchar un bug de la SDL desde fuera...

hazlo en tu port... ya vere yo cuando llegue a eso... ahora estoy en otras cosas con bennugd...
En realidad yo no lo llamaría "arreglar", pero sí :)

SplinterGU

yo tampoco lo llamo arreglar... parchar que es mas triste...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

panreyes

Si funciona, me importa un pedo que sea un arreglo, un parche o el fascismo xD

SplinterGU

Download Lastest BennuGD Release: http://www.bennugd.org/node/2