Я новичок в DirectX, и у меня возникла проблема с DX9. Поэтому я хочу написать функцию для моего D3DClass
до ведьмы между полноэкранным и оконным режимом . Мой класс D3D имеет член ID3DXSprite
, который в основном использует функцию рисования. Однако я не могу заставить приложение нормально работать после Reset()
метода. Вот мой код:
void SystemClass::ChangeDisplayMode(bool NewMode)
{
if (NewMode != CurrentMode) // if the new display mode is difference from the current mode
{
CurrentMode = NewMode;
if (CurrentMode==true) // 1 is fullscreen, 0 is none
{
// I have only written the case where the app will change from Windowed to Fullscreen
auto d3d = m_Graphics->m_D3D; // m_D3D is an D3DClass object
auto d3dpp = d3d->m_d3dpp;
auto d3ddev = d3d->m_d3ddev;
auto sprite = d3d->m_sprite;
d3dpp.Windowed = false;
sprite->OnLostDevice();
d3ddev->Reset(&d3dpp); // My Render() will not render when the CheckDevice() doesn't return D3D_OK, which is why after i call this function, my render will never render again leading to the frontbuffer stuck at the frame before i called this function.
sprite->OnResetDevice();
HRESULT result = d3ddev->TestCooperativeLevel();
if (result == D3DERR_DEVICENOTRESET)
{
Debug("Device no reset"); // The debug printed this, i don't know how to handle this
}
}
}
}
Вот мой код, когда я инициализирую D3DClass, который в начале вызывается только один:
bool D3DClass::Initialize(int width, int height, bool fullscreen, HWND hwnd)
{
m_d3d = Direct3DCreate9(D3D_SDK_VERSION);
// Present Parameters
m_d3dpp.Windowed = !fullscreen;
m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
m_d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
m_d3dpp.BackBufferCount = 1;
m_d3dpp.BackBufferWidth = width;
m_d3dpp.BackBufferHeight = height;
m_d3dpp.hDeviceWindow = hwnd;
HRESULT result = D3D_OK;
result = m_d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&m_d3dpp,
&m_d3ddev
);
result = m_d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_backbuffer);
result = D3DXCreateSprite(m_d3ddev, &m_sprite); // I wonder if we need to call this function again after reset as well, tks
if (result != D3D_OK) return false;
return true;
}
Я где-то читал, что мне нужно выпустить все ресурсы до звонка Reset()
но я не знаю как это сделать. Вот моя функция загрузки текстуры:
HRESULT D3DClass::LoadTexture(string filepath, Texture* texture) // Texture is a structure which have 2 members which are `D3DIMAGE_INFO` and `IDirect3DTexture9*`
{
HRESULT result;
result = D3DXGetImageInfoFromFileA(filepath.c_str(), &texture->t_info);
if (result != D3D_OK) return result;
result = D3DXCreateTextureFromFileExA(
m_d3ddev,
filepath.c_str(),
texture->t_info.Width,
texture->t_info.Height,
1,
D3DPOOL_DEFAULT, // If i change this value to D3DPOOL_MANAGED, nothing will be drawn by the sprite, i don't know if it will affect the Reset() method at all
D3DFMT_UNKNOWN,
D3DPOOL_MANAGED,
D3DX_DEFAULT,
D3DX_DEFAULT,
D3DCOLOR_XRGB(255, 0, 255),
&texture->t_info,
NULL,
&texture->t_content
);
return result;
}
РЕДАКТИРОВАТЬ: Больше информации. Это мой способ обработки ошибки в функции Render()
. Я использовал пример кода из здесь .
bool GraphicsClass::Render()
{
bool result;
HRESULT hresult;
hresult = m_D3D->CheckDevice();
switch (hresult)
{
case D3DERR_DEVICELOST:
// If the device is lost and cannot be reset yet, then sleep for a bit and and try again at the next window loop
Sleep(20);
return true; // Stop rendering immediately until device is ready
case D3DERR_DEVICENOTRESET:
m_D3D->OnLostDevice();
m_D3D->m_d3ddev->Reset(&m_D3D->m_d3dpp);
m_D3D->OnResetDevice();
return true; // Stop rendering immediately until device is ready
}
result = m_D3D->BeginScene(0, 0, 0);
result = DrawScene(); // Use the m_sprite to draw in this function
result = m_D3D->EndScene();
return result;
}