Center the old SDL 1.2 screen in the window if we can't get the size we wanted.
authorSam Lantinga <slouken@libsdl.org>
Sun, 13 Feb 2011 23:09:18 -0800
changeset 5294 4801b8bede31
parent 5293 7e9cdbbf7ba1
child 5295 b88d05603e4b
Center the old SDL 1.2 screen in the window if we can't get the size we wanted.
src/SDL_compat.c
src/video/SDL_rect.c
src/video/SDL_rect_c.h
src/video/SDL_video.c
--- a/src/SDL_compat.c	Sun Feb 13 22:53:12 2011 -0800
+++ b/src/SDL_compat.c	Sun Feb 13 23:09:18 2011 -0800
@@ -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 @@
             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 @@
             //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 @@
 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 @@
         }
     }
     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 @@
         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_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_GetDesktopDisplayMode(GetVideoDisplay(), &desktop_mode);
+    SDL_GetDesktopDisplayMode(display, &desktop_mode);
 
     if (width == 0) {
         width = desktop_mode.w;
@@ -472,6 +501,7 @@
         SDL_ShadowSurface = NULL;
     }
     if (SDL_VideoSurface) {
+        SDL_VideoSurface->flags &= ~SDL_DONTFREE;
         SDL_FreeSurface(SDL_VideoSurface);
         SDL_VideoSurface = NULL;
     }
@@ -548,11 +578,31 @@
     }
 
     /* 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_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 @@
         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);
+        }
     }
 }
 
--- a/src/video/SDL_rect.c	Sun Feb 13 22:53:12 2011 -0800
+++ b/src/video/SDL_rect.c	Sun Feb 13 23:09:18 2011 -0800
@@ -23,6 +23,7 @@
 
 #include "SDL_rect.h"
 
+
 SDL_bool
 SDL_HasIntersection(const SDL_Rect * A, const SDL_Rect * B)
 {
@@ -339,4 +340,42 @@
     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: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/SDL_rect_c.h	Sun Feb 13 23:09:18 2011 -0800
@@ -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: */
--- a/src/video/SDL_video.c	Sun Feb 13 22:53:12 2011 -0800
+++ b/src/video/SDL_video.c	Sun Feb 13 23:09:18 2011 -0800
@@ -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 @@
 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 @@
         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);
+
+        SDL_RenderPresent(data->renderer);
     }
-#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);
     return 0;
 }