From 2d345499d2e131f3dd58bdb52cee655f9cac3d0d Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 15 Apr 2020 09:47:43 +0200 Subject: [PATCH] subsystems and videomodes implemented (except SDL2); smaller fixes too --- skeleton/glfw.cpp | 10 +- skeleton/sdl2.cpp | 10 +- skeleton/skeleton.cpp | 29 +- skeleton/skeleton.h | 2 +- skeleton/win.cpp | 4 +- src/base.cpp | 10 +- src/camera.cpp | 4 +- src/d3d/d3d.cpp | 1 + src/d3d/d3d8.cpp | 1 + src/d3d/d3d8render.cpp | 1 + src/d3d/d3d9.cpp | 1 + src/d3d/d3d9render.cpp | 1 + src/d3d/d3ddevice.cpp | 345 ++++++++++++++++++------ src/d3d/d3dimmed.cpp | 1 + src/d3d/d3drender.cpp | 1 + src/d3d/rwd3d.h | 38 ++- src/d3d/{xboxmatx.cpp => xboxmatfx.cpp} | 0 src/engine.cpp | 102 ++++++- src/frame.cpp | 8 +- src/geometry.cpp | 39 +-- src/gl/gl3device.cpp | 244 ++++++++++++++--- src/gl/gl3raster.cpp | 3 +- src/gl/rwgl3.h | 3 +- src/ps2/rwps2.h | 2 +- src/rwbase.h | 10 +- src/rwengine.h | 62 ++++- src/rwobjects.h | 29 +- src/rwplugins.h | 4 +- src/rwrender.h | 6 +- src/world.cpp | 22 ++ tools/clumpview/main.cpp | 4 +- tools/clumpview/ras_test.cpp | 2 + tools/imguitest/main.cpp | 2 +- tools/ps2test/main.cpp | 6 +- 34 files changed, 778 insertions(+), 229 deletions(-) rename src/d3d/{xboxmatx.cpp => xboxmatfx.cpp} (100%) diff --git a/skeleton/glfw.cpp b/skeleton/glfw.cpp index 5c513d6..23832c0 100644 --- a/skeleton/glfw.cpp +++ b/skeleton/glfw.cpp @@ -217,10 +217,10 @@ main(int argc, char *argv[]) if(EventHandler(INITIALIZE, nil) == EVENTERROR) return 0; - engineStartParams.width = sk::globals.width; - engineStartParams.height = sk::globals.height; - engineStartParams.windowtitle = sk::globals.windowtitle; - engineStartParams.window = &window; + engineOpenParams.width = sk::globals.width; + engineOpenParams.height = sk::globals.height; + engineOpenParams.windowtitle = sk::globals.windowtitle; + engineOpenParams.window = &window; if(EventHandler(RWINITIALIZE, nil) == EVENTERROR) return 0; @@ -253,7 +253,7 @@ namespace sk { void SetMousePosition(int x, int y) { - glfwSetCursorPos(*engineStartParams.window, (double)x, (double)y); + glfwSetCursorPos(*engineOpenParams.window, (double)x, (double)y); } } diff --git a/skeleton/sdl2.cpp b/skeleton/sdl2.cpp index 264afe5..4cb7c0f 100644 --- a/skeleton/sdl2.cpp +++ b/skeleton/sdl2.cpp @@ -215,10 +215,10 @@ main(int argc, char *argv[]) if(EventHandler(INITIALIZE, nil) == EVENTERROR) return 0; - engineStartParams.width = sk::globals.width; - engineStartParams.height = sk::globals.height; - engineStartParams.windowtitle = sk::globals.windowtitle; - engineStartParams.window = &window; + engineOpenParams.width = sk::globals.width; + engineOpenParams.height = sk::globals.height; + engineOpenParams.windowtitle = sk::globals.windowtitle; + engineOpenParams.window = &window; if(EventHandler(RWINITIALIZE, nil) == EVENTERROR) return 0; @@ -316,7 +316,7 @@ namespace sk { void SetMousePosition(int x, int y) { - SDL_WarpMouseInWindow(*engineStartParams.window, x, y); + SDL_WarpMouseInWindow(*engineOpenParams.window, x, y); } } diff --git a/skeleton/skeleton.cpp b/skeleton/skeleton.cpp index 119dd97..7d2a064 100644 --- a/skeleton/skeleton.cpp +++ b/skeleton/skeleton.cpp @@ -13,9 +13,34 @@ InitRW(void) return false; if(AppEventHandler(sk::PLUGINATTACH, nil) == EVENTERROR) return false; - if(!rw::Engine::open()) + if(!rw::Engine::open(&engineOpenParams)) return false; - if(!rw::Engine::start(&engineStartParams)) + + SubSystemInfo info; + int i, n; + n = Engine::getNumSubSystems(); + for(i = 0; i < n; i++) + if(Engine::getSubSystemInfo(&info, i)) + printf("subsystem: %s\n", info.name); + + int want = -1; + VideoMode mode; + n = Engine::getNumVideoModes(); + for(i = 0; i < n; i++) + if(Engine::getVideoModeInfo(&mode, i)){ + if(mode.width == 640 && mode.height == 480 && mode.depth == 32) + want = i; + printf("mode: %dx%dx%d %d\n", mode.width, mode.height, mode.depth, mode.flags); + } +// if(want >= 0) Engine::setVideoMode(want); + Engine::getVideoModeInfo(&mode, Engine::getCurrentVideoMode()); + + if(mode.flags & VIDEOMODEEXCLUSIVE){ + globals.width = mode.width; + globals.height = mode.height; + } + + if(!rw::Engine::start()) return false; rw::Image::setSearchPath("./"); diff --git a/skeleton/skeleton.h b/skeleton/skeleton.h index cec41dd..9604602 100644 --- a/skeleton/skeleton.h +++ b/skeleton/skeleton.h @@ -1,4 +1,4 @@ -extern rw::EngineStartParams engineStartParams; +extern rw::EngineOpenParams engineOpenParams; namespace sk { diff --git a/skeleton/win.cpp b/skeleton/win.cpp index ba8f30e..9f1ee5a 100644 --- a/skeleton/win.cpp +++ b/skeleton/win.cpp @@ -254,7 +254,7 @@ WinMain(HINSTANCE instance, HINSTANCE, MessageBox(0, "MakeWindow() - FAILED", 0, 0); return 0; } - engineStartParams.window = win; + engineOpenParams.window = win; initkeymap(); if(EventHandler(RWINITIALIZE, nil) == EVENTERROR) @@ -283,7 +283,7 @@ void SetMousePosition(int x, int y) { POINT pos = { x, y }; - ClientToScreen(engineStartParams.window, &pos); + ClientToScreen(engineOpenParams.window, &pos); SetCursorPos(pos.x, pos.y); } diff --git a/src/base.cpp b/src/base.cpp index fe2d6e4..d48f4c5 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -310,7 +310,7 @@ Matrix::transpose(Matrix *dst, const Matrix *src) } Matrix* -Matrix::rotate(V3d *axis, float32 angle, CombineOp op) +Matrix::rotate(const V3d *axis, float32 angle, CombineOp op) { Matrix tmp, rot; makeRotation(&rot, axis, angle); @@ -351,7 +351,7 @@ Matrix::rotate(const Quat &q, CombineOp op) return this; } Matrix* -Matrix::translate(V3d *translation, CombineOp op) +Matrix::translate(const V3d *translation, CombineOp op) { Matrix tmp; Matrix trans = identMat; @@ -374,7 +374,7 @@ Matrix::translate(V3d *translation, CombineOp op) } Matrix* -Matrix::scale(V3d *scale, CombineOp op) +Matrix::scale(const V3d *scale, CombineOp op) { Matrix tmp; Matrix scl = identMat; @@ -398,7 +398,7 @@ Matrix::scale(V3d *scale, CombineOp op) } Matrix* -Matrix::transform(Matrix *mat, CombineOp op) +Matrix::transform(const Matrix *mat, CombineOp op) { Matrix tmp; switch(op){ @@ -534,7 +534,7 @@ Matrix::invertGeneral(Matrix *dst, const Matrix *src) } void -Matrix::makeRotation(Matrix *dst, V3d *axis, float32 angle) +Matrix::makeRotation(Matrix *dst, const V3d *axis, float32 angle) { V3d v = normalize(*axis); angle = angle*(float)M_PI/180.0f; diff --git a/src/camera.cpp b/src/camera.cpp index 5109d22..b07983e 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -415,10 +415,10 @@ Camera::setProjection(int32 proj) } int32 -Camera::frustumTestSphere(Sphere *s) +Camera::frustumTestSphere(const Sphere *s) const { int32 res = SPHEREINSIDE; - FrustumPlane *p = this->frustumPlanes; + const FrustumPlane *p = this->frustumPlanes; for(int32 i = 0; i < 6; i++){ float32 dist = dot(p->plane.normal, s->center) - p->plane.distance; if(s->radius < dist) diff --git a/src/d3d/d3d.cpp b/src/d3d/d3d.cpp index ed1fa22..c6746e4 100644 --- a/src/d3d/d3d.cpp +++ b/src/d3d/d3d.cpp @@ -3,6 +3,7 @@ #include #include +#define WITH_D3D #include "../rwbase.h" #include "../rwplg.h" #include "../rwpipeline.h" diff --git a/src/d3d/d3d8.cpp b/src/d3d/d3d8.cpp index e207550..0cfa398 100644 --- a/src/d3d/d3d8.cpp +++ b/src/d3d/d3d8.cpp @@ -3,6 +3,7 @@ #include #include +#define WITH_D3D #include "../rwbase.h" #include "../rwerror.h" #include "../rwplg.h" diff --git a/src/d3d/d3d8render.cpp b/src/d3d/d3d8render.cpp index cf09199..3fa0d39 100644 --- a/src/d3d/d3d8render.cpp +++ b/src/d3d/d3d8render.cpp @@ -3,6 +3,7 @@ #include #include +#define WITH_D3D #include "../rwbase.h" #include "../rwplg.h" #include "../rwpipeline.h" diff --git a/src/d3d/d3d9.cpp b/src/d3d/d3d9.cpp index f67abfb..923c62a 100644 --- a/src/d3d/d3d9.cpp +++ b/src/d3d/d3d9.cpp @@ -3,6 +3,7 @@ #include #include +#define WITH_D3D #include "../rwbase.h" #include "../rwerror.h" #include "../rwplg.h" diff --git a/src/d3d/d3d9render.cpp b/src/d3d/d3d9render.cpp index 029d5ed..f2a25c5 100644 --- a/src/d3d/d3d9render.cpp +++ b/src/d3d/d3d9render.cpp @@ -3,6 +3,7 @@ #include #include +#define WITH_D3D #include "../rwbase.h" #include "../rwplg.h" #include "../rwpipeline.h" diff --git a/src/d3d/d3ddevice.cpp b/src/d3d/d3ddevice.cpp index bca94a2..e9aefd1 100644 --- a/src/d3d/d3ddevice.cpp +++ b/src/d3d/d3ddevice.cpp @@ -3,6 +3,7 @@ #include #include +#define WITH_D3D #include "../rwbase.h" #include "../rwplg.h" #include "../rwerror.h" @@ -20,11 +21,25 @@ namespace d3d { #ifdef RW_D3D9 +struct DisplayMode +{ + D3DDISPLAYMODE mode; + uint32 flags; +}; + struct D3d9Globals { HWND window; - bool windowed; - int presentWidth, presentHeight; + + IDirect3D9 *d3d9; + int numAdapters; + int adapter; + D3DCAPS9 caps; + DisplayMode *modes; + int numModes; + int currentMode; + + D3DPRESENT_PARAMETERS present; } d3d9Globals; // Keep track of rasters exclusively in video memory @@ -96,6 +111,7 @@ static D3DMATERIAL9 d3dmaterial; static uint32 blendMap[] = { + D3DBLEND_ZERO, // actually invalid D3DBLEND_ZERO, D3DBLEND_ONE, D3DBLEND_SRCCOLOR, @@ -116,6 +132,7 @@ static uint32 alphafuncMap[] = { }; static uint32 cullmodeMap[] = { + D3DCULL_NONE, // actually invalid D3DCULL_NONE, D3DCULL_CW, D3DCULL_CCW @@ -721,29 +738,13 @@ clearCamera(Camera *cam, RGBA *col, uint32 mode) BOOL icon = IsIconic(d3d9Globals.window); Raster *ras = cam->frameBuffer; if(!icon && - (r.right != d3d9Globals.presentWidth || r.bottom != d3d9Globals.presentHeight)){ + (r.right != d3d9Globals.present.BackBufferWidth || r.bottom != d3d9Globals.present.BackBufferHeight)){ releaseVidmemRasters(); - D3DPRESENT_PARAMETERS d3dpp; - d3dpp.BackBufferWidth = r.right; - d3dpp.BackBufferHeight = r.bottom; - d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; - d3dpp.BackBufferCount = 1; - d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; - d3dpp.MultiSampleQuality = 0; - d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; - d3dpp.hDeviceWindow = d3d9Globals.window; - d3dpp.Windowed = d3d9Globals.windowed; - d3dpp.EnableAutoDepthStencil = true; - d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; - d3dpp.Flags = 0; - d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; - d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; -// d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + d3d9Globals.present.BackBufferWidth = r.right; + d3d9Globals.present.BackBufferHeight = r.bottom; // TODO: check result - d3d::d3ddevice->Reset(&d3dpp); - d3d9Globals.presentWidth = r.right; - d3d9Globals.presentHeight = r.bottom; + d3d::d3ddevice->Reset(&d3d9Globals.present); resetD3d9Device(); } @@ -760,82 +761,209 @@ showRaster(Raster *raster) d3ddevice->Present(nil, nil, 0, nil); } -// taken from Frank Luna's d3d9 book + +// +// Device +// + static int -openD3D(EngineStartParams *params) +findFormatDepth(uint32 format) +{ + // not all formats actually + switch(format){ + case D3DFMT_R8G8B8: return 24; + case D3DFMT_A8R8G8B8: return 32; + case D3DFMT_X8R8G8B8: return 32; + case D3DFMT_R5G6B5: return 16; + case D3DFMT_X1R5G5B5: return 16; + case D3DFMT_A1R5G5B5: return 16; + case D3DFMT_A4R4G4B4: return 16; + case D3DFMT_R3G3B2: return 8; + case D3DFMT_A8: return 8; + case D3DFMT_A8R3G3B2: return 16; + case D3DFMT_X4R4G4B4: return 16; + case D3DFMT_A2B10G10R10: return 32; + case D3DFMT_A8B8G8R8: return 32; + case D3DFMT_X8B8G8R8: return 32; + case D3DFMT_G16R16: return 32; + case D3DFMT_A2R10G10B10: return 32; + case D3DFMT_A16B16G16R16: return 64; + + case D3DFMT_L8: return 8; + case D3DFMT_D16: return 16; + case D3DFMT_D24X8: return 32; + case D3DFMT_D32: return 32; + + default: return 0; + } +} + +// the commented ones don't "work" +static D3DFORMAT fbFormats[] = { +// D3DFMT_A1R5G5B5, +/// D3DFMT_A2R10G10B10, // works but let's not use it... +// D3DFMT_A8R8G8B8, + D3DFMT_R5G6B5, +// D3DFMT_X1R5G5B5, + D3DFMT_X8R8G8B8 +}; + +static void +addVideoMode(D3DDISPLAYMODE *mode) +{ + int i; + + for(i = 1; i < d3d9Globals.numModes; i++){ + if(d3d9Globals.modes[i].mode.Width == mode->Width && + d3d9Globals.modes[i].mode.Height == mode->Height && + d3d9Globals.modes[i].mode.Format == mode->Format){ + // had this format already, remember highest refresh rate + if(mode->RefreshRate > d3d9Globals.modes[i].mode.RefreshRate) + d3d9Globals.modes[i].mode.RefreshRate = mode->RefreshRate; + return; + } + } + + // none found, add + d3d9Globals.modes[d3d9Globals.numModes].mode = *mode; + d3d9Globals.modes[d3d9Globals.numModes].flags = VIDEOMODEEXCLUSIVE; + d3d9Globals.numModes++; +} + +static void +makeVideoModeList(void) +{ + int i, j; + D3DDISPLAYMODE mode; + + d3d9Globals.numModes = 1; + for(i = 0; i < nelem(fbFormats); i++) + d3d9Globals.numModes += d3d9Globals.d3d9->GetAdapterModeCount(d3d9Globals.adapter, fbFormats[i]); + + rwFree(d3d9Globals.modes); + d3d9Globals.modes = rwNewT(DisplayMode, d3d9Globals.numModes, ID_DRIVER | MEMDUR_EVENT); + + // first mode is current mode as windowed + d3d9Globals.d3d9->GetAdapterDisplayMode(d3d9Globals.adapter, &d3d9Globals.modes[0].mode); + d3d9Globals.modes[0].flags = 0; + d3d9Globals.numModes = 1; + + for(i = 0; i < nelem(fbFormats); i++){ + int n = d3d9Globals.d3d9->GetAdapterModeCount(d3d9Globals.adapter, fbFormats[i]); + for(j = 0; j < n; j++){ + d3d9Globals.d3d9->EnumAdapterModes(d3d9Globals.adapter, fbFormats[i], j, &mode); + addVideoMode(&mode); + } + } +} + +static int +openD3D(EngineOpenParams *params) { HWND win = params->window; - bool windowed = true; d3d9Globals.window = win; - d3d9Globals.windowed = windowed; + d3d9Globals.numAdapters = 0; + d3d9Globals.modes = nil; + d3d9Globals.numModes = 0; + d3d9Globals.currentMode = 0; - HRESULT hr = 0; - IDirect3D9 *d3d9 = 0; - d3d9 = Direct3DCreate9(D3D_SDK_VERSION); - if(!d3d9){ + d3d9Globals.d3d9 = Direct3DCreate9(D3D_SDK_VERSION); + if(d3d9Globals.d3d9 == nil){ RWERROR((ERR_GENERAL, "Direct3DCreate9() failed")); return 0; } - D3DCAPS9 caps; - d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps); - int vp = 0; - if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) - vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; - else - vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; + d3d9Globals.numAdapters = d3d9Globals.d3d9->GetAdapterCount(); + d3d9Globals.adapter = 0; - RECT rect; - GetClientRect(win, &rect); - int width = rect.right - rect.left; - int height = rect.bottom - rect.top; + for(d3d9Globals.adapter = 0; d3d9Globals.adapter < d3d9Globals.numAdapters; d3d9Globals.adapter++) + if(d3d9Globals.d3d9->GetDeviceCaps(d3d9Globals.adapter, D3DDEVTYPE_HAL, &d3d9Globals.caps) == D3D_OK) + goto found; + // no adapter + d3d9Globals.d3d9->Release(); + d3d9Globals.d3d9 = nil; + RWERROR((ERR_GENERAL, "Direct3DCreate9() failed")); + return 0; - d3d9Globals.presentWidth = width; - d3d9Globals.presentHeight = height; - D3DPRESENT_PARAMETERS d3dpp; - d3dpp.BackBufferWidth = width; - d3dpp.BackBufferHeight = height; - d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; - d3dpp.BackBufferCount = 1; - d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; - d3dpp.MultiSampleQuality = 0; - d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; - d3dpp.hDeviceWindow = win; - d3dpp.Windowed = windowed; - d3dpp.EnableAutoDepthStencil = true; - d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; - d3dpp.Flags = 0; - d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; - d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; -// d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - - IDirect3DDevice9 *dev; - hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, win, - vp, &d3dpp, &dev); - if(FAILED(hr)){ - // try again using a 16-bit depth buffer - d3dpp.AutoDepthStencilFormat = D3DFMT_D16; - - hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, - win, vp, &d3dpp, &dev); - - if(FAILED(hr)){ - RWERROR((ERR_GENERAL, "CreateDevice() failed")); - d3d9->Release(); - return 0; - } - } - d3d9->Release(); - d3d::d3ddevice = dev; +found: + makeVideoModeList(); return 1; } static int closeD3D(void) { - d3d::d3ddevice->Release(); - d3d::d3ddevice = nil; + d3d9Globals.d3d9->Release(); + d3d9Globals.d3d9 = nil; + return 1; +} + +static int +startD3D(void) +{ + HRESULT hr; + int vp; + if(d3d9Globals.caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) + vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; + else + vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; + + uint32 width, height, depth; + D3DFORMAT format, zformat; + format = d3d9Globals.modes[d3d9Globals.currentMode].mode.Format; + + // Use window size in windowed mode, otherwise get size from video mode + if(d3d9Globals.modes[d3d9Globals.currentMode].flags & VIDEOMODEEXCLUSIVE){ + width = d3d9Globals.modes[d3d9Globals.currentMode].mode.Width; + height = d3d9Globals.modes[d3d9Globals.currentMode].mode.Height; + }else{ + RECT rect; + GetClientRect(d3d9Globals.window, &rect); + width = rect.right - rect.left; + height = rect.bottom - rect.top; + } + + bool windowed = !(d3d9Globals.modes[d3d9Globals.currentMode].flags & VIDEOMODEEXCLUSIVE); + + // See if we can get an alpha channel + if(format == D3DFMT_X8R8G8B8){ + if(d3d9Globals.d3d9->CheckDeviceType(d3d9Globals.adapter, D3DDEVTYPE_HAL, format, D3DFMT_A8R8G8B8, windowed) == D3D_OK) + format = D3DFMT_A8R8G8B8; + } + + depth = findFormatDepth(format); + + // TOOD: use something more sophisticated maybe? + if(depth == 32) + zformat = D3DFMT_D24S8; + else + zformat = D3DFMT_D16; + + d3d9Globals.present.BackBufferWidth = width; + d3d9Globals.present.BackBufferHeight = height; + d3d9Globals.present.BackBufferFormat = format; + d3d9Globals.present.BackBufferCount = 1; + d3d9Globals.present.MultiSampleType = D3DMULTISAMPLE_NONE; + d3d9Globals.present.MultiSampleQuality = 0; + d3d9Globals.present.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3d9Globals.present.hDeviceWindow = d3d9Globals.window; + d3d9Globals.present.Windowed = windowed; + d3d9Globals.present.EnableAutoDepthStencil = true; + d3d9Globals.present.AutoDepthStencilFormat = zformat; + d3d9Globals.present.Flags = 0; + d3d9Globals.present.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; + d3d9Globals.present.PresentationInterval = D3DPRESENT_INTERVAL_ONE; +// d3d9Globals.present.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + + IDirect3DDevice9 *dev; + hr = d3d9Globals.d3d9->CreateDevice(d3d9Globals.adapter, D3DDEVTYPE_HAL, + d3d9Globals.window, vp, &d3d9Globals.present, &dev); + if(FAILED(hr)){ + RWERROR((ERR_GENERAL, "CreateDevice() failed")); + return 0; + } + d3d::d3ddevice = dev; return 1; } @@ -1027,6 +1155,9 @@ termD3D(void) { closeIm3D(); closeIm2D(); + + d3d::d3ddevice->Release(); + d3d::d3ddevice = nil; return 1; } @@ -1037,21 +1168,69 @@ finalizeD3D(void) } static int -deviceSystem(DeviceReq req, void *arg0) +deviceSystem(DeviceReq req, void *arg, int32 n) { + D3DADAPTER_IDENTIFIER9 adapter; + VideoMode *rwmode; + switch(req){ case DEVICEOPEN: - return openD3D((EngineStartParams*)arg0); + return openD3D((EngineOpenParams*)arg); case DEVICECLOSE: return closeD3D(); case DEVICEINIT: - return initD3D(); + return startD3D() && initD3D(); case DEVICETERM: return termD3D(); case DEVICEFINALIZE: return finalizeD3D(); + + + case DEVICEGETNUMSUBSYSTEMS: + return d3d9Globals.numAdapters; + + case DEVICEGETCURRENTSUBSYSTEM: + return d3d9Globals.adapter; + + case DEVICESETSUBSYSTEM: + if(n >= d3d9Globals.numAdapters) + return 0; + d3d9Globals.adapter = n; + if(d3d9Globals.d3d9->GetDeviceCaps(d3d9Globals.adapter, D3DDEVTYPE_HAL, &d3d9Globals.caps) != D3D_OK) + return 0; + makeVideoModeList(); + return 1; + + case DEVICEGETSUBSSYSTEMINFO: + if(n >= d3d9Globals.numAdapters) + return 0; + if(d3d9Globals.d3d9->GetAdapterIdentifier(d3d9Globals.adapter, 0, &adapter) != D3D_OK) + return 0; + strncpy(((SubSystemInfo*)arg)->name, adapter.Description, sizeof(SubSystemInfo::name)); + return 1; + + + case DEVICEGETNUMVIDEOMODES: + return d3d9Globals.numModes; + + case DEVICEGETCURRENTVIDEOMODE: + return d3d9Globals.currentMode; + + case DEVICESETVIDEOMODE: + if(n >= d3d9Globals.numModes) + return 0; + d3d9Globals.currentMode = n; + return 1; + + case DEVICEGETVIDEOMODEINFO: + rwmode = (VideoMode*)arg; + rwmode->width = d3d9Globals.modes[n].mode.Width; + rwmode->height = d3d9Globals.modes[n].mode.Height; + rwmode->depth = findFormatDepth(d3d9Globals.modes[n].mode.Format); + rwmode->flags = d3d9Globals.modes[n].flags; + return 1; } return 1; } diff --git a/src/d3d/d3dimmed.cpp b/src/d3d/d3dimmed.cpp index 4154253..9a55bd6 100644 --- a/src/d3d/d3dimmed.cpp +++ b/src/d3d/d3dimmed.cpp @@ -3,6 +3,7 @@ #include #include +#define WITH_D3D #include "../rwbase.h" #include "../rwplg.h" #include "../rwpipeline.h" diff --git a/src/d3d/d3drender.cpp b/src/d3d/d3drender.cpp index e982f19..072d0fa 100644 --- a/src/d3d/d3drender.cpp +++ b/src/d3d/d3drender.cpp @@ -3,6 +3,7 @@ #include #include +#define WITH_D3D #include "../rwbase.h" #include "../rwplg.h" #include "../rwpipeline.h" diff --git a/src/d3d/rwd3d.h b/src/d3d/rwd3d.h index 2e4996c..f4b619d 100644 --- a/src/d3d/rwd3d.h +++ b/src/d3d/rwd3d.h @@ -1,37 +1,56 @@ #ifdef RW_D3D9 -#define NOMINMAX 1 +#ifdef WITH_D3D #include #endif +#endif namespace rw { #ifdef RW_D3D9 -struct EngineStartParams + +#ifdef _WINDOWS_ +struct EngineOpenParams { HWND window; }; +#else +struct EngineOpenParams +{ + uint32 please_include_windows_h; +}; +#endif +#else +#ifdef _D3D9_H_ +#error "please don't include d3d9.h for non-d3d9 platforms" +#endif #endif namespace d3d { extern bool32 isP8supported; -#ifdef RW_D3D9 -extern IDirect3DDevice9 *d3ddevice; extern Device renderdevice; +#ifdef RW_D3D9 +#ifdef _D3D9_H_ +extern IDirect3DDevice9 *d3ddevice; +void setD3dMaterial(D3DMATERIAL9 *mat9); +#endif + void lightingCB(bool32 normals); +#define COLOR_ARGB(a, r, g, b) ((rw::uint32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff))) + struct Im3DVertex { V3d position; - D3DCOLOR color; + uint32 color; float32 u, v; void setX(float32 x) { this->position.x = x; } void setY(float32 y) { this->position.y = y; } void setZ(float32 z) { this->position.z = z; } - void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { this->color = D3DCOLOR_ARGB(a, r, g, b); } + void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { this->color = COLOR_ARGB(a, r, g, b); } void setU(float32 u) { this->u = u; } void setV(float32 v) { this->v = v; } @@ -48,7 +67,7 @@ struct Im2DVertex { float32 x, y, z; float32 w; - D3DCOLOR color; + uint32 color; float32 u, v; void setScreenX(float32 x) { this->x = x; } @@ -56,7 +75,7 @@ struct Im2DVertex void setScreenZ(float32 z) { this->z = z; } void setCameraZ(float32 z) { } void setRecipCameraZ(float32 recipz) { this->w = recipz; } - void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { this->color = D3DCOLOR_ARGB(a, r, g, b); } + void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { this->color = COLOR_ARGB(a, r, g, b); } void setU(float32 u, float recipZ) { this->u = u; } void setV(float32 v, float recipZ) { this->v = v; } @@ -70,8 +89,6 @@ struct Im2DVertex float getV(void) { return this->v; } }; -void setD3dMaterial(D3DMATERIAL9 *mat9); - #else enum { D3DLOCK_NOSYSLOCK = 0, // ignored @@ -120,7 +137,6 @@ enum { D3DDECLUSAGE_DEPTH, // 12 D3DDECLUSAGE_SAMPLE // 13 }; - #endif extern int vertFormatMap[]; diff --git a/src/d3d/xboxmatx.cpp b/src/d3d/xboxmatfx.cpp similarity index 100% rename from src/d3d/xboxmatx.cpp rename to src/d3d/xboxmatfx.cpp diff --git a/src/engine.cpp b/src/engine.cpp index d89d524..8cd671d 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -99,9 +99,8 @@ Engine::init(void) } // This is where RW allocates the engine and e.g. opens d3d -// TODO: this will probably take an argument with device specific data bool32 -Engine::open(void) +Engine::open(EngineOpenParams *p) { if(engine || Engine::state != Initialized){ RWERROR((ERR_ENGINEOPEN)); @@ -125,7 +124,8 @@ Engine::open(void) engine->device = null::renderdevice; #endif - // TODO: open device; create d3d object/get video mode + // TODO: create d3d object/get video mode + engine->device.system(DEVICEOPEN, (void*)p, 0); // TODO: init driver functions ObjPipeline *defpipe = new ObjPipeline(PLATFORM_NULL); @@ -150,24 +150,22 @@ Engine::open(void) } // This is where RW creates the actual rendering device -// ans calls the engine plugin ctors +// and calls the engine plugin ctors bool32 -Engine::start(EngineStartParams *p) +Engine::start(void) { if(engine == nil || Engine::state != Opened){ RWERROR((ERR_ENGINESTART)); return 0; } - // TODO: put this into Open? - engine->device.system(DEVICEOPEN, (void*)p); - engine->device.system(DEVICEINIT, nil); + engine->device.system(DEVICEINIT, nil, 0); Engine::s_plglist.construct(engine); for(uint i = 0; i < NUM_PLATFORMS; i++) Driver::s_plglist[i].construct(rw::engine->driver[i]); - engine->device.system(DEVICEFINALIZE, nil); + engine->device.system(DEVICEFINALIZE, nil, 0); Engine::state = Started; return 1; @@ -177,30 +175,100 @@ void Engine::term(void) { // TODO + if(engine || Engine::state != Initialized){ + RWERROR((ERR_GENERAL)); + return; + } + Engine::state = Dead; } void Engine::close(void) { - // TODO + if(engine == nil || Engine::state != Opened){ + RWERROR((ERR_GENERAL)); + return; + } + + engine->device.system(DEVICECLOSE, nil, 0); for(uint i = 0; i < NUM_PLATFORMS; i++) rwFree(rw::engine->driver[i]); rwFree(engine); + engine = nil; Engine::state = Initialized; } void Engine::stop(void) { - engine->device.system(DEVICETERM, nil); - engine->device.system(DEVICECLOSE, nil); + if(engine == nil || Engine::state != Started){ + RWERROR((ERR_GENERAL)); + return; + } + + engine->device.system(DEVICETERM, nil, 0); for(uint i = 0; i < NUM_PLATFORMS; i++) Driver::s_plglist[i].destruct(rw::engine->driver[i]); Engine::s_plglist.destruct(engine); Engine::state = Opened; } + +int32 +Engine::getNumSubSystems(void) +{ + return engine->device.system(DEVICEGETNUMSUBSYSTEMS, nil, 0); +} + +int32 +Engine::getCurrentSubSystem(void) +{ + return engine->device.system(DEVICEGETCURRENTSUBSYSTEM, nil, 0); +} + +bool32 +Engine::setSubSystem(int32 subsys) +{ + return engine->device.system(DEVICESETSUBSYSTEM, nil, subsys); +} + +SubSystemInfo* +Engine::getSubSystemInfo(SubSystemInfo *info, int32 subsys) +{ + if(engine->device.system(DEVICEGETSUBSSYSTEMINFO, info, subsys)) + return info; + return nil; +} + + +int32 +Engine::getNumVideoModes(void) +{ + return engine->device.system(DEVICEGETNUMVIDEOMODES, nil, 0); +} + +int32 +Engine::getCurrentVideoMode(void) +{ + return engine->device.system(DEVICEGETCURRENTVIDEOMODE, nil, 0); +} + +bool32 +Engine::setVideoMode(int32 mode) +{ + return engine->device.system(DEVICESETVIDEOMODE, nil, mode); +} + +VideoMode* +Engine::getVideoModeInfo(VideoMode *info, int32 mode) +{ + if(engine->device.system(DEVICEGETVIDEOMODEINFO, info, mode)) + return info; + return nil; +} + + namespace null { void beginUpdate(Camera*) { } @@ -273,8 +341,16 @@ rasterToImage(Raster*) } int -deviceSystem(DeviceReq req, void *arg0) +deviceSystem(DeviceReq req, void *arg0, int32 n) { + switch(req){ + case DEVICEGETNUMSUBSYSTEMS: + return 0; + case DEVICEGETCURRENTSUBSYSTEM: + return 0; + case DEVICEGETSUBSSYSTEMINFO: + return 0; + } return 1; } diff --git a/src/frame.cpp b/src/frame.cpp index b3e0071..8f7f6c1 100644 --- a/src/frame.cpp +++ b/src/frame.cpp @@ -258,28 +258,28 @@ Frame::syncDirty(void) } void -Frame::rotate(V3d *axis, float32 angle, CombineOp op) +Frame::rotate(const V3d *axis, float32 angle, CombineOp op) { this->matrix.rotate(axis, angle, op); updateObjects(); } void -Frame::translate(V3d *trans, CombineOp op) +Frame::translate(const V3d *trans, CombineOp op) { this->matrix.translate(trans, op); updateObjects(); } void -Frame::scale(V3d *scl, CombineOp op) +Frame::scale(const V3d *scl, CombineOp op) { this->matrix.scale(scl, op); updateObjects(); } void -Frame::transform(Matrix *mat, CombineOp op) +Frame::transform(const Matrix *mat, CombineOp op) { this->matrix.transform(mat, op); updateObjects(); diff --git a/src/geometry.cpp b/src/geometry.cpp index 5e1f299..6fa4876 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -330,21 +330,7 @@ Geometry::calculateBoundingSphere(void) { for(int32 i = 0; i < this->numMorphTargets; i++){ MorphTarget *m = &this->morphTargets[i]; - V3d min = { 1000000.0f, 1000000.0f, 1000000.0f }; - V3d max = { -1000000.0f, -1000000.0f, -1000000.0f }; - V3d *v = m->vertices; - for(int32 j = 0; j < this->numVertices; j++){ - if(v->x > max.x) max.x = v->x; - if(v->x < min.x) min.x = v->x; - if(v->y > max.y) max.y = v->y; - if(v->y < min.y) min.y = v->y; - if(v->z > max.z) max.z = v->z; - if(v->z < min.z) min.z = v->z; - v++; - } - m->boundingSphere.center = scale(add(min, max), 1/2.0f); - max = sub(max, m->boundingSphere.center); - m->boundingSphere.radius = length(max); + m->boundingSphere = m->calculateBoundingSphere(); } } @@ -673,6 +659,29 @@ Geometry::removeUnusedMaterials(void) rwFree(map); } +Sphere +MorphTarget::calculateBoundingSphere(void) const +{ + Sphere sphere; + V3d min = { 1000000.0f, 1000000.0f, 1000000.0f }; + V3d max = { -1000000.0f, -1000000.0f, -1000000.0f }; + V3d *v = this->vertices; + for(int32 j = 0; j < this->parent->numVertices; j++){ + if(v->x > max.x) max.x = v->x; + if(v->x < min.x) min.x = v->x; + if(v->y > max.y) max.y = v->y; + if(v->y < min.y) min.y = v->y; + if(v->z > max.z) max.z = v->z; + if(v->z < min.z) min.z = v->z; + v++; + } + sphere.center = scale(add(min, max), 1/2.0f); + max = sub(max, sphere.center); + sphere.radius = length(max); + return sphere; +} + + // // MaterialList // diff --git a/src/gl/gl3device.cpp b/src/gl/gl3device.cpp index ad5c10d..375e6d8 100644 --- a/src/gl/gl3device.cpp +++ b/src/gl/gl3device.cpp @@ -26,6 +26,13 @@ namespace rw { namespace gl3 { +struct DisplayMode +{ + GLFWvidmode mode; + int32 depth; + uint32 flags; +}; + struct GlGlobals { #ifdef LIBRW_SDL2 @@ -33,8 +40,21 @@ struct GlGlobals SDL_GLContext glcontext; #else GLFWwindow *window; + + GLFWmonitor *monitor; + int numMonitors; + int currentMonitor; + + DisplayMode *modes; + int numModes; + int currentMode; #endif int presentWidth, presentHeight; + + // for opening the window + int winWidth, winHeight; + const char *winTitle; + GLFWwindow **pWindow; } glGlobals; struct UniformState @@ -119,6 +139,7 @@ static RwStateCache rwStateCache; static int32 activeTexture; static uint32 blendMap[] = { + GL_ZERO, // actually invalid GL_ZERO, GL_ONE, GL_SRC_COLOR, @@ -728,10 +749,10 @@ beginUpdate(Camera *cam) #ifdef LIBRW_SDL2 static int -openSDL2(EngineStartParams *startparams) +openSDL2(EngineOpenParams *openparams) { - if (!startparams){ - RWERROR((ERR_GENERAL, "startparams invalid")); + if (!openparams){ + RWERROR((ERR_GENERAL, "openparams invalid")); return 0; } @@ -752,9 +773,9 @@ openSDL2(EngineStartParams *startparams) SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); int flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL; - if (startparams->fullscreen) + if (openparams->fullscreen) flags |= SDL_WINDOW_FULLSCREEN; - win = SDL_CreateWindow(startparams->windowtitle, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, startparams->width, startparams->height, flags); + win = SDL_CreateWindow(openparams->windowtitle, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, openparams->width, openparams->height, flags); if(win == nil){ RWERROR((ERR_ENGINEOPEN, SDL_GetError())); SDL_QuitSubSystem(SDL_INIT_VIDEO); @@ -781,7 +802,7 @@ openSDL2(EngineStartParams *startparams) } glGlobals.window = win; glGlobals.glcontext = ctx; - *startparams->window = win; + *openparams->window = win; return 1; } @@ -794,11 +815,64 @@ closeSDL2(void) return 1; } #else -static int -openGLFW(EngineStartParams *startparams) + +static void +addVideoMode(const GLFWvidmode *mode) { - GLenum status; - GLFWwindow *win; + int i; + + for(i = 1; i < glGlobals.numModes; i++){ + if(glGlobals.modes[i].mode.width == mode->width && + glGlobals.modes[i].mode.height == mode->height && + glGlobals.modes[i].mode.redBits == mode->redBits && + glGlobals.modes[i].mode.greenBits == mode->greenBits && + glGlobals.modes[i].mode.blueBits == mode->blueBits){ + // had this mode already, remember highest refresh rate + if(mode->refreshRate > glGlobals.modes[i].mode.refreshRate) + glGlobals.modes[i].mode.refreshRate = mode->refreshRate; + return; + } + } + + // none found, add + glGlobals.modes[glGlobals.numModes].mode = *mode; + glGlobals.modes[glGlobals.numModes].flags = VIDEOMODEEXCLUSIVE; + glGlobals.numModes++; +} + +static void +makeVideoModeList(void) +{ + int i, num; + const GLFWvidmode *modes; + + modes = glfwGetVideoModes(glGlobals.monitor, &num); + rwFree(glGlobals.modes); + glGlobals.modes = rwNewT(DisplayMode, num, ID_DRIVER | MEMDUR_EVENT); + + glGlobals.modes[0].mode = *glfwGetVideoMode(glGlobals.monitor); + glGlobals.modes[0].flags = 0; + glGlobals.numModes = 1; + + for(i = 0; i < num; i++) + addVideoMode(&modes[i]); + + for(i = 0; i < glGlobals.numModes; i++){ + num = glGlobals.modes[i].mode.redBits + + glGlobals.modes[i].mode.greenBits + + glGlobals.modes[i].mode.blueBits; + // set depth to power of two + for(glGlobals.modes[i].depth = 1; glGlobals.modes[i].depth < num; glGlobals.modes[i].depth <<= 1); + } +} + +static int +openGLFW(EngineOpenParams *openparams) +{ + glGlobals.winWidth = openparams->width; + glGlobals.winHeight = openparams->height; + glGlobals.winTitle = openparams->windowtitle; + glGlobals.pWindow = openparams->window; /* Init GLFW */ if(!glfwInit()){ @@ -811,20 +885,42 @@ openGLFW(EngineStartParams *startparams) glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - win = glfwCreateWindow(startparams->width, startparams->height, startparams->windowtitle, 0, 0); + glGlobals.monitor = glfwGetMonitors(&glGlobals.numMonitors)[0]; + + makeVideoModeList(); + + return 1; +} + +static int +closeGLFW(void) +{ + glfwTerminate(); + return 1; +} + +static int +startGLFW(void) +{ + GLenum status; + GLFWwindow *win; + DisplayMode *mode; + + mode = &glGlobals.modes[glGlobals.currentMode]; + + glfwWindowHint(GLFW_RED_BITS, mode->mode.redBits); + glfwWindowHint(GLFW_GREEN_BITS, mode->mode.greenBits); + glfwWindowHint(GLFW_BLUE_BITS, mode->mode.blueBits); + glfwWindowHint(GLFW_REFRESH_RATE, mode->mode.refreshRate); + + if(mode->flags & VIDEOMODEEXCLUSIVE) + win = glfwCreateWindow(mode->mode.width, mode->mode.height, glGlobals.winTitle, glGlobals.monitor, nil); + else + win = glfwCreateWindow(glGlobals.winWidth, glGlobals.winHeight, glGlobals.winTitle, nil, nil); if(win == nil){ RWERROR((ERR_GENERAL, "glfwCreateWindow() failed")); - glfwTerminate(); return 0; } - if(startparams->fullscreen){ - int nbmonitors; - auto monitors = glfwGetMonitors(&nbmonitors); - if (nbmonitors){ - const GLFWvidmode* mode = glfwGetVideoMode(monitors[0]); - glfwSetWindowMonitor(win, monitors[0], 0, 0, mode->width, mode->height, mode->refreshRate); - } - } glfwMakeContextCurrent(win); /* Init GLEW */ @@ -833,25 +929,22 @@ openGLFW(EngineStartParams *startparams) if(status != GLEW_OK){ RWERROR((ERR_GENERAL, glewGetErrorString(status))); glfwDestroyWindow(win); - glfwTerminate(); return 0; } if(!GLEW_VERSION_3_3){ RWERROR((ERR_GENERAL, "OpenGL 3.3 needed")); glfwDestroyWindow(win); - glfwTerminate(); return 0; } glGlobals.window = win; - *startparams->window = win; + *glGlobals.pWindow = win; return 1; } static int -closeGLFW(void) +stopGLFW(void) { glfwDestroyWindow(glGlobals.window); - glfwTerminate(); return 1; } #endif @@ -925,34 +1018,105 @@ finalizeOpenGL(void) return 1; } +#ifdef LIBRW_SDL2 static int -deviceSystem(DeviceReq req, void *arg0) +deviceSystemSDL2(DeviceReq req, void *arg, int32 n) { switch(req){ case DEVICEOPEN: -#ifdef LIBRW_SDL2 - return openSDL2((EngineStartParams*)arg0); -#else - return openGLFW((EngineStartParams*)arg0); -#endif + return openSDL2((EngineOpenParams*)arg); case DEVICECLOSE: -#ifdef LIBRW_SDL2 return closeSDL2(); -#else - return closeGLFW(); -#endif case DEVICEINIT: return initOpenGL(); case DEVICETERM: return termOpenGL(); - case DEVICEFINALIZE: - return finalizeOpenGL(); + // TODO: implement subsystems and video modes + + default: + assert(0 && "not implemented"); + return 0; } return 1; } +#else + +static int +deviceSystemGLFW(DeviceReq req, void *arg, int32 n) +{ + GLFWmonitor **monitors; + VideoMode *rwmode; + int num; + + switch(req){ + case DEVICEOPEN: + return openGLFW((EngineOpenParams*)arg); + case DEVICECLOSE: + return closeGLFW(); + + case DEVICEINIT: + return startGLFW() && initOpenGL(); + case DEVICETERM: + return termOpenGL() && stopGLFW(); + + case DEVICEFINALIZE: + return finalizeOpenGL(); + + + case DEVICEGETNUMSUBSYSTEMS: + return glGlobals.numMonitors; + + case DEVICEGETCURRENTSUBSYSTEM: + return glGlobals.currentMonitor; + + case DEVICESETSUBSYSTEM: + monitors = glfwGetMonitors(&glGlobals.numMonitors); + if(n >= glGlobals.numMonitors) + return 0; + glGlobals.currentMonitor = n; + glGlobals.monitor = monitors[glGlobals.currentMonitor]; + return 1; + + case DEVICEGETSUBSSYSTEMINFO: + monitors = glfwGetMonitors(&glGlobals.numMonitors); + if(n >= glGlobals.numMonitors) + return 0; + strncpy(((SubSystemInfo*)arg)->name, glfwGetMonitorName(monitors[n]), sizeof(SubSystemInfo::name)); + return 1; + + + case DEVICEGETNUMVIDEOMODES: + return glGlobals.numModes; + + case DEVICEGETCURRENTVIDEOMODE: + return glGlobals.currentMode; + + case DEVICESETVIDEOMODE: + if(n >= glGlobals.numModes) + return 0; + glGlobals.currentMode = n; + return 1; + + case DEVICEGETVIDEOMODEINFO: + rwmode = (VideoMode*)arg; + rwmode->width = glGlobals.modes[n].mode.width; + rwmode->height = glGlobals.modes[n].mode.height; + rwmode->depth = glGlobals.modes[n].depth; + rwmode->flags = glGlobals.modes[n].flags; + return 1; + + default: + assert(0 && "not implemented"); + return 0; + } + return 1; +} + +#endif + Device renderdevice = { -1.0f, 1.0f, gl3::beginUpdate, @@ -968,7 +1132,11 @@ Device renderdevice = { gl3::im3DTransform, gl3::im3DRenderIndexed, gl3::im3DEnd, - gl3::deviceSystem +#ifdef LIBRW_SDL2 + gl3::deviceSystemSDL2 +#else + gl3::deviceSystemGLFW +#endif }; } diff --git a/src/gl/gl3raster.cpp b/src/gl/gl3raster.cpp index d9826f0..9fa5049 100644 --- a/src/gl/gl3raster.cpp +++ b/src/gl/gl3raster.cpp @@ -43,6 +43,7 @@ rasterCreate(Raster *raster) // TODO: set/check width, height, depth, format? raster->flags |= Raster::DONTALLOCATE; break; + case Raster::NORMAL: case Raster::TEXTURE: // continue below break; @@ -53,8 +54,6 @@ rasterCreate(Raster *raster) if(raster->flags & Raster::DONTALLOCATE) return; - assert(raster->type == Raster::TEXTURE); - #ifdef RW_OPENGL Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); switch(raster->format & 0xF00){ diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index 9479dd5..210d7cf 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -10,7 +10,7 @@ namespace rw { #ifdef RW_GL3 -struct EngineStartParams +struct EngineOpenParams { #ifdef LIBRW_SDL2 SDL_Window **window; @@ -18,7 +18,6 @@ struct EngineStartParams GLFWwindow **window; #endif int width, height; - bool32 fullscreen; const char *windowtitle; }; #endif diff --git a/src/ps2/rwps2.h b/src/ps2/rwps2.h index 9e94e23..fbf66ec 100644 --- a/src/ps2/rwps2.h +++ b/src/ps2/rwps2.h @@ -1,7 +1,7 @@ namespace rw { #ifdef RW_PS2 -struct EngineStartParams +struct EngineOpenParams { }; #endif diff --git a/src/rwbase.h b/src/rwbase.h index 984ebba..255dd6a 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -322,11 +322,11 @@ struct Matrix static Matrix *mult(Matrix *dst, const Matrix *src1, const Matrix *src2); static Matrix *invert(Matrix *dst, const Matrix *src); static Matrix *transpose(Matrix *dst, const Matrix *src); - Matrix *rotate(V3d *axis, float32 angle, CombineOp op); + Matrix *rotate(const V3d *axis, float32 angle, CombineOp op); Matrix *rotate(const Quat &q, CombineOp op); - Matrix *translate(V3d *translation, CombineOp op); - Matrix *scale(V3d *scl, CombineOp op); - Matrix *transform(Matrix *mat, CombineOp op); + Matrix *translate(const V3d *translation, CombineOp op); + Matrix *scale(const V3d *scl, CombineOp op); + Matrix *transform(const Matrix *mat, CombineOp op); Quat getRotation(void); void lookAt(const V3d &dir, const V3d &up); @@ -334,7 +334,7 @@ struct Matrix static void mult_(Matrix *dst, const Matrix *src1, const Matrix *src2); static void invertOrthonormal(Matrix *dst, const Matrix *src); static Matrix *invertGeneral(Matrix *dst, const Matrix *src); - static void makeRotation(Matrix *dst, V3d *axis, float32 angle); + static void makeRotation(Matrix *dst, const V3d *axis, float32 angle); static void makeRotation(Matrix *dst, const Quat &q); private: float32 normalError(void); diff --git a/src/rwengine.h b/src/rwengine.h index b2892fe..503bc57 100644 --- a/src/rwengine.h +++ b/src/rwengine.h @@ -2,22 +2,34 @@ namespace rw { enum DeviceReq { - // Device/Context creation - DEVICEOPEN, - // Device/Context shutdown - DEVICECLOSE, - // Device initialization before Engine/Driver plugins are opened DEVICEINIT, // Device de-initialization after Engine/Driver plugins are closed DEVICETERM, + // Device/Context creation + DEVICEOPEN, + // Device/Context shutdown + DEVICECLOSE, + // Device initialization after Engine/Driver plugins are opened - DEVICEFINALIZE + DEVICEFINALIZE, // TODO? counterpart to FINALIZE? + + // Video adapters + DEVICEGETNUMSUBSYSTEMS, + DEVICEGETCURRENTSUBSYSTEM, + DEVICESETSUBSYSTEM, + DEVICEGETSUBSSYSTEMINFO, + + // Video modes + DEVICEGETNUMVIDEOMODES, + DEVICEGETCURRENTVIDEOMODE, + DEVICESETVIDEOMODE, + DEVICEGETVIDEOMODEINFO }; -typedef int DeviceSystem(DeviceReq req, void *arg0); +typedef int DeviceSystem(DeviceReq req, void *arg, int32 n); struct Camera; struct Image; @@ -75,7 +87,7 @@ struct Driver } }; -struct EngineStartParams; +struct EngineOpenParams; enum MemHint { @@ -101,6 +113,25 @@ struct MemoryFunctions void *(*rwmustrealloc)(void *p, size_t sz, uint32 hint); }; +struct SubSystemInfo +{ + char name[80]; +}; + +enum VideoModeFlags +{ + VIDEOMODEEXCLUSIVE = 1 +}; + +struct VideoMode +{ + int32 width; + int32 height; + int32 depth; + uint32 flags; +}; + + // This is for platform independent things // TODO: move more stuff into this struct Engine @@ -124,12 +155,23 @@ struct Engine static State state; static bool32 init(void); - static bool32 open(void); - static bool32 start(EngineStartParams*); + static bool32 open(EngineOpenParams*); + static bool32 start(void); static void term(void); static void close(void); static void stop(void); + static int32 getNumSubSystems(void); + static int32 getCurrentSubSystem(void); + static bool32 setSubSystem(int32 subsys); + static SubSystemInfo *getSubSystemInfo(SubSystemInfo *info, int32 subsys); + + static int32 getNumVideoModes(void); + static int32 getCurrentVideoMode(void); + static bool32 setVideoMode(int32 mode); + static VideoMode *getVideoModeInfo(VideoMode *info, int32 mode); + + static PluginList s_plglist; static int32 registerPlugin(int32 size, uint32 id, Constructor ctor, Destructor dtor){ diff --git a/src/rwobjects.h b/src/rwobjects.h index a7b92e5..91ca74f 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -62,16 +62,16 @@ struct Frame Frame *addChild(Frame *f, bool32 append = 0); Frame *removeChild(void); Frame *forAllChildren(Callback cb, void *data); - Frame *getParent(void){ + Frame *getParent(void) const { return (Frame*)this->object.parent; } int32 count(void); - bool32 dirty(void) { + bool32 dirty(void) const { return !!(this->root->object.privateFlags & HIERARCHYSYNC); } Matrix *getLTM(void); - void rotate(V3d *axis, float32 angle, CombineOp op); - void translate(V3d *trans, CombineOp op); - void scale(V3d *scale, CombineOp op); - void transform(Matrix *mat, CombineOp op); + void rotate(const V3d *axis, float32 angle, CombineOp op); + void translate(const V3d *trans, CombineOp op); + void scale(const V3d *scale, CombineOp op); + void transform(const Matrix *mat, CombineOp op); void updateObjects(void); @@ -350,6 +350,8 @@ struct MorphTarget Sphere boundingSphere; V3d *vertices; V3d *normals; + + Sphere calculateBoundingSphere(void) const; }; struct InstanceDataHeader @@ -482,7 +484,7 @@ struct Atomic this->object.setFrame(f); this->object.object.privateFlags |= WORLDBOUNDDIRTY; } - Frame *getFrame(void) { return (Frame*)this->object.object.parent; } + Frame *getFrame(void) const { return (Frame*)this->object.object.parent; } static Atomic *fromClump(LLLink *lnk){ return LLLinkGetData(lnk, Atomic, inClump); } void removeFromClump(void); @@ -498,7 +500,7 @@ struct Atomic this->renderCB = defaultRenderCB; }; void setFlags(uint32 flags) { this->object.object.flags = flags; } - uint32 getFlags(void) { return this->object.object.flags; } + uint32 getFlags(void) const { return this->object.object.flags; } static Atomic *streamReadClump(Stream *stream, FrameList_ *frameList, Geometry **geometryList); bool streamWriteClump(Stream *stream, FrameList_ *frmlst); @@ -530,7 +532,7 @@ struct Light static Light *create(int32 type); void destroy(void); void setFrame(Frame *f) { this->object.setFrame(f); } - Frame *getFrame(void){ return (Frame*)this->object.object.parent; } + Frame *getFrame(void) const { return (Frame*)this->object.object.parent; } static Light *fromClump(LLLink *lnk){ return LLLinkGetData(lnk, Light, inClump); } static Light *fromWorld(LLLink *lnk){ @@ -617,7 +619,7 @@ struct Camera Camera *clone(void); void destroy(void); void setFrame(Frame *f) { this->object.setFrame(f); } - Frame *getFrame(void){ return (Frame*)this->object.object.parent; } + Frame *getFrame(void)const { return (Frame*)this->object.object.parent; } static Camera *fromClump(LLLink *lnk){ return LLLinkGetData(lnk, Camera, inClump); } void beginUpdate(void) { this->beginUpdateCB(this); } @@ -629,7 +631,7 @@ struct Camera void setViewWindow(const V2d *window); void setViewOffset(const V2d *offset); void setProjection(int32 proj); - int32 frustumTestSphere(Sphere *s); + int32 frustumTestSphere(const Sphere *s) const; static Camera *streamRead(Stream *stream); bool streamWrite(Stream *stream); uint32 streamGetSize(void); @@ -669,7 +671,7 @@ struct Clump } void setFrame(Frame *f){ this->object.parent = f; } - Frame *getFrame(void){ + Frame *getFrame(void) const { return (Frame*)this->object.parent; } static Clump *streamRead(Stream *stream); bool streamWrite(Stream *stream); @@ -687,8 +689,11 @@ struct World LinkList directionalLights; // these do not (type < 0x80) static World *create(void); + void destroy(void); void addLight(Light *light); + void removeLight(Light *light); void addCamera(Camera *cam); + void removeCamera(Camera *cam); }; struct TexDictionary diff --git a/src/rwplugins.h b/src/rwplugins.h index 440d94f..1f2b972 100644 --- a/src/rwplugins.h +++ b/src/rwplugins.h @@ -218,7 +218,7 @@ struct Skin void findUsedBones(int32 numVertices); static void setPipeline(Atomic *a, int32 type); - static Skin *get(Geometry *geo){ + static Skin *get(const Geometry *geo){ return *PLUGINOFFSET(Skin*, geo, skinGlobals.geoOffset); } static void set(Geometry *geo, Skin *skin){ @@ -228,7 +228,7 @@ struct Skin *PLUGINOFFSET(HAnimHierarchy*, atomic, skinGlobals.atomicOffset) = hier; } - static HAnimHierarchy *getHierarchy(Atomic *atomic){ + static HAnimHierarchy *getHierarchy(const Atomic *atomic){ return *PLUGINOFFSET(HAnimHierarchy*, atomic, skinGlobals.atomicOffset); } diff --git a/src/rwrender.h b/src/rwrender.h index db335df..577bbfd 100644 --- a/src/rwrender.h +++ b/src/rwrender.h @@ -29,21 +29,21 @@ enum RenderState enum AlphaTestFunc { - ALPHAALWAYS = 0, + ALPHAALWAYS, ALPHAGREATEREQUAL, ALPHALESS }; enum CullMode { - CULLNONE, + CULLNONE = 1, CULLBACK, CULLFRONT }; enum BlendFunction { - BLENDZERO = 0, + BLENDZERO = 1, BLENDONE, BLENDSRCCOLOR, BLENDINVSRCCOLOR, diff --git a/src/world.cpp b/src/world.cpp index 51545b8..fdee70b 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -26,9 +26,17 @@ World::create(void) world->object.init(World::ID, 0); world->lights.init(); world->directionalLights.init(); + s_plglist.construct(world); return world; } +void +World::destroy(void) +{ + s_plglist.destruct(this); + rwFree(this); +} + void World::addLight(Light *light) { @@ -42,6 +50,13 @@ World::addLight(Light *light) } } +void +World::removeLight(Light *light) +{ + if(light->world == this) + light->inWorld.remove(); +} + void World::addCamera(Camera *cam) { @@ -50,4 +65,11 @@ World::addCamera(Camera *cam) cam->getFrame()->updateObjects(); } +void +World::removeCamera(Camera *cam) +{ + if(cam->world == this) + cam->world = nil; +} + } diff --git a/tools/clumpview/main.cpp b/tools/clumpview/main.cpp index e0f229a..bac5cc1 100644 --- a/tools/clumpview/main.cpp +++ b/tools/clumpview/main.cpp @@ -12,9 +12,9 @@ struct SceneGlobals { } Scene; rw::Texture *tex, *tex2; rw::Raster *testras; -rw::EngineStartParams engineStartParams; +rw::EngineOpenParams engineOpenParams; -bool dosoftras = 1; +bool dosoftras = 0; namespace gen { void tlTest(rw::Clump *clump); diff --git a/tools/clumpview/ras_test.cpp b/tools/clumpview/ras_test.cpp index d9db39d..d5c0435 100644 --- a/tools/clumpview/ras_test.cpp +++ b/tools/clumpview/ras_test.cpp @@ -843,6 +843,8 @@ endSoftras(void) { int i; uint8 *dst = testras->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH); + if(dst == nil) + return; uint8 *src = rs::canvas->fb; for(i = 0; i < rs::canvas->w*rs::canvas->h; i++){ dst[0] = src[1]; diff --git a/tools/imguitest/main.cpp b/tools/imguitest/main.cpp index 5051b54..675f095 100644 --- a/tools/imguitest/main.cpp +++ b/tools/imguitest/main.cpp @@ -7,7 +7,7 @@ struct SceneGlobals { rw::World *world; rw::Camera *camera; } Scene; -rw::EngineStartParams engineStartParams; +rw::EngineOpenParams engineOpenParams; void Init(void) diff --git a/tools/ps2test/main.cpp b/tools/ps2test/main.cpp index 8dcd1e3..4c7e2ba 100644 --- a/tools/ps2test/main.cpp +++ b/tools/ps2test/main.cpp @@ -626,7 +626,7 @@ beginCamera(void) f[3] = 0.0f; } -rw::EngineStartParams engineStartParams; +rw::EngineOpenParams engineOpenParams; void pluginattach(void) @@ -654,9 +654,9 @@ initrw(void) if(!rw::Engine::init()) return 0; pluginattach(); - if(!rw::Engine::open()) + if(!rw::Engine::open(&engineOpenParams)) return 0; - if(!rw::Engine::start(&engineStartParams)) + if(!rw::Engine::start()) return 0; rw::Texture::setLoadTextures(0);