From 3d523b2bdc0c963ba8ac46cc38e17a7e59092126 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 20 Dec 2008 13:14:28 +0000 Subject: [PATCH] Added stubs for software implementations of blending fills and line drawing --- include/SDL_surface.h | 28 ++++++++ src/video/SDL_blendline.c | 49 ++++++++++++++ src/video/SDL_blendrect.c | 52 +++++++++++++++ src/video/SDL_drawline.c | 48 ++++++++++++++ src/video/{SDL_fill.c => SDL_fillrect.c} | 0 src/video/SDL_renderer_sw.c | 83 +++++++++++++++++++++--- src/video/dummy/SDL_nullrender.c | 49 ++++++++++++-- src/video/x11/SDL_x11render.c | 1 + 8 files changed, 296 insertions(+), 14 deletions(-) create mode 100644 src/video/SDL_blendline.c create mode 100644 src/video/SDL_blendrect.c create mode 100644 src/video/SDL_drawline.c rename src/video/{SDL_fill.c => SDL_fillrect.c} (100%) diff --git a/include/SDL_surface.h b/include/SDL_surface.h index 3d9be5616..656aae971 100644 --- a/include/SDL_surface.h +++ b/include/SDL_surface.h @@ -365,6 +365,23 @@ extern DECLSPEC void SDLCALL SDL_GetClipRect(SDL_Surface * surface, extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurface (SDL_Surface * src, SDL_PixelFormat * fmt, Uint32 flags); +/* + * This function draws a line with 'color' + * The color should be a pixel of the format used by the surface, and + * can be generated by the SDL_MapRGB() function. + * This function returns 0 on success, or -1 on error. + */ +extern DECLSPEC int SDLCALL SDL_DrawLine + (SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color); + +/* + * This function blends an RGBA value along a line + * This function returns 0 on success, or -1 on error. + */ +extern DECLSPEC int SDLCALL SDL_BlendLine + (SDL_Surface * dst, int x1, int y1, int x2, int y2, int blendMode, + Uint8 r, Uint8 g, Uint8 b, Uint8 a); + /* * This function performs a fast fill of the given rectangle with 'color' * The given rectangle is clipped to the destination surface clip area @@ -377,6 +394,17 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurface extern DECLSPEC int SDLCALL SDL_FillRect (SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color); +/* + * This function blends an RGBA value into the given rectangle. + * The given rectangle is clipped to the destination surface clip area + * and the final fill rectangle is saved in the passed in pointer. + * If 'dstrect' is NULL, the whole surface will be filled with 'color' + * This function returns 0 on success, or -1 on error. + */ +extern DECLSPEC int SDLCALL SDL_BlendRect + (SDL_Surface * dst, SDL_Rect * dstrect, int blendMode, Uint8 r, Uint8 g, + Uint8 b, Uint8 a); + /* * This performs a fast blit from the source surface to the destination * surface. It assumes that the source and destination rectangles are diff --git a/src/video/SDL_blendline.c b/src/video/SDL_blendline.c new file mode 100644 index 000000000..99e3b9386 --- /dev/null +++ b/src/video/SDL_blendline.c @@ -0,0 +1,49 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 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_blit.h" + + +int +SDL_BlendLine(SDL_Surface * dst, int x1, int y1, int x2, int y2, + int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + /* This function doesn't work on surfaces < 8 bpp */ + if (dst->format->BitsPerPixel < 8) { + SDL_SetError("SDL_BlendLine(): Unsupported surface format"); + return (-1); + } + + /* Perform clipping */ + /* FIXME + if (!SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect)) { + return (0); + } + */ + + SDL_Unsupported(); + return -1; +} + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_blendrect.c b/src/video/SDL_blendrect.c new file mode 100644 index 000000000..7ddc387ad --- /dev/null +++ b/src/video/SDL_blendrect.c @@ -0,0 +1,52 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 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_blit.h" + + +int +SDL_BlendRect(SDL_Surface * dst, SDL_Rect * dstrect, int blendMode, Uint8 r, + Uint8 g, Uint8 b, Uint8 a) +{ + /* This function doesn't work on surfaces < 8 bpp */ + if (dst->format->BitsPerPixel < 8) { + SDL_SetError("SDL_BlendRect(): Unsupported surface format"); + return (-1); + } + + /* If 'dstrect' == NULL, then fill the whole surface */ + if (dstrect) { + /* Perform clipping */ + if (!SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect)) { + return (0); + } + } else { + dstrect = &dst->clip_rect; + } + + SDL_Unsupported(); + return -1; +} + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_drawline.c b/src/video/SDL_drawline.c new file mode 100644 index 000000000..5d28fe2ec --- /dev/null +++ b/src/video/SDL_drawline.c @@ -0,0 +1,48 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 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_blit.h" + + +int +SDL_DrawLine(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color) +{ + /* This function doesn't work on surfaces < 8 bpp */ + if (dst->format->BitsPerPixel < 8) { + SDL_SetError("SDL_DrawLine(): Unsupported surface format"); + return (-1); + } + + /* Perform clipping */ + /* FIXME + if (!SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect)) { + return (0); + } + */ + + SDL_Unsupported(); + return -1; +} + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_fill.c b/src/video/SDL_fillrect.c similarity index 100% rename from src/video/SDL_fill.c rename to src/video/SDL_fillrect.c diff --git a/src/video/SDL_renderer_sw.c b/src/video/SDL_renderer_sw.c index 264c33b32..e25499f87 100644 --- a/src/video/SDL_renderer_sw.c +++ b/src/video/SDL_renderer_sw.c @@ -60,6 +60,9 @@ static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, int *pitch); static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); static int SW_SetDrawColor(SDL_Renderer * renderer); +static int SW_SetDrawBlendMode(SDL_Renderer * renderer); +static int SW_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, + int y2); static int SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect); static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect); @@ -223,11 +226,8 @@ SW_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->DisplayModeChanged = SW_DisplayModeChanged; renderer->SetDrawColor = SW_SetDrawColor; - /* FIXME : Implement - renderer->SetDrawBlendMode = GL_SetDrawBlendMode; - renderer->RenderLine = GL_RenderLine; - */ - + renderer->SetDrawBlendMode = SW_SetDrawBlendMode; + renderer->RenderLine = SW_RenderLine; renderer->RenderFill = SW_RenderFill; renderer->RenderCopy = SW_RenderCopy; renderer->RenderPresent = SW_RenderPresent; @@ -531,11 +531,66 @@ SW_SetDrawColor(SDL_Renderer * renderer) return 0; } +static int +SW_SetDrawBlendMode(SDL_Renderer * renderer) +{ + return 0; +} + +static int +SW_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2) +{ + SW_RenderData *data = (SW_RenderData *) renderer->driverdata; + int status; + + if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) { + SDL_Rect rect; + + if (x1 < x2) { + rect.x = x1; + rect.w = (x2 - x1) + 1; + } else { + rect.x = x2; + rect.w = (x1 - x2) + 1; + } + if (y1 < y2) { + rect.y = y1; + rect.h = (y2 - y1) + 1; + } else { + rect.y = y2; + rect.h = (y1 - y2) + 1; + } + SDL_AddDirtyRect(&data->dirty, &rect); + } + + if (data->renderer->LockTexture(data->renderer, + data->texture[data->current_texture], + NULL, 1, &data->surface.pixels, + &data->surface.pitch) < 0) { + return -1; + } + + if (renderer->blendMode == SDL_BLENDMODE_NONE) { + Uint32 color = + SDL_MapRGBA(data->surface.format, renderer->r, renderer->g, + renderer->b, renderer->a); + + status = SDL_DrawLine(&data->surface, x1, y1, x2, y2, color); + } else { + status = + SDL_BlendLine(&data->surface, x1, y1, x2, y2, renderer->blendMode, + renderer->r, renderer->g, renderer->b, renderer->a); + } + + data->renderer->UnlockTexture(data->renderer, + data->texture[data->current_texture]); + return status; +} + static int SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect) { SW_RenderData *data = (SW_RenderData *) renderer->driverdata; - Uint32 color; SDL_Rect real_rect; int status; @@ -543,22 +598,30 @@ SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect) SDL_AddDirtyRect(&data->dirty, rect); } - color = SDL_MapRGBA(data->surface.format, - renderer->r, renderer->g, renderer->b, renderer->a); - if (data->renderer->LockTexture(data->renderer, data->texture[data->current_texture], rect, 1, &data->surface.pixels, &data->surface.pitch) < 0) { return -1; } + data->surface.w = rect->w; data->surface.h = rect->h; data->surface.clip_rect.w = rect->w; data->surface.clip_rect.h = rect->h; real_rect = data->surface.clip_rect; - status = SDL_FillRect(&data->surface, &real_rect, color); + if (renderer->blendMode == SDL_BLENDMODE_NONE) { + Uint32 color = + SDL_MapRGBA(data->surface.format, renderer->r, renderer->g, + renderer->b, renderer->a); + + status = SDL_FillRect(&data->surface, &real_rect, color); + } else { + status = + SDL_BlendRect(&data->surface, &real_rect, renderer->blendMode, + renderer->r, renderer->g, renderer->b, renderer->a); + } data->renderer->UnlockTexture(data->renderer, data->texture[data->current_texture]); diff --git a/src/video/dummy/SDL_nullrender.c b/src/video/dummy/SDL_nullrender.c index 0ed409e6a..50a677be6 100644 --- a/src/video/dummy/SDL_nullrender.c +++ b/src/video/dummy/SDL_nullrender.c @@ -32,6 +32,9 @@ static SDL_Renderer *SDL_DUMMY_CreateRenderer(SDL_Window * window, Uint32 flags); static int SDL_DUMMY_SetDrawColor(SDL_Renderer * renderer); +static int SDL_DUMMY_SetDrawBlendMode(SDL_Renderer * renderer); +static int SDL_DUMMY_RenderLine(SDL_Renderer * renderer, int x1, int y1, + int x2, int y2); static int SDL_DUMMY_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect); static int SDL_DUMMY_RenderCopy(SDL_Renderer * renderer, @@ -90,6 +93,8 @@ SDL_DUMMY_CreateRenderer(SDL_Window * window, Uint32 flags) SDL_zerop(data); renderer->SetDrawColor = SDL_DUMMY_SetDrawColor; + renderer->SetDrawBlendMode = SDL_DUMMY_SetDrawBlendMode; + renderer->RenderLine = SDL_DUMMY_RenderLine; renderer->RenderFill = SDL_DUMMY_RenderFill; renderer->RenderCopy = SDL_DUMMY_RenderCopy; renderer->RenderPresent = SDL_DUMMY_RenderPresent; @@ -131,19 +136,55 @@ SDL_DUMMY_SetDrawColor(SDL_Renderer * renderer) return 0; } +static int +SDL_DUMMY_SetDrawBlendMode(SDL_Renderer * renderer) +{ + return 0; +} + +static int +SDL_DUMMY_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2) +{ + SDL_DUMMY_RenderData *data = + (SDL_DUMMY_RenderData *) renderer->driverdata; + SDL_Surface *target = data->screens[data->current_screen]; + int status; + + if (renderer->blendMode == SDL_BLENDMODE_NONE) { + Uint32 color = + SDL_MapRGBA(target->format, renderer->r, renderer->g, renderer->b, + renderer->a); + + status = SDL_DrawLine(target, x1, y1, x2, y2, color); + } else { + status = + SDL_BlendLine(target, x1, y1, x2, y2, renderer->blendMode, + renderer->r, renderer->g, renderer->b, renderer->a); + } + return status; +} + static int SDL_DUMMY_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect) { SDL_DUMMY_RenderData *data = (SDL_DUMMY_RenderData *) renderer->driverdata; SDL_Surface *target = data->screens[data->current_screen]; - Uint32 color; SDL_Rect real_rect = *rect; + int status; - color = SDL_MapRGBA(target->format, - renderer->r, renderer->g, renderer->b, renderer->a); + if (renderer->blendMode == SDL_BLENDMODE_NONE) { + Uint32 color = + SDL_MapRGBA(target->format, renderer->r, renderer->g, renderer->b, + renderer->a); - return SDL_FillRect(target, &real_rect, color); + status = SDL_FillRect(target, &real_rect, color); + } else { + status = + SDL_BlendRect(target, &real_rect, renderer->blendMode, + renderer->r, renderer->g, renderer->b, renderer->a); + } + return status; } static int diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 7a22b0652..be221b0cf 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -597,6 +597,7 @@ X11_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2) { X11_RenderData *data = (X11_RenderData *) renderer->driverdata; unsigned long foreground; + if (data->makedirty) { SDL_Rect rect;