Files
BlitzNext/Runtime/blitz3d/cachedtexture.cpp
T
Michael Fabian 'Xaymar' Dirks 3afa84df85 runtime/blitz3d: Fixup C++ification
2019-01-18 21:26:42 +01:00

187 lines
4.3 KiB
C++

#include "cachedtexture.hpp"
#include <stdutil.hpp>
#include <gxcanvas.hpp>
#include <gxgraphics.hpp>
int active_texs;
extern gxRuntime* gx_runtime;
extern gxGraphics* gx_graphics;
std::set<CachedTexture::CTInstance*> CachedTexture::rep_set;
static std::string path;
struct CachedTexture::CTInstance {
int ref_cnt;
std::string file;
int flags, w, h, first;
std::vector<gxCanvas*> frames;
CTInstance(int w, int h, int flags, int cnt) : ref_cnt(1), flags(flags), w(w), h(h), first(0)
{
++active_texs;
while (cnt-- > 0) {
if (gxCanvas* t = gx_graphics->createCanvas(w, h, flags)) {
frames.push_back(t);
} else
break;
}
}
CTInstance(const std::string& f, int flags, int w, int h, int first, int cnt)
: ref_cnt(1), file(f), flags(flags), w(w), h(h), first(first)
{
++active_texs;
if (!(flags & gxCanvas::CANVAS_TEX_CUBE)) {
if (w <= 0 || h <= 0 || first < 0 || cnt <= 0) {
w = h = first = 0;
if (gxCanvas* t = gx_graphics->loadCanvas(f, flags)) {
frames.push_back(t);
}
return;
}
}
int t_flags = flags
& (gxCanvas::CANVAS_TEX_RGB | gxCanvas::CANVAS_TEX_ALPHA | gxCanvas::CANVAS_TEX_MASK
| gxCanvas::CANVAS_TEX_HICOLOR)
| gxCanvas::CANVAS_NONDISPLAY;
gxCanvas* t = gx_graphics->loadCanvas(f, t_flags);
if (!t)
return;
if (!t->getDepth()) {
gx_graphics->freeCanvas(t);
return;
}
if (flags & gxCanvas::CANVAS_TEX_CUBE) {
int w = t->getWidth() / 6;
if (w * 6 != t->getWidth())
return;
int h = t->getHeight();
gxCanvas* tex = gx_graphics->createCanvas(w, h, flags);
if (tex) {
frames.push_back(tex);
for (int face = 0; face < 6; ++face) {
tex->setCubeFace(face);
gx_graphics->copy(tex, 0, 0, tex->getWidth(), tex->getHeight(), t, face * w, 0, w, h);
}
tex->setCubeFace(1);
}
} else {
int x_tiles = t->getWidth() / w;
int y_tiles = t->getHeight() / h;
if (first + cnt > x_tiles * y_tiles) {
gx_graphics->freeCanvas(t);
return;
}
int x = (first % x_tiles) * w;
int y = (first / x_tiles) * h;
while (cnt--) {
gxCanvas* p = gx_graphics->createCanvas(w, h, flags);
gx_graphics->copy(p, 0, 0, p->getWidth(), p->getHeight(), t, x, y, w, h);
frames.push_back(p);
x = x + w;
if (x + w > t->getWidth()) {
x = 0;
y = y + h;
}
}
}
gx_graphics->freeCanvas(t);
}
~CTInstance()
{
--active_texs;
for (int k = 0; k < frames.size(); ++k)
gx_graphics->freeCanvas(frames[k]);
}
};
CachedTexture::CTInstance* CachedTexture::findRep(const std::string& f, int flags, int w, int h, int first, int cnt)
{
std::set<CTInstance*>::const_iterator it;
for (it = rep_set.begin(); it != rep_set.end(); ++it) {
CTInstance* rep = *it;
if (rep->file == f && rep->flags == flags && rep->w == w && rep->h == h && rep->first == first
&& rep->frames.size() == cnt) {
++rep->ref_cnt;
return rep;
}
}
return 0;
}
CachedTexture::CachedTexture(int w, int h, int flags, int cnt) : rep(new CTInstance(w, h, flags, cnt)) {}
CachedTexture::CachedTexture(const std::string& f_, int flags, int w, int h, int first, int cnt)
{
std::string f = f_;
if (f.substr(0, 2) == ".\\")
f = f.substr(2);
if (path.size()) {
std::string t = path + tolower(filenamefile(f));
if (rep = findRep(t, flags, w, h, first, cnt))
return;
rep = new CTInstance(t, flags, w, h, first, cnt);
if (rep->frames.size()) {
rep_set.insert(rep);
return;
}
delete rep;
}
std::string t = tolower(fullfilename(f));
if (rep = findRep(t, flags, w, h, first, cnt))
return;
rep = new CTInstance(t, flags, w, h, first, cnt);
rep_set.insert(rep);
}
CachedTexture::CachedTexture(const CachedTexture& t) : rep(t.rep)
{
++rep->ref_cnt;
}
CachedTexture::~CachedTexture()
{
if (!--rep->ref_cnt) {
rep_set.erase(rep);
delete rep;
}
}
CachedTexture& CachedTexture::operator=(const CachedTexture& t)
{
++t.rep->ref_cnt;
if (!--rep->ref_cnt) {
rep_set.erase(rep);
delete rep;
}
rep = t.rep;
return *this;
}
std::string CachedTexture::getName() const
{
return rep->file;
}
const std::vector<gxCanvas*>& CachedTexture::getFrames() const
{
return rep->frames;
}
void CachedTexture::setPath(const std::string& t)
{
path = tolower(t);
if (int sz = path.size()) {
if (path[sz - 1] != '/' && path[sz - 1] != '\\')
path += '\\';
}
}