611 lines
16 KiB
C++
611 lines
16 KiB
C++
|
|
#include "std.hpp"
|
|
#include "gxgraphics.hpp"
|
|
#include "gxruntime.hpp"
|
|
|
|
extern gxRuntime *gx_runtime;
|
|
|
|
gxGraphics::gxGraphics(gxRuntime *rt, IDirectDraw7 *dd, IDirectDrawSurface7 *fs, IDirectDrawSurface7 *bs, bool d3d) :
|
|
runtime(rt), dirDraw(dd), dir3d(0), dir3dDev(0), def_font(0), gfx_lost(false), dummy_mesh(0) {
|
|
|
|
dirDraw->QueryInterface(IID_IDirectDraw, (void**)&ds_dirDraw);
|
|
|
|
front_canvas = new gxCanvas(this, fs, 0);
|
|
back_canvas = new gxCanvas(this, bs, 0);
|
|
|
|
front_canvas->cls();
|
|
back_canvas->cls();
|
|
|
|
def_font = loadFont("courier", 12, 0);
|
|
|
|
front_canvas->setFont(def_font);
|
|
back_canvas->setFont(def_font);
|
|
|
|
memset(&primFmt, 0, sizeof(primFmt));
|
|
primFmt.dwSize = sizeof(primFmt);
|
|
fs->GetPixelFormat(&primFmt);
|
|
|
|
//are we fullscreen?
|
|
_gamma = 0;
|
|
if (fs != bs) {
|
|
if (fs->QueryInterface(IID_IDirectDrawGammaControl, (void**)&_gamma) >= 0) {
|
|
if (_gamma->GetGammaRamp(0, &_gammaRamp) < 0) _gamma = 0;
|
|
}
|
|
}
|
|
if (!_gamma) {
|
|
for (int k = 0; k < 256; ++k) _gammaRamp.red[k] = _gammaRamp.blue[k] = _gammaRamp.green[k] = k;
|
|
}
|
|
}
|
|
|
|
gxGraphics::~gxGraphics() {
|
|
if (_gamma) _gamma->Release();
|
|
while (scene_set.size()) freeScene(*scene_set.begin());
|
|
while (movie_set.size()) closeMovie(*movie_set.begin());
|
|
while (font_set.size()) freeFont(*font_set.begin());
|
|
while (canvas_set.size()) freeCanvas(*canvas_set.begin());
|
|
|
|
set<string>::iterator it;
|
|
for (it = font_res.begin(); it != font_res.end(); ++it) RemoveFontResource((*it).c_str());
|
|
font_res.clear();
|
|
|
|
delete back_canvas;
|
|
delete front_canvas;
|
|
|
|
ds_dirDraw->Release();
|
|
|
|
dirDraw->RestoreDisplayMode();
|
|
dirDraw->Release();
|
|
}
|
|
|
|
void gxGraphics::setGamma(int r, int g, int b, float dr, float dg, float db) {
|
|
_gammaRamp.red[r & 255] = dr*257.0f;
|
|
_gammaRamp.green[g & 255] = dg*257.0f;
|
|
_gammaRamp.blue[b & 255] = db*257.0f;
|
|
}
|
|
|
|
void gxGraphics::updateGamma(bool calibrate) {
|
|
if (!_gamma) return;
|
|
_gamma->SetGammaRamp(calibrate ? DDSGR_CALIBRATE : 0, &_gammaRamp);
|
|
}
|
|
|
|
void gxGraphics::getGamma(int r, int g, int b, float *dr, float *dg, float *db) {
|
|
*dr = _gammaRamp.red[r & 255] / 257.0f;
|
|
*dg = _gammaRamp.green[g & 255] / 257.0f;
|
|
*db = _gammaRamp.blue[b & 255] / 257.0f;
|
|
}
|
|
|
|
void gxGraphics::backup() {
|
|
}
|
|
|
|
bool gxGraphics::restore() {
|
|
|
|
while (dirDraw->TestCooperativeLevel() != DD_OK) {
|
|
|
|
if (dirDraw->TestCooperativeLevel() == DDERR_WRONGMODE) return false;
|
|
|
|
Sleep(100);
|
|
}
|
|
|
|
if (back_canvas->getSurface()->IsLost() == DD_OK) return true;
|
|
|
|
dirDraw->RestoreAllSurfaces();
|
|
|
|
//restore all canvases
|
|
set<gxCanvas*>::iterator it;
|
|
for (it = canvas_set.begin(); it != canvas_set.end(); ++it) {
|
|
(*it)->restore();
|
|
}
|
|
|
|
//restore all meshes (b3d surfaces)
|
|
set<gxMesh*>::iterator mesh_it;
|
|
for (mesh_it = mesh_set.begin(); mesh_it != mesh_set.end(); ++mesh_it) {
|
|
(*mesh_it)->restore();
|
|
}
|
|
if (dir3d) dir3d->EvictManagedTextures();
|
|
|
|
return true;
|
|
}
|
|
|
|
gxCanvas *gxGraphics::getFrontCanvas()const {
|
|
return front_canvas;
|
|
}
|
|
|
|
gxCanvas *gxGraphics::getBackCanvas()const {
|
|
return back_canvas;
|
|
}
|
|
|
|
gxFont *gxGraphics::getDefaultFont()const {
|
|
return def_font;
|
|
}
|
|
|
|
void gxGraphics::vwait() {
|
|
dirDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
|
|
}
|
|
|
|
void gxGraphics::flip(bool v) {
|
|
runtime->flip(v);
|
|
}
|
|
|
|
void gxGraphics::copy(gxCanvas *dest, int dx, int dy, int dw, int dh, gxCanvas *src, int sx, int sy, int sw, int sh) {
|
|
RECT r = { dx,dy,dx + dw,dy + dh };
|
|
ddUtil::copy(dest->getSurface(), dx, dy, dw, dh, src->getSurface(), sx, sy, sw, sh);
|
|
dest->damage(r);
|
|
}
|
|
|
|
int gxGraphics::getScanLine()const {
|
|
DWORD t = 0;
|
|
dirDraw->GetScanLine(&t);
|
|
return t;
|
|
}
|
|
|
|
int gxGraphics::getTotalVidmem()const {
|
|
DDCAPS caps = { sizeof(caps) };
|
|
dirDraw->GetCaps(&caps, 0);
|
|
return caps.dwVidMemTotal;
|
|
}
|
|
|
|
int gxGraphics::getAvailVidmem()const {
|
|
DDCAPS caps = { sizeof(caps) };
|
|
dirDraw->GetCaps(&caps, 0);
|
|
return caps.dwVidMemFree;
|
|
}
|
|
|
|
gxMovie *gxGraphics::openMovie(const string &file, int flags) {
|
|
|
|
/*IAMMultiMediaStream *iam_stream;
|
|
|
|
if (CoCreateInstance(
|
|
CLSID_AMMultiMediaStream, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IAMMultiMediaStream, (void **)&iam_stream) == S_OK) {
|
|
|
|
if (iam_stream->Initialize(STREAMTYPE_READ, AMMSF_NOGRAPHTHREAD, NULL) == S_OK) {
|
|
|
|
if (iam_stream->AddMediaStream(ds_dirDraw, &MSPID_PrimaryVideo, 0, NULL) == S_OK) {
|
|
|
|
iam_stream->AddMediaStream(NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL);
|
|
|
|
WCHAR *path = new WCHAR[file.size() + 1];
|
|
MultiByteToWideChar(CP_ACP, 0, file.c_str(), -1, path, sizeof(WCHAR)*(file.size() + 1));
|
|
int n = iam_stream->OpenFile(path, 0);
|
|
delete path;
|
|
|
|
if (n == S_OK) {
|
|
gxMovie *movie = new gxMovie(this, iam_stream);
|
|
movie_set.insert(movie);
|
|
return movie;
|
|
}
|
|
}
|
|
}
|
|
iam_stream->Release();
|
|
}*/
|
|
return 0;
|
|
}
|
|
|
|
gxMovie *gxGraphics::verifyMovie(gxMovie *m) {
|
|
return movie_set.count(m) ? m : 0;
|
|
}
|
|
|
|
void gxGraphics::closeMovie(gxMovie *m) {
|
|
if (movie_set.erase(m)) delete m;
|
|
}
|
|
|
|
gxCanvas *gxGraphics::createCanvas(int w, int h, int flags) {
|
|
IDirectDrawSurface7 *s = ddUtil::createSurface(w, h, flags, this);
|
|
if (!s) return 0;
|
|
gxCanvas *c = new gxCanvas(this, s, flags);
|
|
canvas_set.insert(c);
|
|
c->cls();
|
|
return c;
|
|
}
|
|
|
|
gxCanvas *gxGraphics::loadCanvas(const string &f, int flags) {
|
|
IDirectDrawSurface7 *s = ddUtil::loadSurface(f, flags, this);
|
|
if (!s) return 0;
|
|
gxCanvas *c = new gxCanvas(this, s, flags);
|
|
canvas_set.insert(c);
|
|
return c;
|
|
}
|
|
|
|
gxCanvas *gxGraphics::verifyCanvas(gxCanvas *c) {
|
|
return canvas_set.count(c) || c == front_canvas || c == back_canvas ? c : 0;
|
|
}
|
|
|
|
void gxGraphics::freeCanvas(gxCanvas *c) {
|
|
if (canvas_set.erase(c)) delete c;
|
|
}
|
|
|
|
int gxGraphics::getWidth()const {
|
|
return front_canvas->getWidth();
|
|
}
|
|
|
|
int gxGraphics::getHeight()const {
|
|
return front_canvas->getHeight();
|
|
}
|
|
|
|
int gxGraphics::getDepth()const {
|
|
return front_canvas->getDepth();
|
|
}
|
|
|
|
gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
|
|
|
|
int bold = flags & gxFont::FONT_BOLD ? FW_BOLD : FW_REGULAR;
|
|
int italic = flags & gxFont::FONT_ITALIC ? 1 : 0;
|
|
int underline = flags & gxFont::FONT_UNDERLINE ? 1 : 0;
|
|
int strikeout = 0;
|
|
|
|
string t;
|
|
int n = f.find('.');
|
|
if (n != string::npos) {
|
|
t = fullfilename(f);
|
|
if (!font_res.count(t) && AddFontResource(t.c_str())) font_res.insert(t);
|
|
t = filenamefile(f.substr(0, n));
|
|
} else {
|
|
t = f;
|
|
}
|
|
|
|
//save and turn off font smoothing....
|
|
BOOL smoothing = FALSE;
|
|
SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &smoothing, 0);
|
|
SystemParametersInfo(SPI_SETFONTSMOOTHING, FALSE, 0, 0);
|
|
|
|
HFONT hfont = CreateFont(
|
|
height, 0, 0, 0,
|
|
bold, italic, underline, strikeout,
|
|
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
|
|
DEFAULT_PITCH | FF_DONTCARE, t.c_str());
|
|
|
|
if (!hfont) {
|
|
//restore font smoothing
|
|
SystemParametersInfo(SPI_SETFONTSMOOTHING, smoothing, 0, 0);
|
|
return 0;
|
|
}
|
|
|
|
HDC hdc = CreateCompatibleDC(0);
|
|
HFONT pfont = (HFONT)SelectObject(hdc, hfont);
|
|
|
|
TEXTMETRIC tm = { 0 };
|
|
if (!GetTextMetrics(hdc, &tm)) {
|
|
SelectObject(hdc, pfont);
|
|
DeleteDC(hdc);
|
|
DeleteObject(hfont);
|
|
SystemParametersInfo(SPI_SETFONTSMOOTHING, smoothing, 0, 0);
|
|
return 0;
|
|
}
|
|
height = tm.tmHeight;
|
|
|
|
int first = tm.tmFirstChar, last = tm.tmLastChar;
|
|
int sz = last - first + 1;
|
|
int *offs = new int[sz];
|
|
int *widths = new int[sz];
|
|
int *as = new int[sz];
|
|
|
|
//calc size of canvas to hold font.
|
|
int x = 0, y = 0, max_x = 0;
|
|
for (int k = 0; k < sz; ++k) {
|
|
|
|
char t = k + first;
|
|
|
|
SIZE sz;
|
|
GetTextExtentPoint32(hdc, &t, 1, &sz);
|
|
int w = sz.cx;
|
|
|
|
as[k] = 0;
|
|
|
|
ABC abc;
|
|
if (GetCharABCWidths(hdc, t, t, &abc)) {
|
|
if (abc.abcA < 0) {
|
|
as[k] = ceil(-abc.abcA);
|
|
w += as[k];
|
|
}
|
|
if (abc.abcC < 0) w += (int)ceil(-abc.abcC);
|
|
}
|
|
|
|
if (x && x + w > getWidth()) { x = 0; y += height; }
|
|
offs[k] = (x << 16) | y;
|
|
widths[k] = w;
|
|
x += w; if (x > max_x) max_x = x;
|
|
}
|
|
SelectObject(hdc, pfont);
|
|
DeleteDC(hdc);
|
|
|
|
int cw = max_x, ch = y + height;
|
|
|
|
if (gxCanvas *c = createCanvas(cw, ch, 0)) {
|
|
IDirectDrawSurface7 *surf = c->getSurface();
|
|
|
|
HDC surf_hdc;
|
|
if (surf->GetDC(&surf_hdc) >= 0) {
|
|
HFONT pfont = (HFONT)SelectObject(surf_hdc, hfont);
|
|
|
|
SetBkColor(surf_hdc, 0x000000);
|
|
SetTextColor(surf_hdc, 0xffffff);
|
|
|
|
for (int k = 0; k < sz; ++k) {
|
|
int x = (offs[k] >> 16) & 0xffff, y = offs[k] & 0xffff;
|
|
char t = k + first;
|
|
RECT rect = { x,y,x + widths[k],y + height };
|
|
ExtTextOut(surf_hdc, x + as[k], y, ETO_CLIPPED, &rect, &t, 1, 0);
|
|
}
|
|
|
|
SelectObject(surf_hdc, pfont);
|
|
surf->ReleaseDC(surf_hdc);
|
|
DeleteObject(hfont);
|
|
delete[] as;
|
|
|
|
c->backup();
|
|
gxFont *font = new gxFont(this, c, tm.tmMaxCharWidth, height, first, last + 1, tm.tmDefaultChar, offs, widths);
|
|
font_set.insert(font);
|
|
|
|
//restore font smoothing
|
|
SystemParametersInfo(SPI_SETFONTSMOOTHING, smoothing, 0, 0);
|
|
return font;
|
|
} else {
|
|
}
|
|
freeCanvas(c);
|
|
} else {
|
|
}
|
|
DeleteObject(hfont);
|
|
delete[] as;
|
|
delete[] widths;
|
|
delete[] offs;
|
|
|
|
//restore font smoothing
|
|
SystemParametersInfo(SPI_SETFONTSMOOTHING, smoothing, 0, 0);
|
|
return 0;
|
|
}
|
|
|
|
gxFont *gxGraphics::verifyFont(gxFont *f) {
|
|
return font_set.count(f) ? f : 0;
|
|
}
|
|
|
|
void gxGraphics::freeFont(gxFont *f) {
|
|
if (font_set.erase(f)) delete f;
|
|
}
|
|
|
|
//////////////
|
|
// 3D STUFF //
|
|
//////////////
|
|
|
|
static int maxDevType;
|
|
|
|
static HRESULT CALLBACK enumDevice(char *desc, char *name, D3DDEVICEDESC7 *devDesc, void *context) {
|
|
gxGraphics *g = (gxGraphics*)context;
|
|
int t = 0;
|
|
GUID guid = devDesc->deviceGUID;
|
|
if (guid == IID_IDirect3DRGBDevice) t = 1;
|
|
else if (guid == IID_IDirect3DHALDevice) t = 2;
|
|
else if (guid == IID_IDirect3DTnLHalDevice) t = 3;
|
|
if (t > maxDevType) {
|
|
g->dir3dDevDesc = *devDesc;
|
|
maxDevType = t;
|
|
}
|
|
return D3DENUMRET_OK;
|
|
}
|
|
|
|
static HRESULT CALLBACK enumZbuffFormat(LPDDPIXELFORMAT format, void *context) {
|
|
gxGraphics *g = (gxGraphics*)context;
|
|
if (format->dwZBufferBitDepth == g->primFmt.dwRGBBitCount) {
|
|
g->zbuffFmt = *format;
|
|
return D3DENUMRET_CANCEL;
|
|
}
|
|
if (format->dwZBufferBitDepth > g->zbuffFmt.dwZBufferBitDepth) {
|
|
if (format->dwZBufferBitDepth < g->primFmt.dwRGBBitCount) {
|
|
g->zbuffFmt = *format;
|
|
}
|
|
}
|
|
return D3DENUMRET_OK;
|
|
}
|
|
|
|
struct TexFmt {
|
|
DDPIXELFORMAT fmt;
|
|
int bits, a_bits, rgb_bits;
|
|
};
|
|
|
|
static int cntBits(int mask) {
|
|
int n = 0;
|
|
for (int k = 0; k < 32; ++k) {
|
|
if (mask & (1 << k)) ++n;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
static vector<TexFmt> tex_fmts;
|
|
|
|
static HRESULT CALLBACK enumTextureFormat(DDPIXELFORMAT *fmt, void *p) {
|
|
TexFmt t;
|
|
t.fmt = *fmt;
|
|
t.bits = fmt->dwRGBBitCount;
|
|
t.a_bits = (fmt->dwFlags & DDPF_ALPHAPIXELS) ? cntBits(fmt->dwRGBAlphaBitMask) : 0;
|
|
t.rgb_bits = (fmt->dwFlags & DDPF_RGB) ? cntBits(fmt->dwRBitMask | fmt->dwGBitMask | fmt->dwBBitMask) : 0;
|
|
|
|
tex_fmts.push_back(t);
|
|
|
|
return D3DENUMRET_OK;
|
|
}
|
|
|
|
static string itobin(int n) {
|
|
string t;
|
|
for (int k = 0; k < 32; n <<= 1, ++k) {
|
|
t += (n & 0x80000000) ? '1' : '0';
|
|
}
|
|
return t;
|
|
}
|
|
|
|
static void debugPF(const DDPIXELFORMAT &pf) {
|
|
string t;
|
|
t = "Bits:" + itoa(pf.dwRGBBitCount);
|
|
gx_runtime->debugLog(t.c_str());
|
|
t = "R Mask:" + itobin(pf.dwRBitMask);
|
|
gx_runtime->debugLog(t.c_str());
|
|
t = "G Mask:" + itobin(pf.dwGBitMask);
|
|
gx_runtime->debugLog(t.c_str());
|
|
t = "B Mask:" + itobin(pf.dwBBitMask);
|
|
gx_runtime->debugLog(t.c_str());
|
|
t = "A Mask:" + itobin(pf.dwRGBAlphaBitMask);
|
|
gx_runtime->debugLog(t.c_str());
|
|
}
|
|
|
|
static void pickTexFmts(gxGraphics *g, int hi) {
|
|
//texRGBFmt.
|
|
{
|
|
int pick = -1, max = 0, bits;
|
|
for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) {
|
|
for (int k = 0; k < tex_fmts.size(); ++k) {
|
|
const TexFmt &t = tex_fmts[k];
|
|
if (t.bits > d || !t.rgb_bits || t.rgb_bits < max) continue;
|
|
if (t.rgb_bits == max && t.bits >= bits) continue;
|
|
pick = k; max = t.rgb_bits; bits = t.bits;
|
|
}
|
|
if (!hi && pick >= 0) break;
|
|
}
|
|
if (pick < 0) g->texRGBFmt[hi] = g->primFmt;
|
|
else g->texRGBFmt[hi] = tex_fmts[pick].fmt;
|
|
}
|
|
//texAlphaFmt
|
|
{
|
|
int pick = -1, max = 0, bits;
|
|
for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) {
|
|
for (int k = 0; k < tex_fmts.size(); ++k) {
|
|
const TexFmt &t = tex_fmts[k];
|
|
if (t.bits > d || !t.a_bits || t.a_bits < max) continue;
|
|
if (t.a_bits == max && t.bits >= bits) continue;
|
|
pick = k; max = t.a_bits; bits = t.bits;
|
|
}
|
|
if (!hi && pick >= 0) break;
|
|
}
|
|
if (pick < 0) g->texAlphaFmt[hi] = g->primFmt;
|
|
else g->texAlphaFmt[hi] = tex_fmts[pick].fmt;
|
|
}
|
|
//texRGBAlphaFmt
|
|
{
|
|
int pick = -1, a8rgb8 = -1, max = 0, bits;
|
|
for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) {
|
|
for (int k = 0; k < tex_fmts.size(); ++k) {
|
|
const TexFmt &t = tex_fmts[k];
|
|
if (t.a_bits == 8 && t.bits == 16) { a8rgb8 = k; continue; }
|
|
if (t.bits > d || !t.a_bits || !t.rgb_bits || t.a_bits < max) continue;
|
|
if (t.a_bits == max && t.bits >= bits) continue;
|
|
pick = k; max = t.a_bits; bits = t.bits;
|
|
}
|
|
if (!hi && pick >= 0) break;
|
|
}
|
|
if (pick < 0) pick = a8rgb8;
|
|
if (pick < 0) g->texRGBAlphaFmt[hi] = g->primFmt;
|
|
else g->texRGBAlphaFmt[hi] = tex_fmts[pick].fmt;
|
|
}
|
|
//texRGBMaskFmt...
|
|
{
|
|
int pick = -1, max = 0, bits;
|
|
for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) {
|
|
for (int k = 0; k < tex_fmts.size(); ++k) {
|
|
const TexFmt &t = tex_fmts[k];
|
|
if (!t.a_bits || !t.rgb_bits || t.rgb_bits < max) continue;
|
|
if (t.rgb_bits == max && t.bits >= bits) continue;
|
|
pick = k; max = t.rgb_bits; bits = t.bits;
|
|
}
|
|
if (!hi && pick >= 0) break;
|
|
}
|
|
if (pick < 0) g->texRGBMaskFmt[hi] = g->primFmt;
|
|
else g->texRGBMaskFmt[hi] = tex_fmts[pick].fmt;
|
|
}
|
|
}
|
|
|
|
gxScene *gxGraphics::createScene(int flags) {
|
|
if (scene_set.size()) return 0;
|
|
|
|
//get d3d
|
|
if (dirDraw->QueryInterface(IID_IDirect3D7, (void**)&dir3d) >= 0) {
|
|
//enum devices
|
|
maxDevType = 0;
|
|
if (dir3d->EnumDevices(enumDevice, this) >= 0 && maxDevType > 1) {
|
|
//enum zbuffer formats
|
|
zbuffFmt.dwZBufferBitDepth = 0;
|
|
if (dir3d->EnumZBufferFormats(dir3dDevDesc.deviceGUID, enumZbuffFormat, this) >= 0) {
|
|
//create zbuff for back buffer
|
|
if (back_canvas->attachZBuffer()) {
|
|
//create 3d device
|
|
if (dir3d->CreateDevice(dir3dDevDesc.deviceGUID, back_canvas->getSurface(), &dir3dDev) >= 0) {
|
|
//enum texture formats
|
|
tex_fmts.clear();
|
|
if (dir3dDev->EnumTextureFormats(enumTextureFormat, this) >= 0) {
|
|
pickTexFmts(this, 0);
|
|
pickTexFmts(this, 1);
|
|
tex_fmts.clear();
|
|
#ifdef BETA
|
|
gx_runtime->debugLog("Texture RGB format:");
|
|
debugPF(texRGBFmt);
|
|
gx_runtime->debugLog("Texture Alpha format:");
|
|
debugPF(texAlphaFmt);
|
|
gx_runtime->debugLog("Texture RGB Alpha format:");
|
|
debugPF(texRGBAlphaFmt);
|
|
gx_runtime->debugLog("Texture RGB Mask format:");
|
|
debugPF(texRGBMaskFmt);
|
|
gx_runtime->debugLog("Texture Primary format:");
|
|
debugPF(primFmt);
|
|
string ts = "ZBuffer Bit Depth:" + itoa(zbuffFmt.dwZBufferBitDepth);
|
|
gx_runtime->debugLog(ts.c_str());
|
|
#endif
|
|
gxScene *scene = new gxScene(this, back_canvas);
|
|
scene_set.insert(scene);
|
|
|
|
dummy_mesh = createMesh(8, 12, 0);
|
|
|
|
return scene;
|
|
}
|
|
dir3dDev->Release();
|
|
dir3dDev = 0;
|
|
}
|
|
back_canvas->releaseZBuffer();
|
|
}
|
|
}
|
|
}
|
|
dir3d->Release();
|
|
dir3d = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
gxScene *gxGraphics::verifyScene(gxScene *s) {
|
|
return scene_set.count(s) ? s : 0;
|
|
}
|
|
|
|
void gxGraphics::freeScene(gxScene *scene) {
|
|
if (!scene_set.erase(scene)) return;
|
|
dummy_mesh = 0;
|
|
while (mesh_set.size()) freeMesh(*mesh_set.begin());
|
|
back_canvas->releaseZBuffer();
|
|
if (dir3dDev) { dir3dDev->Release(); dir3dDev = 0; }
|
|
if (dir3d) { dir3d->Release(); dir3d = 0; }
|
|
delete scene;
|
|
}
|
|
|
|
gxMesh *gxGraphics::createMesh(int max_verts, int max_tris, int flags) {
|
|
|
|
static const int VTXFMT =
|
|
D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2 |
|
|
D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1);
|
|
|
|
int vbflags = 0;
|
|
|
|
//XP or less?
|
|
/*if (runtime->osinfo.dwMajorVersion < 6) {
|
|
vbflags |= D3DVBCAPS_WRITEONLY;
|
|
}*/
|
|
|
|
D3DVERTEXBUFFERDESC desc = { sizeof(desc),vbflags,VTXFMT,max_verts };
|
|
|
|
IDirect3DVertexBuffer7 *buff;
|
|
if (dir3d->CreateVertexBuffer(&desc, &buff, 0) < 0) return 0;
|
|
WORD *indices = new WORD[max_tris * 3];
|
|
gxMesh *mesh = new gxMesh(this, buff, indices, max_verts, max_tris);
|
|
mesh_set.insert(mesh);
|
|
return mesh;
|
|
}
|
|
|
|
gxMesh *gxGraphics::verifyMesh(gxMesh *m) {
|
|
return mesh_set.count(m) ? m : 0;
|
|
}
|
|
|
|
void gxGraphics::freeMesh(gxMesh *mesh) {
|
|
if (mesh_set.erase(mesh)) delete mesh;
|
|
} |