Files
BlitzNext/Runtime/blitz3d/cachedtexture.cpp
T

187 lines
4.3 KiB
C++
Raw Normal View History

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