TINYGL: Move more TexelBuffer code into texelbuffer.cpp

This commit is contained in:
Cameron Cawley 2023-02-01 15:09:34 +00:00
parent 4c1fdb81d5
commit 2773eea09d
3 changed files with 121 additions and 100 deletions

View File

@ -22,6 +22,7 @@
#include "graphics/tinygl/gl.h"
#include "graphics/tinygl/zgl.h"
#include "graphics/tinygl/zbuffer.h"
#include "graphics/tinygl/colormasks.h"
#include "graphics/tinygl/pixelbuffer.h"
#include "graphics/tinygl/texelbuffer.h"
@ -78,6 +79,16 @@ void TexelBuffer::getARGBAt(
}
// Nearest: store texture in original size.
class BaseNearestTexelBuffer : public TexelBuffer {
public:
BaseNearestTexelBuffer(const byte *buf, const Graphics::PixelFormat &format, uint width, uint height, uint textureSize);
~BaseNearestTexelBuffer();
protected:
byte *_buf;
Graphics::PixelFormat _format;
};
BaseNearestTexelBuffer::BaseNearestTexelBuffer(const byte *buf, const Graphics::PixelFormat &format, uint width, uint height, uint textureSize) : TexelBuffer(width, height, textureSize), _format(format) {
uint count = _width * _height * _format.bytesPerPixel;
_buf = new byte[count];
@ -88,12 +99,104 @@ BaseNearestTexelBuffer::~BaseNearestTexelBuffer() {
delete[] _buf;
}
template<uint Format, uint Type>
class NearestTexelBuffer final : public BaseNearestTexelBuffer {
public:
NearestTexelBuffer(const byte *buf, const Graphics::PixelFormat &format, uint width, uint height, uint textureSize)
: BaseNearestTexelBuffer(buf, format, width, height, textureSize) {}
protected:
void getARGBAt(
uint pixel,
uint, uint,
uint8 &a, uint8 &r, uint8 &g, uint8 &b
) const override {
Pixel col = *(((const Pixel *)_buf) + pixel);
_format.colorToARGBT<ColorMask>(col, a, r, g, b);
}
typedef ColorMasks<Format, Type> ColorMask;
typedef typename ColorMask::PixelType Pixel;
};
template<>
class NearestTexelBuffer<TGL_RGB, TGL_UNSIGNED_BYTE> final : public BaseNearestTexelBuffer {
public:
NearestTexelBuffer(const byte *buf, const Graphics::PixelFormat &format, uint width, uint height, uint textureSize)
: BaseNearestTexelBuffer(buf, format, width, height, textureSize) {}
protected:
void getARGBAt(
uint pixel,
uint, uint,
uint8 &a, uint8 &r, uint8 &g, uint8 &b
) const override {
byte *col = _buf + (pixel * 3);
a = 0xff;
r = col[0];
g = col[1];
b = col[2];
}
};
TexelBuffer *createNearestTexelBuffer(const byte *buf, const Graphics::PixelFormat &pf, uint format, uint type, uint width, uint height, uint textureSize) {
if (format == TGL_RGBA && type == TGL_UNSIGNED_BYTE) {
return new NearestTexelBuffer<TGL_RGBA, TGL_UNSIGNED_BYTE>(
buf, pf,
width, height,
textureSize
);
} else if (format == TGL_RGB && type == TGL_UNSIGNED_BYTE) {
return new NearestTexelBuffer<TGL_RGB, TGL_UNSIGNED_BYTE>(
buf, pf,
width, height,
textureSize
);
} else if (format == TGL_RGB && type == TGL_UNSIGNED_SHORT_5_6_5) {
return new NearestTexelBuffer<TGL_RGB, TGL_UNSIGNED_SHORT_5_6_5>(
buf, pf,
width, height,
textureSize
);
} else if (format == TGL_RGBA && type == TGL_UNSIGNED_SHORT_5_5_5_1) {
return new NearestTexelBuffer<TGL_RGBA, TGL_UNSIGNED_SHORT_5_5_5_1>(
buf, pf,
width, height,
textureSize
);
} else if (format == TGL_RGBA && type == TGL_UNSIGNED_SHORT_4_4_4_4) {
return new NearestTexelBuffer<TGL_RGBA, TGL_UNSIGNED_SHORT_4_4_4_4>(
buf, pf,
width, height,
textureSize
);
} else {
error("TinyGL texture: format 0x%04x and type 0x%04x combination not supported", format, type);
}
}
// Bilinear: each texture coordinates corresponds to the 4 original image
// pixels linear interpolation has to work on, so that they are near each
// other in CPU data cache, and a single actual memory fetch happens. This
// allows applying linear filtering at render time at a very low performance
// cost. As we expect to work on small-ish textures (512*512 ?) the 4x memory
// usage increase should be negligible.
class BilinearTexelBuffer : public TexelBuffer {
public:
BilinearTexelBuffer(byte *buf, const Graphics::PixelFormat &format, uint width, uint height, uint textureSize);
~BilinearTexelBuffer();
protected:
void getARGBAt(
uint pixel,
uint ds, uint dt,
uint8 &a, uint8 &r, uint8 &g, uint8 &b
) const override;
private:
uint32 *_texels;
};
#define A_OFFSET (0 * 4)
#define R_OFFSET (1 * 4)
#define G_OFFSET (2 * 4)
@ -216,4 +319,12 @@ void BilinearTexelBuffer::getARGBAt(
);
}
TexelBuffer *createBilinearTexelBuffer(byte *buf, const Graphics::PixelFormat &pf, uint format, uint type, uint width, uint height, uint textureSize) {
return new BilinearTexelBuffer(
buf, pf,
width, height,
textureSize
);
}
} // end of namespace TinyGL

View File

@ -23,7 +23,6 @@
#define GRAPHICS_TEXELBUFFER_H
#include "graphics/pixelformat.h"
#include "graphics/tinygl/colormasks.h"
namespace TinyGL {
@ -48,71 +47,8 @@ protected:
float _widthRatio, _heightRatio;
};
class BaseNearestTexelBuffer : public TexelBuffer {
public:
BaseNearestTexelBuffer(const byte *buf, const Graphics::PixelFormat &format, uint width, uint height, uint textureSize);
~BaseNearestTexelBuffer();
protected:
byte *_buf;
Graphics::PixelFormat _format;
};
template<uint Format, uint Type>
class NearestTexelBuffer final : public BaseNearestTexelBuffer {
public:
NearestTexelBuffer(const byte *buf, const Graphics::PixelFormat &format, uint width, uint height, uint textureSize)
: BaseNearestTexelBuffer(buf, format, width, height, textureSize) {}
protected:
void getARGBAt(
uint pixel,
uint, uint,
uint8 &a, uint8 &r, uint8 &g, uint8 &b
) const override {
Pixel col = *(((const Pixel *)_buf) + pixel);
_format.colorToARGBT<ColorMask>(col, a, r, g, b);
}
typedef ColorMasks<Format, Type> ColorMask;
typedef typename ColorMask::PixelType Pixel;
};
template<>
class NearestTexelBuffer<TGL_RGB, TGL_UNSIGNED_BYTE> final : public BaseNearestTexelBuffer {
public:
NearestTexelBuffer(const byte *buf, const Graphics::PixelFormat &format, uint width, uint height, uint textureSize)
: BaseNearestTexelBuffer(buf, format, width, height, textureSize) {}
protected:
void getARGBAt(
uint pixel,
uint, uint,
uint8 &a, uint8 &r, uint8 &g, uint8 &b
) const override {
byte *col = _buf + (pixel * 3);
a = 0xff;
r = col[0];
g = col[1];
b = col[2];
}
};
class BilinearTexelBuffer : public TexelBuffer {
public:
BilinearTexelBuffer(byte *buf, const Graphics::PixelFormat &format, uint width, uint height, uint textureSize);
~BilinearTexelBuffer();
protected:
void getARGBAt(
uint pixel,
uint ds, uint dt,
uint8 &a, uint8 &r, uint8 &g, uint8 &b
) const override;
private:
uint32 *_texels;
};
TexelBuffer *createNearestTexelBuffer(const byte *buf, const Graphics::PixelFormat &pf, uint format, uint type, uint width, uint height, uint textureSize);
TexelBuffer *createBilinearTexelBuffer(byte *buf, const Graphics::PixelFormat &pf, uint format, uint type, uint width, uint height, uint textureSize);
} // end of namespace TinyGL

View File

@ -164,46 +164,20 @@ void GLContext::glopTexImage2D(GLParam *p) {
case TGL_LINEAR_MIPMAP_NEAREST:
case TGL_LINEAR_MIPMAP_LINEAR:
case TGL_LINEAR:
im->pixmap = new BilinearTexelBuffer(
im->pixmap = createBilinearTexelBuffer(
pixels, pf,
format, type,
width, height,
_textureSize
);
break;
default:
if (format == TGL_RGBA && type == TGL_UNSIGNED_BYTE) {
im->pixmap = new NearestTexelBuffer<TGL_RGBA, TGL_UNSIGNED_BYTE>(
pixels, pf,
width, height,
_textureSize
);
} else if (format == TGL_RGB && type == TGL_UNSIGNED_BYTE) {
im->pixmap = new NearestTexelBuffer<TGL_RGB, TGL_UNSIGNED_BYTE>(
pixels, pf,
width, height,
_textureSize
);
} else if (format == TGL_RGB && type == TGL_UNSIGNED_SHORT_5_6_5) {
im->pixmap = new NearestTexelBuffer<TGL_RGB, TGL_UNSIGNED_SHORT_5_6_5>(
pixels, pf,
width, height,
_textureSize
);
} else if (format == TGL_RGBA && type == TGL_UNSIGNED_SHORT_5_5_5_1) {
im->pixmap = new NearestTexelBuffer<TGL_RGBA, TGL_UNSIGNED_SHORT_5_5_5_1>(
pixels, pf,
width, height,
_textureSize
);
} else if (format == TGL_RGBA && type == TGL_UNSIGNED_SHORT_4_4_4_4) {
im->pixmap = new NearestTexelBuffer<TGL_RGBA, TGL_UNSIGNED_SHORT_4_4_4_4>(
pixels, pf,
width, height,
_textureSize
);
} else {
error("TinyGL texture: format 0x%04x and type 0x%04x combination not supported", format, type);
}
im->pixmap = createNearestTexelBuffer(
pixels, pf,
format, type,
width, height,
_textureSize
);
break;
}
}