TINYGL: refined blit interface.

This commit is contained in:
Stefano Musumeci 2014-07-07 18:17:54 +02:00
parent 62aa0af91a
commit 75908d68d8
2 changed files with 230 additions and 102 deletions

View File

@ -1,117 +1,197 @@
#include "graphics/tinygl/zblit.h"
#include "graphics/tinygl/zgl.h"
#include "graphics/pixelbuffer.h"
namespace TinyGL {
struct TinyGLBlitTexture {
public:
TinyGLBlitTexture() : width(0), height(0) { }
struct TinyGLBlitTexture {
public:
TinyGLBlitTexture() { }
void loadData(int width, int height, Graphics::PixelBuffer &buffer, int colorKey) {
this->width = width;
this->height = height;
this->dataBuffer = Graphics::PixelBuffer(Graphics::PixelFormat(4, 8, 8, 8 , 8, 8, 16, 24, 0), width * height, DisposeAfterUse::YES);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int pixel = buffer.getValueAt(y * width + x);
if (pixel == colorKey) {
dataBuffer.setPixelAt(y * width + x, 0, 255, 255, 255); // Color keyed pixels become transparent white.
} else {
dataBuffer.setPixelAt(y * width + x, pixel);
}
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);
}
}
// Create opaque lines data.
}
// Create opaque lines data.
}
Graphics::PixelBuffer dataBuffer;
int width, height;
};
~TinyGLBlitTexture() {
_surface.free();
}
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 == NULL) {
handle = i;
c->blitTextures[i] = new TinyGLBlitTexture();
break;
}
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;
}
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;
}
void tglUploadBlitTexture(int textureHandle, int width, int height, Graphics::PixelBuffer &buffer, int colorKey) {
TinyGL::GLContext *c = TinyGL::gl_get_context();
TinyGLBlitTexture *texture = (TinyGLBlitTexture *)c->blitTextures[textureHandle];
texture->loadData(width, height, buffer, colorKey);
if (width == 0 && height == 0) {
width = srcWidth;
height = srcHeight;
}
void tglDeleteBlitTexture(int textureHandle) {
TinyGL::GLContext *c = TinyGL::gl_get_context();
TinyGLBlitTexture *texture = (TinyGLBlitTexture *)c->blitTextures[textureHandle];
c->blitTextures[textureHandle] = NULL;
delete texture;
if (dstX >= c->fb->xsize|| dstY >= c->fb->ysize)
return;
int clampWidth, clampHeight;
if (dstX + width > c->fb->xsize)
clampWidth = c->fb->xsize - dstX;
else
clampWidth = width;
if (dstY + height > c->fb->ysize)
clampHeight = c->fb->ysize - dstY;
else
clampHeight = height;
if (dstX < 0)
dstX = 0;
if (dstY < 0)
dstY = 0;
Graphics::PixelBuffer srcBuf(texture->_surface.format, (byte *)texture->_surface.getPixels());
if (flipVertical) {
srcBuf.shiftBy(srcX + ((srcY + srcHeight - 1) * texture->_surface.w));
} else {
srcBuf.shiftBy(srcX + (srcY * texture->_surface.w));
}
template <bool disableBlending, bool disableColoring, bool disableTransform>
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 rTint, float gTint, float bTint, float aTint) {
TinyGL::GLContext *c = TinyGL::gl_get_context();
Graphics::PixelBuffer dstBuf(c->fb->cmode, c->fb->getPixelBuffer());
if (dstX >= c->fb->xsize|| dstY >= c->fb->ysize)
return;
int clampWidth, clampHeight;
if (dstX + width > c->fb->xsize)
clampWidth = c->fb->xsize - dstX;
else
clampWidth = width;
if (dstY + height > c->fb->ysize)
clampHeight = c->fb->ysize - dstY;
else
clampHeight = height;
TinyGLBlitTexture *texture = (TinyGLBlitTexture *)c->blitTextures[blitTextureHandle];
Graphics::PixelBuffer srcBuf(texture->dataBuffer);
srcBuf.shiftBy(srcX + (srcY * texture->width));
for (int l = 0; l < clampHeight; l++) {
for (int r = 0; r < clampWidth; ++r) {
byte aDst, rDst, gDst, bDst;
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 {
srcBuf.getARGBAt(r, aDst, rDst, gDst, bDst);
c->fb->writePixel((dstX + r) + (dstY + l) * c->fb->xsize, aDst * aTint, rDst * rTint, gDst * gTint, bDst * bTint);
}
srcBuf.shiftBy(srcWidth);
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);
}
}
}
}
void tglBlit(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 rTint, float gTint, float bTint, float aTint) {
TinyGL::GLContext *c =TinyGL::gl_get_context();
bool disableColor = aTint == 1.0f && bTint == 1.0f && gTint == 1.0f && rTint == 1.0f;
bool disableTransform = srcWidth == width && srcHeight == height && rotation == 0;
bool disableBlend = c->enableBlend == false;
if (disableColor && disableTransform && disableBlend) {
tglBlitGeneric<true, true, true>(blitTextureHandle, dstX, dstY, width, height, srcX, srcY, srcWidth, srcHeight, rotation, originX, originY, rTint, gTint, bTint, aTint);
} else if (disableColor && disableTransform) {
tglBlitGeneric<false, true, true>(blitTextureHandle, dstX, dstY, width, height, srcX, srcY, srcWidth, srcHeight, rotation, originX, originY, rTint, gTint, bTint, aTint);
} else if (disableTransform) {
tglBlitGeneric<false, false, true>(blitTextureHandle, dstX, dstY, width, height, srcX, srcY, srcWidth, srcHeight, rotation, originX, originY, rTint, gTint, bTint, aTint);
if (flipVertical) {
srcBuf.shiftBy(-texture->_surface.w);
} else {
tglBlitGeneric<false, false, false>(blitTextureHandle, dstX, dstY, width, height, srcX, srcY, srcWidth, srcHeight, rotation, originX, originY, rTint, gTint, bTint, aTint);
srcBuf.shiftBy(texture->_surface.w);
}
}
}
//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) {
if (disableColor && disableTransform && disableBlend) {
tglBlitGeneric<true, true, true, true, false>(blitTextureHandle, transform);
} else if (disableColor && disableTransform) {
tglBlitGeneric<false, true, true, true, false>(blitTextureHandle, transform);
} else if (disableTransform) {
tglBlitGeneric<false, false, true, true, false>(blitTextureHandle, transform);
} else {
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);
}
}
void tglBlitNoBlend(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 rTint, float gTint, float bTint, float aTint) {
tglBlitGeneric<true, false, false>(blitTextureHandle, dstX, dstY, width, height, srcX, srcY, srcWidth, srcHeight, rotation, originX, originY, rTint, gTint, bTint, aTint);
}
}
void tglBlitFast(int blitTextureHandle, int x, int y, int width, int height) {
tglBlitGeneric<true, true, true>(blitTextureHandle, x, y, width, height, 0, 0, width, height, 0, 0, 0, 255, 255, 255 ,255);
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);
}
}
}
void tglBlitFast(int blitTextureHandle, int x, int y) {
BlitTransform transform(x, y);
tglBlitGeneric<true, true, true, false, false>(blitTextureHandle, transform);
}

View File

@ -1,22 +1,70 @@
#ifndef _tgl_zblit_h_
#define _tgl_zblit_h_
#include "graphics/pixelbuffer.h"
#include "graphics/surface.h"
namespace TinyGL {
struct BlitTransform {
BlitTransform(int dstX, int dstY) {
_dstX = dstX;
_dstY = dstY;
_srcX = _srcY = 0;
_srcWidth = _srcHeight = _width = _height = 0;
_aTint = _rTint = _gTint = _bTint = 1.0f;
_rotation = 0.0f;
_originX = _originY = 0.0f;
_flipHorizontally = _flipVertically = false;
}
int tglGenBlitTexture();
void tglUploadBlitTexture(int textureHandle, int width, int height, Graphics::PixelBuffer &buffer, int colorKey);
void tglDeleteBlitTexture(int textureHandle);
void sourceRectangle(int srcX, int srcY, int srcWidth, int srcHeight) {
_srcX = srcX;
_srcY = srcY;
_srcWidth = srcWidth;
_srcHeight = srcHeight;
}
void tglBlit(int blitTextureHandle, int dstX, int dstY, int width, int height, int srcX, int srcY, int srcWidth, int srcHeight,
float rotation = 0, float originX = 0, float originY = 0, float rTint = 1.0f, float gTint = 1.0f, float bTint = 1.0f, float aTint = 1.0f);
void tint(float aTint, float rTint = 1.0f, float gTint = 1.0f, float bTint = 1.0f) {
_aTint = aTint;
_rTint = rTint;
_gTint = gTint;
_bTint = bTint;
}
void scale(int width, int height) {
_width = width;
_height = height;
}
void rotate(float rotation, float originX, float originY) {
_rotation = rotation;
_originX = originX;
_originY = originY;
}
void flip(bool verticalFlip, bool horizontalFlip) {
_flipVertically = verticalFlip;
_flipHorizontally = horizontalFlip;
}
int _dstX, _dstY;
int _srcX, _srcY;
int _srcWidth, _srcHeight;
int _width, _height;
float _rotation;
float _originX, _originY;
float _aTint, _rTint, _gTint, _bTint;
bool _flipHorizontally, _flipVertically;
};
int tglGenBlitTexture();
void tglUploadBlitTexture(int textureHandle, const Graphics::Surface& surface, int colorKey, bool applyColorKey);
void tglDeleteBlitTexture(int textureHandle);
void tglBlit(int blitTextureHandle, const BlitTransform &transform);
// Disables blending explicitly.
void tglBlitNoBlend(int blitTextureHandle, int dstX, int dstY, int width, int height, int srcX, int srcY, int srcWidth, int srcHeight, float rotation, float rTint, float gTint, float bTint, float aTint);
// Disables blending explicitly.
void tglBlitNoBlend(int blitTextureHandle, const BlitTransform &transform);
// Disables blending, transforms and tinting.
void tglBlitFast(int blitTextureHandle, int x, int y, int width, int height);
}
// Disables blending, transforms and tinting.
void tglBlitFast(int blitTextureHandle, int x, int y);
#endif