2014-07-02 19:08:47 +02:00
|
|
|
#include "graphics/tinygl/zblit.h"
|
|
|
|
#include "graphics/tinygl/zgl.h"
|
2014-07-07 18:17:54 +02:00
|
|
|
#include "graphics/pixelbuffer.h"
|
|
|
|
|
|
|
|
struct TinyGLBlitTexture {
|
|
|
|
public:
|
|
|
|
TinyGLBlitTexture() { }
|
|
|
|
|
|
|
|
void loadData(const Graphics::Surface& surface, int colorKey, bool applyColorKey) {
|
|
|
|
Graphics::PixelFormat textureFormat(4, 8, 8, 8, 8, 0, 8, 16, 24);
|
|
|
|
_surface.create(surface.w, surface.h, textureFormat);
|
|
|
|
Graphics::PixelBuffer buffer(surface.format, (byte *)surface.getPixels());
|
|
|
|
Graphics::PixelBuffer dataBuffer(textureFormat, (byte *)_surface.getPixels());
|
|
|
|
for (int x = 0; x < surface.w; x++) {
|
|
|
|
for (int y = 0; y < surface.h; y++) {
|
|
|
|
uint32 pixel = buffer.getValueAt(y * surface.w + x);
|
|
|
|
if (pixel == colorKey && applyColorKey) {
|
|
|
|
dataBuffer.setPixelAt(y * surface.w + x, 0, 255, 255, 255); // Color keyed pixels become transparent white.
|
|
|
|
} else {
|
|
|
|
dataBuffer.setPixelAt(y * surface.w + x, pixel);
|
2014-07-04 19:34:12 +02:00
|
|
|
}
|
|
|
|
}
|
2014-07-02 19:08:47 +02:00
|
|
|
}
|
2014-07-07 18:17:54 +02:00
|
|
|
// Create opaque lines data.
|
|
|
|
}
|
2014-07-02 19:08:47 +02:00
|
|
|
|
2014-07-07 18:17:54 +02:00
|
|
|
~TinyGLBlitTexture() {
|
|
|
|
_surface.free();
|
2014-07-02 19:08:47 +02:00
|
|
|
}
|
|
|
|
|
2014-07-07 18:17:54 +02:00
|
|
|
Graphics::Surface _surface;
|
|
|
|
};
|
|
|
|
|
|
|
|
int tglGenBlitTexture() {
|
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
|
|
|
int handle = -1;
|
|
|
|
for(int i = 0; i < BLIT_TEXTURE_MAX_COUNT; i++) {
|
|
|
|
if (c->blitTextures[i] == NULL) {
|
|
|
|
handle = i;
|
|
|
|
c->blitTextures[i] = new TinyGLBlitTexture();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tglUploadBlitTexture(int textureHandle, const Graphics::Surface& surface, int colorKey, bool applyColorKey) {
|
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
|
|
|
TinyGLBlitTexture *texture = (TinyGLBlitTexture *)c->blitTextures[textureHandle];
|
|
|
|
texture->loadData(surface, colorKey, applyColorKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tglDeleteBlitTexture(int textureHandle) {
|
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
|
|
|
TinyGLBlitTexture *texture = (TinyGLBlitTexture *)c->blitTextures[textureHandle];
|
|
|
|
c->blitTextures[textureHandle] = NULL;
|
|
|
|
delete texture;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <bool disableBlending, bool disableColoring, bool disableTransform, bool flipVertical, bool flipHorizontal>
|
|
|
|
void tglBlitGeneric(int blitTextureHandle, int dstX, int dstY, int width, int height, int srcX, int srcY, int srcWidth, int srcHeight, float rotation,
|
|
|
|
float originX, float originY, float aTint, float rTint, float gTint, float bTint) {
|
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
|
|
|
TinyGLBlitTexture *texture = (TinyGLBlitTexture *)c->blitTextures[blitTextureHandle];
|
|
|
|
|
|
|
|
if (srcWidth == 0 || srcHeight == 0) {
|
|
|
|
srcWidth = texture->_surface.w;
|
|
|
|
srcHeight = texture->_surface.h;
|
2014-07-04 19:34:12 +02:00
|
|
|
}
|
2014-07-02 19:08:47 +02:00
|
|
|
|
2014-07-07 18:17:54 +02:00
|
|
|
if (width == 0 && height == 0) {
|
|
|
|
width = srcWidth;
|
|
|
|
height = srcHeight;
|
2014-07-02 19:08:47 +02:00
|
|
|
}
|
|
|
|
|
2014-07-07 18:17:54 +02:00
|
|
|
if (dstX >= c->fb->xsize|| dstY >= c->fb->ysize)
|
|
|
|
return;
|
2014-07-02 19:08:47 +02:00
|
|
|
|
2014-07-07 18:17:54 +02:00
|
|
|
int clampWidth, clampHeight;
|
2014-07-02 19:08:47 +02:00
|
|
|
|
2014-07-07 18:17:54 +02:00
|
|
|
if (dstX + width > c->fb->xsize)
|
|
|
|
clampWidth = c->fb->xsize - dstX;
|
|
|
|
else
|
|
|
|
clampWidth = width;
|
2014-07-02 19:08:47 +02:00
|
|
|
|
2014-07-07 18:17:54 +02:00
|
|
|
if (dstY + height > c->fb->ysize)
|
|
|
|
clampHeight = c->fb->ysize - dstY;
|
|
|
|
else
|
|
|
|
clampHeight = height;
|
2014-07-02 19:08:47 +02:00
|
|
|
|
2014-07-07 18:17:54 +02:00
|
|
|
if (dstX < 0)
|
|
|
|
dstX = 0;
|
|
|
|
if (dstY < 0)
|
|
|
|
dstY = 0;
|
2014-07-02 19:08:47 +02:00
|
|
|
|
|
|
|
|
2014-07-07 18:17:54 +02:00
|
|
|
Graphics::PixelBuffer srcBuf(texture->_surface.format, (byte *)texture->_surface.getPixels());
|
2014-07-02 19:08:47 +02:00
|
|
|
|
2014-07-07 18:17:54 +02:00
|
|
|
if (flipVertical) {
|
|
|
|
srcBuf.shiftBy(srcX + ((srcY + srcHeight - 1) * texture->_surface.w));
|
|
|
|
} else {
|
|
|
|
srcBuf.shiftBy(srcX + (srcY * texture->_surface.w));
|
|
|
|
}
|
|
|
|
|
|
|
|
Graphics::PixelBuffer dstBuf(c->fb->cmode, c->fb->getPixelBuffer());
|
|
|
|
|
|
|
|
for (int l = 0; l < clampHeight; l++) {
|
|
|
|
for (int r = 0; r < clampWidth; ++r) {
|
|
|
|
byte aDst, rDst, gDst, bDst;
|
|
|
|
if (flipHorizontal) {
|
|
|
|
srcBuf.getARGBAt(clampWidth - r, aDst, rDst, gDst, bDst);
|
|
|
|
} else {
|
2014-07-02 19:08:47 +02:00
|
|
|
srcBuf.getARGBAt(r, aDst, rDst, gDst, bDst);
|
|
|
|
}
|
2014-07-07 18:17:54 +02:00
|
|
|
if (disableColoring) {
|
|
|
|
if (disableBlending && aDst != 0) {
|
|
|
|
dstBuf.setPixelAt((dstX + r) + (dstY + l) * c->fb->xsize, aDst, rDst, gDst, bDst);
|
|
|
|
} else {
|
|
|
|
c->fb->writePixel((dstX + r) + (dstY + l) * c->fb->xsize, aDst, rDst, gDst, bDst);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (disableBlending && aDst != 0) {
|
|
|
|
dstBuf.setPixelAt((dstX + r) + (dstY + l) * c->fb->xsize, aDst * aTint, rDst * rTint, gDst * gTint, bDst * bTint);
|
|
|
|
} else {
|
|
|
|
c->fb->writePixel((dstX + r) + (dstY + l) * c->fb->xsize, aDst * aTint, rDst * rTint, gDst * gTint, bDst * bTint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (flipVertical) {
|
|
|
|
srcBuf.shiftBy(-texture->_surface.w);
|
|
|
|
} else {
|
|
|
|
srcBuf.shiftBy(texture->_surface.w);
|
2014-07-02 19:08:47 +02:00
|
|
|
}
|
|
|
|
}
|
2014-07-07 18:17:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Utility function.
|
|
|
|
template <bool disableBlending, bool disableColoring, bool disableTransform, bool flipVertical, bool flipHorizontal>
|
|
|
|
FORCEINLINE void tglBlitGeneric(int blitTextureHandle, const BlitTransform &transform) {
|
|
|
|
tglBlitGeneric<disableBlending, disableColoring, disableTransform, flipVertical, flipHorizontal>(blitTextureHandle, transform._dstX, transform._dstY,
|
|
|
|
transform._width, transform._height, transform._srcX, transform._srcY, transform._srcWidth, transform._srcHeight, transform._rotation,
|
|
|
|
transform._originX, transform._originY, transform._aTint, transform._rTint, transform._gTint, transform._bTint);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tglBlit(int blitTextureHandle, const BlitTransform &transform) {
|
|
|
|
TinyGL::GLContext *c =TinyGL::gl_get_context();
|
|
|
|
bool disableColor = transform._aTint == 1.0f && transform._bTint == 1.0f && transform._gTint == 1.0f && transform._rTint == 1.0f;
|
|
|
|
bool disableTransform = transform._width == 0 && transform._height == 0 && transform._rotation == 0;
|
|
|
|
bool disableBlend = c->enableBlend == false;
|
|
|
|
if (transform._flipHorizontally == false && transform._flipVertically == false) {
|
|
|
|
if (disableColor && disableTransform && disableBlend) {
|
|
|
|
tglBlitGeneric<true, true, true, false, false>(blitTextureHandle, transform);
|
|
|
|
} else if (disableColor && disableTransform) {
|
|
|
|
tglBlitGeneric<false, true, true, false, false>(blitTextureHandle, transform);
|
|
|
|
} else if (disableTransform) {
|
|
|
|
tglBlitGeneric<false, false, true, false, false>(blitTextureHandle, transform);
|
|
|
|
} else {
|
|
|
|
tglBlitGeneric<false, false, false, false, false>(blitTextureHandle, transform);
|
|
|
|
}
|
|
|
|
} else if (transform._flipHorizontally == false) {
|
2014-07-02 19:08:47 +02:00
|
|
|
if (disableColor && disableTransform && disableBlend) {
|
2014-07-07 18:17:54 +02:00
|
|
|
tglBlitGeneric<true, true, true, true, false>(blitTextureHandle, transform);
|
2014-07-02 19:08:47 +02:00
|
|
|
} else if (disableColor && disableTransform) {
|
2014-07-07 18:17:54 +02:00
|
|
|
tglBlitGeneric<false, true, true, true, false>(blitTextureHandle, transform);
|
2014-07-02 19:08:47 +02:00
|
|
|
} else if (disableTransform) {
|
2014-07-07 18:17:54 +02:00
|
|
|
tglBlitGeneric<false, false, true, true, false>(blitTextureHandle, transform);
|
2014-07-02 19:08:47 +02:00
|
|
|
} else {
|
2014-07-07 18:17:54 +02:00
|
|
|
tglBlitGeneric<false, false, false, true, false>(blitTextureHandle, transform);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (disableColor && disableTransform && disableBlend) {
|
|
|
|
tglBlitGeneric<true, true, true, true, true>(blitTextureHandle, transform);
|
|
|
|
} else if (disableColor && disableTransform) {
|
|
|
|
tglBlitGeneric<false, true, true, true, true>(blitTextureHandle, transform);
|
|
|
|
} else if (disableTransform) {
|
|
|
|
tglBlitGeneric<false, false, true, true, true>(blitTextureHandle, transform);
|
|
|
|
} else {
|
|
|
|
tglBlitGeneric<false, false, false, true, true>(blitTextureHandle, transform);
|
2014-07-02 19:08:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-07 18:17:54 +02:00
|
|
|
}
|
2014-07-02 19:08:47 +02:00
|
|
|
|
2014-07-07 18:17:54 +02:00
|
|
|
void tglBlitNoBlend(int blitTextureHandle, const BlitTransform &transform) {
|
|
|
|
if (transform._flipHorizontally == false && transform._flipVertically == false) {
|
|
|
|
tglBlitGeneric<true, false, false, false, false>(blitTextureHandle, transform);
|
|
|
|
} else if(transform._flipHorizontally == false) {
|
|
|
|
tglBlitGeneric<true, false, false, true, false>(blitTextureHandle, transform);
|
|
|
|
} else {
|
|
|
|
tglBlitGeneric<true, false, false, true, true>(blitTextureHandle, transform);
|
2014-07-02 19:08:47 +02:00
|
|
|
}
|
2014-07-07 18:17:54 +02:00
|
|
|
}
|
2014-07-02 19:08:47 +02:00
|
|
|
|
2014-07-07 18:17:54 +02:00
|
|
|
void tglBlitFast(int blitTextureHandle, int x, int y) {
|
|
|
|
BlitTransform transform(x, y);
|
|
|
|
tglBlitGeneric<true, true, true, false, false>(blitTextureHandle, transform);
|
|
|
|
}
|