From 3c6de0da94ce187d252982692ad8832591c608c8 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 13 Feb 2011 23:09:18 -0800 Subject: [PATCH] Center the old SDL 1.2 screen in the window if we can't get the size we wanted. --- src/SDL_compat.c | 116 +++++++++++++++++++++++++++++++++-------- src/video/SDL_rect.c | 39 ++++++++++++++ src/video/SDL_rect_c.h | 26 +++++++++ src/video/SDL_video.c | 40 +++++--------- 4 files changed, 170 insertions(+), 51 deletions(-) create mode 100644 src/video/SDL_rect_c.h diff --git a/src/SDL_compat.c b/src/SDL_compat.c index 8ff4dd861..e85d2293e 100644 --- a/src/SDL_compat.c +++ b/src/SDL_compat.c @@ -32,11 +32,13 @@ static SDL_Window *SDL_VideoWindow = NULL; +static SDL_Surface *SDL_WindowSurface = NULL; static SDL_Surface *SDL_VideoSurface = NULL; static SDL_Surface *SDL_ShadowSurface = NULL; static SDL_Surface *SDL_PublicSurface = NULL; static SDL_GLContext *SDL_VideoContext = NULL; static Uint32 SDL_VideoFlags = 0; +static SDL_Rect SDL_VideoViewport; static char *wm_title = NULL; static SDL_Surface *SDL_VideoIcon; static int SDL_enabled_UNICODE = 0; @@ -211,10 +213,15 @@ SDL_CompatEventFilter(void *userdata, SDL_Event * event) break; case SDL_WINDOWEVENT_RESIZED: SDL_FlushEvent(SDL_VIDEORESIZE); - fake.type = SDL_VIDEORESIZE; - fake.resize.w = event->window.data1; - fake.resize.h = event->window.data2; - SDL_PushEvent(&fake); + /* We don't want to expose that the window width and height will + be different if we don't get the desired fullscreen mode. + */ + if (SDL_VideoWindow && !(SDL_GetWindowFlags(SDL_VideoWindow) & SDL_WINDOW_FULLSCREEN)) { + fake.type = SDL_VIDEORESIZE; + fake.resize.w = event->window.data1; + fake.resize.h = event->window.data2; + SDL_PushEvent(&fake); + } break; case SDL_WINDOWEVENT_MINIMIZED: fake.type = SDL_ACTIVEEVENT; @@ -282,6 +289,19 @@ SDL_CompatEventFilter(void *userdata, SDL_Event * event) //printf("TEXTINPUT: '%s'\n", event->text.text); break; } + case SDL_MOUSEMOTION: + { + event->motion.x -= SDL_VideoViewport.x; + event->motion.y -= SDL_VideoViewport.y; + break; + } + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + { + event->button.x -= SDL_VideoViewport.x; + event->button.y -= SDL_VideoViewport.y; + break; + } case SDL_MOUSEWHEEL: { Uint8 button; @@ -321,6 +341,7 @@ SDL_CompatEventFilter(void *userdata, SDL_Event * event) static void GetEnvironmentWindowPosition(int w, int h, int *x, int *y) { + int display = GetVideoDisplay(); const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS"); const char *center = SDL_getenv("SDL_VIDEO_CENTERED"); if (window) { @@ -332,22 +353,20 @@ GetEnvironmentWindowPosition(int w, int h, int *x, int *y) } } if (center) { - SDL_DisplayMode mode; - SDL_GetDesktopDisplayMode(GetVideoDisplay(), &mode); - *x = (mode.w - w) / 2; - *y = (mode.h - h) / 2; + *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display); + *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display); } } static void ClearVideoSurface() { - Uint32 black; - - /* Clear the surface for display */ - black = SDL_MapRGB(SDL_PublicSurface->format, 0, 0, 0); - SDL_FillRect(SDL_PublicSurface, NULL, black); - SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0); + if (SDL_ShadowSurface) { + SDL_FillRect(SDL_ShadowSurface, NULL, + SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0)); + } + SDL_FillRect(SDL_WindowSurface, NULL, 0); + SDL_UpdateWindowSurface(SDL_VideoWindow); } static void @@ -408,11 +427,18 @@ SDL_ResizeVideoMode(int width, int height, int bpp, Uint32 flags) return 0; } - /* Destroy the screen texture and recreate it */ - SDL_VideoSurface = SDL_GetWindowSurface(SDL_VideoWindow); - if (!SDL_VideoSurface) { + SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow); + if (!SDL_WindowSurface) { + return -1; + } + if (SDL_VideoSurface->format != SDL_WindowSurface->format) { return -1; } + SDL_VideoSurface->w = width; + SDL_VideoSurface->h = height; + SDL_VideoSurface->pixels = SDL_WindowSurface->pixels; + SDL_VideoSurface->pitch = SDL_WindowSurface->pitch; + SDL_SetClipRect(SDL_VideoSurface, NULL); if (SDL_ShadowSurface) { SDL_ShadowSurface->w = width; @@ -436,8 +462,11 @@ SDL_Surface * SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) { SDL_DisplayMode desktop_mode; - int window_x = SDL_WINDOWPOS_UNDEFINED; - int window_y = SDL_WINDOWPOS_UNDEFINED; + int display = GetVideoDisplay(); + 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; @@ -447,7 +476,7 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) } } - SDL_GetDesktopDisplayMode(GetVideoDisplay(), &desktop_mode); + SDL_GetDesktopDisplayMode(display, &desktop_mode); if (width == 0) { width = desktop_mode.w; @@ -472,6 +501,7 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) SDL_ShadowSurface = NULL; } if (SDL_VideoSurface) { + SDL_VideoSurface->flags &= ~SDL_DONTFREE; SDL_FreeSurface(SDL_VideoSurface); SDL_VideoSurface = NULL; } @@ -548,11 +578,31 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) } /* Create the screen surface */ - SDL_VideoSurface = SDL_GetWindowSurface(SDL_VideoWindow); - if (!SDL_VideoSurface) { + SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow); + if (!SDL_WindowSurface) { return NULL; } + + /* Center the public surface in the window surface */ + SDL_GetWindowSize(SDL_VideoWindow, &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; + + SDL_VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0); SDL_VideoSurface->flags |= surface_flags; + SDL_VideoSurface->flags |= SDL_DONTFREE; + SDL_FreeFormat(SDL_VideoSurface->format); + SDL_VideoSurface->format = SDL_WindowSurface->format; + SDL_VideoSurface->format->refcount++; + SDL_VideoSurface->w = width; + SDL_VideoSurface->h = height; + SDL_VideoSurface->pitch = SDL_WindowSurface->pitch; + SDL_VideoSurface->pixels = (void *)((Uint8 *)SDL_WindowSurface->pixels + + SDL_VideoViewport.y * SDL_VideoSurface->pitch + + SDL_VideoViewport.x * SDL_VideoSurface->format->BytesPerPixel); + SDL_SetClipRect(SDL_VideoSurface, NULL); /* Create a shadow surface if necessary */ if ((bpp != SDL_VideoSurface->format->BitsPerPixel) @@ -571,6 +621,8 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) SDL_DitherColors(SDL_ShadowSurface->format->palette->colors, SDL_ShadowSurface->format->BitsPerPixel); } + SDL_FillRect(SDL_ShadowSurface, NULL, + SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0)); } SDL_PublicSurface = (SDL_ShadowSurface ? SDL_ShadowSurface : SDL_VideoSurface); @@ -719,7 +771,25 @@ SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects) screen = SDL_VideoSurface; } if (screen == SDL_VideoSurface) { - SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, numrects, rects); + if (SDL_VideoViewport.x || SDL_VideoViewport.y) { + SDL_Rect *stackrects = SDL_stack_alloc(SDL_Rect, numrects); + SDL_Rect *stackrect; + const SDL_Rect *rect; + + /* Offset all the rectangles before updating */ + for (i = 0; i < numrects; ++i) { + rect = &rects[i]; + stackrect = &stackrects[i]; + stackrect->x = SDL_VideoViewport.x + rect->x; + stackrect->y = SDL_VideoViewport.y + rect->y; + stackrect->w = rect->w; + stackrect->h = rect->h; + } + SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, numrects, stackrects); + SDL_stack_free(stackrects); + } else { + SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, numrects, rects); + } } } diff --git a/src/video/SDL_rect.c b/src/video/SDL_rect.c index 99930445f..2b66d3991 100644 --- a/src/video/SDL_rect.c +++ b/src/video/SDL_rect.c @@ -23,6 +23,7 @@ #include "SDL_rect.h" + SDL_bool SDL_HasIntersection(const SDL_Rect * A, const SDL_Rect * B) { @@ -339,4 +340,42 @@ SDL_IntersectRectAndLine(const SDL_Rect * rect, int *X1, int *Y1, int *X2, return SDL_TRUE; } +SDL_bool +SDL_GetSpanEnclosingRect(int width, int height, + int numrects, SDL_Rect * rects, SDL_Rect *span) +{ + int i; + int span_y1, span_y2; + int rect_y1, rect_y2; + + /* Initialize to empty rect */ + span_y1 = height; + span_y2 = 0; + + for (i = 0; i < numrects; ++i) { + rect_y1 = rects[i].y; + rect_y2 = rect_y1 + rects[i].h; + + /* Clip out of bounds rectangles, and expand span rect */ + if (rect_y1 < 0) { + span_y1 = 0; + } else if (rect_y1 < span_y1) { + span_y1 = rect_y1; + } + if (rect_y2 > height) { + span_y2 = height; + } else if (rect_y2 > span_y2) { + span_y2 = rect_y2; + } + } + if (span_y2 > span_y1) { + span->x = 0; + span->y = span_y1; + span->w = width; + span->h = (span_y2 - span_y1); + return SDL_TRUE; + } + return SDL_FALSE; +} + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_rect_c.h b/src/video/SDL_rect_c.h new file mode 100644 index 000000000..a1ddcd0c6 --- /dev/null +++ b/src/video/SDL_rect_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2011 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +extern SDL_bool SDL_GetSpanEnclosingRect(int width, int height, int numrects, SDL_Rect * rects, SDL_Rect *span); + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index ea0518f9d..95ca8fa21 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -28,6 +28,7 @@ #include "SDL_sysvideo.h" #include "SDL_blit.h" #include "SDL_pixels_c.h" +#include "SDL_rect_c.h" #include "../events/SDL_events_c.h" #if SDL_VIDEO_OPENGL @@ -306,12 +307,8 @@ static int SDL_UpdateWindowTexture(_THIS, SDL_Window * window, int numrects, SDL_Rect * rects) { SDL_WindowTextureData *data; -#ifdef UPDATE_TEXTURE_SUBRECTS - void *src, *dst; - int src_pitch; - int dst_pitch; - int i, row, length; -#endif + SDL_Rect rect; + void *src; data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA); if (!data || !data->texture) { @@ -319,34 +316,21 @@ SDL_UpdateWindowTexture(_THIS, SDL_Window * window, int numrects, SDL_Rect * rec return -1; } -#ifdef UPDATE_TEXTURE_SUBRECTS - src_pitch = data->pitch; - for (i = 0; i < numrects; ++i) { + /* Update a single rect that contains subrects for best DMA performance */ + if (SDL_GetSpanEnclosingRect(window->w, window->h, numrects, rects, &rect)) { src = (void *)((Uint8 *)data->pixels + - rects[i].y * src_pitch + - rects[i].x * data->bytes_per_pixel); - if (SDL_LockTexture(data->texture, &rects[i], &dst, &dst_pitch) < 0) { + rect.y * data->pitch + + rect.x * data->bytes_per_pixel); + if (SDL_UpdateTexture(data->texture, &rect, src, data->pitch) < 0) { return -1; } - length = rects[i].w * data->bytes_per_pixel; - for (row = rects[i].h; row--; ) { - SDL_memcpy(dst, src, length); - src = (Uint8*)src + src_pitch; - dst = (Uint8*)dst + dst_pitch; + + if (SDL_RenderCopy(data->renderer, data->texture, NULL, NULL) < 0) { + return -1; } - SDL_UnlockTexture(data->texture); - } -#else - if (SDL_UpdateTexture(data->texture, NULL, data->pixels, data->pitch) < 0) { - return -1; - } -#endif - if (SDL_RenderCopy(data->renderer, data->texture, NULL, NULL) < 0) { - return -1; + SDL_RenderPresent(data->renderer); } - - SDL_RenderPresent(data->renderer); return 0; }