diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 87c2c380..aa2293d4 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "103.11"; + static const string Version = "103.12"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/target-tomoko/configuration/configuration.cpp b/higan/target-tomoko/configuration/configuration.cpp index c75feb71..f31eadd8 100644 --- a/higan/target-tomoko/configuration/configuration.cpp +++ b/higan/target-tomoko/configuration/configuration.cpp @@ -30,7 +30,7 @@ Settings::Settings() { set("Video/Windowed/AspectCorrection", true); set("Video/Windowed/IntegralScaling", true); - set("Video/Windowed/AdaptiveSizing", false); + set("Video/Windowed/Adaptive", false); set("Video/Windowed/Scale", "Small"); set("Video/Windowed/Scale/Small", "640x480"); set("Video/Windowed/Scale/Medium", "960x720"); @@ -38,6 +38,7 @@ Settings::Settings() { set("Video/Fullscreen/AspectCorrection", true); set("Video/Fullscreen/IntegralScaling", true); + set("Video/Fullscreen/Exclusive", false); set("Audio/Driver", ruby::Audio::optimalDriver()); set("Audio/Device", ""); diff --git a/higan/target-tomoko/input/hotkeys.cpp b/higan/target-tomoko/input/hotkeys.cpp index 42d2095c..e390bda1 100644 --- a/higan/target-tomoko/input/hotkeys.cpp +++ b/higan/target-tomoko/input/hotkeys.cpp @@ -96,12 +96,12 @@ auto InputManager::appendHotkeys() -> void { } auto InputManager::pollHotkeys() -> void { - if(!presentation || !presentation->focused()) return; - - for(auto& hotkey : hotkeys) { - int16 state = hotkey->poll(); - if(hotkey->state == 0 && state == 1 && hotkey->press) hotkey->press(); - if(hotkey->state == 1 && state == 0 && hotkey->release) hotkey->release(); - hotkey->state = state; + if(program->allowInput(true)) { + for(auto& hotkey : hotkeys) { + int16 state = hotkey->poll(); + if(hotkey->state == 0 && state == 1 && hotkey->press) hotkey->press(); + if(hotkey->state == 1 && state == 0 && hotkey->release) hotkey->release(); + hotkey->state = state; + } } } diff --git a/higan/target-tomoko/presentation/presentation.cpp b/higan/target-tomoko/presentation/presentation.cpp index 58768891..f5a367f2 100644 --- a/higan/target-tomoko/presentation/presentation.cpp +++ b/higan/target-tomoko/presentation/presentation.cpp @@ -269,7 +269,7 @@ auto Presentation::resizeViewport(bool resizeWindow) -> void { viewportHeight = resolution(1).natural(); } - if(settings["Video/Windowed/AdaptiveSizing"].boolean() && resizeWindow) { + if(settings["Video/Windowed/Adaptive"].boolean() && resizeWindow) { uint multiplier = min(viewportWidth / emulatorWidth, viewportHeight / emulatorHeight); emulatorWidth *= multiplier; emulatorHeight *= multiplier; @@ -312,13 +312,13 @@ auto Presentation::toggleFullScreen() -> void { if(!fullScreen()) { menuBar.setVisible(false); statusBar.setVisible(false); - setResizable(true); setFullScreen(true); + video->set(Video::Exclusive, settings["Video/Fullscreen/Exclusive"].boolean()); if(!input->acquired()) input->acquire(); } else { if(input->acquired()) input->release(); + video->set(Video::Exclusive, false); setFullScreen(false); - setResizable(false); menuBar.setVisible(true); statusBar.setVisible(settings["UserInterface/ShowStatusBar"].boolean()); } diff --git a/higan/target-tomoko/program/interface.cpp b/higan/target-tomoko/program/interface.cpp index d466f9a3..9d487224 100644 --- a/higan/target-tomoko/program/interface.cpp +++ b/higan/target-tomoko/program/interface.cpp @@ -96,7 +96,7 @@ auto Program::audioSample(const double* samples, uint channels) -> void { } auto Program::inputPoll(uint port, uint device, uint input) -> int16 { - if(presentation->focused() || settings["Input/FocusLoss/AllowInput"].boolean()) { + if(allowInput()) { inputManager->poll(); auto& mapping = inputManager->emulator->ports[port].devices[device].mappings[input]; return mapping.poll(); @@ -105,7 +105,7 @@ auto Program::inputPoll(uint port, uint device, uint input) -> int16 { } auto Program::inputRumble(uint port, uint device, uint input, bool enable) -> void { - if(presentation->focused() || settings["Input/FocusLoss/AllowInput"].boolean() || !enable) { + if(allowInput() || !enable) { auto& mapping = inputManager->emulator->ports[port].devices[device].mappings[input]; return mapping.rumble(enable); } diff --git a/higan/target-tomoko/program/program.hpp b/higan/target-tomoko/program/program.hpp index 12d26ce1..39def148 100644 --- a/higan/target-tomoko/program/program.hpp +++ b/higan/target-tomoko/program/program.hpp @@ -35,6 +35,7 @@ struct Program : Emulator::Platform { auto updateVideoShader() -> void; auto updateAudioDriver() -> void; auto updateAudioEffects() -> void; + auto allowInput(bool hotkey = false) -> bool; bool hasQuit = false; bool pause = false; diff --git a/higan/target-tomoko/program/utility.cpp b/higan/target-tomoko/program/utility.cpp index ae1c3114..a7e11ccc 100644 --- a/higan/target-tomoko/program/utility.cpp +++ b/higan/target-tomoko/program/utility.cpp @@ -92,3 +92,17 @@ auto Program::updateAudioEffects() -> void { auto reverbEnable = settings["Audio/Reverb/Enable"].boolean(); Emulator::audio.setReverb(reverbEnable); } + +auto Program::allowInput(bool hotkey) -> bool { + //exclusive mode creates its own top-level window: presentation window will not have focus + if(video->cap(Video::Exclusive)) { + auto value = video->get(Video::Exclusive); + if(value.is() && value.get()) return true; + } + + if(presentation && presentation->focused()) return true; + + if(!hotkey && settings["Input/FocusLoss/AllowInput"].boolean()) return true; + + return false; +} diff --git a/higan/target-tomoko/settings/audio.cpp b/higan/target-tomoko/settings/audio.cpp index dbcacb1b..768466b8 100644 --- a/higan/target-tomoko/settings/audio.cpp +++ b/higan/target-tomoko/settings/audio.cpp @@ -32,7 +32,7 @@ AudioSettings::AudioSettings(TabFrame* parent) : TabFrameItem(parent) { resamplerCombo.append(ComboButtonItem().setText("IIR - Biquad")); resamplerCombo.setEnabled(false); - exclusiveMode.setText("Exclusive Mode"); + exclusiveMode.setText("Exclusive mode"); exclusiveMode.setChecked(settings["Audio/Exclusive"].boolean()).onToggle([&] { updateDriver(); }); if(!audio->cap(Audio::Exclusive)) exclusiveMode.remove(); diff --git a/higan/target-tomoko/settings/settings.hpp b/higan/target-tomoko/settings/settings.hpp index 556a0a87..6eeaff53 100644 --- a/higan/target-tomoko/settings/settings.hpp +++ b/higan/target-tomoko/settings/settings.hpp @@ -28,11 +28,12 @@ struct VideoSettings : TabFrameItem { HorizontalLayout windowedModeLayout{&layout, Size{~0, 0}}; CheckLabel windowedModeAspectCorrection{&windowedModeLayout, Size{0, 0}}; CheckLabel windowedModeIntegralScaling{&windowedModeLayout, Size{0, 0}}; - CheckLabel windowedModeAdaptiveSizing{&windowedModeLayout, Size{0, 0}}; + CheckLabel windowedModeAdaptive{&windowedModeLayout, Size{0, 0}}; Label fullscreenModeLabel{&layout, Size{~0, 0}, 2}; HorizontalLayout fullscreenModeLayout{&layout, Size{~0, 0}}; CheckLabel fullscreenModeAspectCorrection{&fullscreenModeLayout, Size{0, 0}}; CheckLabel fullscreenModeIntegralScaling{&fullscreenModeLayout, Size{0, 0}}; + CheckLabel fullscreenModeExclusive{&fullscreenModeLayout, Size{0, 0}}; auto updateColor(bool initializing = false) -> void; auto updateViewport(bool initializing = false) -> void; diff --git a/higan/target-tomoko/settings/video.cpp b/higan/target-tomoko/settings/video.cpp index 578cd649..05f388cf 100644 --- a/higan/target-tomoko/settings/video.cpp +++ b/higan/target-tomoko/settings/video.cpp @@ -26,11 +26,13 @@ VideoSettings::VideoSettings(TabFrame* parent) : TabFrameItem(parent) { windowedModeLabel.setFont(Font().setBold()).setText("Windowed Mode"); windowedModeAspectCorrection.setText("Aspect correction").setChecked(settings["Video/Windowed/AspectCorrection"].boolean()).onToggle([&] { updateViewport(); }); windowedModeIntegralScaling.setText("Integral scaling").setChecked(settings["Video/Windowed/IntegralScaling"].boolean()).onToggle([&] { updateViewport(); }); - windowedModeAdaptiveSizing.setText("Adaptive sizing").setChecked(settings["Video/Windowed/AdaptiveSizing"].boolean()).onToggle([&] { updateViewport(); }); + windowedModeAdaptive.setText("Adaptive sizing").setChecked(settings["Video/Windowed/Adaptive"].boolean()).onToggle([&] { updateViewport(); }); fullscreenModeLabel.setFont(Font().setBold()).setText("Fullscreen Mode"); fullscreenModeAspectCorrection.setText("Aspect correction").setChecked(settings["Video/Fullscreen/AspectCorrection"].boolean()).onToggle([&] { updateViewport(); }); fullscreenModeIntegralScaling.setText("Integral scaling").setChecked(settings["Video/Fullscreen/IntegralScaling"].boolean()).onToggle([&] { updateViewport(); }); + fullscreenModeExclusive.setText("Exclusive mode").setChecked(settings["Video/Fullscreen/Exclusive"].boolean()).onToggle([&] { updateViewport(); }); + if(!video->cap(Video::Exclusive)) fullscreenModeExclusive.remove(); updateColor(true); updateViewport(true); @@ -48,16 +50,17 @@ auto VideoSettings::updateColor(bool initializing) -> void { } auto VideoSettings::updateViewport(bool initializing) -> void { - bool wasAdaptive = settings["Video/Windowed/AdaptiveSizing"].boolean(); - bool isAdaptive = windowedModeAdaptiveSizing.checked(); + bool wasAdaptive = settings["Video/Windowed/Adaptive"].boolean(); + bool isAdaptive = windowedModeAdaptive.checked(); settings["Video/Overscan/Horizontal"].setValue(horizontalMaskSlider.position()); settings["Video/Overscan/Vertical"].setValue(verticalMaskSlider.position()); settings["Video/Windowed/AspectCorrection"].setValue(windowedModeAspectCorrection.checked()); settings["Video/Windowed/IntegralScaling"].setValue(windowedModeIntegralScaling.checked()); - settings["Video/Windowed/AdaptiveSizing"].setValue(windowedModeAdaptiveSizing.checked()); + settings["Video/Windowed/Adaptive"].setValue(windowedModeAdaptive.checked()); settings["Video/Fullscreen/AspectCorrection"].setValue(fullscreenModeAspectCorrection.checked()); settings["Video/Fullscreen/IntegralScaling"].setValue(fullscreenModeIntegralScaling.checked()); + settings["Video/Fullscreen/Exclusive"].setValue(fullscreenModeExclusive.checked()); horizontalMaskValue.setText({horizontalMaskSlider.position()}); verticalMaskValue.setText({verticalMaskSlider.position()}); diff --git a/ruby/ruby.cpp b/ruby/ruby.cpp index a54cd2f2..9cfd3d4b 100644 --- a/ruby/ruby.cpp +++ b/ruby/ruby.cpp @@ -72,14 +72,15 @@ using namespace ruby; namespace ruby { +const string Video::Exclusive = "Exclusive"; const string Video::Handle = "Handle"; const string Video::Synchronize = "Synchronize"; const string Video::Depth = "Depth"; const string Video::Filter = "Filter"; const string Video::Shader = "Shader"; -const unsigned Video::FilterNearest = 0; -const unsigned Video::FilterLinear = 1; +const uint Video::FilterNearest = 0; +const uint Video::FilterLinear = 1; auto Video::create(const string& driver) -> Video* { if(!driver) return create(optimalDriver()); @@ -89,11 +90,11 @@ auto Video::create(const string& driver) -> Video* { #endif #if defined(VIDEO_DIRECT3D) - if(driver == "Direct3D") return new VideoD3D; + if(driver == "Direct3D") return new VideoDirect3D; #endif #if defined(VIDEO_DIRECTDRAW) - if(driver == "DirectDraw") return new VideoDD; + if(driver == "DirectDraw") return new VideoDirectDraw; #endif #if defined(VIDEO_GDI) diff --git a/ruby/ruby.hpp b/ruby/ruby.hpp index 5b2fffb2..dd66d8fc 100644 --- a/ruby/ruby.hpp +++ b/ruby/ruby.hpp @@ -3,7 +3,7 @@ /* ruby * author: byuu * license: ISC - * version: 0.15 (2016-04-18) + * version: 0.16 (2017-07-08) * * ruby is a cross-platform hardware abstraction layer. * it provides a common interface to video, audio and input devices. @@ -14,14 +14,15 @@ namespace ruby { struct Video { + static const nall::string Exclusive; static const nall::string Handle; static const nall::string Synchronize; static const nall::string Depth; static const nall::string Filter; static const nall::string Shader; - static const unsigned FilterNearest; - static const unsigned FilterLinear; + static const uint FilterNearest; + static const uint FilterLinear; static auto create(const nall::string& driver = "") -> Video*; static auto optimalDriver() -> nall::string; @@ -34,7 +35,7 @@ struct Video { virtual auto get(const nall::string& name) -> nall::any { return false; } virtual auto set(const nall::string& name, const nall::any& value) -> bool { return false; } - virtual auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool { return false; } + virtual auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool { return false; } virtual auto unlock() -> void {} virtual auto clear() -> void {} virtual auto refresh() -> void {} @@ -96,13 +97,13 @@ struct Input { virtual auto init() -> bool { return true; } virtual auto term() -> void {} - auto onChange(const nall::function, unsigned, unsigned, int16_t, int16_t)>& callback) { _onChange = callback; } - auto doChange(nall::shared_pointer device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) -> void { + auto onChange(const nall::function, uint, uint, int16_t, int16_t)>& callback) { _onChange = callback; } + auto doChange(nall::shared_pointer device, uint group, uint input, int16_t oldValue, int16_t newValue) -> void { if(_onChange) _onChange(device, group, input, oldValue, newValue); } private: - nall::function device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue)> _onChange; + nall::function device, uint group, uint input, int16_t oldValue, int16_t newValue)> _onChange; }; } diff --git a/ruby/video/direct3d.cpp b/ruby/video/direct3d.cpp index 4567f051..3f42c8cb 100644 --- a/ruby/video/direct3d.cpp +++ b/ruby/video/direct3d.cpp @@ -1,67 +1,87 @@ #undef interface #define interface struct #include -#include #undef interface -#define D3DVERTEX (D3DFVF_XYZRHW | D3DFVF_TEX1) +static LRESULT CALLBACK VideoDirect3D_WindowProcedure(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + return DefWindowProc(hwnd, msg, wparam, lparam); +} -typedef HRESULT (__stdcall* EffectProc)(LPDIRECT3DDEVICE9, LPCVOID, UINT, D3DXMACRO const*, LPD3DXINCLUDE, DWORD, LPD3DXEFFECTPOOL, LPD3DXEFFECT*, LPD3DXBUFFER*); -typedef HRESULT (__stdcall* TextureProc)(LPDIRECT3DDEVICE9, LPCTSTR, LPDIRECT3DTEXTURE9*); +struct VideoDirect3D : Video { + VideoDirect3D() { + POINT point = {0, 0}; + HMONITOR monitor = MonitorFromPoint(point, MONITOR_DEFAULTTOPRIMARY); + MONITORINFOEX information = {}; + information.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(monitor, &information); + monitorWidth = information.rcMonitor.right - information.rcMonitor.left; + monitorHeight = information.rcMonitor.bottom - information.rcMonitor.top; -struct VideoD3D : Video { - ~VideoD3D() { term(); } + WNDCLASS windowClass = {}; + windowClass.cbClsExtra = 0; + windowClass.cbWndExtra = 0; + windowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + windowClass.hCursor = LoadCursor(0, IDC_ARROW); + windowClass.hIcon = LoadIcon(nullptr, IDI_APPLICATION); + windowClass.hInstance = GetModuleHandle(0); + windowClass.lpfnWndProc = VideoDirect3D_WindowProcedure; + windowClass.lpszClassName = L"VideoDirect3D_Window"; + windowClass.lpszMenuName = 0; + windowClass.style = CS_HREDRAW | CS_VREDRAW; + RegisterClass(&windowClass); - LPDIRECT3D9 lpd3d = nullptr; - LPDIRECT3DDEVICE9 device = nullptr; - LPDIRECT3DVERTEXBUFFER9 vertex_buffer = nullptr; - LPDIRECT3DVERTEXBUFFER9* vertex_ptr = nullptr; - D3DPRESENT_PARAMETERS presentation; - D3DSURFACE_DESC d3dsd; - D3DLOCKED_RECT d3dlr; - D3DRASTER_STATUS d3drs; - D3DCAPS9 d3dcaps; - LPDIRECT3DTEXTURE9 texture = nullptr; - LPDIRECT3DSURFACE9 surface = nullptr; - LPD3DXEFFECT effect = nullptr; - string shader_source_markup; + settings.exclusiveHandle = CreateWindowEx(WS_EX_TOPMOST, L"VideoDirect3D_Window", L"", WS_POPUP, + information.rcMonitor.left, information.rcMonitor.top, monitorWidth, monitorHeight, + nullptr, nullptr, GetModuleHandle(0), nullptr); + } + + ~VideoDirect3D() { + term(); + DestroyWindow(settings.exclusiveHandle); + } + + LPDIRECT3D9 context = nullptr; + LPDIRECT3DDEVICE9 device = nullptr; + LPDIRECT3DVERTEXBUFFER9 vertexBuffer = nullptr; + D3DPRESENT_PARAMETERS presentation = {}; + D3DCAPS9 capabilities = {}; + LPDIRECT3DTEXTURE9 texture = nullptr; + LPDIRECT3DSURFACE9 surface = nullptr; bool lost = true; - unsigned iwidth; - unsigned iheight; + uint windowWidth; + uint windowHeight; + uint textureWidth; + uint textureHeight; + uint monitorWidth; + uint monitorHeight; - struct d3dvertex { - float x, y, z, rhw; //screen coords - float u, v; //texture coords + struct Vertex { + float x, y, z, rhw; //screen coordinates + float u, v; //texture coordinates }; struct { - uint32_t t_usage, v_usage; - uint32_t t_pool, v_pool; - uint32_t lock; + uint32_t textureUsage; + uint32_t texturePool; + uint32_t vertexUsage; + uint32_t vertexPool; uint32_t filter; } flags; struct { - bool dynamic; //device supports dynamic textures - bool shader; //device supports pixel shaders - } caps; - - struct { + bool exclusive = false; HWND handle = nullptr; bool synchronize = false; - unsigned filter = Video::FilterLinear; + uint filter = Video::FilterLinear; - unsigned width; - unsigned height; + HWND exclusiveHandle = nullptr; + uint width; + uint height; } settings; - struct { - unsigned width; - unsigned height; - } state; - auto cap(const string& name) -> bool { + if(name == Video::Exclusive) return true; if(name == Video::Handle) return true; if(name == Video::Synchronize) return true; if(name == Video::Filter) return true; @@ -70,6 +90,7 @@ struct VideoD3D : Video { } auto get(const string& name) -> any { + if(name == Video::Exclusive) return settings.exclusive; if(name == Video::Handle) return (uintptr_t)settings.handle; if(name == Video::Synchronize) return settings.synchronize; if(name == Video::Filter) return settings.filter; @@ -77,8 +98,14 @@ struct VideoD3D : Video { } auto set(const string& name, const any& value) -> bool { - if(name == Video::Handle && value.is()) { - settings.handle = (HWND)value.get(); + if(name == Video::Exclusive && value.is()) { + settings.exclusive = value.get(); + if(context) init(); + return true; + } + + if(name == Video::Handle && value.is()) { + settings.handle = (HWND)value.get(); return true; } @@ -87,18 +114,12 @@ struct VideoD3D : Video { return true; } - if(name == Video::Filter && value.is()) { - settings.filter = value.get(); - if(lpd3d) update_filter(); + if(name == Video::Filter && value.is()) { + settings.filter = value.get(); + if(context) updateFilter(); return true; } - if(name == Video::Shader && value.is()) { - return false; - //set_shader(value.get()); - //return true; - } - return false; } @@ -106,94 +127,74 @@ struct VideoD3D : Video { if(!device) return false; if(lost) { - release_resources(); + if(vertexBuffer) { vertexBuffer->Release(); vertexBuffer = nullptr; } + if(surface) { surface->Release(); surface = nullptr; } + if(texture) { texture->Release(); texture = nullptr; } if(device->Reset(&presentation) != D3D_OK) return false; } - lost = false; device->SetDialogBoxMode(false); - device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); device->SetRenderState(D3DRS_LIGHTING, false); - device->SetRenderState(D3DRS_ZENABLE, false); + device->SetRenderState(D3DRS_ZENABLE, false); device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); device->SetRenderState(D3DRS_ALPHABLENDENABLE, false); - device->SetVertexShader(NULL); - device->SetFVF(D3DVERTEX); + device->SetVertexShader(nullptr); + device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); - device->CreateVertexBuffer(sizeof(d3dvertex) * 4, flags.v_usage, D3DVERTEX, (D3DPOOL)flags.v_pool, &vertex_buffer, NULL); - iwidth = 0; - iheight = 0; + device->CreateVertexBuffer(sizeof(Vertex) * 4, flags.vertexUsage, D3DFVF_XYZRHW | D3DFVF_TEX1, + (D3DPOOL)flags.vertexPool, &vertexBuffer, nullptr); + textureWidth = 0; + textureHeight = 0; resize(settings.width = 256, settings.height = 256); - update_filter(); + updateFilter(); clear(); return true; } - auto rounded_power_of_two(unsigned n) -> unsigned { - n--; - n |= n >> 1; - n |= n >> 2; - n |= n >> 4; - n |= n >> 8; - n |= n >> 16; - return n + 1; - } + auto resize(uint width, uint height) -> void { + if(textureWidth >= width && textureHeight >= height) return; - auto resize(unsigned width, unsigned height) -> void { - if(iwidth >= width && iheight >= height) return; + textureWidth = bit::round(max(width, textureWidth)); + textureHeight = bit::round(max(height, textureHeight)); - iwidth = rounded_power_of_two(max(width, iwidth )); - iheight = rounded_power_of_two(max(height, iheight)); - - if(d3dcaps.MaxTextureWidth < iwidth || d3dcaps.MaxTextureWidth < iheight) { - //TODO: attempt to handle this more gracefully - return; - } + if(capabilities.MaxTextureWidth < textureWidth || capabilities.MaxTextureWidth < textureHeight) return; if(texture) texture->Release(); - device->CreateTexture(iwidth, iheight, 1, flags.t_usage, D3DFMT_X8R8G8B8, (D3DPOOL)flags.t_pool, &texture, NULL); + device->CreateTexture(textureWidth, textureHeight, 1, flags.textureUsage, D3DFMT_X8R8G8B8, + (D3DPOOL)flags.texturePool, &texture, nullptr); } - auto update_filter() -> void { + auto updateFilter() -> void { if(!device) return; if(lost && !recover()) return; - flags.filter = (settings.filter == Video::FilterNearest ? D3DTEXF_POINT : D3DTEXF_LINEAR); + flags.filter = settings.filter == Video::FilterNearest ? D3DTEXF_POINT : D3DTEXF_LINEAR; device->SetSamplerState(0, D3DSAMP_MINFILTER, flags.filter); device->SetSamplerState(0, D3DSAMP_MAGFILTER, flags.filter); } - // Vertex format: - // - // 0----------1 - // | /| - // | / | - // | / | - // | / | - // | / | - // 2----------3 - // - // (x,y) screen coords, in pixels - // (u,v) texture coords, betweeen 0.0 (top, left) to 1.0 (bottom, right) - auto set_vertex( + //(x,y) screen coordinates, in pixels + //(u,v) texture coordinates, betweeen 0.0 (top, left) to 1.0 (bottom, right) + auto setVertex( uint32_t px, uint32_t py, uint32_t pw, uint32_t ph, uint32_t tw, uint32_t th, uint32_t x, uint32_t y, uint32_t w, uint32_t h ) -> void { - d3dvertex vertex[4]; + Vertex vertex[4]; vertex[0].x = vertex[2].x = (double)(x - 0.5); vertex[1].x = vertex[3].x = (double)(x + w - 0.5); vertex[0].y = vertex[1].y = (double)(y - 0.5); @@ -210,17 +211,19 @@ struct VideoD3D : Video { vertex[0].v = vertex[1].v = (double)(py ) / rh; vertex[2].v = vertex[3].v = (double)(py + h) / rh; - vertex_buffer->Lock(0, sizeof(d3dvertex) * 4, (void**)&vertex_ptr, 0); - memcpy(vertex_ptr, vertex, sizeof(d3dvertex) * 4); - vertex_buffer->Unlock(); + LPDIRECT3DVERTEXBUFFER9* vertexPointer = nullptr; + vertexBuffer->Lock(0, sizeof(Vertex) * 4, (void**)&vertexPointer, 0); + memory::copy(vertexPointer, vertex, sizeof(Vertex) * 4); + vertexBuffer->Unlock(); - device->SetStreamSource(0, vertex_buffer, 0, sizeof(d3dvertex)); + device->SetStreamSource(0, vertexBuffer, 0, sizeof(Vertex)); } auto clear() -> void { if(lost && !recover()) return; - texture->GetLevelDesc(0, &d3dsd); + D3DSURFACE_DESC surfaceDescription; + texture->GetLevelDesc(0, &surfaceDescription); texture->GetSurfaceLevel(0, &surface); if(surface) { @@ -230,25 +233,27 @@ struct VideoD3D : Video { } //clear primary display and all backbuffers - for(unsigned i = 0; i < 3; i++) { + for(uint n : range(3)) { device->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0x00, 0x00, 0x00), 1.0f, 0); device->Present(0, 0, 0, 0); } } - auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool { + auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool { if(lost && !recover()) return false; if(width != settings.width || height != settings.height) { resize(settings.width = width, settings.height = height); } - texture->GetLevelDesc(0, &d3dsd); + D3DSURFACE_DESC surfaceDescription; + texture->GetLevelDesc(0, &surfaceDescription); texture->GetSurfaceLevel(0, &surface); - surface->LockRect(&d3dlr, 0, flags.lock); - pitch = d3dlr.Pitch; - return data = (uint32_t*)d3dlr.pBits; + D3DLOCKED_RECT lockedRectangle; + surface->LockRect(&lockedRectangle, 0, D3DLOCK_NOSYSLOCK | D3DLOCK_DISCARD); + pitch = lockedRectangle.Pitch; + return data = (uint32_t*)lockedRectangle.pBits; } auto unlock() -> void { @@ -260,184 +265,111 @@ struct VideoD3D : Video { auto refresh() -> void { if(lost && !recover()) return; - RECT rd, rs; //dest, source rectangles - GetClientRect(settings.handle, &rd); - SetRect(&rs, 0, 0, settings.width, settings.height); + RECT rectangle; + GetClientRect(settings.handle, &rectangle); //if output size changed, driver must be re-initialized. //failure to do so causes scaling issues on some video drivers. - if(state.width != rd.right || state.height != rd.bottom) { - init(); - set_shader(shader_source_markup); - return; - } - - if(caps.shader && effect) { - device->BeginScene(); - set_vertex(0, 0, settings.width, settings.height, iwidth, iheight, 0, 0, rd.right, rd.bottom); - - D3DXVECTOR4 rubyTextureSize; - rubyTextureSize.x = iwidth; - rubyTextureSize.y = iheight; - rubyTextureSize.z = 1.0 / iheight; - rubyTextureSize.w = 1.0 / iwidth; - effect->SetVector("rubyTextureSize", &rubyTextureSize); - - D3DXVECTOR4 rubyInputSize; - rubyInputSize.x = settings.width; - rubyInputSize.y = settings.height; - rubyInputSize.z = 1.0 / settings.height; - rubyInputSize.w = 1.0 / settings.width; - effect->SetVector("rubyInputSize", &rubyInputSize); - - D3DXVECTOR4 rubyOutputSize; - rubyOutputSize.x = rd.right; - rubyOutputSize.y = rd.bottom; - rubyOutputSize.z = 1.0 / rd.bottom; - rubyOutputSize.w = 1.0 / rd.right; - effect->SetVector("rubyOutputSize", &rubyOutputSize); - - UINT passes; - effect->Begin(&passes, 0); - effect->SetTexture("rubyTexture", texture); - device->SetTexture(0, texture); - for(unsigned pass = 0; pass < passes; pass++) { - effect->BeginPass(pass); - device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); - effect->EndPass(); - } - effect->End(); - device->EndScene(); - } else { - device->BeginScene(); - set_vertex(0, 0, settings.width, settings.height, iwidth, iheight, 0, 0, rd.right, rd.bottom); - device->SetTexture(0, texture); - device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); - device->EndScene(); + if(windowWidth != rectangle.right || windowHeight != rectangle.bottom) init(); + + device->BeginScene(); + uint x = 0, y = 0; + if(settings.exclusive) { + //center output in exclusive mode fullscreen window + x = (monitorWidth - windowWidth) / 2; + y = (monitorHeight - windowHeight) / 2; } + setVertex(0, 0, settings.width, settings.height, textureWidth, textureHeight, x, y, windowWidth, windowHeight); + device->SetTexture(0, texture); + device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + device->EndScene(); if(settings.synchronize) { D3DRASTER_STATUS status; - //wait for a previous vblank to finish, if necessary - while(true) { + while(true) { //wait for a previous vblank to finish, if necessary device->GetRasterStatus(0, &status); - if(status.InVBlank == false) break; + if(!status.InVBlank) break; } - //wait for next vblank to begin - while(true) { + while(true) { //wait for next vblank to begin device->GetRasterStatus(0, &status); - if(status.InVBlank == true) break; + if(status.InVBlank) break; } } if(device->Present(0, 0, 0, 0) == D3DERR_DEVICELOST) lost = true; } - auto set_shader(const char* source) -> void { - if(!caps.shader) return; - - if(effect) { - effect->Release(); - effect = NULL; - } - - if(!source || !*source) { - shader_source_markup = ""; - return; - } - shader_source_markup = source; - - auto document = BML::unserialize(shader_source_markup); - bool is_hlsl = document["shader"]["language"].text() == "HLSL"; - string shader_source = document["shader"]["source"].text(); - if(shader_source == "") return; - - HMODULE d3dx; - for(unsigned i = 0; i < 256; i++) { - char t[256]; - sprintf(t, "d3dx9_%u.dll", i); - d3dx = LoadLibraryW(utf16_t(t)); - if(d3dx) break; - } - if(!d3dx) d3dx = LoadLibraryW(L"d3dx9.dll"); - if(!d3dx) return; - - EffectProc effectProc = (EffectProc)GetProcAddress(d3dx, "D3DXCreateEffect"); - TextureProc textureProc = (TextureProc)GetProcAddress(d3dx, "D3DXCreateTextureFromFileA"); - - LPD3DXBUFFER pBufferErrors = NULL; - effectProc(device, (const void*)shader_source.data(), lstrlenA(shader_source), NULL, NULL, 0, NULL, &effect, &pBufferErrors); - - D3DXHANDLE hTech; - effect->FindNextValidTechnique(NULL, &hTech); - effect->SetTechnique(hTech); - } - auto init() -> bool { - RECT rd; - GetClientRect(settings.handle, &rd); - state.width = rd.right; - state.height = rd.bottom; + term(); - lpd3d = Direct3DCreate9(D3D_SDK_VERSION); - if(!lpd3d) return false; + RECT rectangle; + GetClientRect(settings.handle, &rectangle); + windowWidth = rectangle.right; + windowHeight = rectangle.bottom; - memset(&presentation, 0, sizeof(presentation)); - presentation.Flags = D3DPRESENTFLAG_VIDEO; - presentation.SwapEffect = D3DSWAPEFFECT_FLIP; - presentation.hDeviceWindow = settings.handle; - presentation.BackBufferCount = 1; - presentation.MultiSampleType = D3DMULTISAMPLE_NONE; - presentation.MultiSampleQuality = 0; + context = Direct3DCreate9(D3D_SDK_VERSION); + if(!context) return false; + + memory::fill(&presentation, sizeof(presentation)); + presentation.Flags = D3DPRESENTFLAG_VIDEO; + presentation.SwapEffect = D3DSWAPEFFECT_DISCARD; + presentation.BackBufferCount = 1; + presentation.MultiSampleType = D3DMULTISAMPLE_NONE; + presentation.MultiSampleQuality = 0; presentation.EnableAutoDepthStencil = false; presentation.AutoDepthStencilFormat = D3DFMT_UNKNOWN; - presentation.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - presentation.Windowed = true; - presentation.BackBufferFormat = D3DFMT_UNKNOWN; - presentation.BackBufferWidth = 0; - presentation.BackBufferHeight = 0; + presentation.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - if(lpd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, settings.handle, - D3DCREATE_FPU_PRESERVE | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentation, &device) != D3D_OK) { - return false; + if(!settings.exclusive) { + presentation.hDeviceWindow = settings.handle; + presentation.Windowed = true; + presentation.BackBufferFormat = D3DFMT_UNKNOWN; + presentation.BackBufferWidth = 0; + presentation.BackBufferHeight = 0; + + ShowWindow(settings.exclusiveHandle, SW_HIDE); + if(context->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, settings.handle, + D3DCREATE_FPU_PRESERVE | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentation, &device) != D3D_OK) { + return false; + } + } else { + presentation.hDeviceWindow = settings.exclusiveHandle; + presentation.Windowed = false; + presentation.BackBufferFormat = D3DFMT_X8R8G8B8; + presentation.BackBufferWidth = monitorWidth; + presentation.BackBufferHeight = monitorHeight; + presentation.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; + + ShowWindow(settings.exclusiveHandle, SW_SHOWNORMAL); + if(context->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, settings.exclusiveHandle, + D3DCREATE_FPU_PRESERVE | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentation, &device) != D3D_OK) { + return false; + } } - device->GetDeviceCaps(&d3dcaps); + device->GetDeviceCaps(&capabilities); - caps.dynamic = bool(d3dcaps.Caps2 & D3DCAPS2_DYNAMICTEXTURES); - caps.shader = d3dcaps.PixelShaderVersion > D3DPS_VERSION(1, 4); - - if(caps.dynamic == true) { - flags.t_usage = D3DUSAGE_DYNAMIC; - flags.v_usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC; - flags.t_pool = D3DPOOL_DEFAULT; - flags.v_pool = D3DPOOL_DEFAULT; - flags.lock = D3DLOCK_NOSYSLOCK | D3DLOCK_DISCARD; + if(capabilities.Caps2 & D3DCAPS2_DYNAMICTEXTURES) { + flags.textureUsage = D3DUSAGE_DYNAMIC; + flags.texturePool = D3DPOOL_DEFAULT; + flags.vertexUsage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC; + flags.vertexPool = D3DPOOL_DEFAULT; } else { - flags.t_usage = 0; - flags.v_usage = D3DUSAGE_WRITEONLY; - flags.t_pool = D3DPOOL_MANAGED; - flags.v_pool = D3DPOOL_MANAGED; - flags.lock = D3DLOCK_NOSYSLOCK | D3DLOCK_DISCARD; + flags.textureUsage = 0; + flags.texturePool = D3DPOOL_MANAGED; + flags.vertexUsage = D3DUSAGE_WRITEONLY; + flags.vertexPool = D3DPOOL_MANAGED; } lost = false; - recover(); - return true; - } - - auto release_resources() -> void { - if(effect) { effect->Release(); effect = 0; } - if(vertex_buffer) { vertex_buffer->Release(); vertex_buffer = 0; } - if(surface) { surface->Release(); surface = 0; } - if(texture) { texture->Release(); texture = 0; } + return recover(); } auto term() -> void { - release_resources(); - if(device) { device->Release(); device = 0; } - if(lpd3d) { lpd3d->Release(); lpd3d = 0; } + if(vertexBuffer) { vertexBuffer->Release(); vertexBuffer = nullptr; } + if(surface) { surface->Release(); surface = nullptr; } + if(texture) { texture->Release(); texture = nullptr; } + if(device) { device->Release(); device = nullptr; } + if(context) { context->Release(); context = nullptr; } } }; - -#undef D3DVERTEX diff --git a/ruby/video/directdraw.cpp b/ruby/video/directdraw.cpp index 645153f3..6cdb3f91 100644 --- a/ruby/video/directdraw.cpp +++ b/ruby/video/directdraw.cpp @@ -1,7 +1,7 @@ #include -struct VideoDD : Video { - ~VideoDD() { term(); } +struct VideoDirectDraw : Video { + ~VideoDirectDraw() { term(); } LPDIRECTDRAW lpdd = nullptr; LPDIRECTDRAW7 lpdd7 = nullptr; @@ -10,15 +10,15 @@ struct VideoDD : Video { LPDIRECTDRAWCLIPPER clipper = nullptr; DDSURFACEDESC2 ddsd; DDSCAPS2 ddscaps; - unsigned iwidth; - unsigned iheight; + uint iwidth; + uint iheight; struct { HWND handle = nullptr; bool synchronize = false; - unsigned width; - unsigned height; + uint width; + uint height; } settings; auto cap(const string& name) -> bool { @@ -34,8 +34,8 @@ struct VideoDD : Video { } auto set(const string& name, const any& value) -> bool { - if(name == Video::Handle && value.is()) { - settings.handle = (HWND)value.get(); + if(name == Video::Handle && value.is()) { + settings.handle = (HWND)value.get(); return true; } @@ -47,7 +47,7 @@ struct VideoDD : Video { return false; } - auto resize(unsigned width, unsigned height) -> void { + auto resize(uint width, uint height) -> void { if(iwidth >= width && iheight >= height) return; iwidth = max(width, iwidth); @@ -94,7 +94,7 @@ struct VideoDD : Video { raster->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx); } - auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool { + auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool { if(width != settings.width || height != settings.height) { resize(settings.width = width, settings.height = height); } @@ -136,6 +136,8 @@ struct VideoDD : Video { } auto init() -> bool { + term(); + DirectDrawCreate(0, &lpdd, 0); lpdd->QueryInterface(IID_IDirectDraw7, (void**)&lpdd7); if(lpdd) { lpdd->Release(); lpdd = 0; } diff --git a/ruby/video/gdi.cpp b/ruby/video/gdi.cpp index 530f49cd..3afb811e 100644 --- a/ruby/video/gdi.cpp +++ b/ruby/video/gdi.cpp @@ -28,8 +28,8 @@ struct VideoGDI : Video { } auto set(const string& name, const any& value) -> bool { - if(name == Video::Handle && value.is()) { - settings.handle = (HWND)value.get(); + if(name == Video::Handle && value.is()) { + settings.handle = (HWND)value.get(); return true; } @@ -44,7 +44,7 @@ struct VideoGDI : Video { DeleteObject(device.dc); } settings.buffer = new uint32_t[width * height](); - settings.width = width; + settings.width = width; settings.height = height; HDC hdc = GetDC(settings.handle); @@ -56,13 +56,13 @@ struct VideoGDI : Video { ReleaseDC(settings.handle, hdc); memory::fill(&device.info, sizeof(BITMAPINFO)); - device.info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - device.info.bmiHeader.biWidth = width; - device.info.bmiHeader.biHeight = -height; - device.info.bmiHeader.biPlanes = 1; - device.info.bmiHeader.biBitCount = 32; + device.info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + device.info.bmiHeader.biWidth = width; + device.info.bmiHeader.biHeight = -height; + device.info.bmiHeader.biPlanes = 1; + device.info.bmiHeader.biBitCount = 32; device.info.bmiHeader.biCompression = BI_RGB; - device.info.bmiHeader.biSizeImage = width * height * sizeof(uint32_t); + device.info.bmiHeader.biSizeImage = width * height * sizeof(uint32_t); } data = settings.buffer; diff --git a/ruby/video/glx2.cpp b/ruby/video/glx2.cpp index afe8d282..d9e3b410 100644 --- a/ruby/video/glx2.cpp +++ b/ruby/video/glx2.cpp @@ -6,9 +6,9 @@ struct VideoGLX2 : Video { ~VideoGLX2() { term(); } - auto (*glXSwapInterval)(signed) -> signed = nullptr; + auto (*glXSwapInterval)(int) -> int = nullptr; Display* display = nullptr; - signed screen = 0; + int screen = 0; Window xwindow = 0; Colormap colormap = 0; GLXContext glxcontext = nullptr; @@ -17,10 +17,10 @@ struct VideoGLX2 : Video { struct { Window handle = 0; bool synchronize = false; - unsigned filter = 1; //linear + uint filter = Video::FilterLinear; - unsigned width = 256; - unsigned height = 256; + uint width = 256; + uint height = 256; bool isDoubleBuffered = false; bool isDirect = false; @@ -34,15 +34,15 @@ struct VideoGLX2 : Video { } auto get(const string& name) -> any { - if(name == Video::Handle) return (uintptr_t)settings.handle; + if(name == Video::Handle) return (uintptr)settings.handle; if(name == Video::Synchronize) return settings.synchronize; if(name == Video::Filter) return settings.filter; return {}; } auto set(const string& name, const any& value) -> bool { - if(name == Video::Handle && value.is()) { - settings.handle = value.get(); + if(name == Video::Handle && value.is()) { + settings.handle = value.get(); return true; } @@ -54,15 +54,15 @@ struct VideoGLX2 : Video { } } - if(name == Video::Filter && value.is()) { - settings.filter = value.get(); + if(name == Video::Filter && value.is()) { + settings.filter = value.get(); return true; } return false; } - auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool { + auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool { if(width != settings.width || height != settings.height) resize(width, height); pitch = glwidth * sizeof(uint32_t); return data = glbuffer; @@ -105,8 +105,8 @@ struct VideoGLX2 : Video { double w = (double)settings.width / (double)glwidth; double h = (double)settings.height / (double)glheight; - signed u = parent.width; - signed v = parent.height; + int u = parent.width; + int v = parent.height; glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0, 0); glVertex3i(0, v, 0); @@ -123,14 +123,14 @@ struct VideoGLX2 : Video { display = XOpenDisplay(0); screen = DefaultScreen(display); - signed versionMajor = 0, versionMinor = 0; + int versionMajor = 0, versionMinor = 0; glXQueryVersion(display, &versionMajor, &versionMinor); if(versionMajor < 1 || (versionMajor == 1 && versionMinor < 2)) return false; XWindowAttributes windowAttributes; XGetWindowAttributes(display, settings.handle, &windowAttributes); - signed attributeList[] = { + int attributeList[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DOUBLEBUFFER, True, @@ -140,7 +140,7 @@ struct VideoGLX2 : Video { None }; - signed fbCount = 0; + int fbCount = 0; auto fbConfig = glXChooseFBConfig(display, screen, attributeList, &fbCount); if(fbCount == 0) return false; @@ -163,12 +163,12 @@ struct VideoGLX2 : Video { glxcontext = glXCreateContext(display, vi, 0, GL_TRUE); glXMakeCurrent(display, glxwindow = xwindow, glxcontext); - if(!glXSwapInterval) glXSwapInterval = (signed (*)(signed))glGetProcAddress("glXSwapIntervalMESA"); - if(!glXSwapInterval) glXSwapInterval = (signed (*)(signed))glGetProcAddress("glXSwapIntervalSGI"); + if(!glXSwapInterval) glXSwapInterval = (int (*)(int))glGetProcAddress("glXSwapIntervalMESA"); + if(!glXSwapInterval) glXSwapInterval = (int (*)(int))glGetProcAddress("glXSwapIntervalSGI"); if(glXSwapInterval) glXSwapInterval(settings.synchronize); - signed value = 0; + int value = 0; glXGetConfig(display, vi, GLX_DOUBLEBUFFER, &value); settings.isDoubleBuffered = value; settings.isDirect = glXIsDirect(display, glxcontext); @@ -224,10 +224,10 @@ struct VideoGLX2 : Video { private: GLuint gltexture = 0; uint32_t* glbuffer = nullptr; - unsigned glwidth = 0; - unsigned glheight = 0; + uint glwidth = 0; + uint glheight = 0; - auto resize(unsigned width, unsigned height) -> void { + auto resize(uint width, uint height) -> void { settings.width = width; settings.height = height; diff --git a/ruby/video/sdl.cpp b/ruby/video/sdl.cpp index da335e0b..be74dc0a 100644 --- a/ruby/video/sdl.cpp +++ b/ruby/video/sdl.cpp @@ -11,14 +11,14 @@ struct VideoSDL : Video { Display* display = nullptr; SDL_Surface* screen = nullptr; SDL_Surface* buffer = nullptr; - unsigned iwidth = 0; - unsigned iheight = 0; + uint iwidth = 0; + uint iheight = 0; struct { - uintptr_t handle = 0; + uintptr handle = 0; - unsigned width = 0; - unsigned height = 0; + uint width = 0; + uint height = 0; } settings; auto cap(const string& name) -> bool { @@ -32,15 +32,15 @@ struct VideoSDL : Video { } auto set(const string& name, const any& value) -> bool { - if(name == Video::Handle && value.is()) { - settings.handle = value.get(); + if(name == Video::Handle && value.is()) { + settings.handle = value.get(); return true; } return false; } - auto resize(unsigned width, unsigned height) -> void { + auto resize(uint width, uint height) -> void { if(iwidth >= width && iheight >= height) return; iwidth = max(width, iwidth); @@ -53,7 +53,7 @@ struct VideoSDL : Video { ); } - auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool { + auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool { if(width != settings.width || height != settings.height) { resize(settings.width = width, settings.height = height); } @@ -69,9 +69,9 @@ struct VideoSDL : Video { auto clear() -> void { if(SDL_MUSTLOCK(buffer)) SDL_LockSurface(buffer); - for(unsigned y = 0; y < iheight; y++) { + for(uint y : range(iheight)) { uint32_t* data = (uint32_t*)buffer->pixels + y * (buffer->pitch >> 2); - for(unsigned x = 0; x < iwidth; x++) *data++ = 0xff000000; + for(uint x : range(iwidth)) *data++ = 0xff000000; } if(SDL_MUSTLOCK(buffer)) SDL_UnlockSurface(buffer); refresh(); @@ -82,9 +82,9 @@ struct VideoSDL : Video { //as SDL forces us to use a 32-bit buffer, we must set alpha to 255 (full opacity) //to prevent blending against the window beneath when X window visual is 32-bits. if(SDL_MUSTLOCK(buffer)) SDL_LockSurface(buffer); - for(unsigned y = 0; y < settings.height; y++) { + for(uint y : range(settings.height)) { uint32_t* data = (uint32_t*)buffer->pixels + y * (buffer->pitch >> 2); - for(unsigned x = 0; x < settings.width; x++) *data++ |= 0xff000000; + for(uint x : range(settings.width)) *data++ |= 0xff000000; } if(SDL_MUSTLOCK(buffer)) SDL_UnlockSurface(buffer); @@ -119,8 +119,8 @@ struct VideoSDL : Video { screen = SDL_SetVideoMode(2560, 1600, 32, SDL_HWSURFACE); XUndefineCursor(display, settings.handle); - buffer = 0; - iwidth = 0; + buffer = nullptr; + iwidth = 0; iheight = 0; resize(settings.width = 256, settings.height = 256); diff --git a/ruby/video/wgl.cpp b/ruby/video/wgl.cpp index f556f581..a6c6ffbc 100644 --- a/ruby/video/wgl.cpp +++ b/ruby/video/wgl.cpp @@ -93,10 +93,10 @@ struct VideoWGL : Video, OpenGL { auto init() -> bool { GLuint pixel_format; PIXELFORMATDESCRIPTOR pfd; - memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); - pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + memory::fill(&pfd, sizeof(PIXELFORMATDESCRIPTOR)); + pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; display = GetDC(settings.handle); @@ -117,7 +117,7 @@ struct VideoWGL : Video, OpenGL { }; HGLRC context = wglCreateContextAttribs(display, 0, attributes); if(context) { - wglMakeCurrent(NULL, NULL); + wglMakeCurrent(nullptr, nullptr); wglDeleteContext(wglcontext); wglMakeCurrent(display, wglcontext = context); }