Created
January 15, 2015 15:32
-
-
Save Jakz/da135795a24d0382881e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <type_traits> | |
#include <cstring> | |
typedef unsigned char u8; | |
typedef unsigned short u16; | |
typedef unsigned int u32; | |
enum GfxBufferFormat | |
{ | |
FORMAT_XRGB888, | |
FORMAT_RGB565, | |
FORMAT_RGBA5551, | |
FORMAT_RGBA8888, | |
}; | |
struct GfxBuffer | |
{ | |
u16 width; | |
u16 height; | |
u8* data; | |
}; | |
struct Offset | |
{ | |
u16 x; | |
u16 y; | |
}; | |
struct SDL_Surface | |
{ | |
void* pixels; | |
u16 w; | |
u16 h; | |
}; | |
void SDL_LockSurface(SDL_Surface* surface) { } | |
void SDL_UnlockSurface(SDL_Surface* surface) { } | |
class Blitter | |
{ | |
protected: | |
template<typename T> | |
inline void rawBlit(SDL_Surface *dest, const GfxBuffer &buffer, const Offset &offset) | |
{ | |
SDL_LockSurface(dest); | |
T *p = static_cast<T*>(dest->pixels) + offset.x + offset.y*dest->w; | |
T *sp = reinterpret_cast<T*>(buffer.data); | |
for (int i = 0; i < buffer.height; ++i) | |
memcpy(p+(i*dest->w), sp+i*buffer.width, sizeof(T)*buffer.width); | |
SDL_UnlockSurface(dest); | |
} | |
public: | |
Blitter() { } | |
virtual void blit(const GfxBuffer& buffer, const Offset& offset, SDL_Surface* dest) = 0; | |
virtual ~Blitter() { } | |
}; | |
template<GfxBufferFormat FROM, GfxBufferFormat TO> | |
class FormatBlitter : public Blitter | |
{ | |
private: | |
typedef typename std::conditional<FROM == FORMAT_XRGB888 || FROM == FORMAT_RGBA8888, u32, u16>::type pixel_from; | |
typedef typename std::conditional<TO == FORMAT_XRGB888 || TO == FORMAT_RGBA8888, u32, u16>::type pixel_to; | |
public: | |
void blit(const GfxBuffer& buffer, const Offset& offset, SDL_Surface* dest) | |
{ | |
SDL_LockSurface(dest); | |
pixel_to* d = reinterpret_cast<pixel_to*>(dest->pixels) + offset.x + offset.y*dest->w; | |
pixel_from* s = reinterpret_cast<pixel_from*>(buffer.data); | |
for (int y = 0; y < buffer.height; ++y) | |
{ | |
pixel_to* bd = d + y*dest->w; | |
pixel_from* bs = s + y*buffer.width; | |
for (int x = 0; x < buffer.width; ++x, ++bd, ++bs) | |
*bd = convert(*bs); | |
} | |
SDL_UnlockSurface(dest); | |
} | |
template< bool cond, typename U > using conversion_type = typename std::enable_if<cond, U >::type; | |
template<GfxBufferFormat F = FROM> | |
static inline conversion_type<F == FORMAT_XRGB888 && TO == FORMAT_RGB565, pixel_to> convert(pixel_from c) | |
{ | |
u8 r = (c >> 16) / 8; | |
u8 g = ((c >> 8) & 0xFF) / 4; | |
u8 b = ((c) & 0xFF) / 8; | |
return (r << 11) | (g << 5) | b; | |
} | |
template<GfxBufferFormat F = FROM> | |
static inline conversion_type<F == FORMAT_XRGB888 && TO == FORMAT_RGBA8888, pixel_to> convert(pixel_from c) | |
{ | |
return c << 8; | |
} | |
}; | |
template<> | |
inline void FormatBlitter<FORMAT_RGB565, FORMAT_RGB565>::blit(const GfxBuffer &buffer, const Offset &offset, SDL_Surface *dest) | |
{ | |
rawBlit<u16>(dest, buffer, offset); | |
} | |
template<> | |
inline void FormatBlitter<FORMAT_RGBA5551, FORMAT_RGBA5551>::blit(const GfxBuffer &buffer, const Offset &offset, SDL_Surface *dest) | |
{ | |
rawBlit<u16>(dest, buffer, offset); | |
} | |
template<> | |
inline void FormatBlitter<FORMAT_RGBA8888, FORMAT_RGBA8888>::blit(const GfxBuffer &buffer, const Offset &offset, SDL_Surface *dest) | |
{ | |
rawBlit<u32>(dest, buffer, offset); | |
} | |
int main(void) | |
{ | |
SDL_Surface *dest = new SDL_Surface(); | |
dest->pixels = new u16[32*24]; | |
dest->w = 32; | |
dest->h = 24; | |
GfxBuffer src = {20,20,new u8[20*20*sizeof(u32)]}; | |
Offset offset = {5,5}; | |
Blitter* blitter = new FormatBlitter<FORMAT_XRGB888, FORMAT_RGB565>(); | |
blitter->blit(src, offset, dest); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment