mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-10 03:40:25 +00:00
TINYGL: refined blit interface.
This commit is contained in:
parent
62aa0af91a
commit
75908d68d8
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user