Okay, I´ve debugged it and it is working, just didn´t expect to get a global counter of 143 straight after createDeviceEx!
Using the leak demo, code as below, after createDeviceEx driver counter is 8, and global 143.
After setting up the scene, driver same, global increases to 159.
After running the begin-end scene loop, global increased to 165.
After removeAllTextures global reduces to 158.
So just before the device drop call, the driver has 8 counts, and globally there are 158.
During the device drop operation the global count is reduced to 8, with no further calls to drop.
... a small leak?
Code: Select all
/** Modified Irrlich Example 014 Win32 Window
Leak tester Mk1:
*** This sample can be used to cycle test the Irrlich engine to look for driver or engine memory leaks ***
For Windows 7, 8 or XP.
Compiled and tested on Windows 7 64-bit, with VS 2010, 32-bit output, in debug mode.
NOTE!!! Testing this now with 1.8, a memory leak occurs when the flag to create scene content, bCreateScene, is set to false!
Why should a massive leak occur just because there is no scene content?
Robmar 15/11/2012
***
This example only runs under MS Windows and demonstrates that Irrlicht can
render inside a win32 window. MFC and .NET Windows.Forms windows are possible,
too.
In the beginning, we create a windows window using the windows API. I'm not
going to explain this code, because it is windows specific. See the MSDN or a
windows book for details.
*/
#include <irrlicht.h>
#ifndef _IRR_WINDOWS_
#error Windows only example
#else
#include <windows.h> // this example only runs with windows
#include <iostream>
#include "driverChoice.h"
using namespace irr;
#pragma comment(lib, "irrlicht.lib")
HWND hOKButton;
HWND hWnd;
static LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
HWND hwndCtl = (HWND)lParam;
int code = HIWORD(wParam);
if (hwndCtl == hOKButton)
{
DestroyWindow(hWnd);
PostQuitMessage(0);
return 0;
}
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
/*
Now ask for the driver and create the Windows specific window.
*/
int main()
{
// ask user for driver
video::E_DRIVER_TYPE driverType=driverChoiceConsole();
if (driverType==video::EDT_COUNT)
return 1;
printf("Select the render window (some dead window may exist too):\n"\
" (a) Window with button (via CreationParam)\n"\
" (b) Window with button (via beginScene)\n"\
" (c) Own Irrlicht window (default behavior)\n"\
" (otherKey) exit\n\n");
char key;
std::cin >> key;
if (key != 'a' && key != 'b' && key != 'c')
return 1;
HINSTANCE hInstance = 0;
// create dialog
const char* Win32ClassName = "CIrrlichtWindowsTestDialog";
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)CustomWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = DLGWINDOWEXTRA;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wcex.lpszMenuName = 0;
wcex.lpszClassName = Win32ClassName;
wcex.hIconSm = 0;
RegisterClassEx(&wcex);
DWORD style = WS_SYSMENU | WS_BORDER | WS_CAPTION |
WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX;
int windowWidth = 800;
int windowHeight = 600;
hWnd = CreateWindow( Win32ClassName, "Irrlicht Win32 Leak Test",
style, 100, 100, windowWidth, windowHeight,
NULL, NULL, hInstance, NULL);
RECT clientRect;
GetClientRect(hWnd, &clientRect);
windowWidth = clientRect.right;
windowHeight = clientRect.bottom;
// create ok button
hOKButton = CreateWindow("BUTTON", "OK - Close", WS_CHILD | WS_VISIBLE | BS_TEXT,
windowWidth - 160, windowHeight - 40, 150, 30, hWnd, NULL, hInstance, NULL);
// create some text
CreateWindow("STATIC", "This is Irrlicht running inside a standard Win32 window.\n"\
"Also mixing with MFC and .NET Windows.Forms is possible.",
WS_CHILD | WS_VISIBLE, 20, 20, 400, 40, hWnd, NULL, hInstance, NULL);
// create window to put irrlicht in
HWND hIrrlichtWindow = NULL;
//hIrrlichtWindow = CreateWindow("BUTTON", "",
// WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
// 50, 80, 320, 220, hWnd, NULL, hInstance, NULL);
video::SExposedVideoData videodata((key=='b')?hIrrlichtWindow:0);
// show and execute dialog
ShowWindow(hWnd , SW_SHOW);
UpdateWindow(hWnd);
/*
So now that we have some window, we can create an Irrlicht device
inside of it. We use Irrlicht createEx() function for this. We only
need the handle (HWND) to that window, set it as windowsID parameter
and start up the engine as usual. That's it.
*/
// create irrlicht device in the button window
irr::IrrlichtDevice *device;
irr::video::IVideoDriver * pDriver;
irr::scene::ISceneManager * pSmgr;
irr::SIrrlichtCreationParameters *pParam;
irr::video::SColor sc;
sc.set( 0xff, 0, 0, 0x32 );
// do message queue
/*
Now the only thing missing is the drawing loop using
IrrlichtDevice::run(). We do this as usual. But instead of this, there
is another possibility: You can also simply use your own message loop
using GetMessage, DispatchMessage and whatever. Calling
Device->run() will cause Irrlicht to dispatch messages internally too.
You need not call Device->run() if you want to do your own message
dispatching loop, but Irrlicht will not be able to fetch user input
then and you have to do it on your own using the window messages,
DirectInput, or whatever.
*/
MSG msg;
while (true)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
break;
}
bool bCreateScene = 1;
while ( 1 )
{
int iLoopCycle = 50; // Max loop count
//std::cin >> key; // Run loop un key stroke to monitor resource use step by step
//if ( key == 'x' && key == 'X' )
// return 1;
pParam = new irr::SIrrlichtCreationParameters;
pParam->DriverType = driverType;
if (key=='a')
pParam->WindowId = reinterpret_cast<void*>(hIrrlichtWindow);
pParam->AntiAlias = irr::video::EAAM_LINE_SMOOTH; // 4
pParam->WindowId = reinterpret_cast<void*>(hWnd); // From external CWnd (important as OpenFL driver seems to have a problem when using ext windows)
video::SExposedVideoData videodata( hWnd ); // Structure for holding data describing driver and operating system specific data
pParam->DeviceType = EIDT_WIN32;
pParam->DriverType = video::EDT_OPENGL; // EDT_DIRECT3D9 EDT_DIRECT3D8 EDT_OPENGL
//pParam->DriverType = video::EDT_DIRECT3D9; // EDT_DIRECT3D8 EDT_OPENGL
pParam->Stencilbuffer = true; // Needed for shadows
pParam->Bits = 32;
pParam->Doublebuffer = true; // To avoid drawing artifacts
pParam->Vsync = true; // If set false, shearing may occur
//pParam->Vsync = true; // If set false, shearing may occur
pParam->EventReceiver = NULL;
//pParam->EventReceiver = &receiver; // Crashes logger in debug mode with MFC ex Wnd, and otherwise doesn't work from separate thread!
pParam->WindowSize = core::dimension2d<u32>( 1024, 768 );
pParam->HighPrecisionFPU = true; // MUST BE SET TO AVOID MATHS FAILURES EN COLEDATETIME AND POSSIBLY OTHER MS/MFC FUNCTIONS
pParam->WithAlphaChannel = true;
device = irr::createDeviceEx( *pParam ); // Create 3D engine
if (!device)
return 1;
// Get drivers
pDriver = device->getVideoDriver();
pSmgr = device->getSceneManager();
irr::s32 GlobRefCount1 = pDriver->getGlobalReferenceCount();
int iDRC = pDriver->getReferenceCount();
if ( driverType == video::EDT_OPENGL )
{
// SO WHY IS THIS CODE NEEDED? - wglShareLists : Enables multiple OpenGL rendering contexts to share a single display-list space
HDC HDc=GetDC(hIrrlichtWindow);
PIXELFORMATDESCRIPTOR pfd={0};
pfd.nSize=sizeof(PIXELFORMATDESCRIPTOR);
int pf = GetPixelFormat(HDc);
DescribePixelFormat(HDc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.cDepthBits=16;
pf = ChoosePixelFormat(HDc, &pfd);
SetPixelFormat(HDc, pf, &pfd);
videodata.OpenGLWin32.HDc = HDc;
videodata.OpenGLWin32.HRc=wglCreateContext(HDc);
wglShareLists((HGLRC)pDriver->getExposedVideoData().OpenGLWin32.HRc, (HGLRC)videodata.OpenGLWin32.HRc);
}
device->setResizable( true ); // Window is resizeable
pDriver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, TRUE);
pDriver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, TRUE);
pDriver->setTextureCreationFlag(video::ETCF_NO_ALPHA_CHANNEL, FALSE); // Use alpha
if ( !pDriver->queryFeature( video::EVDF_TEXTURE_NPOT ) ) // If non power-2 supported, allow // NOTE: ALWAYS ADJUST TO REDUCE CPU OVERHEAD
pDriver->setTextureCreationFlag( video::ETCF_ALLOW_NON_POWER_2 );
// advance virtual time
device->getTimer()->tick();
if ( bCreateScene )
{
scene::ICameraSceneNode* cam = pSmgr->addCameraSceneNode();
cam->setTarget(core::vector3df(0,0,0));
scene::ISceneNodeAnimator* anim =
pSmgr->createFlyCircleAnimator(core::vector3df(0,15,0), 30.0f);
cam->addAnimator(anim);
anim->drop();
scene::ISceneNode* cube = pSmgr->addCubeSceneNode(20);
cube->setMaterialTexture(0, pDriver->getTexture("../../media/wall.bmp"));
cube->setMaterialTexture(1, pDriver->getTexture("../../media/water.jpg"));
cube->setMaterialFlag( video::EMF_LIGHTING, false );
cube->setMaterialType( video::EMT_REFLECTION_2_LAYER );
}
irr::s32 GlobRefCount2 = pDriver->getGlobalReferenceCount();
int iDRC2 = pDriver->getReferenceCount();
while ( device->run() && iLoopCycle-- )
{
pDriver->beginScene( true, true, sc ); // Call before rendering, clear screen
// pDriver->beginScene( true, true, sc, videodata ); // Call before rendering, clear screen
pSmgr->drawAll();
pDriver->endScene(); // The updated (engine animations only) screen frame now gets presented
Sleep( 1000/50 ); // Maintain cycle rate independent of content loading
}
irr::s32 GlobRefCount3 = pDriver->getGlobalReferenceCount();
int iDRC3 = pDriver->getReferenceCount();
pDriver->removeAllTextures();
irr::s32 GlobRefCount4 = pDriver->getGlobalReferenceCount();
int iDRC4 = pDriver->getReferenceCount();
device->closeDevice();
device->run();
irr::s32 GlobRefCount5 = pDriver->getGlobalReferenceCount();
int iDRC5 = pDriver->getReferenceCount();
device->drop();
if ( pParam )
delete pParam; // Delete and recreate on each loop
}
}
return 0;
}
#endif // if windows
/*
That's it, Irrlicht now runs in your own windows window.
**/