Mercurial > sdl-ios-xcode
diff src/video/SDL_renderer_sw.c @ 1985:8055185ae4ed
Added source color and alpha modulation support.
Added perl script to generate optimized render copy functions.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 28 Aug 2006 03:17:39 +0000 |
parents | a0e278364188 |
children | 5b5f5de5433f |
line wrap: on
line diff
--- a/src/video/SDL_renderer_sw.c Thu Aug 24 12:49:59 2006 +0000 +++ b/src/video/SDL_renderer_sw.c Mon Aug 28 03:17:39 2006 +0000 @@ -26,6 +26,7 @@ #include "SDL_pixels_c.h" #include "SDL_rect_c.h" #include "SDL_yuv_sw_c.h" +#include "SDL_rendercopy.h" /* SDL surface based renderer implementation */ @@ -44,22 +45,28 @@ static int SW_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture, SDL_Color * colors, int firstcolor, int ncolors); -static int SW_UpdateTexture(SDL_Renderer * renderer, - SDL_Texture * texture, const SDL_Rect * rect, - const void *pixels, int pitch); +static int SW_SetTextureColorMod(SDL_Renderer * renderer, + SDL_Texture * texture); +static int SW_SetTextureAlphaMod(SDL_Renderer * renderer, + SDL_Texture * texture); +static int SW_SetTextureBlendMode(SDL_Renderer * renderer, + SDL_Texture * texture); +static int SW_SetTextureScaleMode(SDL_Renderer * renderer, + SDL_Texture * texture); +static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, const void *pixels, + int pitch); static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * rect, int markDirty, - void **pixels, int *pitch); + const SDL_Rect * rect, int markDirty, void **pixels, + int *pitch); static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); static void SW_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects, const SDL_Rect * rects); -static int SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect, - Uint32 color); +static int SW_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b, + Uint8 a, const SDL_Rect * rect); static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * srcrect, - const SDL_Rect * dstrect, int blendMode, - int scaleMode); + const SDL_Rect * srcrect, const SDL_Rect * dstrect); static void SW_RenderPresent(SDL_Renderer * renderer); static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture); static void SW_DestroyRenderer(SDL_Renderer * renderer); @@ -72,8 +79,11 @@ (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY | SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 | SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_PRESENTVSYNC), + (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR | + SDL_TEXTUREMODULATE_ALPHA), (SDL_TEXTUREBLENDMODE_NONE | SDL_TEXTUREBLENDMODE_MASK | - SDL_TEXTUREBLENDMODE_BLEND), + SDL_TEXTUREBLENDMODE_BLEND | SDL_TEXTUREBLENDMODE_ADD | + SDL_TEXTUREBLENDMODE_MOD), (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST), 11, { @@ -188,6 +198,10 @@ renderer->QueryTexturePixels = SW_QueryTexturePixels; renderer->SetTexturePalette = SW_SetTexturePalette; renderer->GetTexturePalette = SW_GetTexturePalette; + renderer->SetTextureColorMod = SW_SetTextureColorMod; + renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod; + renderer->SetTextureBlendMode = SW_SetTextureBlendMode; + renderer->SetTextureScaleMode = SW_SetTextureScaleMode; renderer->UpdateTexture = SW_UpdateTexture; renderer->LockTexture = SW_LockTexture; renderer->UnlockTexture = SW_UnlockTexture; @@ -333,6 +347,7 @@ if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { texture->driverdata = SDL_SW_CreateYUVTexture(texture); } else { + SDL_Surface *surface; int bpp; Uint32 Rmask, Gmask, Bmask, Amask; @@ -400,6 +415,72 @@ } } +static void +SW_UpdateRenderCopyFunc(SDL_Renderer * renderer, SDL_Texture * texture) +{ + SW_RenderData *data = (SW_RenderData *) renderer->driverdata; + SDL_Surface *surface = (SDL_Surface *) texture->driverdata; + + surface->userdata = + SDL_GetRenderCopyFunc(texture->format, data->format, texture->modMode, + texture->blendMode, texture->scaleMode); +} + +static int +SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture) +{ + SW_UpdateRenderCopyFunc(renderer, texture); + return 0; +} + +static int +SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture) +{ + SW_UpdateRenderCopyFunc(renderer, texture); + return 0; +} + +static int +SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture) +{ + switch (texture->blendMode) { + case SDL_TEXTUREBLENDMODE_NONE: + case SDL_TEXTUREBLENDMODE_MASK: + case SDL_TEXTUREBLENDMODE_BLEND: + case SDL_TEXTUREBLENDMODE_ADD: + case SDL_TEXTUREBLENDMODE_MOD: + SW_UpdateRenderCopyFunc(renderer, texture); + return 0; + default: + SDL_Unsupported(); + texture->blendMode = SDL_TEXTUREBLENDMODE_NONE; + SW_UpdateRenderCopyFunc(renderer, texture); + return -1; + } +} + +static int +SW_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture) +{ + switch (texture->scaleMode) { + case SDL_TEXTURESCALEMODE_NONE: + case SDL_TEXTURESCALEMODE_FAST: + SW_UpdateRenderCopyFunc(renderer, texture); + return 0; + case SDL_TEXTURESCALEMODE_SLOW: + case SDL_TEXTURESCALEMODE_BEST: + SDL_Unsupported(); + texture->scaleMode = SDL_TEXTURESCALEMODE_FAST; + SW_UpdateRenderCopyFunc(renderer, texture); + return -1; + default: + SDL_Unsupported(); + texture->scaleMode = SDL_TEXTURESCALEMODE_NONE; + SW_UpdateRenderCopyFunc(renderer, texture); + return -1; + } +} + static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, int pitch) @@ -462,10 +543,11 @@ } static int -SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect, Uint32 color) +SW_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a, + const SDL_Rect * rect) { SW_RenderData *data = (SW_RenderData *) renderer->driverdata; - Uint8 r, g, b, a; + Uint32 color; SDL_Rect real_rect; int status; @@ -473,10 +555,6 @@ SDL_AddDirtyRect(&data->dirty, rect); } - a = (Uint8) ((color >> 24) & 0xFF); - r = (Uint8) ((color >> 16) & 0xFF); - g = (Uint8) ((color >> 8) & 0xFF); - b = (Uint8) (color & 0xFF); color = SDL_MapRGBA(data->surface.format, r, g, b, a); if (data->renderer-> @@ -500,8 +578,7 @@ static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * srcrect, const SDL_Rect * dstrect, - int blendMode, int scaleMode) + const SDL_Rect * srcrect, const SDL_Rect * dstrect) { SW_RenderData *data = (SW_RenderData *) renderer->driverdata; SDL_Window *window = SDL_GetWindowFromID(renderer->window); @@ -525,27 +602,55 @@ data->surface.pixels, data->surface.pitch); } else { SDL_Surface *surface = (SDL_Surface *) texture->driverdata; - SDL_Rect real_srcrect = *srcrect; - SDL_Rect real_dstrect; + SDL_RenderCopyFunc copyfunc = (SDL_RenderCopyFunc) surface->userdata; - 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; + if (copyfunc) { + SDL_RenderCopyData copydata; - if (blendMode & - (SDL_TEXTUREBLENDMODE_MASK | SDL_TEXTUREBLENDMODE_BLEND)) { - SDL_SetAlpha(surface, SDL_SRCALPHA, 0); + copydata.src = + (Uint8 *) surface->pixels + srcrect->y * surface->pitch + + srcrect->x * surface->format->BytesPerPixel; + copydata.src_w = srcrect->w; + copydata.src_h = srcrect->h; + copydata.src_pitch = surface->pitch; + copydata.dst = (Uint8 *) data->surface.pixels; + copydata.dst_w = dstrect->w; + copydata.dst_h = dstrect->h; + copydata.dst_pitch = data->surface.pitch; + copydata.flags = 0; + if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) { + copydata.flags |= SDL_RENDERCOPY_MODULATE_COLOR; + copydata.r = texture->r; + copydata.g = texture->g; + copydata.b = texture->b; + } + if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) { + copydata.flags |= SDL_RENDERCOPY_MODULATE_ALPHA; + copydata.a = texture->a; + } + if (texture-> + blendMode & (SDL_TEXTUREBLENDMODE_MASK | + SDL_TEXTUREBLENDMODE_BLEND)) { + copydata.flags |= SDL_RENDERCOPY_BLEND; + } else if (texture->blendMode & SDL_TEXTUREBLENDMODE_ADD) { + copydata.flags |= SDL_RENDERCOPY_ADD; + } else if (texture->blendMode & SDL_TEXTUREBLENDMODE_MOD) { + copydata.flags |= SDL_RENDERCOPY_MOD; + } + if (texture->scaleMode) { + copydata.flags |= SDL_RENDERCOPY_NEAREST; + } + status = copyfunc(©data); } else { - SDL_SetAlpha(surface, 0, 0); - } - if (scaleMode != SDL_TEXTURESCALEMODE_NONE && - (srcrect->w != dstrect->w || srcrect->h != dstrect->h)) { - status = - SDL_SoftStretch(surface, &real_srcrect, &data->surface, - &real_dstrect); - } else { + SDL_Rect real_srcrect = *srcrect; + SDL_Rect real_dstrect; + + 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); @@ -567,9 +672,7 @@ SDL_DirtyRect *dirty; for (dirty = data->dirty.list; dirty; dirty = dirty->next) { data->renderer->RenderCopy(data->renderer, texture, &dirty->rect, - &dirty->rect, - SDL_TEXTUREBLENDMODE_NONE, - SDL_TEXTURESCALEMODE_NONE); + &dirty->rect); } SDL_ClearDirtyRects(&data->dirty); } else { @@ -578,9 +681,7 @@ rect.y = 0; rect.w = texture->w; rect.h = texture->h; - data->renderer->RenderCopy(data->renderer, texture, &rect, &rect, - SDL_TEXTUREBLENDMODE_NONE, - SDL_TEXTURESCALEMODE_NONE); + data->renderer->RenderCopy(data->renderer, texture, &rect, &rect); } data->renderer->RenderPresent(data->renderer);