Jump to content
  • Advertisement
Sign in to follow this  
LordAndy

DirectX draw after minimize

This topic is 2570 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys,

I'm new in this programming area, I just start using DX and run some simple example until I can fully understand how all things work. My first example doesn't makes many things, just rotate a blue triangle on the screen:
#include "stdafx.h"
#include "DirectX_Test.h"
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>

#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void InitD3D(HWND hWnd);
void RenderD3D(void);
void ReleaseD3D(void);
void InitGfx(void);

LPDIRECT3D9 d3dInterface;
LPDIRECT3DDEVICE9 d3dDevice;
LPDIRECT3DVERTEXBUFFER9 VertexBuffer = NULL;

struct CUSTOMVERTEX {FLOAT X, Y, Z; DWORD COLOR;};
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)
#define W 1024
#define H 768

int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wndClass;
ZeroMemory(&wndClass, sizeof(WNDCLASSEX));
wndClass.hbrBackground = (HBRUSH)COLOR_WINDOW;
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WindowProc;
wndClass.hInstance = hInstance;
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.lpszClassName = L"WindowClass";
RegisterClassEx(&wndClass);
hWnd = CreateWindowEx(NULL, L"WindowClass", L"DirectX Example",
WS_EX_TOPMOST | WS_POPUP, 0, 0, W, H,
NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);

MSG msg;
InitD3D(hWnd);
while(TRUE)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

if(msg.message == WM_QUIT)
break;

RenderD3D();
}
ReleaseD3D();
return msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
{
PostQuitMessage(0);
return 0;
} break;
}

return DefWindowProc (hWnd, message, wParam, lParam);
}

void InitD3D(HWND hWnd)
{
D3DPRESENT_PARAMETERS d3dParams;
ZeroMemory(&d3dParams, sizeof(d3dParams));
d3dParams.Windowed = FALSE;
d3dParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dParams.hDeviceWindow = hWnd;
d3dParams.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dParams.BackBufferWidth = W;
d3dParams.BackBufferHeight = H;

d3dInterface = Direct3DCreate9(D3D_SDK_VERSION);
d3dInterface->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dParams,
&d3dDevice);

InitGfx();

d3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
}

void RenderD3D(void)
{
d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(64, 128, 255), 1.0f, 0);
d3dDevice->BeginScene();
d3dDevice->SetFVF(CUSTOMFVF);

D3DXMATRIX RotateZ;
static float index = 0.0f; index+=0.025f;
D3DXMatrixRotationZ(&RotateZ, index);
d3dDevice->SetTransform(D3DTS_WORLD, &RotateZ);

D3DXMATRIX View;
D3DXMatrixLookAtLH(&View,
&D3DXVECTOR3 (0.0f, 0.0f, 10.0f),
&D3DXVECTOR3 (0.0f, 0.0f, 0.0f),
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f));
d3dDevice->SetTransform(D3DTS_VIEW, &View);

D3DXMATRIX Trans;
D3DXMatrixPerspectiveFovLH(&Trans,
D3DXToRadian(60),
(FLOAT)W / (FLOAT)H,
1.0f,
100.0f);
d3dDevice->SetTransform(D3DTS_PROJECTION, &Trans);

d3dDevice->SetStreamSource(0, VertexBuffer, 0, sizeof(CUSTOMVERTEX));

d3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);

d3dDevice->EndScene();

d3dDevice->Present(NULL, NULL, NULL, NULL);
}

void ReleaseD3D(void)
{
VertexBuffer->Release();
d3dDevice->Release();
d3dInterface->Release();
}


void InitGfx(void)
{
CUSTOMVERTEX vertices[] =
{
{ 3.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 128), },
{ 0.0f, 3.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 128), },
{ -3.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 128), },
};

d3dDevice->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&VertexBuffer,
NULL);

VOID* pVoid;

VertexBuffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, vertices, sizeof(vertices));
VertexBuffer->Unlock();
}

Until now all are good. The application run in full screen mode but if the user press Window key this app go minimize and after restore things gone. How can I fix this? Should I look up for messages like WM_PAINT or WM_NCPAINT and then redraw the scene? And another question: if you look at the triangle seems to appear like in slow motion with some visual effects, can this be fixed and how? I'm sorry if this questions are stupids, as I said I`m beginner with DX and game programming.

Thanks!

Share this post


Link to post
Share on other sites
Advertisement
When the application is deactivated, the rendering device gets lost. You have to reset it manually.

So basically when a device is lost, you have to follow these steps:


Step 1:
- Call OnLostDevice() for all the DX interfaces you might be using. Such as ID3DXFONT, ID3DXSPRITE, etc..
- Release all non-managed resources (Vertex buffers, index buffers, textures...)

In the link i gave you Step 1 is done in the OnLostDevice() function (not implemented by the author)

Step 2:
- Reset the device

D3dDevice->reset(&D3d_present_params);

Step 3:
- Call OnResetDevice() for all the DX interfaces
- Recreate your non-managed resources

Again, this is done in the OnResetDevice() in the link.

As for the visual artifacts, i'm not sure what you're talking about. If you mean the blurring around the edges that's just because the triangle is rotating. Try slowing the rotation and the blurring will go away. Or maybe you're referring to the jagged edges/Aliasing?

Share this post


Link to post
Share on other sites
Thanks guys, I changed a little my intial code to be more practical:
#include "stdafx.h"
#include "DirectX_Test.h"
#include "windows.h"
#include "windowsx.h"
#include "d3d9.h"
#include "d3dx9.h"

#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void InitD3D(HWND hWnd);
void RenderD3D(void);
void ReleaseD3D(void);
void InitGfx(void);

LPDIRECT3D9 d3dInterface;
LPDIRECT3DDEVICE9 d3dDevice;
LPDIRECT3DVERTEXBUFFER9 VertexBuffer = NULL;
D3DPRESENT_PARAMETERS d3dParams;

struct CUSTOMVERTEX {FLOAT X, Y, Z; DWORD COLOR;};
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)
#define W 1024
#define H 768

int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wndClass;
ZeroMemory(&wndClass, sizeof(WNDCLASSEX));
wndClass.hbrBackground = (HBRUSH)COLOR_WINDOW;
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WindowProc;
wndClass.hInstance = hInstance;
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.lpszClassName = L"WindowClass";
RegisterClassEx(&wndClass);
hWnd = CreateWindowEx(NULL, L"WindowClass", L"DirectX Example",
WS_EX_TOPMOST | WS_POPUP, 0, 0, W, H,
NULL, NULL, hInstance, NULL);

MSG msg;
InitD3D(hWnd);
ShowWindow(hWnd, nCmdShow);
while(TRUE)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

if(msg.message == WM_QUIT)
break;
if (d3dDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
{
VertexBuffer->Release();
d3dDevice->Reset(&d3dParams);
InitGfx();
}
RenderD3D();
SleepEx(10,TRUE);
}
ReleaseD3D();
return msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
{
PostQuitMessage(0);
return 0;
} break;
}

return DefWindowProc (hWnd, message, wParam, lParam);
}

void InitD3D(HWND hWnd)
{
ZeroMemory(&d3dParams, sizeof(d3dParams));
d3dParams.Windowed = FALSE;
d3dParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dParams.hDeviceWindow = hWnd;
d3dParams.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dParams.BackBufferWidth = W;
d3dParams.BackBufferHeight = H;

d3dInterface = Direct3DCreate9(D3D_SDK_VERSION);
d3dInterface->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dParams,
&d3dDevice);

InitGfx();
}

void RenderD3D(void)
{
d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(64, 128, 255), 1.0f, 0);
d3dDevice->BeginScene();
d3dDevice->SetFVF(CUSTOMFVF);

D3DXMATRIX RotateZ;
static float index = 0.0f; index+=0.025f;
D3DXMatrixRotationZ(&RotateZ, index);
d3dDevice->SetTransform(D3DTS_WORLD, &RotateZ);

D3DXMATRIX View;
D3DXMatrixLookAtLH(&View,
&D3DXVECTOR3 (0.0f, 0.0f, 10.0f),
&D3DXVECTOR3 (0.0f, 0.0f, 0.0f),
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f));
d3dDevice->SetTransform(D3DTS_VIEW, &View);

D3DXMATRIX Trans;
D3DXMatrixPerspectiveFovLH(&Trans,
D3DXToRadian(60),
(FLOAT)W / (FLOAT)H,
1.0f,
100.0f);
d3dDevice->SetTransform(D3DTS_PROJECTION, &Trans);

d3dDevice->SetStreamSource(0, VertexBuffer, 0, sizeof(CUSTOMVERTEX));

d3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);

d3dDevice->EndScene();

d3dDevice->Present(NULL, NULL, NULL, NULL);
}

void ReleaseD3D(void)
{
VertexBuffer->Release();
d3dDevice->Release();
d3dInterface->Release();
}


void InitGfx(void)
{
CUSTOMVERTEX vertices[] =
{
{ 3.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 128), },
{ 0.0f, 3.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 128), },
{ -3.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 128), },
};

d3dDevice->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&VertexBuffer,
NULL);

VOID* pVoid;

VertexBuffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, vertices, sizeof(vertices));
VertexBuffer->Unlock();
d3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
}

The part of code where I added TestCooperativeLevel is in main loop, is this the proper way, or I shouldn't check this so many time?

Share this post


Link to post
Share on other sites
It'll work in the main loop, but alternatively you can check the HRESULT from your Present call for a D3DERR_DEVICELOST. There are a few other calls that will also return D3DERR_DEVICELOST, but in practice Present is sufficient.

Incidentally, you shouldn't really Release, Reset and recreate straight away as the device may still be lost. The return from TestCooperativeLevel will tell you what you need to do: D3DERR_DEVICELOST means that you do nothing, D3DERR_DEVICENOTRESET means that it's time to Release and Reset, then D3D_OK means that it's time to recreate. That'll give you more robust handling of the loss scenario.

In that scenario TestCooperativeLevel only needs to be called each frame if you've previously got a D3DERR_DEVICELOST from your Present call, and once you get D3D_OK from TCL you can stop testing it.

Share this post


Link to post
Share on other sites
@mhagain something like this?

switch (d3dDevice->TestCooperativeLevel())
{
case D3DERR_DEVICELOST:
break; // Nothing to do
case D3DERR_DEVICENOTRESET:
d3dDevice->Reset(&d3dParams);
d3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
case D3D_OK:
RenderD3D();
}


@Waaayoff thanks for hint

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!