changeset 1735:8dd28c4ef746 SDL-1.3

SDL_Rect now uses int for position and size. Added a few more rectangle functions. Added a dirty rectangle list implementation.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 10 Jul 2006 07:34:50 +0000
parents f7c667ded87d
children 06be4b33029d
files include/SDL_video.h src/SDL_compat.c src/video/SDL_rect.c src/video/SDL_rect_c.h src/video/SDL_renderer_sw.c src/video/SDL_surface.c src/video/SDL_video.c src/video/win32/SDL_win32modes.c
diffstat 8 files changed, 300 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/include/SDL_video.h	Sun Jul 09 18:09:16 2006 +0000
+++ b/include/SDL_video.h	Mon Jul 10 07:34:50 2006 +0000
@@ -53,8 +53,8 @@
  */
 typedef struct SDL_Rect
 {
-    Sint16 x, y;
-    Uint16 w, h;
+    int x, y;
+    int w, h;
 } SDL_Rect;
 
 /**
@@ -177,7 +177,8 @@
     SDL_Renderer_PresentVSync = 0x00000010,     /**< Present is synchronized with the refresh rate */
     SDL_Renderer_RenderTarget = 0x00000020,     /**< The renderer can create texture render targets */
     SDL_Renderer_Accelerated = 0x00000040,      /**< The renderer uses hardware acceleration */
-    SDL_Renderer_Minimal = 0x00000080,          /**< The renderer only supports the read/write pixel and present functions */
+    SDL_Renderer_ = 0x00000080,      /**< The renderer uses hardware acceleration */
+    SDL_Renderer_Minimal = 0x00000100,          /**< The renderer only supports the read/write pixel and present functions */
 } SDL_RendererFlags;
 
 /**
@@ -1525,12 +1526,50 @@
  */
 extern DECLSPEC void SDLCALL SDL_GL_DeleteContext(SDL_GLContext context);
 
-/*
- * Calculate the intersection of two rectangles
+/**
+ * \def SDL_RectEmpty()
+ *
+ * \brief Returns true if the rectangle has no area.
+ */
+#define SDL_RectEmpty(X)    (((X)->w <= 0) || ((X)->h <= 0))
+
+/**
+ * \def SDL_RectEquals()
+ *
+ * \brief Returns true if the two rectangles are equal.
+ */
+#define SDL_RectEquals(A, B)   (((A)->x == (B)->x) && ((A)->y == (B)->y) && \
+                                ((A)->w == (B)->w) && ((A)->h == (B)->h))
+
+/**
+ * \fn SDL_bool SDL_HasIntersection(const SDL_Rect * A, const SDL_Rect * B);
+ *
+ * \brief Determine whether two rectangles intersect.
+ *
+ * \return SDL_TRUE if there is an intersection, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasIntersection(const SDL_Rect * A,
+                                                     const SDL_Rect * B);
+
+/**
+ * \fn SDL_bool SDL_IntersectRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result)
+ *
+ * \brief Calculate the intersection of two rectangles.
+ *
+ * \return SDL_TRUE if there is an intersection, SDL_FALSE otherwise.
  */
 extern DECLSPEC SDL_bool SDLCALL SDL_IntersectRect(const SDL_Rect * A,
                                                    const SDL_Rect * B,
-                                                   SDL_Rect * intersection);
+                                                   SDL_Rect * result);
+
+/**
+ * \fn void SDL_UnionRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result)
+ *
+ * \brief Calculate the union of two rectangles
+ */
+extern DECLSPEC void SDLCALL SDL_UnionRect(const SDL_Rect * A,
+                                           const SDL_Rect * B,
+                                           SDL_Rect * result);
 
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus
--- a/src/SDL_compat.c	Sun Jul 09 18:09:16 2006 +0000
+++ b/src/SDL_compat.c	Mon Jul 10 07:34:50 2006 +0000
@@ -307,8 +307,6 @@
 SDL_Surface *
 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
 {
-    SDL_EventFilter filter;
-    void *filterparam;
     const SDL_DisplayMode *desktop_mode;
     SDL_DisplayMode mode;
     int window_x = SDL_WINDOWPOS_UNDEFINED;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/SDL_rect.c	Mon Jul 10 07:34:50 2006 +0000
@@ -0,0 +1,189 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2006 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"
+
+#include "SDL_video.h"
+#include "SDL_rect_c.h"
+
+SDL_bool
+SDL_HasIntersection(const SDL_Rect * A, const SDL_Rect * B)
+{
+    int Amin, Amax, Bmin, Bmax;
+
+    /* Horizontal intersection */
+    Amin = A->x;
+    Amax = Amin + A->w;
+    Bmin = B->x;
+    Bmax = Bmin + B->w;
+    if (Bmin > Amin)
+        Amin = Bmin;
+    if (Bmax < Amax)
+        Amax = Bmax;
+    if (Amax <= Amin)
+        return SDL_FALSE;
+
+    /* Vertical intersection */
+    Amin = A->y;
+    Amax = Amin + A->h;
+    Bmin = B->y;
+    Bmax = Bmin + B->h;
+    if (Bmin > Amin)
+        Amin = Bmin;
+    if (Bmax < Amax)
+        Amax = Bmax;
+    if (Amax <= Amin)
+        return SDL_FALSE;
+
+    return SDL_TRUE;
+}
+
+SDL_bool
+SDL_IntersectRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result)
+{
+    int Amin, Amax, Bmin, Bmax;
+
+    /* Horizontal intersection */
+    Amin = A->x;
+    Amax = Amin + A->w;
+    Bmin = B->x;
+    Bmax = Bmin + B->w;
+    if (Bmin > Amin)
+        Amin = Bmin;
+    result->x = Amin;
+    if (Bmax < Amax)
+        Amax = Bmax;
+    result->w = Amax - Amin;
+
+    /* Vertical intersection */
+    Amin = A->y;
+    Amax = Amin + A->h;
+    Bmin = B->y;
+    Bmax = Bmin + B->h;
+    if (Bmin > Amin)
+        Amin = Bmin;
+    result->y = Amin;
+    if (Bmax < Amax)
+        Amax = Bmax;
+    result->h = Amax - Amin;
+
+    return !SDL_RectEmpty(result);
+}
+
+void
+SDL_UnionRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result)
+{
+    int Amin, Amax, Bmin, Bmax;
+
+    /* Horizontal union */
+    Amin = A->x;
+    Amax = Amin + A->w;
+    Bmin = B->x;
+    Bmax = Bmin + B->w;
+    if (Bmin < Amin)
+        Amin = Bmin;
+    result->x = Amin;
+    if (Bmax > Amax)
+        Amax = Bmax;
+    result->w = Amax - Amin;
+
+    /* Vertical intersection */
+    Amin = A->y;
+    Amax = Amin + A->h;
+    Bmin = B->y;
+    Bmax = Bmin + B->h;
+    if (Bmin < Amin)
+        Amin = Bmin;
+    result->y = Amin;
+    if (Bmax > Amax)
+        Amax = Bmax;
+    result->h = Amax - Amin;
+}
+
+void
+SDL_AddDirtyRect(SDL_DirtyRectList * list, const SDL_Rect * rect)
+{
+    SDL_DirtyRect *dirty;
+    SDL_DirtyRect *check, *prev, *next;
+
+    if (list->free) {
+        dirty = list->free;
+        list->free = dirty->next;
+    } else {
+        dirty = (SDL_DirtyRect *) SDL_malloc(sizeof(*dirty));
+        if (!dirty) {
+            return;
+        }
+    }
+    dirty->rect = *rect;
+
+    /* FIXME: At what point is this optimization too expensive? */
+    for (prev = NULL, check = list->list; check; check = next) {
+        next = check->next;
+
+        if (SDL_HasIntersection(&dirty->rect, &check->rect)) {
+            SDL_UnionRect(&dirty->rect, &check->rect, &dirty->rect);
+            if (prev) {
+                prev->next = next;
+            } else {
+                list->list = next;
+            }
+            check->next = list->free;
+            list->free = check;
+            --list->count;
+        } else {
+            prev = check;
+        }
+    }
+
+    dirty->next = list->list;
+    list->list = dirty;
+    ++list->count;
+}
+
+void
+SDL_ClearDirtyRects(SDL_DirtyRectList * list)
+{
+    while (list->list) {
+        SDL_DirtyRect *elem = list->list;
+        list->list = elem->next;
+        elem->next = list->free;
+        list->free = elem;
+    }
+    list->count = 0;
+}
+
+void
+SDL_FreeDirtyRects(SDL_DirtyRectList * list)
+{
+    while (list->list) {
+        SDL_DirtyRect *elem = list->list;
+        list->list = elem->next;
+        SDL_free(elem);
+    }
+    while (list->free) {
+        SDL_DirtyRect *elem = list->free;
+        list->free = elem->next;
+        SDL_free(elem);
+    }
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/SDL_rect_c.h	Mon Jul 10 07:34:50 2006 +0000
@@ -0,0 +1,41 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2006 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"
+
+typedef struct SDL_DirtyRect
+{
+    SDL_Rect rect;
+    struct SDL_DirtyRect *next;
+} SDL_DirtyRect;
+
+typedef struct SDL_DirtyRectList
+{
+    int count;
+    SDL_DirtyRect *list;
+    SDL_DirtyRect *free;
+} SDL_DirtyRectList;
+
+extern void SDL_AddDirtyRect(SDL_DirtyRectList * list, const SDL_Rect * rect);
+extern void SDL_ClearDirtyRects(SDL_DirtyRectList * list);
+extern void SDL_FreeDirtyRects(SDL_DirtyRectList * list);
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/SDL_renderer_sw.c	Sun Jul 09 18:09:16 2006 +0000
+++ b/src/video/SDL_renderer_sw.c	Mon Jul 10 07:34:50 2006 +0000
@@ -23,6 +23,7 @@
 
 #include "SDL_video.h"
 #include "SDL_sysvideo.h"
+#include "SDL_rect_c.h"
 #include "SDL_yuv_sw_c.h"
 
 
@@ -96,8 +97,8 @@
       SDL_PixelFormat_BGRA8888,
       SDL_PixelFormat_YUY2,
       SDL_PixelFormat_UYVY},
-     32768,
-     32768}
+     0,
+     0}
 };
 
 typedef struct
@@ -106,6 +107,7 @@
     SDL_Surface *screens[3];
     SDL_Surface *target;
     SDL_Renderer *renderer;
+    SDL_DirtyRectList dirty;
 } SDL_SW_RenderData;
 
 SDL_Renderer *
@@ -125,12 +127,11 @@
         return NULL;
     }
 
-    renderer = (SDL_Renderer *) SDL_malloc(sizeof(*renderer));
+    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
     if (!renderer) {
         SDL_OutOfMemory();
         return NULL;
     }
-    SDL_zerop(renderer);
 
     data = (SDL_SW_RenderData *) SDL_malloc(sizeof(*data));
     if (!data) {
@@ -363,6 +364,8 @@
     SDL_Rect real_rect = *rect;
     Uint8 r, g, b, a;
 
+    SDL_AddDirtyRect(&data->dirty, rect);
+
     a = (Uint8) ((color >> 24) & 0xFF);
     r = (Uint8) ((color >> 16) & 0xFF);
     g = (Uint8) ((color >> 8) & 0xFF);
@@ -381,6 +384,8 @@
     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
 
+    SDL_AddDirtyRect(&data->dirty, dstrect);
+
     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
         SDL_Surface *target = data->target;
         void *pixels =
@@ -445,6 +450,8 @@
     int row;
     size_t length;
 
+    SDL_AddDirtyRect(&data->dirty, rect);
+
     src = (Uint8 *) pixels;
     dst =
         (Uint8 *) surface->pixels + rect->y * surface->pitch +
@@ -463,19 +470,22 @@
 {
     SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata;
     SDL_Surface *surface = data->screens[data->current_screen];
-    SDL_Rect rect;
+    SDL_DirtyRect *dirty;
     int new_screen;
 
     /* Send the data to the display */
-    /* FIXME: implement dirty rect updates */
-    rect.x = 0;
-    rect.y = 0;
-    rect.w = surface->w;
-    rect.h = surface->h;
-    data->renderer->RenderWritePixels(data->renderer, &rect, surface->pixels,
-                                      surface->pitch);
+    for (dirty = data->dirty.list; dirty; dirty = dirty->next) {
+        void *pixels =
+            (void *) ((Uint8 *) surface->pixels +
+                      dirty->rect.y * surface->pitch +
+                      dirty->rect.x * surface->format->BytesPerPixel);
+        data->renderer->RenderWritePixels(data->renderer, &dirty->rect,
+                                          pixels, surface->pitch);
+    }
+    SDL_ClearDirtyRects(&data->dirty);
     data->renderer->RenderPresent(data->renderer);
 
+
     /* Update the flipping chain, if any */
     if (renderer->info.flags & SDL_Renderer_PresentFlip2) {
         new_screen = (data->current_screen + 1) % 2;
@@ -514,6 +524,7 @@
                 SDL_FreeSurface(data->screens[i]);
             }
         }
+        SDL_FreeDirtyRects(&data->dirty);
         SDL_free(data);
     }
     SDL_free(renderer);
--- a/src/video/SDL_surface.c	Sun Jul 09 18:09:16 2006 +0000
+++ b/src/video/SDL_surface.c	Mon Jul 10 07:34:50 2006 +0000
@@ -41,14 +41,6 @@
 {
     SDL_Surface *surface;
 
-    /* FIXME!! */
-    /* Make sure the size requested doesn't overflow our datatypes */
-    /* Next time I write a library like SDL, I'll use int for size. :) */
-    if (width >= 16384 || height >= 65536) {
-        SDL_SetError("Width or height is too large");
-        return NULL;
-    }
-
     /* Allocate the surface */
     surface = (SDL_Surface *) SDL_malloc(sizeof(*surface));
     if (surface == NULL) {
@@ -211,6 +203,7 @@
             surface->flags |= SDL_HWSURFACE;
             surface->w = w;
             surface->h = h;
+            surface->pitch = SDL_CalculatePitch(surface);
             SDL_SetClipRect(surface, NULL);
         }
     }
@@ -415,43 +408,6 @@
 }
 
 /*
- * A function to calculate the intersection of two rectangles:
- * return true if the rectangles intersect, false otherwise
- */
-SDL_bool
-SDL_IntersectRect(const SDL_Rect * A, const SDL_Rect * B,
-                  SDL_Rect * intersection)
-{
-    int Amin, Amax, Bmin, Bmax;
-
-    /* Horizontal intersection */
-    Amin = A->x;
-    Amax = Amin + A->w;
-    Bmin = B->x;
-    Bmax = Bmin + B->w;
-    if (Bmin > Amin)
-        Amin = Bmin;
-    intersection->x = Amin;
-    if (Bmax < Amax)
-        Amax = Bmax;
-    intersection->w = Amax - Amin > 0 ? Amax - Amin : 0;
-
-    /* Vertical intersection */
-    Amin = A->y;
-    Amax = Amin + A->h;
-    Bmin = B->y;
-    Bmax = Bmin + B->h;
-    if (Bmin > Amin)
-        Amin = Bmin;
-    intersection->y = Amin;
-    if (Bmax < Amax)
-        Amax = Bmax;
-    intersection->h = Amax - Amin > 0 ? Amax - Amin : 0;
-
-    return (intersection->w && intersection->h);
-}
-
-/*
  * Set the clipping rectangle for a blittable surface
  */
 SDL_bool
--- a/src/video/SDL_video.c	Sun Jul 09 18:09:16 2006 +0000
+++ b/src/video/SDL_video.c	Mon Jul 10 07:34:50 2006 +0000
@@ -1110,6 +1110,7 @@
             SDL_SetDisplayMode(NULL);
         }
     }
+    return 0;
 }
 
 void
--- a/src/video/win32/SDL_win32modes.c	Sun Jul 09 18:09:16 2006 +0000
+++ b/src/video/win32/SDL_win32modes.c	Mon Jul 10 07:34:50 2006 +0000
@@ -135,7 +135,6 @@
         printf("Device: %s\n", WIN_StringToUTF8(DeviceName));
 #endif
         for (j = 0;; ++j) {
-            int index;
             SDL_VideoDisplay display;
             SDL_DisplayData *displaydata;
             SDL_DisplayMode mode;