From d0a8e400c94802660503e583d83a70ef3cd2734a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 24 Jun 2006 16:51:01 +0000 Subject: [PATCH] Added a multi-window version of testsprite using the new API. --- include/SDL_video.h | 2 +- src/video/SDL_bmp.c | 1 - src/video/SDL_pixels.c | 7 +- src/video/SDL_renderer_sw.c | 20 +-- src/video/SDL_sysvideo.h | 7 +- src/video/SDL_video.c | 74 ++++++--- src/video/dummy/SDL_nullrender.c | 9 +- test/Makefile.in | 5 +- test/testsprite2.c | 257 +++++++++++++++++++++++++++++++ 9 files changed, 340 insertions(+), 42 deletions(-) create mode 100644 test/testsprite2.c diff --git a/include/SDL_video.h b/include/SDL_video.h index a8bc6a351..d7f283616 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -763,7 +763,7 @@ extern DECLSPEC int SDLCALL SDL_SelectRenderer(SDL_WindowID windowID); /** * \fn SDL_TextureID SDL_CreateTexture(Uint32 format, int access, int w, int h) * - * \brief Create a texture + * \brief Create a texture for the current rendering context. * * \param format The format of the texture * \param access One of the enumerated values in SDL_TextureAccess diff --git a/src/video/SDL_bmp.c b/src/video/SDL_bmp.c index 364f3c027..443f88465 100644 --- a/src/video/SDL_bmp.c +++ b/src/video/SDL_bmp.c @@ -232,7 +232,6 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc) SDL_RWread(src, &palette->colors[i].unused, 1, 1); } } - palette->ncolors = biClrUsed; } /* Read the surface pixels. Note that the bmp image is upside down */ diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c index 7f1d9d01c..839a3eca9 100644 --- a/src/video/SDL_pixels.c +++ b/src/video/SDL_pixels.c @@ -642,8 +642,11 @@ Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical) if (identical) { if (src->ncolors <= dst->ncolors) { /* If an identical palette, no need to map */ - if (SDL_memcmp(src->colors, dst->colors, src->ncolors * - sizeof(SDL_Color)) == 0) { + if (src == dst + || + (SDL_memcmp + (src->colors, dst->colors, + src->ncolors * sizeof(SDL_Color)) == 0)) { *identical = 1; return (NULL); } diff --git a/src/video/SDL_renderer_sw.c b/src/video/SDL_renderer_sw.c index df1be2464..e6f57846c 100644 --- a/src/video/SDL_renderer_sw.c +++ b/src/video/SDL_renderer_sw.c @@ -111,7 +111,8 @@ typedef struct SDL_Renderer * SDL_SW_CreateRenderer(SDL_Window * window, Uint32 flags) { - SDL_DisplayMode *displayMode = &window->display->current_mode; + SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); + SDL_DisplayMode *displayMode = &display->current_mode; SDL_Renderer *renderer; SDL_SW_RenderData *data; int i, n; @@ -156,7 +157,7 @@ SDL_SW_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->DestroyTexture = SDL_SW_DestroyTexture; renderer->DestroyRenderer = SDL_SW_DestroyRenderer; renderer->info = SDL_SW_RenderDriver.info; - renderer->window = window; + renderer->window = window->id; renderer->driverdata = data; renderer->info.flags = SDL_Renderer_RenderTarget; @@ -179,14 +180,14 @@ SDL_SW_CreateRenderer(SDL_Window * window, Uint32 flags) SDL_SW_DestroyRenderer(renderer); return NULL; } - SDL_SetSurfacePalette(data->screens[i], window->display->palette); + SDL_SetSurfacePalette(data->screens[i], display->palette); } data->current_screen = 0; data->target = data->screens[0]; /* Find a render driver that we can use to display data */ - for (i = 0; i < window->display->num_render_drivers; ++i) { - SDL_RenderDriver *driver = &window->display->render_drivers[i]; + for (i = 0; i < display->num_render_drivers; ++i) { + SDL_RenderDriver *driver = &display->render_drivers[i]; if (driver->info.name != SDL_SW_RenderDriver.info.name) { data->renderer = driver->CreateRenderer(window, SDL_Renderer_PresentDiscard); @@ -195,7 +196,7 @@ SDL_SW_CreateRenderer(SDL_Window * window, Uint32 flags) } } } - if (i == window->display->num_render_drivers) { + if (i == display->num_render_drivers) { SDL_SW_DestroyRenderer(renderer); SDL_SetError("Couldn't find display render driver"); return NULL; @@ -377,6 +378,8 @@ SDL_SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, int blendMode, int scaleMode) { SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; + SDL_Window *window = SDL_GetWindowFromID(renderer->window); + SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { SDL_Surface *target = data->target; @@ -384,9 +387,8 @@ SDL_SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, (Uint8 *) target->pixels + dstrect->y * target->pitch + dstrect->x * target->format->BytesPerPixel; return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata, - srcrect, - renderer->window->display->current_mode. - format, dstrect->w, dstrect->h, pixels, + srcrect, display->current_mode.format, + dstrect->w, dstrect->h, pixels, target->pitch); } else { SDL_Surface *surface = (SDL_Surface *) texture->driverdata; diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 61b42ff2a..97db7c09f 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -104,7 +104,7 @@ struct SDL_Renderer SDL_RendererInfo info; /* The window associated with the renderer */ - SDL_Window *window; + SDL_WindowID window; void *driverdata; }; @@ -130,7 +130,7 @@ struct SDL_Window Uint16 *gamma; - SDL_VideoDisplay *display; + int display; SDL_Renderer *renderer; void *userdata; @@ -445,6 +445,9 @@ extern void SDL_AddDisplayMode(int displayIndex, extern void SDL_AddRenderDriver(int displayIndex, const SDL_RenderDriver * driver); +extern SDL_Window *SDL_GetWindowFromID(SDL_WindowID windowID); +extern SDL_VideoDisplay *SDL_GetDisplayFromWindow(SDL_Window * window); + #endif /* _SDL_sysvideo_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 7aac9743e..b2fb80aa5 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -507,6 +507,16 @@ SDL_GetClosestDisplayMode(const SDL_DisplayMode * mode, } else { closest->refresh_rate = mode->refresh_rate; } + /* Pick some reasonable defaults if the app and driver don't care */ + if (!closest->format) { + closest->format = SDL_PixelFormat_RGB888; + } + if (!closest->w) { + closest->w = 640; + } + if (!closest->h) { + closest->h = 480; + } return closest; } return NULL; @@ -577,6 +587,8 @@ SDL_SetDisplayMode(const SDL_DisplayMode * mode) if (!display->palette) { return -1; } + SDL_DitherColors(display->palette->colors, + SDL_BITSPERPIXEL(display_mode.format)); } } @@ -664,7 +676,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) window.w = w; window.h = h; window.flags = (flags & allowed_flags); - window.display = &SDL_CurrentDisplay; + window.display = _this->current_display; if (_this->CreateWindow && _this->CreateWindow(_this, &window) < 0) { if (window.title) { @@ -707,7 +719,7 @@ SDL_CreateWindowFrom(const void *data) SDL_zero(window); window.id = _this->next_object_id++; - window.display = &SDL_CurrentDisplay; + window.display = _this->current_display; if (!_this->CreateWindowFrom || _this->CreateWindowFrom(_this, &window, data) < 0) { @@ -734,7 +746,7 @@ SDL_CreateWindowFrom(const void *data) return window.id; } -static __inline__ SDL_Window * +SDL_Window * SDL_GetWindowFromID(SDL_WindowID windowID) { int i, j; @@ -755,6 +767,15 @@ SDL_GetWindowFromID(SDL_WindowID windowID) return NULL; } +SDL_VideoDisplay * +SDL_GetDisplayFromWindow(SDL_Window * window) +{ + if (!_this) { + return NULL; + } + return &_this->displays[window->display]; +} + Uint32 SDL_GetWindowFlags(SDL_WindowID windowID) { @@ -1221,11 +1242,20 @@ SDL_CreateTextureFromSurface(Uint32 format, int access, SDL_Surface * surface) return 0; } } else { - bpp = fmt->BitsPerPixel; - Rmask = fmt->Rmask; - Gmask = fmt->Gmask; - Bmask = fmt->Bmask; - Amask = fmt->Amask; + if (fmt->Amask || !(surface_flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA))) { + bpp = fmt->BitsPerPixel; + Rmask = fmt->Rmask; + Gmask = fmt->Gmask; + Bmask = fmt->Bmask; + Amask = fmt->Amask; + } else { + /* Need a format with alpha */ + bpp = 32; + Rmask = 0x00FF0000; + Gmask = 0x0000FF00; + Bmask = 0x000000FF; + Amask = 0xFF000000; + } format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask); if (!format) { SDL_SetError("Unknown pixel format"); @@ -1261,14 +1291,10 @@ SDL_CreateTextureFromSurface(Uint32 format, int access, SDL_Surface * surface) } /* Copy the palette if any */ - if (fmt->palette && dst.format->palette) { + if (fmt->palette) { SDL_SetTexturePalette(textureID, fmt->palette->colors, 0, fmt->palette->ncolors); - - SDL_memcpy(dst.format->palette->colors, - fmt->palette->colors, - fmt->palette->ncolors * sizeof(SDL_Color)); - dst.format->palette->ncolors = fmt->palette->ncolors; + SDL_SetSurfacePalette(&dst, fmt->palette); } /* Make the texture transparent if the surface has colorkey */ @@ -1552,10 +1578,11 @@ SDL_RenderFill(const SDL_Rect * rect, Uint32 color) } if (!rect) { + SDL_Window *window = SDL_GetWindowFromID(renderer->window); full_rect.x = 0; full_rect.y = 0; - full_rect.w = renderer->window->w; - full_rect.h = renderer->window->h; + full_rect.w = window->w; + full_rect.h = window->h; rect = &full_rect; } @@ -1588,10 +1615,11 @@ SDL_RenderCopy(SDL_TextureID textureID, const SDL_Rect * srcrect, srcrect = &full_srcrect; } if (!dstrect) { + SDL_Window *window = SDL_GetWindowFromID(renderer->window); full_dstrect.x = 0; full_dstrect.y = 0; - full_dstrect.w = renderer->window->w; - full_dstrect.h = renderer->window->h; + full_dstrect.w = window->w; + full_dstrect.h = window->h; dstrect = &full_dstrect; } @@ -1615,10 +1643,11 @@ SDL_RenderReadPixels(const SDL_Rect * rect, void *pixels, int pitch) } if (!rect) { + SDL_Window *window = SDL_GetWindowFromID(renderer->window); full_rect.x = 0; full_rect.y = 0; - full_rect.w = renderer->window->w; - full_rect.h = renderer->window->h; + full_rect.w = window->w; + full_rect.h = window->h; rect = &full_rect; } @@ -1641,10 +1670,11 @@ SDL_RenderWritePixels(const SDL_Rect * rect, const void *pixels, int pitch) } if (!rect) { + SDL_Window *window = SDL_GetWindowFromID(renderer->window); full_rect.x = 0; full_rect.y = 0; - full_rect.w = renderer->window->w; - full_rect.h = renderer->window->h; + full_rect.w = window->w; + full_rect.h = window->h; rect = &full_rect; } diff --git a/src/video/dummy/SDL_nullrender.c b/src/video/dummy/SDL_nullrender.c index e9d009a20..ee6badebd 100644 --- a/src/video/dummy/SDL_nullrender.c +++ b/src/video/dummy/SDL_nullrender.c @@ -63,7 +63,8 @@ typedef struct SDL_Renderer * SDL_DUMMY_CreateRenderer(SDL_Window * window, Uint32 flags) { - SDL_DisplayMode *displayMode = &window->display->current_mode; + SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); + SDL_DisplayMode *displayMode = &display->current_mode; SDL_Renderer *renderer; SDL_DUMMY_RenderData *data; int i, n; @@ -96,7 +97,7 @@ SDL_DUMMY_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->RenderPresent = SDL_DUMMY_RenderPresent; renderer->DestroyRenderer = SDL_DUMMY_DestroyRenderer; renderer->info = SDL_DUMMY_RenderDriver.info; - renderer->window = window; + renderer->window = window->id; renderer->driverdata = data; data->surface = @@ -106,7 +107,7 @@ SDL_DUMMY_CreateRenderer(SDL_Window * window, Uint32 flags) SDL_DUMMY_DestroyRenderer(renderer); return NULL; } - SDL_SetSurfacePalette(data->surface, window->display->palette); + SDL_SetSurfacePalette(data->surface, display->palette); return renderer; } @@ -170,7 +171,7 @@ SDL_DUMMY_RenderPresent(SDL_Renderer * renderer) if (SDL_getenv("SDL_VIDEO_DUMMY_SAVE_FRAMES")) { char file[128]; SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp", - renderer->window->id, ++frame_number); + renderer->window, ++frame_number); SDL_SaveBMP(surface, file); } } diff --git a/test/Makefile.in b/test/Makefile.in index 52fd803e5..bb1699434 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -7,7 +7,7 @@ EXE = @EXE@ CFLAGS = @CFLAGS@ LIBS = @LIBS@ -TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testdyngl$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) threadwin$(EXE) torturethread$(EXE) +TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testdyngl$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) threadwin$(EXE) torturethread$(EXE) all: $(TARGETS) @@ -80,6 +80,9 @@ testsem$(EXE): $(srcdir)/testsem.c testsprite$(EXE): $(srcdir)/testsprite.c $(CC) -o $@ $? $(CFLAGS) $(LIBS) @MATHLIB@ +testsprite2$(EXE): $(srcdir)/testsprite2.c + $(CC) -o $@ $? $(CFLAGS) $(LIBS) @MATHLIB@ + testtimer$(EXE): $(srcdir)/testtimer.c $(CC) -o $@ $? $(CFLAGS) $(LIBS) diff --git a/test/testsprite2.c b/test/testsprite2.c new file mode 100644 index 000000000..51f044a45 --- /dev/null +++ b/test/testsprite2.c @@ -0,0 +1,257 @@ +/* Simple program: Move N sprites around on the screen as fast as possible */ + +#include +#include +#include +#include +#include +#include + +#include "SDL.h" + +#define NUM_WINDOWS 2 +#define WINDOW_W 640 +#define WINDOW_H 480 +#define NUM_SPRITES 100 +#define MAX_SPEED 1 + +static int num_windows; +static int num_sprites; +static SDL_WindowID *windows; +static SDL_TextureID *sprites; +static SDL_Rect *positions; +static SDL_Rect *velocities; +static int sprite_w, sprite_h; + +/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ +static void +quit(int rc) +{ + if (windows) { + SDL_free(windows); + } + if (sprites) { + SDL_free(sprites); + } + if (positions) { + SDL_free(positions); + } + if (velocities) { + SDL_free(velocities); + } + SDL_Quit(); + exit(rc); +} + +int +LoadSprite(char *file) +{ + int i; + SDL_Surface *temp; + + /* Load the sprite image */ + temp = SDL_LoadBMP(file); + if (temp == NULL) { + fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError()); + return (-1); + } + sprite_w = temp->w; + sprite_h = temp->h; + + /* Set transparent pixel as the pixel at (0,0) */ + if (temp->format->palette) { + SDL_SetColorKey(temp, SDL_SRCCOLORKEY, *(Uint8 *) temp->pixels); + } + + /* Create textures from the image */ + for (i = 0; i < num_windows; ++i) { + SDL_SelectRenderer(windows[i]); + sprites[i] = + SDL_CreateTextureFromSurface(0, SDL_TextureAccess_Remote, temp); + if (!sprites[i]) { + fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError()); + SDL_FreeSurface(temp); + return (-1); + } + } + SDL_FreeSurface(temp); + + /* We're ready to roll. :) */ + return (0); +} + +void +MoveSprites(SDL_WindowID window, SDL_TextureID sprite) +{ + int i, n; + int window_w, window_h; + SDL_Rect area, *position, *velocity; + + SDL_SelectRenderer(window); + + SDL_RenderFill(NULL, 0); + + /* Query the sizes */ + SDL_GetWindowSize(window, &window_w, &window_h); + + /* Move the sprite, bounce at the wall, and draw */ + n = 0; + for (i = 0; i < num_sprites; ++i) { + position = &positions[i]; + velocity = &velocities[i]; + position->x += velocity->x; + if ((position->x < 0) || (position->x >= (window_w - sprite_w))) { + velocity->x = -velocity->x; + position->x += velocity->x; + } + position->y += velocity->y; + if ((position->y < 0) || (position->y >= (window_h - sprite_w))) { + velocity->y = -velocity->y; + position->y += velocity->y; + } + + /* Blit the sprite onto the screen */ + SDL_RenderCopy(sprite, NULL, position, SDL_TextureBlendMode_Mask, + SDL_TextureScaleMode_None); + } + + /* Update the screen! */ + SDL_RenderPresent(); +} + +int +main(int argc, char *argv[]) +{ + const SDL_DisplayMode *current_mode; + int window_w, window_h; + int i, done; + SDL_Event event; + Uint32 then, now, frames; + + /* Initialize SDL */ + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); + return (1); + } + + num_windows = NUM_WINDOWS; + num_sprites = NUM_SPRITES; + window_w = WINDOW_W; + window_h = WINDOW_H; + while (argc > 1) { + --argc; + if (strcmp(argv[argc - 1], "-width") == 0) { + window_w = atoi(argv[argc]); + --argc; + } else if (strcmp(argv[argc - 1], "-height") == 0) { + window_h = atoi(argv[argc]); + --argc; + } else if (isdigit(argv[argc][0])) { + num_sprites = atoi(argv[argc]); + } else { + fprintf(stderr, + "Usage: %s [-width] [-height] [numsprites]\n", argv[0]); + quit(1); + } + } + + /* Initialize the video mode, if necessary */ + current_mode = SDL_GetCurrentDisplayMode(); + if (!current_mode->w || !current_mode->h) { + SDL_DisplayMode mode; + + /* Let the driver pick something it likes, we don't care */ + mode.format = 0; + mode.w = 0; + mode.h = 0; + mode.refresh_rate = 0; + + if (SDL_SetDisplayMode(&mode) < 0) { + fprintf(stderr, "Couldn't set display mode: %s\n", + SDL_GetError()); + quit(2); + } + } + + /* Create the windows, initialize the renderers, and load the textures */ + windows = (SDL_WindowID *) SDL_malloc(num_windows * sizeof(*windows)); + sprites = (SDL_TextureID *) SDL_malloc(num_windows * sizeof(*sprites)); + if (!windows || !sprites) { + fprintf(stderr, "Out of memory!\n"); + quit(2); + } + for (i = 0; i < num_windows; ++i) { + char title[32]; + + SDL_snprintf(title, sizeof(title), "testsprite %d", i + 1); + windows[i] = + SDL_CreateWindow(title, -1, -1, window_w, window_h, + SDL_WINDOW_SHOWN); + if (!windows[i]) { + fprintf(stderr, "Couldn't create window: %s\n", SDL_GetError()); + quit(2); + } + + if (SDL_CreateRenderer(windows[i], -1, 0) < 0) { + fprintf(stderr, "Couldn't create renderer: %s\n", SDL_GetError()); + quit(2); + } + } + if (LoadSprite("icon.bmp") < 0) { + quit(2); + } + + /* Allocate memory for the sprite info */ + positions = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect)); + velocities = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect)); + if (!positions || !velocities) { + fprintf(stderr, "Out of memory!\n"); + quit(2); + } + srand(time(NULL)); + for (i = 0; i < num_sprites; ++i) { + positions[i].x = rand() % (window_w - sprite_w); + positions[i].y = rand() % (window_h - sprite_h); + positions[i].w = sprite_w; + positions[i].h = sprite_h; + velocities[i].x = 0; + velocities[i].y = 0; + while (!velocities[i].x && !velocities[i].y) { + velocities[i].x = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED; + velocities[i].y = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED; + } + } + + /* Loop, blitting sprites and waiting for a keystroke */ + frames = 0; + then = SDL_GetTicks(); + done = 0; + while (!done) { + /* Check for events */ + ++frames; + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_KEYDOWN: + /* Any keypress quits the app... */ + case SDL_QUIT: + done = 1; + break; + default: + break; + } + } + for (i = 0; i < num_windows; ++i) { + MoveSprites(windows[i], sprites[i]); + } + } + + /* Print out some timing information */ + now = SDL_GetTicks(); + if (now > then) { + printf("%2.2f frames per second\n", + ((double) frames * 1000) / (now - then)); + } + quit(0); +} + +/* vi: set ts=4 sw=4 expandtab: */