Batch #897 by ragnarok-clanker: 1 byte-identical, 0 confirmed by peer review. - fn_01907 DeviceOwnerDX9Noop: byte-identical Merged automatically: every function is byte-identical to the original.
280 lines
7.8 KiB
C++
280 lines
7.8 KiB
C++
#include "Render/DX9/DeviceOwnerDX9.h"
|
|
|
|
#include <cstring>
|
|
|
|
namespace {
|
|
constexpr HRESULT invalidDevice = static_cast<HRESULT>(0x8200000Eu);
|
|
constexpr HRESULT deviceError = static_cast<HRESULT>(0x82000000u);
|
|
}
|
|
|
|
struct DisplayModeSelectorDX9 {
|
|
/* 0000 */ const D3DFORMAT& format;
|
|
/* 0004 */ DeviceOwnerDX9* owner;
|
|
/* 0008 */ const UINT& adapter;
|
|
/* 000C */ const UINT& width;
|
|
/* 0010 */ const UINT& height;
|
|
|
|
bool Select(D3DSCANLINEORDERING ordering);
|
|
};
|
|
|
|
// OFFSET: 0x0054B7C0
|
|
// FUNCTION: fn_01906
|
|
DeviceOwnerDX9::DeviceOwnerDX9() {
|
|
this->adapter = 0;
|
|
this->window = nullptr;
|
|
this->direct3D = nullptr;
|
|
this->device = nullptr;
|
|
std::memset(&this->presentation, 0, sizeof(this->presentation) + sizeof(this->displayMode) + sizeof(this->backBufferDescription) + sizeof(this->caps));
|
|
this->backBuffer = nullptr;
|
|
this->capturedBackBuffer = nullptr;
|
|
this->dynamicTextures = false;
|
|
this->lastPresent = 0;
|
|
}
|
|
|
|
// FUNCTION: fn_01907
|
|
void DeviceOwnerDX9Noop() {}
|
|
|
|
// OFFSET: 0x0054B840
|
|
// FUNCTION: fn_01908
|
|
bool DisplayModeSelectorDX9::Select(D3DSCANLINEORDERING ordering) {
|
|
D3DDISPLAYMODEFILTER filter{sizeof(filter), format, ordering};
|
|
const UINT count = this->owner->direct3D->GetAdapterModeCountEx(this->adapter, &filter);
|
|
UINT refresh = 0;
|
|
|
|
for (UINT index = 0; index < count; ++index) {
|
|
D3DDISPLAYMODEEX mode{};
|
|
mode.Size = sizeof(mode);
|
|
|
|
if (SUCCEEDED(this->owner->direct3D->EnumAdapterModesEx(this->adapter, &filter, index, &mode)) && mode.Width == this->width &&
|
|
mode.Height == this->height && mode.RefreshRate >= refresh) {
|
|
refresh = mode.RefreshRate;
|
|
this->owner->displayMode = mode;
|
|
}
|
|
}
|
|
|
|
return refresh != 0;
|
|
}
|
|
|
|
// OFFSET: 0x0054B980
|
|
// FUNCTION: fn_01910
|
|
UINT* DeviceOwnerDX9::AdjustTextureDimensions(UINT* output, UINT width, UINT height) const {
|
|
const auto roundUp = [](UINT value) {
|
|
--value;
|
|
value |= value >> 1;
|
|
value |= value >> 2;
|
|
value |= value >> 4;
|
|
value |= value >> 8;
|
|
value |= value >> 16;
|
|
++value;
|
|
|
|
return value + (value == 0);
|
|
};
|
|
|
|
UINT adjustedWidth = roundUp(width);
|
|
UINT adjustedHeight = roundUp(height);
|
|
const DWORD ratio = this->caps.MaxTextureAspectRatio;
|
|
|
|
if (this->caps.MaxTextureWidth < adjustedWidth) {
|
|
adjustedWidth = this->caps.MaxTextureWidth;
|
|
}
|
|
|
|
if (this->caps.MaxTextureHeight < adjustedHeight) {
|
|
adjustedHeight = this->caps.MaxTextureHeight;
|
|
}
|
|
|
|
if (ratio != 0) {
|
|
if (adjustedWidth / adjustedHeight > ratio) {
|
|
adjustedHeight = adjustedWidth / ratio;
|
|
}
|
|
|
|
if (adjustedHeight / adjustedWidth > ratio) {
|
|
adjustedWidth = adjustedHeight / ratio;
|
|
}
|
|
}
|
|
|
|
output[0] = adjustedWidth;
|
|
output[1] = adjustedHeight;
|
|
return output;
|
|
}
|
|
|
|
// OFFSET: 0x0054BD10
|
|
// FUNCTION: fn_01914
|
|
HRESULT DeviceOwnerDX9::CreateDevice(UINT selectedAdapter, const DeviceOptionsDX9& options) {
|
|
HRESULT result = Direct3DCreate9Ex(D3D_SDK_VERSION, &this->direct3D);
|
|
|
|
if (FAILED(result)) {
|
|
return result;
|
|
}
|
|
|
|
this->adapter = selectedAdapter;
|
|
UINT width = options.width;
|
|
UINT height = options.height;
|
|
|
|
if (options.fullscreen == 0) {
|
|
RECT rectangle;
|
|
GetClientRect(this->window, &rectangle);
|
|
width = rectangle.right - rectangle.left;
|
|
height = rectangle.bottom - rectangle.top;
|
|
}
|
|
|
|
this->presentation = {};
|
|
this->presentation.BackBufferWidth = width;
|
|
this->presentation.BackBufferHeight = height;
|
|
this->presentation.BackBufferFormat = D3DFMT_X8R8G8B8;
|
|
this->presentation.BackBufferCount = 1;
|
|
this->presentation.MultiSampleType = D3DMULTISAMPLE_NONE;
|
|
this->presentation.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
|
this->presentation.hDeviceWindow = this->window;
|
|
this->presentation.Windowed = options.fullscreen == 0;
|
|
this->presentation.EnableAutoDepthStencil = TRUE;
|
|
this->presentation.AutoDepthStencilFormat = D3DFMT_D24S8;
|
|
this->presentation.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER | D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
|
|
|
|
if (!this->presentation.Windowed) {
|
|
const D3DFORMAT format = D3DFMT_X8R8G8B8;
|
|
DisplayModeSelectorDX9 selectMode{format, this, selectedAdapter, width, height};
|
|
if (!selectMode.Select(D3DSCANLINEORDERING_PROGRESSIVE) && !selectMode.Select(D3DSCANLINEORDERING_INTERLACED)) {
|
|
D3DDISPLAYMODEEX mode{};
|
|
mode.Size = sizeof(mode);
|
|
D3DDISPLAYROTATION rotation = D3DDISPLAYROTATION_IDENTITY;
|
|
|
|
if (FAILED(this->direct3D->GetAdapterDisplayModeEx(selectedAdapter, &mode, &rotation))) {
|
|
return deviceError;
|
|
}
|
|
|
|
this->displayMode = mode;
|
|
}
|
|
|
|
this->presentation.BackBufferWidth = this->displayMode.Width;
|
|
this->presentation.BackBufferHeight = this->displayMode.Height;
|
|
this->presentation.FullScreen_RefreshRateInHz = this->displayMode.RefreshRate;
|
|
}
|
|
|
|
result = this->direct3D->CreateDeviceEx(
|
|
selectedAdapter, D3DDEVTYPE_HAL, this->window, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &this->presentation,
|
|
this->presentation.Windowed ? nullptr : &this->displayMode, &this->device
|
|
);
|
|
|
|
if (FAILED(result)) {
|
|
return static_cast<HRESULT>(0x82000004u);
|
|
}
|
|
|
|
if (FAILED(this->AcquireBackBuffer())) {
|
|
return static_cast<HRESULT>(0x8200000Au);
|
|
}
|
|
|
|
if (FAILED(this->device->GetDeviceCaps(&this->caps))) {
|
|
return deviceError;
|
|
}
|
|
|
|
return D3D_OK;
|
|
}
|
|
|
|
// OFFSET: 0x0054B920
|
|
// FUNCTION: fn_01909
|
|
HRESULT DeviceOwnerDX9::AcquireBackBuffer() {
|
|
IDirect3DSurface9* surface = nullptr;
|
|
HRESULT result = this->device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
|
|
|
|
if (FAILED(result)) {
|
|
return result;
|
|
}
|
|
|
|
result = surface->GetDesc(&this->backBufferDescription);
|
|
|
|
if (FAILED(result)) {
|
|
return result;
|
|
}
|
|
|
|
if (this->backBuffer) {
|
|
this->backBuffer->Release();
|
|
}
|
|
|
|
this->backBuffer = surface;
|
|
return D3D_OK;
|
|
}
|
|
|
|
// OFFSET: 0x0054C140
|
|
// FUNCTION: fn_01918
|
|
HRESULT DeviceOwnerDX9::Initialize(HWND value, UINT selectedAdapter, const DeviceOptionsDX9& options) {
|
|
if (!value) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
this->window = value;
|
|
const HRESULT result = this->CreateDevice(selectedAdapter, options);
|
|
|
|
if (FAILED(result)) {
|
|
this->Close();
|
|
return result;
|
|
}
|
|
|
|
this->state.Initialize(this->device);
|
|
this->state.SetInitialStates();
|
|
this->dynamicTextures = (this->caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0 && options.dynamicTextures != 0;
|
|
this->ClipFullscreenCursor();
|
|
|
|
return D3D_OK;
|
|
}
|
|
|
|
// OFFSET: 0x0054BFA0
|
|
// FUNCTION: fn_01915
|
|
HRESULT DeviceOwnerDX9::Close() {
|
|
if (this->backBuffer) {
|
|
this->backBuffer->Release();
|
|
this->backBuffer = nullptr;
|
|
}
|
|
|
|
if (this->capturedBackBuffer) {
|
|
this->capturedBackBuffer->Release();
|
|
this->capturedBackBuffer = nullptr;
|
|
}
|
|
|
|
ULONG references = 0;
|
|
|
|
if (this->device) {
|
|
references = this->device->Release();
|
|
this->device = nullptr;
|
|
}
|
|
|
|
if (this->direct3D) {
|
|
this->direct3D->Release();
|
|
this->direct3D = nullptr;
|
|
}
|
|
|
|
return references != 0 ? static_cast<HRESULT>(0x8200000Bu) : D3D_OK;
|
|
}
|
|
|
|
// OFFSET: 0x0054C490
|
|
// FUNCTION: fn_01920
|
|
HRESULT DeviceOwnerDX9::ClipFullscreenCursor() {
|
|
if (!this->presentation.Windowed) {
|
|
RECT rectangle;
|
|
GetWindowRect(this->window, &rectangle);
|
|
ClipCursor(&rectangle);
|
|
}
|
|
|
|
return D3D_OK;
|
|
}
|
|
|
|
// OFFSET: 0x0054C510
|
|
// FUNCTION: fn_01921
|
|
HRESULT DeviceOwnerDX9::Present(int) {
|
|
if (!this->device) {
|
|
return invalidDevice;
|
|
}
|
|
|
|
this->lastPresent = this->device->Present(nullptr, nullptr, nullptr, nullptr);
|
|
return this->lastPresent;
|
|
}
|
|
|
|
SurfaceDX9Context DeviceOwnerDX9::SurfaceContext() const {
|
|
return {this->device, this->backBufferDescription, this->backBuffer};
|
|
}
|
|
|
|
TextureDX9Context DeviceOwnerDX9::TextureContext(
|
|
D3DX9Runtime& d3dx, RenderPrimitivePool& primitives, RenderQueues& queues, bool depthAlpha, float depthStart, float depthEnd
|
|
) const {
|
|
return {this->direct3D, this->device, this->adapter, this->presentation.BackBufferFormat, this->caps, this->dynamicTextures, &d3dx, &primitives, &queues,
|
|
depthAlpha, depthStart, depthEnd};
|
|
}
|