From f48f1610fc40ad9f6980771c4f623e49e0d2e5f9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 10 Jul 2006 07:34:50 +0000 Subject: [PATCH] SDL_Rect now uses int for position and size. Added a few more rectangle functions. Added a dirty rectangle list implementation. --- include/SDL_video.h | 51 ++++++++- src/SDL_compat.c | 2 - src/video/SDL_rect.c | 189 +++++++++++++++++++++++++++++++ src/video/SDL_rect_c.h | 41 +++++++ src/video/SDL_renderer_sw.c | 35 ++++-- src/video/SDL_surface.c | 46 +------- src/video/SDL_video.c | 1 + src/video/win32/SDL_win32modes.c | 1 - 8 files changed, 300 insertions(+), 66 deletions(-) create mode 100644 src/video/SDL_rect.c create mode 100644 src/video/SDL_rect_c.h diff --git a/include/SDL_video.h b/include/SDL_video.h index 116907a13..a42187638 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -53,8 +53,8 @@ extern "C" { */ typedef struct SDL_Rect { - Sint16 x, y; - Uint16 w, h; + int x, y; + int w, h; } SDL_Rect; /** @@ -177,7 +177,8 @@ typedef enum 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_SwapBuffers(void); */ 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 diff --git a/src/SDL_compat.c b/src/SDL_compat.c index 3a88534ef..a9b7d7a66 100644 --- a/src/SDL_compat.c +++ b/src/SDL_compat.c @@ -307,8 +307,6 @@ GetEnvironmentWindowPosition(int w, int h, int *x, int *y) 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; diff --git a/src/video/SDL_rect.c b/src/video/SDL_rect.c new file mode 100644 index 000000000..27c3ad86f --- /dev/null +++ b/src/video/SDL_rect.c @@ -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: */ diff --git a/src/video/SDL_rect_c.h b/src/video/SDL_rect_c.h new file mode 100644 index 000000000..0f4d3bf06 --- /dev/null +++ b/src/video/SDL_rect_c.h @@ -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: */ diff --git a/src/video/SDL_renderer_sw.c b/src/video/SDL_renderer_sw.c index 6dbf24fc1..4cbbd4ca2 100644 --- a/src/video/SDL_renderer_sw.c +++ b/src/video/SDL_renderer_sw.c @@ -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_RenderDriver SDL_SW_RenderDriver = { SDL_PixelFormat_BGRA8888, SDL_PixelFormat_YUY2, SDL_PixelFormat_UYVY}, - 32768, - 32768} + 0, + 0} }; typedef struct @@ -106,6 +107,7 @@ typedef struct SDL_Surface *screens[3]; SDL_Surface *target; SDL_Renderer *renderer; + SDL_DirtyRectList dirty; } SDL_SW_RenderData; SDL_Renderer * @@ -125,12 +127,11 @@ SDL_SW_CreateRenderer(SDL_Window * window, Uint32 flags) 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_SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect, 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_SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, 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 @@ SDL_SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect, 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_RenderPresent(SDL_Renderer * renderer) { 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_SW_DestroyRenderer(SDL_Renderer * renderer) SDL_FreeSurface(data->screens[i]); } } + SDL_FreeDirtyRects(&data->dirty); SDL_free(data); } SDL_free(renderer); diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index e3c41eebc..87eae187a 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -41,14 +41,6 @@ SDL_CreateRGBSurface(Uint32 flags, { 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 @@ SDL_CreateRGBSurfaceFromTexture(SDL_TextureID textureID) surface->flags |= SDL_HWSURFACE; surface->w = w; surface->h = h; + surface->pitch = SDL_CalculatePitch(surface); SDL_SetClipRect(surface, NULL); } } @@ -414,43 +407,6 @@ SDL_SetAlphaChannel(SDL_Surface * surface, Uint8 value) return 0; } -/* - * 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 */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 0ea0b3b39..9b76c2069 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1110,6 +1110,7 @@ SDL_SetWindowFullscreen(SDL_WindowID windowID, int fullscreen) SDL_SetDisplayMode(NULL); } } + return 0; } void diff --git a/src/video/win32/SDL_win32modes.c b/src/video/win32/SDL_win32modes.c index 8a3efb682..c4a091750 100644 --- a/src/video/win32/SDL_win32modes.c +++ b/src/video/win32/SDL_win32modes.c @@ -135,7 +135,6 @@ WIN_InitModes(_THIS) printf("Device: %s\n", WIN_StringToUTF8(DeviceName)); #endif for (j = 0;; ++j) { - int index; SDL_VideoDisplay display; SDL_DisplayData *displaydata; SDL_DisplayMode mode;