Commit d1be2d9e authored by Sam Lantinga's avatar Sam Lantinga

Solved the performance problems by introducing the concept of a single-buffered

display, which is a fast path used for the whole-surface SDL 1.2 API.
Solved the flicker problems by implementing a backbuffer in the GDI renderer.

Unfortunately, now using the GDI renderer with a backbuffer and HBITMAPs is
significantly slower than SDL's surface code.  *sigh*

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401942
parent 58d76aea
...@@ -170,14 +170,14 @@ typedef enum ...@@ -170,14 +170,14 @@ typedef enum
*/ */
typedef enum typedef enum
{ {
SDL_Renderer_PresentDiscard = 0x00000001, /**< Present leaves the contents of the backbuffer undefined */ SDL_Renderer_SingleBuffer = 0x00000001, /**< Render directly to the window, if possible */
SDL_Renderer_PresentCopy = 0x00000002, /**< Present uses a copy from back buffer to the front buffer */ SDL_Renderer_PresentCopy = 0x00000002, /**< Present uses a copy from back buffer to the front buffer */
SDL_Renderer_PresentFlip2 = 0x00000004, /**< Present uses a flip, swapping back buffer and front buffer */ SDL_Renderer_PresentFlip2 = 0x00000004, /**< Present uses a flip, swapping back buffer and front buffer */
SDL_Renderer_PresentFlip3 = 0x00000008, /**< Present uses a flip, rotating between two back buffers and a front buffer */ SDL_Renderer_PresentFlip3 = 0x00000008, /**< Present uses a flip, rotating between two back buffers and a front buffer */
SDL_Renderer_PresentVSync = 0x00000010, /**< Present is synchronized with the refresh rate */ SDL_Renderer_PresentDiscard = 0x00000010, /**< Present leaves the contents of the backbuffer undefined */
SDL_Renderer_RenderTarget = 0x00000020, /**< The renderer can create texture render targets */ SDL_Renderer_PresentVSync = 0x00000020, /**< Present is synchronized with the refresh rate */
SDL_Renderer_Accelerated = 0x00000040, /**< The renderer uses hardware acceleration */ SDL_Renderer_RenderTarget = 0x00000040, /**< The renderer can create texture render targets */
SDL_Renderer_ = 0x00000080, /**< The renderer uses hardware acceleration */ SDL_Renderer_Accelerated = 0x00000080, /**< The renderer uses hardware acceleration */
SDL_Renderer_Minimal = 0x00000100, /**< The renderer only supports the read/write pixel and present functions */ SDL_Renderer_Minimal = 0x00000100, /**< The renderer only supports the read/write pixel and present functions */
} SDL_RendererFlags; } SDL_RendererFlags;
......
...@@ -442,7 +442,8 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) ...@@ -442,7 +442,8 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
} }
/* Create a renderer for the window */ /* Create a renderer for the window */
if (SDL_CreateRenderer(SDL_VideoWindow, -1, 0) < 0) { if (SDL_CreateRenderer(SDL_VideoWindow, -1, SDL_Renderer_SingleBuffer) <
0) {
return NULL; return NULL;
} }
...@@ -517,6 +518,7 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) ...@@ -517,6 +518,7 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
/* Clear the surface for display */ /* Clear the surface for display */
SDL_FillRect(SDL_PublicSurface, NULL, 0); SDL_FillRect(SDL_PublicSurface, NULL, 0);
SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0);
/* We're finally done! */ /* We're finally done! */
return SDL_PublicSurface; return SDL_PublicSurface;
...@@ -617,21 +619,11 @@ SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h) ...@@ -617,21 +619,11 @@ SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
if (screen) { if (screen) {
SDL_Rect rect; SDL_Rect rect;
/* Perform some checking */
if (w == 0)
w = screen->w;
if (h == 0)
h = screen->h;
if ((int) (x + w) > screen->w)
return;
if ((int) (y + h) > screen->h)
return;
/* Fill the rectangle */ /* Fill the rectangle */
rect.x = (Sint16) x; rect.x = (int) x;
rect.y = (Sint16) y; rect.y = (int) y;
rect.w = (Uint16) w; rect.w = (int) (w ? w : screen->w);
rect.h = (Uint16) h; rect.h = (int) (h ? h : screen->h);
SDL_UpdateRects(screen, 1, &rect); SDL_UpdateRects(screen, 1, &rect);
} }
} }
......
...@@ -77,12 +77,11 @@ SDL_RenderDriver SDL_SW_RenderDriver = { ...@@ -77,12 +77,11 @@ SDL_RenderDriver SDL_SW_RenderDriver = {
SDL_SW_CreateRenderer, SDL_SW_CreateRenderer,
{ {
"software", "software",
(SDL_Renderer_PresentDiscard | (SDL_Renderer_SingleBuffer | SDL_Renderer_PresentCopy |
SDL_Renderer_PresentCopy | SDL_Renderer_PresentFlip2 | SDL_Renderer_PresentFlip3 |
SDL_Renderer_PresentFlip2 | SDL_Renderer_PresentDiscard | SDL_Renderer_RenderTarget),
SDL_Renderer_PresentFlip3 | SDL_Renderer_RenderTarget), (SDL_TextureBlendMode_None | SDL_TextureBlendMode_Mask |
(SDL_TextureBlendMode_None | SDL_TextureBlendMode_Blend),
SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend),
(SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast), (SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast),
11, 11,
{ {
...@@ -108,6 +107,7 @@ typedef struct ...@@ -108,6 +107,7 @@ typedef struct
SDL_Surface *target; SDL_Surface *target;
SDL_Renderer *renderer; SDL_Renderer *renderer;
SDL_DirtyRectList dirty; SDL_DirtyRectList dirty;
SDL_bool makedirty;
} SDL_SW_RenderData; } SDL_SW_RenderData;
SDL_Renderer * SDL_Renderer *
...@@ -185,13 +185,16 @@ SDL_SW_CreateRenderer(SDL_Window * window, Uint32 flags) ...@@ -185,13 +185,16 @@ SDL_SW_CreateRenderer(SDL_Window * window, Uint32 flags)
} }
data->current_screen = 0; data->current_screen = 0;
data->target = data->screens[0]; data->target = data->screens[0];
data->makedirty = SDL_TRUE;
/* Find a render driver that we can use to display data */ /* Find a render driver that we can use to display data */
for (i = 0; i < display->num_render_drivers; ++i) { for (i = 0; i < display->num_render_drivers; ++i) {
SDL_RenderDriver *driver = &display->render_drivers[i]; SDL_RenderDriver *driver = &display->render_drivers[i];
if (driver->info.name != SDL_SW_RenderDriver.info.name) { if (driver->info.name != SDL_SW_RenderDriver.info.name) {
data->renderer = data->renderer =
driver->CreateRenderer(window, SDL_Renderer_PresentDiscard); driver->CreateRenderer(window,
(SDL_Renderer_SingleBuffer |
SDL_Renderer_PresentDiscard));
if (data->renderer) { if (data->renderer) {
break; break;
} }
...@@ -351,8 +354,10 @@ SDL_SW_SelectRenderTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -351,8 +354,10 @@ SDL_SW_SelectRenderTexture(SDL_Renderer * renderer, SDL_Texture * texture)
if (texture) { if (texture) {
data->target = (SDL_Surface *) texture->driverdata; data->target = (SDL_Surface *) texture->driverdata;
data->makedirty = SDL_FALSE;
} else { } else {
data->target = data->screens[data->current_screen]; data->target = data->screens[data->current_screen];
data->makedirty = SDL_TRUE;
} }
} }
...@@ -364,7 +369,9 @@ SDL_SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect, ...@@ -364,7 +369,9 @@ SDL_SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect,
SDL_Rect real_rect = *rect; SDL_Rect real_rect = *rect;
Uint8 r, g, b, a; Uint8 r, g, b, a;
if (data->makedirty) {
SDL_AddDirtyRect(&data->dirty, rect); SDL_AddDirtyRect(&data->dirty, rect);
}
a = (Uint8) ((color >> 24) & 0xFF); a = (Uint8) ((color >> 24) & 0xFF);
r = (Uint8) ((color >> 16) & 0xFF); r = (Uint8) ((color >> 16) & 0xFF);
...@@ -384,7 +391,9 @@ SDL_SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, ...@@ -384,7 +391,9 @@ SDL_SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
SDL_Window *window = SDL_GetWindowFromID(renderer->window); SDL_Window *window = SDL_GetWindowFromID(renderer->window);
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
if (data->makedirty) {
SDL_AddDirtyRect(&data->dirty, dstrect); SDL_AddDirtyRect(&data->dirty, dstrect);
}
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
SDL_Surface *target = data->target; SDL_Surface *target = data->target;
...@@ -450,7 +459,9 @@ SDL_SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect, ...@@ -450,7 +459,9 @@ SDL_SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
int row; int row;
size_t length; size_t length;
if (data->makedirty) {
SDL_AddDirtyRect(&data->dirty, rect); SDL_AddDirtyRect(&data->dirty, rect);
}
src = (Uint8 *) pixels; src = (Uint8 *) pixels;
dst = dst =
...@@ -471,7 +482,6 @@ SDL_SW_RenderPresent(SDL_Renderer * renderer) ...@@ -471,7 +482,6 @@ SDL_SW_RenderPresent(SDL_Renderer * renderer)
SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata;
SDL_Surface *surface = data->screens[data->current_screen]; SDL_Surface *surface = data->screens[data->current_screen];
SDL_DirtyRect *dirty; SDL_DirtyRect *dirty;
int new_screen;
/* Send the data to the display */ /* Send the data to the display */
for (dirty = data->dirty.list; dirty; dirty = dirty->next) { for (dirty = data->dirty.list; dirty; dirty = dirty->next) {
...@@ -485,19 +495,14 @@ SDL_SW_RenderPresent(SDL_Renderer * renderer) ...@@ -485,19 +495,14 @@ SDL_SW_RenderPresent(SDL_Renderer * renderer)
SDL_ClearDirtyRects(&data->dirty); SDL_ClearDirtyRects(&data->dirty);
data->renderer->RenderPresent(data->renderer); data->renderer->RenderPresent(data->renderer);
/* Update the flipping chain, if any */ /* Update the flipping chain, if any */
if (renderer->info.flags & SDL_Renderer_PresentFlip2) { if (renderer->info.flags & SDL_Renderer_PresentFlip2) {
new_screen = (data->current_screen + 1) % 2; data->current_screen = (data->current_screen + 1) % 2;
data->target = data->screens[data->current_screen];
} else if (renderer->info.flags & SDL_Renderer_PresentFlip3) { } else if (renderer->info.flags & SDL_Renderer_PresentFlip3) {
new_screen = (data->current_screen + 1) % 3; data->current_screen = (data->current_screen + 1) % 3;
} else { data->target = data->screens[data->current_screen];
new_screen = 0;
}
if (data->target == data->screens[data->current_screen]) {
data->target = data->screens[new_screen];
} }
data->current_screen = new_screen;
} }
static void static void
......
...@@ -1769,9 +1769,8 @@ SDL_RenderFill(const SDL_Rect * rect, Uint32 color) ...@@ -1769,9 +1769,8 @@ SDL_RenderFill(const SDL_Rect * rect, Uint32 color)
return 0; return 0;
} }
} }
rect = &real_rect;
return renderer->RenderFill(renderer, rect, color); return renderer->RenderFill(renderer, &real_rect, color);
} }
int int
...@@ -1793,25 +1792,26 @@ SDL_RenderCopy(SDL_TextureID textureID, const SDL_Rect * srcrect, ...@@ -1793,25 +1792,26 @@ SDL_RenderCopy(SDL_TextureID textureID, const SDL_Rect * srcrect,
return -1; return -1;
} }
/* FIXME: implement clipping */
window = SDL_GetWindowFromID(renderer->window); window = SDL_GetWindowFromID(renderer->window);
if (srcrect) {
real_srcrect = *srcrect;
} else {
real_srcrect.x = 0; real_srcrect.x = 0;
real_srcrect.y = 0; real_srcrect.y = 0;
real_srcrect.w = texture->w; real_srcrect.w = texture->w;
real_srcrect.h = texture->h; real_srcrect.h = texture->h;
}
if (dstrect) {
real_dstrect = *dstrect;
} else {
real_dstrect.x = 0; real_dstrect.x = 0;
real_dstrect.y = 0; real_dstrect.y = 0;
real_dstrect.w = window->w; real_dstrect.w = window->w;
real_dstrect.h = window->h; real_dstrect.h = window->h;
if (!srcrect) {
srcrect = &real_srcrect;
}
if (!dstrect) {
dstrect = &real_dstrect;
} }
return renderer->RenderCopy(renderer, texture, srcrect, dstrect, return renderer->RenderCopy(renderer, texture, &real_srcrect,
blendMode, scaleMode); &real_dstrect, blendMode, scaleMode);
} }
int int
...@@ -1882,6 +1882,9 @@ SDL_RenderPresent(void) ...@@ -1882,6 +1882,9 @@ SDL_RenderPresent(void)
return; return;
} }
if (renderer->SelectRenderTexture) {
renderer->SelectRenderTexture(renderer, NULL);
}
renderer->RenderPresent(renderer); renderer->RenderPresent(renderer);
} }
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment