Mercurial > sdl-ios-xcode
diff src/render/software/SDL_renderer_sw.c @ 5169:4d39eeaad00b
Added a way to get a framebuffer interface for a window, and also a way to create a software renderer for an arbitrary surface.
The software renderer has been re-routed to use the framebuffer interface, which makes it possible to have software rendering available even on simple ports.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 03 Feb 2011 15:49:37 -0800 |
parents | d72793305335 |
children |
line wrap: on
line diff
--- a/src/render/software/SDL_renderer_sw.c Thu Feb 03 11:16:57 2011 -0800 +++ b/src/render/software/SDL_renderer_sw.c Thu Feb 03 15:49:37 2011 -0800 @@ -69,7 +69,7 @@ SW_CreateRenderer, { "software", - (SDL_RENDERER_PRESENTVSYNC), + 0, 8, { SDL_PIXELFORMAT_RGB555, @@ -87,61 +87,19 @@ typedef struct { - Uint32 format; SDL_bool updateSize; - SDL_Texture *texture; - SDL_Surface surface; - SDL_Renderer *renderer; + SDL_Surface *surface; } SW_RenderData; -static SDL_Texture * -CreateTexture(SDL_Renderer * renderer, Uint32 format, int w, int h) -{ - SDL_Texture *texture; - - texture = (SDL_Texture *) SDL_calloc(1, sizeof(*texture)); - if (!texture) { - SDL_OutOfMemory(); - return NULL; - } - - texture->format = format; - texture->access = SDL_TEXTUREACCESS_STREAMING; - texture->w = w; - texture->h = h; - texture->renderer = renderer; - - if (renderer->CreateTexture(renderer, texture) < 0) { - SDL_free(texture); - return NULL; - } - return texture; -} - -static void -DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) -{ - renderer->DestroyTexture(renderer, texture); - SDL_free(texture); -} SDL_Renderer * -SW_CreateRenderer(SDL_Window * window, Uint32 flags) +SW_CreateRendererForSurface(SDL_Surface * surface) { SDL_Renderer *renderer; SW_RenderData *data; - int i; - int w, h; - Uint32 format; - int bpp; - Uint32 Rmask, Gmask, Bmask, Amask; - Uint32 renderer_flags; - const char *desired_driver; - format = SDL_GetWindowPixelFormat(window); - if (!SDL_PixelFormatEnumToMasks - (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { - SDL_SetError("Unknown display format"); + if (!surface) { + SDL_SetError("Can't create renderer for NULL surface"); return NULL; } @@ -157,6 +115,8 @@ SDL_OutOfMemory(); return NULL; } + data->surface = surface; + renderer->WindowEvent = SW_WindowEvent; renderer->CreateTexture = SW_CreateTexture; renderer->SetTextureColorMod = SW_SetTextureColorMod; @@ -174,80 +134,34 @@ renderer->RenderPresent = SW_RenderPresent; renderer->DestroyRenderer = SW_DestroyRenderer; renderer->info = SW_RenderDriver.info; - renderer->info.flags = 0; - renderer->window = window; renderer->driverdata = data; - data->format = format; - - /* Find a render driver that we can use to display data */ - renderer_flags = 0; - if (flags & SDL_RENDERER_PRESENTVSYNC) { - renderer_flags |= SDL_RENDERER_PRESENTVSYNC; - } - desired_driver = SDL_getenv("SDL_VIDEO_RENDERER_SWDRIVER"); - for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) { - SDL_RendererInfo info; - SDL_GetRenderDriverInfo(i, &info); - if (SDL_strcmp(info.name, SW_RenderDriver.info.name) == 0) { - continue; - } - if (desired_driver - && SDL_strcasecmp(desired_driver, info.name) != 0) { - continue; - } - data->renderer = SDL_CreateRenderer(window, i, renderer_flags); - if (data->renderer) { - break; - } - } - if (i == SDL_GetNumRenderDrivers()) { - SW_DestroyRenderer(renderer); - SDL_SetError("Couldn't find display render driver"); - return NULL; - } - if (data->renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) { - renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; - } - - /* Create the textures we'll use for display */ - SDL_GetWindowSize(window, &w, &h); - data->texture = CreateTexture(data->renderer, data->format, w, h); - if (!data->texture) { - SW_DestroyRenderer(renderer); - return NULL; - } - - /* Create a surface we'll use for rendering */ - data->surface.flags = SDL_PREALLOC; - data->surface.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); - if (!data->surface.format) { - SW_DestroyRenderer(renderer); - return NULL; - } - return renderer; } -static SDL_Texture * +SDL_Renderer * +SW_CreateRenderer(SDL_Window * window, Uint32 flags) +{ + SDL_Surface *surface; + + surface = SDL_GetWindowSurface(window); + if (!surface) { + return NULL; + } + return SW_CreateRendererForSurface(surface); +} + +static SDL_Surface * SW_ActivateRenderer(SDL_Renderer * renderer) { SW_RenderData *data = (SW_RenderData *) renderer->driverdata; SDL_Window *window = renderer->window; if (data->updateSize) { - /* Recreate the textures for the new window size */ - int w, h; - if (data->texture) { - DestroyTexture(data->renderer, data->texture); - } - SDL_GetWindowSize(window, &w, &h); - data->texture = CreateTexture(data->renderer, data->format, w, h); - if (data->texture) { - data->updateSize = SDL_FALSE; - } + data->surface = SDL_GetWindowSurface(window); + data->updateSize = SDL_FALSE; } - return data->texture; + return data->surface; } static void @@ -356,264 +270,130 @@ SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, int count) { - SW_RenderData *data = (SW_RenderData *) renderer->driverdata; - SDL_Texture *texture = SW_ActivateRenderer(renderer); - SDL_Rect rect; - int i; - int x, y; - int status = 0; - - if (!texture) { - return -1; - } + SDL_Surface *surface = SW_ActivateRenderer(renderer); - /* Get the smallest rectangle that contains everything */ - rect.x = 0; - rect.y = 0; - rect.w = texture->w; - rect.h = texture->h; - if (!SDL_EnclosePoints(points, count, &rect, &rect)) { - /* Nothing to draw */ - return 0; - } - - if (data->renderer->LockTexture(data->renderer, texture, &rect, - &data->surface.pixels, - &data->surface.pitch) < 0) { + if (!surface) { return -1; } - data->surface.clip_rect.w = data->surface.w = rect.w; - data->surface.clip_rect.h = data->surface.h = rect.h; - /* Draw the points! */ if (renderer->blendMode == SDL_BLENDMODE_NONE) { - Uint32 color = SDL_MapRGBA(data->surface.format, + Uint32 color = SDL_MapRGBA(surface->format, renderer->r, renderer->g, renderer->b, renderer->a); - for (i = 0; i < count; ++i) { - x = points[i].x - rect.x; - y = points[i].y - rect.y; - - status = SDL_DrawPoint(&data->surface, x, y, color); - } + return SDL_DrawPoints(surface, points, count, color); } else { - for (i = 0; i < count; ++i) { - x = points[i].x - rect.x; - y = points[i].y - rect.y; - - status = SDL_BlendPoint(&data->surface, x, y, - renderer->blendMode, - renderer->r, renderer->g, renderer->b, - renderer->a); - } + return SDL_BlendPoints(surface, points, count, + renderer->blendMode, + renderer->r, renderer->g, renderer->b, + renderer->a); } - - data->renderer->UnlockTexture(data->renderer, texture); - - return status; } static int SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, int count) { - SW_RenderData *data = (SW_RenderData *) renderer->driverdata; - SDL_Texture *texture = SW_ActivateRenderer(renderer); - SDL_Rect clip, rect; - int i; - int x1, y1, x2, y2; - int status = 0; - - if (!texture) { - return -1; - } + SDL_Surface *surface = SW_ActivateRenderer(renderer); - /* Get the smallest rectangle that contains everything */ - clip.x = 0; - clip.y = 0; - clip.w = texture->w; - clip.h = texture->h; - SDL_EnclosePoints(points, count, NULL, &rect); - if (!SDL_IntersectRect(&rect, &clip, &rect)) { - /* Nothing to draw */ - return 0; - } - - if (data->renderer->LockTexture(data->renderer, texture, &rect, - &data->surface.pixels, - &data->surface.pitch) < 0) { + if (!surface) { return -1; } - data->surface.clip_rect.w = data->surface.w = rect.w; - data->surface.clip_rect.h = data->surface.h = rect.h; - - /* Draw the points! */ + /* Draw the lines! */ if (renderer->blendMode == SDL_BLENDMODE_NONE) { - Uint32 color = SDL_MapRGBA(data->surface.format, + Uint32 color = SDL_MapRGBA(surface->format, renderer->r, renderer->g, renderer->b, renderer->a); - for (i = 1; i < count; ++i) { - x1 = points[i-1].x - rect.x; - y1 = points[i-1].y - rect.y; - x2 = points[i].x - rect.x; - y2 = points[i].y - rect.y; - - status = SDL_DrawLine(&data->surface, x1, y1, x2, y2, color); - } + return SDL_DrawLines(surface, points, count, color); } else { - for (i = 1; i < count; ++i) { - x1 = points[i-1].x - rect.x; - y1 = points[i-1].y - rect.y; - x2 = points[i].x - rect.x; - y2 = points[i].y - rect.y; - - status = SDL_BlendLine(&data->surface, x1, y1, x2, y2, - renderer->blendMode, - renderer->r, renderer->g, renderer->b, - renderer->a); - } + return SDL_BlendLines(surface, points, count, + renderer->blendMode, + renderer->r, renderer->g, renderer->b, + renderer->a); } - - data->renderer->UnlockTexture(data->renderer, texture); - - return status; } static int SW_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) { - SW_RenderData *data = (SW_RenderData *) renderer->driverdata; - SDL_Texture *texture = SW_ActivateRenderer(renderer); - SDL_Rect clip, rect; - Uint32 color = 0; - int i; - int status = 0; + SDL_Surface *surface = SW_ActivateRenderer(renderer); - if (!texture) { + if (!surface) { return -1; } - clip.x = 0; - clip.y = 0; - clip.w = texture->w; - clip.h = texture->h; - if (renderer->blendMode == SDL_BLENDMODE_NONE) { - color = SDL_MapRGBA(data->surface.format, - renderer->r, renderer->g, renderer->b, - renderer->a); + Uint32 color = SDL_MapRGBA(surface->format, + renderer->r, renderer->g, renderer->b, + renderer->a); + return SDL_FillRects(surface, rects, count, color); + } else { + return SDL_BlendFillRects(surface, rects, count, + renderer->blendMode, + renderer->r, renderer->g, renderer->b, + renderer->a); } - - for (i = 0; i < count; ++i) { - if (!SDL_IntersectRect(rects[i], &clip, &rect)) { - /* Nothing to draw */ - continue; - } - - if (data->renderer->LockTexture(data->renderer, texture, &rect, - &data->surface.pixels, - &data->surface.pitch) < 0) { - return -1; - } - - data->surface.clip_rect.w = data->surface.w = rect.w; - data->surface.clip_rect.h = data->surface.h = rect.h; - - if (renderer->blendMode == SDL_BLENDMODE_NONE) { - status = SDL_FillRect(&data->surface, NULL, color); - } else { - status = SDL_BlendFillRect(&data->surface, NULL, - renderer->blendMode, - renderer->r, renderer->g, renderer->b, - renderer->a); - } - - data->renderer->UnlockTexture(data->renderer, texture); - } - return status; } static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect) { - SW_RenderData *data = (SW_RenderData *) renderer->driverdata; - SDL_Surface *surface; - SDL_Rect real_srcrect; - SDL_Rect real_dstrect; - int status; + SDL_Surface *surface = SW_ActivateRenderer(renderer); + SDL_Surface *src = (SDL_Surface *) texture->driverdata; + SDL_Rect final_rect = *dstrect; - if (!SW_ActivateRenderer(renderer)) { + if (!surface) { return -1; } - - if (data->renderer->LockTexture(data->renderer, data->texture, dstrect, - &data->surface.pixels, - &data->surface.pitch) < 0) { - return -1; - } - - surface = (SDL_Surface *) texture->driverdata; - real_srcrect = *srcrect; - - data->surface.w = dstrect->w; - data->surface.h = dstrect->h; - data->surface.clip_rect.w = dstrect->w; - data->surface.clip_rect.h = dstrect->h; - real_dstrect = data->surface.clip_rect; - - status = SDL_LowerBlit(surface, &real_srcrect, &data->surface, &real_dstrect); - data->renderer->UnlockTexture(data->renderer, data->texture); - return status; + return SDL_BlitSurface(src, srcrect, surface, &final_rect); } static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, Uint32 format, void * pixels, int pitch) { - SW_RenderData *data = (SW_RenderData *) renderer->driverdata; + SDL_Surface *surface = SW_ActivateRenderer(renderer); + Uint32 src_format; + void *src_pixels; - if (!SW_ActivateRenderer(renderer)) { + if (!surface) { return -1; } - if (data->renderer->LockTexture(data->renderer, data->texture, rect, - &data->surface.pixels, - &data->surface.pitch) < 0) { + if (rect->x < 0 || rect->x+rect->w > surface->w || + rect->y < 0 || rect->y+rect->h > surface->h) { + SDL_SetError("Tried to read outside of surface bounds"); return -1; } - SDL_ConvertPixels(rect->w, rect->h, - data->format, data->surface.pixels, data->surface.pitch, - format, pixels, pitch); + src_format = SDL_MasksToPixelFormatEnum( + surface->format->BitsPerPixel, + surface->format->Rmask, surface->format->Gmask, + surface->format->Bmask, surface->format->Amask); - data->renderer->UnlockTexture(data->renderer, data->texture); - return 0; + src_pixels = (void*)((Uint8 *) surface->pixels + + rect->y * surface->pitch + + rect->x * surface->format->BytesPerPixel); + + return SDL_ConvertPixels(rect->w, rect->h, + src_format, src_pixels, surface->pitch, + format, pixels, pitch); } static void SW_RenderPresent(SDL_Renderer * renderer) { SW_RenderData *data = (SW_RenderData *) renderer->driverdata; - SDL_Texture *texture = SW_ActivateRenderer(renderer); - SDL_Rect rect; - - if (!texture) { - return; - } + SDL_Window *window = renderer->window; - /* Send the data to the display */ - rect.x = 0; - rect.y = 0; - rect.w = texture->w; - rect.h = texture->h; - data->renderer->RenderCopy(data->renderer, texture, &rect, &rect); - data->renderer->RenderPresent(data->renderer); + if (window) { + SDL_UpdateWindowSurface(window); + } } static void @@ -628,18 +408,8 @@ SW_DestroyRenderer(SDL_Renderer * renderer) { SW_RenderData *data = (SW_RenderData *) renderer->driverdata; - SDL_Window *window = renderer->window; if (data) { - if (data->texture) { - DestroyTexture(data->renderer, data->texture); - } - if (data->surface.format) { - SDL_FreeFormat(data->surface.format); - } - if (data->renderer) { - data->renderer->DestroyRenderer(data->renderer); - } SDL_free(data); } SDL_free(renderer);