view docs/html/guidevideoexamples.html @ 641:df178851293b

Date: 28 Jun 2003 22:42:52 +0100 From: Alan Swanson Subject: Re: [SDL] New XFree 4.3 Video Mode Patch I have a wee amendment that moves the qsort in set_best_resolution to only occur after failing to find an exact match only. This would make absolutely sure we get a user set mode. While I've never had any problems for my normal resolutions (1280x1024, 1024x768, 800x600 & 640,480) while closely examining the output from qsort I've noticed it doesn't seem to sort the modes fully. These is one definite wrong at 1152x768 and a few that just look wrong to me. From a program (attached) I made to examine this more easily. X has sorted its mode list using the same method as ours (plus frequency), and our user modes get inserted without any other movement. On the patch I've made I've also changed cmpmodes to sort on vertical resolution and then horizontal. Ie vertical is now most significant bit.
author Sam Lantinga <slouken@libsdl.org>
date Sat, 28 Jun 2003 21:52:26 +0000
parents 55f1f1b3e27d
children
line wrap: on
line source

<HTML
><HEAD
><TITLE
>Video Examples</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.64
"><LINK
REL="HOME"
TITLE="SDL Library Documentation"
HREF="index.html"><LINK
REL="UP"
TITLE="Examples"
HREF="guideexamples.html"><LINK
REL="PREVIOUS"
TITLE="Examples"
HREF="guideexamples.html"><LINK
REL="NEXT"
TITLE="Event Examples"
HREF="guideeventexamples.html"></HEAD
><BODY
CLASS="SECT1"
BGCOLOR="#FFF8DC"
TEXT="#000000"
LINK="#0000ee"
VLINK="#551a8b"
ALINK="#ff0000"
><DIV
CLASS="NAVHEADER"
><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>SDL Library Documentation</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="guideexamples.html"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
>Chapter 4. Examples</TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="guideeventexamples.html"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="GUIDEVIDEOEXAMPLES"
>Video Examples</A
></H1
><P
></P
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="AEN375"
>Initializing the video display</A
></H2
><P
><PRE
CLASS="PROGRAMLISTING"
>    SDL_Surface *screen;

    /* Initialize the SDL library */
    if( SDL_Init(SDL_INIT_VIDEO) &#60; 0 ) {
        fprintf(stderr,
                "Couldn't initialize SDL: %s\n", SDL_GetError());
        exit(1);
    }

    /* Clean up on exit */
    atexit(SDL_Quit);

    /* Initialize the display in a 640x480 8-bit palettized mode */
    screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE);
    if ( screen == NULL ) {
        fprintf(stderr, "Couldn't set 640x480x8 video mode: %s\n",
                        SDL_GetError());
        exit(1);
    }</PRE
></P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="AEN379"
>Initializing the best video mode</A
></H2
><P
><PRE
CLASS="PROGRAMLISTING"
>    /* Have a preference for 8-bit, but accept any depth */
    screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE|SDL_ANYFORMAT);
    if ( screen == NULL ) {
        fprintf(stderr, "Couldn't set 640x480x8 video mode: %s\n",
                        SDL_GetError());
        exit(1);
    }
    printf("Set 640x480 at %d bits-per-pixel mode\n",
           screen-&#62;format-&#62;BitsPerPixel);</PRE
></P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="AEN383"
>Loading and displaying a BMP file</A
></H2
><P
><PRE
CLASS="PROGRAMLISTING"
>    SDL_Surface *image;
    SDL_Rect dest;
    int ncolors, i;
    SDL_Color *colors;

    /* Load the BMP file into a surface */
    image = SDL_LoadBMP("sample.bmp");
    if ( image == NULL ) {
        fprintf(stderr, "Couldn't load sample.bmp: %s\n",
                        SDL_GetError());
        return;
    }

    /* Set the display colors -- SDL_SetColors() only does something on
       palettized displays, but it doesn't hurt anything on HiColor or
       TrueColor displays.
       If the display colors have already been set, this step can be
       skipped, and the library will automatically map the image to
       the current display colors.
    */
    if ( image-&#62;format-&#62;palette ) {
        ncolors = image-&#62;format-&#62;palette-&#62;ncolors;
        colors  = (SDL_Color *)malloc(ncolors*sizeof(SDL_Color));
        memcpy(colors, image-&#62;format-&#62;palette-&#62;colors, ncolors);
    } 
    else {
        int r, g, b;

        /* Allocate 256 color palette */
        ncolors = 256;
        colors  = (SDL_Color *)malloc(ncolors*sizeof(SDL_Color));

        /* Set a 3,3,2 color cube */
        for ( r=0; r&#60;8; ++r ) {
            for ( g=0; g&#60;8; ++g ) {
                for ( b=0; b&#60;4; ++b ) {
                    i = ((r&#60;&#60;5)|(g&#60;&#60;2)|b);
                    colors[i].r = r&#60;&#60;5;
                    colors[i].g = g&#60;&#60;5;
                    colors[i].b = b&#60;&#60;6;
                }
            }
        }
        /* Note: A better way of allocating the palette might be
           to calculate the frequency of colors in the image
           and create a palette based on that information.
        */
    }
    /* Set colormap, try for all the colors, but don't worry about it */
    SDL_SetColors(screen, colors, 0, ncolors);
    free(colors);

    /* Blit onto the screen surface */
    dest.x = 0;
    dest.y = 0;
    dest.w = image-&#62;w;
    dest.h = image-&#62;h;
    SDL_BlitSurface(image, NULL, screen, &#38;dest);

    SDL_UpdateRects(screen, 1, &#38;dest);

    /* Free the allocated BMP surface */
    SDL_FreeSurface(image);
    return;</PRE
></P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="AEN387"
>Drawing directly to the display</A
></H2
><P
><PRE
CLASS="PROGRAMLISTING"
>    /* Code to set a yellow pixel at the center of the screen */

    Sint32   X, Y;
    Uint32   pixel;
    Uint8   *bits, bpp;

    /* Map the color yellow to this display (R=0xFF, G=0xFF, B=0x00)
       Note:  If the display is palettized, you must set the palette first.
    */
    pixel = SDL_MapRGB(screen-&#62;format, 0xFF, 0xFF, 0x00);

    /* Calculate the framebuffer offset of the center of the screen */
    if ( SDL_MUSTLOCK(screen) ) {
        if ( SDL_LockSurface(screen) &#60; 0 )
            return;
    }
    bpp = screen-&#62;format-&#62;BytesPerPixel;
    X = screen-&#62;w/2;
    Y = screen-&#62;h/2;
    bits = ((Uint8 *)screen-&#62;pixels)+Y*screen-&#62;pitch+X*bpp;

    /* Set the pixel */
    switch(bpp) {
        case 1:
            *((Uint8 *)(bits)) = (Uint8)pixel;
            break;
        case 2:
            *((Uint16 *)(bits)) = (Uint16)pixel;
            break;
        case 3: { /* Format/endian independent */
            Uint8 r, g, b;

            r = (pixel&#62;&#62;screen-&#62;format-&#62;Rshift)&#38;0xFF;
            g = (pixel&#62;&#62;screen-&#62;format-&#62;Gshift)&#38;0xFF;
            b = (pixel&#62;&#62;screen-&#62;format-&#62;Bshift)&#38;0xFF;
            *((bits)+screen-&#62;format-&#62;Rshift/8) = r; 
            *((bits)+screen-&#62;format-&#62;Gshift/8) = g;
            *((bits)+screen-&#62;format-&#62;Bshift/8) = b;
            }
            break;
        case 4:
            *((Uint32 *)(bits)) = (Uint32)pixel;
            break;
    }

    /* Update the display */
    if ( SDL_MUSTLOCK(screen) ) {
        SDL_UnlockSurface(screen);
    }
    SDL_UpdateRect(screen, X, Y, 1, 1);

    return;</PRE
></P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="AEN391"
>Fastest possible surface blit</A
></H2
><P
>There are three different ways you can draw an image to the screen: 
<P
></P
><TABLE
BORDER="0"
><TBODY
><TR
><TD
>1.Create a surface and use <A
HREF="sdlblitsurface.html"
><TT
CLASS="FUNCTION"
>SDL_BlitSurface</TT
></A
> to blit it to the screen</TD
></TR
><TR
><TD
>2.Create the video surface in system memory and call <A
HREF="sdlupdaterect.html"
><TT
CLASS="FUNCTION"
>SDL_UpdateRect</TT
></A
></TD
></TR
><TR
><TD
>3.Create the video surface in video memory and call <A
HREF="sdllocksurface.html"
><TT
CLASS="FUNCTION"
>SDL_LockSurface</TT
></A
></TD
></TR
></TBODY
></TABLE
><P
></P
>
The best way to do this is to combine methods: 
<PRE
CLASS="PROGRAMLISTING"
>#include &#60;stdio.h&#62;
#include &#60;stdlib.h&#62;
#include "SDL.h"
#include "SDL_timer.h"

void ComplainAndExit(void)
{
    fprintf(stderr, "Problem: %s\n", SDL_GetError());
    exit(1);
}

int main(int argc, char *argv[])
{
    SDL_PixelFormat fmt;
    SDL_Surface *screen, *locked;
    SDL_Surface *imagebmp, *image;
    SDL_Rect dstrect;
    int i;
    Uint8 *buffer;

    /* Initialize SDL */
    if ( SDL_Init(SDL_INIT_VIDEO) &#60; 0 ) {
        ComplainAndExit();
    }
    atexit(SDL_Quit);

    /* Load a BMP image into a surface */
    imagebmp = SDL_LoadBMP("image.bmp");
    if ( imagebmp == NULL ) {
        ComplainAndExit();
    }

    /* Set the video mode (640x480 at native depth) */
    screen = SDL_SetVideoMode(640, 480, 0, SDL_HWSURFACE|SDL_FULLSCREEN);
    if ( screen == NULL ) {
        ComplainAndExit();
    }

    /* Set the video colormap */
    if ( imagebmp-&#62;format-&#62;palette != NULL ) {
        SDL_SetColors(screen,
                      imagebmp-&#62;format-&#62;palette-&#62;colors, 0,
                      imagebmp-&#62;format-&#62;palette-&#62;ncolors);
    }

    /* Convert the image to the video format (maps colors) */
    image = SDL_DisplayFormat(imagebmp);
    SDL_FreeSurface(imagebmp);
    if ( image == NULL ) {
        ComplainAndExit();
    }

    /* Draw bands of color on the raw surface */
    if ( SDL_MUSTLOCK(screen) ) {
        if ( SDL_LockSurface(screen) &#60; 0 )
            ComplainAndExit();
    }
    buffer=(Uint8 *)screen-&#62;pixels;
    for ( i=0; i&#60;screen-&#62;h; ++i ) {
        memset(buffer,(i*255)/screen-&#62;h,
               screen-&#62;w*screen-&#62;format-&#62;BytesPerPixel);
               buffer += screen-&#62;pitch;
    }
    if ( SDL_MUSTLOCK(screen) ) {
        SDL_UnlockSurface(screen);
    }

    /* Blit the image to the center of the screen */
    dstrect.x = (screen-&#62;w-image-&#62;w)/2;
    dstrect.y = (screen-&#62;h-image-&#62;h)/2;
    dstrect.w = image-&#62;w;
    dstrect.h = image-&#62;h;
    if ( SDL_BlitSurface(image, NULL, screen, &#38;dstrect) &#60; 0 ) {
        SDL_FreeSurface(image);
        ComplainAndExit();
    }
    SDL_FreeSurface(image);

    /* Update the screen */
    SDL_UpdateRects(screen, 1, &#38;dstrect);

    SDL_Delay(5000);        /* Wait 5 seconds */
    exit(0);
}</PRE
></P
></DIV
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="guideexamples.html"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="guideeventexamples.html"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Examples</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="guideexamples.html"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Event Examples</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>