Jump to content

  • Log In with Google      Sign In   
  • Create Account

Hedanito

Member Since 04 Aug 2010
Offline Last Active Jan 19 2014 11:01 AM

Topics I've Started

Memory tracer and placement new

26 September 2013 - 08:24 AM

So I have this memory tracer I wrote a while back which has worked perfectly since then.

It works by overwriting new, delete, malloc, etc and a static manager class will keep track of everything

Basically like this:

void* operator new (Core::uintp a_Size, const Core::char8* a_File, Core::uint32 a_Line);
void* operator new[] (Core::uintp a_Size, const Core::char8* a_File, Core::uint32 a_Line);
void operator delete (void *a_Memory, const Core::char8* a_File, Core::uint32 a_Line);
void operator delete[] (void *a_Memory, const Core::char8* a_File, Core::uint32 a_Line);
void operator delete (void *a_Memory);
void operator delete[] (void *a_Memory);

#define malloc(a_Size) MemoryTracer::Malloc(a_Size, __FILE__, __LINE__)
#define realloc(a_Memory, a_Size) MemoryTracer::Realloc(a_Memory, a_Size, __FILE__, __LINE__)
#define calloc(a_Count, a_Size) MemoryTracer::Calloc(a_Count, a_Size, __FILE__, __LINE__)
#define free(a_Memory) MemoryTracer::Free(a_Memory, __FILE__, __LINE__)

#define new new(__FILE__, __LINE__)
#define delete MemoryTracer::SetFreeInfo(__FILE__, __LINE__), delete

This worked fine for pretty much everything, until now.

I am currently writing a container class which has to use placement new.

The #define new new(__FILE__, __LINE__) messes up the placement new syntax.

Another problem is that placement new cannot be overwritten.

 

I am not sure what the best solution is for this problem, so I was hoping you guys could give me some suggestions.

Since the placement new doesn't allocate any memory, the solution does not have to involve the memory tracer.

I just want to keep the syntax as close to normal C++ as possible.


Window Frame causing memory corruption

25 July 2013 - 06:42 AM

So as the title says, I get memory corruptions when I create window frames, specificly when I make the frame visible.

Once I make the window visible, either using the ShowWindow function, or setting the WS_VISIBLE style flag, it somehow corrupts memory, and can cause crashes in classes I used before that.

It doesnt seem to have anything to do with the OpenGL context either.

Everything works perfectly right until I make the window visible.

 

I am no expert in the windows API, so I have no idea what I am doing wrong.

I hope I just forgot to set something somewhere, because this bug has been haunting me for a while.

Or maybe you can give me some tips on tracking down the source of the problem.

 

Window class code:

#include <set>
#include <Windows.h>

#include <GL/GL.h>
#include <GL/wglext.h>

#include "eventmanager.h"

#include "windowflag.h"
#include "window.h"

using namespace Core;
using namespace Base;
using namespace Gfx;
using namespace Wnd;

struct Window::Window_Impl
{
    Window_Impl(Window* a_Window);
    ~Window_Impl();

    bool CreateFrame(const vector2i& a_Position, const vector2i& a_Size, const char8* a_Caption, uint32 a_Flags);
    bool DestroyFrame();

    bool CreateWindowClass();
    bool DestroyWindowClass();

    bool CreateContext(const GraphicsLibrary& a_GraphicsLibrary);

    bool CreateContextOpenGL2(const GraphicsLibrary& a_GraphicsLibrary);
    bool CreateContextOpenGL3(const GraphicsLibrary& a_GraphicsLibrary);
    bool CreateContextOpenGL4(const GraphicsLibrary& a_GraphicsLibrary);

    bool CreateContextDirectX9(const GraphicsLibrary& a_GraphicsLibrary);
    bool CreateContextDirectX10(const GraphicsLibrary& a_GraphicsLibrary);
    bool CreateContextDirectX11(const GraphicsLibrary& a_GraphicsLibrary);

    static LRESULT CALLBACK StaticWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

    RECT CalculateFrameRectangle(const vector2i& a_Position, const vector2i& a_Size, uint32 a_Flags) const;

    DWORD GetStyleFromFlags(uint32 a_Flags) const;
    DWORD GetStyleExFromFlags(uint32 a_Flags) const;

    uint32 GetFlagsFromStyle(DWORD a_Style, DWORD a_StyleEx) const;

    HINSTANCE m_HINSTANCE;
    HWND m_HWND;
    HDC m_HDC;
    HGLRC m_HGLRC;
    
    static std::set<HGLRC> m_HGLRCList;

    Window* m_Window;
    char8 m_CaptionBuffer[0xFF];
    GraphicsLibrary m_GraphicsLibrary;

    static uint32 m_WindowCounter;
    static char8* m_WindowClassName;
};

uint32 Window::Window_Impl::m_WindowCounter = 0;
char8* Window::Window_Impl::m_WindowClassName = 0;
std::set<HGLRC> Window::Window_Impl::m_HGLRCList = std::set<HGLRC>();

Window::Window(const vector2i& a_Position, const vector2i& a_Size, const char8* a_Caption, uint32 a_Flags, const GraphicsLibrary& a_GraphicsLibrary)
{
    Logger::Log(CORE_WINDOW_CHANNEL, VB_INSTANTIATION, "Creating Window...");

    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Creating private implementation...");
    m_Impl = new Window_Impl(this);
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Private implementation created.");

    if (!m_Impl->CreateFrame(a_Position, a_Size, a_Caption, a_Flags))
    {
        Logger::Log(CORE_WINDOW_CHANNEL, VB_INSTANTIATION, "Failed to create Window.");
        return;
    }

    if (!m_Impl->CreateContext(a_GraphicsLibrary))
    {
        Logger::Log(CORE_WINDOW_CHANNEL, VB_INSTANTIATION, "Failed to create Window.");
        return;
    }
    
    Logger::Log(CORE_WINDOW_CHANNEL, VB_INSTANTIATION, "Window created.");
}

Window::~Window()
{
    Logger::Log(CORE_WINDOW_CHANNEL, VB_INSTANTIATION, "Destroying Window...");

    m_Impl->DestroyFrame();

    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Deleting private implementation...");
    delete m_Impl;
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Private implementation deleted.");
    
    Logger::Log(CORE_WINDOW_CHANNEL, VB_INSTANTIATION, "Window destroyed.");
}

vector2i Window::GetPosition() const
{
    if (m_Impl->m_HWND != NULL)
    {
        POINT point;
        point.x = 0;
        point.y = 0;

        if (!ClientToScreen(m_Impl->m_HWND, &point))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to get Window position.", GetLastError());
            return vector2i();
        }

        return vector2i(point.x, point.y);
    }
    else
    {
        return vector2i();
    }
}

vector2i Window::GetSize() const
{
    if (m_Impl->m_HWND != NULL)
    {
        RECT rect;

        if (!GetClientRect(m_Impl->m_HWND, &rect))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to get Window size.", GetLastError());
            return vector2i();
        }

        return vector2i(rect.right - rect.left, rect.bottom - rect.top);
    }
    else
    {
        return vector2i();
    }
}

const char8* Window::GetCaption() const
{
    if (m_Impl->m_HWND != NULL)
    {
        if (GetWindowText(m_Impl->m_HWND, m_Impl->m_CaptionBuffer, 0xFF) == 0)
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to get Window caption.", GetLastError());
            return 0;
        }

        return m_Impl->m_CaptionBuffer;
    }

    return 0;
}

uint32 Window::GetFlags() const
{
    if (m_Impl->m_HWND != NULL)
    {
        LONG style = GetWindowLong(m_Impl->m_HWND, GWL_STYLE);
        LONG exstyle = GetWindowLong(m_Impl->m_HWND, GWL_EXSTYLE);

        return m_Impl->GetFlagsFromStyle(style, exstyle);
    }
    else
    {
        return 0;
    }
}

const GraphicsLibrary& Window::GetGraphicsLibrary() const
{
    return m_Impl->m_GraphicsLibrary;
}

void Window::SetPosition(const vector2i& a_Position)
{
    if (m_Impl->m_HWND != 0)
    {
        RECT rect = m_Impl->CalculateFrameRectangle(a_Position, GetSize(), GetFlags());

        if (!SetWindowPos(m_Impl->m_HWND, 0, rect.left, rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to set Window size.", GetLastError());
        }
    }
}

void Window::SetSize(const vector2i& a_Size)
{
    if (m_Impl->m_HWND != NULL)
    {
        RECT rect = m_Impl->CalculateFrameRectangle(GetPosition(), a_Size, GetFlags());

        if (!SetWindowPos(m_Impl->m_HWND, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to set Window size.", GetLastError());
        }
    }
}

void Window::SetCaption(const char8* a_Caption)
{
    if (m_Impl->m_HWND != NULL)
    {
        if (!SetWindowText(m_Impl->m_HWND, a_Caption))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to set Window caption.", GetLastError());
        }
    }
}

void Window::SetFlags(uint32 a_Flags)
{
    if (m_Impl->m_HWND != NULL)
    {
        vector2i position = GetPosition();
        vector2i size = GetSize();

        SetWindowLong(m_Impl->m_HWND, GWL_STYLE, m_Impl->GetStyleFromFlags(a_Flags));
        SetWindowLong(m_Impl->m_HWND, GWL_EXSTYLE, m_Impl->GetStyleExFromFlags(a_Flags));

        SetPosition(position);
        SetSize(size);

        ShowWindow(m_Impl->m_HWND, SW_SHOW);
        UpdateWindow(m_Impl->m_HWND);
    }
}

void Window::SetAsRenderTarget()
{
    if (m_Impl->m_HWND == NULL)
    {
        return;
    }

    switch (m_Impl->m_GraphicsLibrary.m_Type)
    {
        case GLT_NONE:
        break;

        case GLT_OPENGL:
        if (!wglMakeCurrent(m_Impl->m_HDC, m_Impl->m_HGLRC))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to set Window as target.", GetLastError());
            return;
        }
        break;

        case GLT_DIRECTX:
        #define CORE_COMPILER_MESSAGE "TODO: SetAsTarget DirectX"
        #include "compilermessage.h"
        break;

        default:
        Logger::Error(CORE_WINDOW_CHANNEL, "Failed to set Window as target", "Unknown or unsupported Graphics Library (%i).", m_Impl->m_GraphicsLibrary.m_Type);
        break;
    }
}

void Window::Update()
{
    if (m_Impl->m_HWND == 0)
    {
        return;
    }

    MSG msg;

    while (PeekMessage(&msg, m_Impl->m_HWND, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return;
}

void Window::SwapBuffers()
{
    switch (m_Impl->m_GraphicsLibrary.m_Type)
    {
        case GLT_NONE:
        break;

        case GLT_OPENGL:
        if (!::SwapBuffers(m_Impl->m_HDC))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to swap buffers.", GetLastError());
            return;
        }
        break;

        case GLT_DIRECTX:
        #define CORE_COMPILER_MESSAGE "TODO: implement SwapBuffers for DirectX"
        #include "compilermessage.h"
        break;

        default:
        Logger::Error(CORE_WINDOW_CHANNEL,  "Failed to swap buffers", "Unknown or unsupported Graphics Library (%i).", m_Impl->m_GraphicsLibrary.m_Type);
        break;
    }
}

Window::Window_Impl::Window_Impl(Window* a_Window):
    m_Window(a_Window),
    m_HWND(NULL)
{
    m_HINSTANCE = GetModuleHandle(NULL);
}

Window::Window_Impl::~Window_Impl()
{

}

bool Window::Window_Impl::CreateFrame(const vector2i& a_Position, const vector2i& a_Size, const char8* a_Caption, uint32 a_Flags)
{
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Creating Window frame...");

    if (!CreateWindowClass())
    {
        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Failed to create Window frame.");
        return false;
    }

    RECT rect = CalculateFrameRectangle(a_Position, a_Size, a_Flags);

    m_HWND = CreateWindowEx(GetStyleExFromFlags(a_Flags), m_WindowClassName, a_Caption, GetStyleFromFlags(a_Flags),
                            rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, m_HINSTANCE, this);

    if (m_HWND == NULL)
    {
        Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to create Windows frame.", GetLastError());
        return false;
    }

    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Window frame created.");
    
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Getting device context..");
    m_HDC = GetDC(m_HWND);
    if (m_HDC == NULL)
    {
        Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to get device context.", GetLastError());
        return false;
    }
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Device context received.");
    
    return true;
}

bool Window::Window_Impl::DestroyFrame()
{
    if (m_HWND != NULL)
    {
        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Destroying Window frame...");

        if (!DestroyWindow(m_HWND))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to destroy Window frame", GetLastError());
            return false;
        }

        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Window frame destroyed.");
    }

    return DestroyWindowClass();
}

bool Window::Window_Impl::CreateWindowClass()
{
    if (m_WindowCounter == 0)
    {
        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Creating Window class...");

        const uint32 classnamesize = strlen("windowclass") + 1;

        m_WindowClassName = new char8[classnamesize];
        strcpy_s(m_WindowClassName, classnamesize, "windowclass");

        WNDCLASSEX windowclass;
        memset(&windowclass, 0, sizeof(WNDCLASSEX));

        windowclass.cbSize        = sizeof(WNDCLASSEX);
        windowclass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_GLOBALCLASS;
        windowclass.lpfnWndProc   = StaticWndProc;
        windowclass.hInstance     = m_HINSTANCE;
        windowclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
        windowclass.lpszClassName = m_WindowClassName;

        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Registering Window class...");
        if (!RegisterClassEx(&windowclass))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to register Window class", GetLastError());
            Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Failed to create Window class");
            return false;
        }
        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Window class registered.");

        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Window class created.");
    }

    m_WindowCounter++;

    return true;
}

bool Window::Window_Impl::DestroyWindowClass()
{
    m_WindowCounter--;
    bool result = true;

    if (m_WindowCounter == 0)
    {
        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Destroying Window class...");

        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Unregistering Window class");
        if (UnregisterClass(m_WindowClassName, m_HINSTANCE) == 0)
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to unregister Window class.", GetLastError());

            result = false;
        }
        else
        {
            Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Window class unregistered.");
        }

        delete[] m_WindowClassName;
        m_WindowClassName = 0;

        if (result)
        {
            Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Window class destroyed.");
            return true;
        }
        else
        {
            Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Failed to destroy Window class.");
            return false;
        }
    }

    return true;
}

bool Window::Window_Impl::CreateContext(const GraphicsLibrary& a_GraphicsLibrary)
{
    switch (a_GraphicsLibrary.m_Type)
    {
        case GLT_NONE:
        return true;

        case GLT_OPENGL:
        switch (a_GraphicsLibrary.m_VersionMajor)
        {
            case 4:
            if (CreateContextOpenGL4(a_GraphicsLibrary))
            {
                return true;
            }
            Logger::Warning(CORE_WINDOW_CHANNEL, "Failed to initialize OpenGL 4.x.", "Failed to initialize OpenGL 4.x. Falling back to OpenGL 3.x.");

            case 3:
            if (CreateContextOpenGL3(a_GraphicsLibrary))
            {
                return true;
            }
            Logger::Warning(CORE_WINDOW_CHANNEL, "Failed to initialize OpenGL 3.x.", "Failed to initialize OpenGL 3.x. Falling back to OpenGL 2.x or lower.");

            case 2:
            case 1:
            case 0:
            return CreateContextOpenGL2(a_GraphicsLibrary);

            default:
            Logger::Error(CORE_WINDOW_CHANNEL, "Failed to create OpenGL context.", "Unknown OpenGL version: %i.%i", a_GraphicsLibrary.m_VersionMajor, a_GraphicsLibrary.m_VersionMinor);
            return false;
        }

        case GLT_DIRECTX:
        switch (a_GraphicsLibrary.m_VersionMajor)
        {
            case 11:
            if (CreateContextDirectX11(a_GraphicsLibrary))
            {
                return true;
            }
            Logger::Warning(CORE_WINDOW_CHANNEL, "Failed to initialize DirectX 11.", "Failed to initialize DirectX 11.x. Falling back to DirectX 10.x.");

            case 10:
            if (CreateContextDirectX10(a_GraphicsLibrary))
            {
                return true;
            }
            Logger::Warning(CORE_WINDOW_CHANNEL, "Failed to initialize DirectX 10.", "Failed to initialize DirectX 10.x. Falling back to DirectX 9.x.");

            case 9:
            return CreateContextDirectX9(a_GraphicsLibrary);

            default:
            Logger::Error(CORE_WINDOW_CHANNEL, "Failed to create DirectX context.", "Unknown DirectX version: %i.%i", a_GraphicsLibrary.m_VersionMajor, a_GraphicsLibrary.m_VersionMinor);
            return false;
        }
        break;

        default:
        Logger::Error(CORE_WINDOW_CHANNEL, "Unknown or unsupported Graphics Library. (%i)", "Failed to create context", a_GraphicsLibrary.m_Type);
        return false;
    }
}

bool Window::Window_Impl::CreateContextOpenGL2(const GraphicsLibrary& a_GraphicsLibrary)
{
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Creating OpenGL 2.x or lower context...");
    
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Choosing pixel format...");
    PIXELFORMATDESCRIPTOR pfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        32,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        24,
        8,
        0,
        PFD_MAIN_PLANE,
        0, 0, 0, 0
    };

    int32 pfn = ChoosePixelFormat(m_HDC, &pfd);
    if (pfn == 0)
    {
        Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to create an OpenGL 2.x or lower context", GetLastError());
        return false;
    }
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Pixel format chosen.");

    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Setting pixel format...");
    if (!SetPixelFormat(m_HDC, pfn, &pfd))
    {
        Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to create an OpenGL 2.x or lower context", GetLastError());
        return false;
    }
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Pixel format set.");

    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Creating OpenGL context...");
    m_HGLRC = wglCreateContext(m_HDC);
    if (m_HGLRC == 0)
    {
        Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to create an OpenGL 2.x or lower context", GetLastError());
        return false;
    }
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "OpenGL context created.");

    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Making OpenGL context current...");
    if (!wglMakeCurrent(m_HDC, m_HGLRC))
    {
        Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to create an OpenGL 2.x or lower context", GetLastError());
        return false;
    }
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "OpenGL made current.");

    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "OpenGL %i.%i context created.", a_GraphicsLibrary.m_VersionMajor, a_GraphicsLibrary.m_VersionMinor);

    m_GraphicsLibrary = a_GraphicsLibrary;

    if (m_HGLRCList.size() != 0)
    {
        wglShareLists(*(m_HGLRCList.begin()), m_HGLRC);
    }

    m_HGLRCList.insert(m_HGLRC);

    return true;
}

bool Window::Window_Impl::CreateContextOpenGL3(const GraphicsLibrary& a_GraphicsLibrary)
{
    #define CORE_COMPILER_MESSAGE "TODO: implement Window::Window_Impl::CreateContextOpenGL3"
    #include "compilermessage.h"
    return false;
}

bool Window::Window_Impl::CreateContextOpenGL4(const GraphicsLibrary& a_GraphicsLibrary)
{
    #define CORE_COMPILER_MESSAGE "TODO: implement Window::Window_Impl::CreateContextOpenGL4"
    #include "compilermessage.h"
    return false;
}

bool Window::Window_Impl::CreateContextDirectX9(const GraphicsLibrary& a_GraphicsLibrary)
{
    #define CORE_COMPILER_MESSAGE "TODO: implement Window::Window_Impl::CreateContextDirectX9"
    #include "compilermessage.h"
    return false;
}

bool Window::Window_Impl::CreateContextDirectX10(const GraphicsLibrary& a_GraphicsLibrary)
{
    #define CORE_COMPILER_MESSAGE "TODO: implement Window::Window_Impl::CreateContextDirextX10"
    #include "compilermessage.h"
    return false;
}

bool Window::Window_Impl::CreateContextDirectX11(const GraphicsLibrary& a_GraphicsLibrary)
{
    #define CORE_COMPILER_MESSAGE "TODO: implement Window::Window_Impl::CreateContextDirextX11"
    #include "compilermessage.h"
    return false;
}

LRESULT CALLBACK Window::Window_Impl::StaticWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
    Window_Impl* wnd_impl = NULL;

    if (msg == WM_CREATE)
    {
        wnd_impl = (Window_Impl*)(((LPCREATESTRUCT)lParam)->lpCreateParams);

        #if CORE_PLATFORM_BITS == 32
        SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)wnd_impl);
        #endif

        #if CORE_PLATFORM_BITS == 64
        SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)wnd_impl);
        #endif
    }
    else
    {
        #if CORE_PLATFORM_BITS == 32
        wnd_impl = (Window_Impl*)GetWindowLongPtr(hwnd, GWL_USERDATA);
        #endif

        #if CORE_PLATFORM_BITS == 64
        wnd_impl = (Window_Impl*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
        #endif

        if (!wnd_impl)
        {
            return DefWindowProc(hwnd, msg, wParam, lParam);    
        }
    }

    return wnd_impl->WndProc(hwnd, msg, wParam, lParam);
}

LRESULT CALLBACK Window::Window_Impl::WndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_SIZE:
        EventManager::Event("window", "resize", m_Window);
        break;
        
        case WM_MOVE:
        EventManager::Event("window", "move", m_Window);
        break;

        case WM_CLOSE:
        EventManager::Event("window", "close", m_Window);
        return 0;

        case WM_INPUT:
        EventManager::Event("window", "input", ((HRAWINPUT)lParam));
        break;
    }

    return DefWindowProc(hwnd, msg, wParam, lParam);
}

RECT Window::Window_Impl::CalculateFrameRectangle(const vector2i& a_Position, const vector2i& a_Size, uint32 a_Flags) const
{
    RECT rect;
    rect.left = a_Position.x;
    rect.top = a_Position.y;
    rect.right = a_Position.x + a_Size.x;
    rect.bottom = a_Position.y + a_Size.y;

    if (!AdjustWindowRectEx(&rect, GetStyleFromFlags(a_Flags), false, GetStyleExFromFlags(a_Flags)))
    {
        Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to adjust window rect.", GetLastError());
    }

    return rect;
}

DWORD Window::Window_Impl::GetStyleFromFlags(uint32 a_Flags) const
{
    DWORD style = WS_VISIBLE;

    if ((a_Flags & WF_NOFRAME) != 0)
    {
        style |= WS_POPUP;
    }

    if ((a_Flags & WF_RESIZE) != 0)
    {
        style |= WS_MAXIMIZEBOX;
        style |= WS_THICKFRAME;
    }

    if ((a_Flags & WF_NOFRAME) == 0)
    {
        style |= WS_CAPTION;

        if ((a_Flags & WF_NOSYSMENU) == 0)
        {
            style |= WS_SYSMENU;
            style |= WS_MINIMIZEBOX;
        }
    }
    
    return style;
}

DWORD Window::Window_Impl::GetStyleExFromFlags(uint32 a_Flags) const
{
    DWORD style = 0;
    
    if ((a_Flags & WF_WINDOWS_TOOL) != 0)
    {
        style |= WS_EX_TOOLWINDOW;
    }

    if ((a_Flags & WF_TOPMOST) != 0)
    {
        style |= WS_EX_TOPMOST;
    }

    return style;
}

uint32 Window::Window_Impl::GetFlagsFromStyle(DWORD a_Style, DWORD a_StyleEx) const
{
    uint32 flags = 0;

    if ((a_Style & WS_THICKFRAME) != 0)
    {
        flags |= WF_RESIZE;
    }

    if ((a_Style & WS_CAPTION) == 0)
    {
        flags |= WF_NOFRAME;
    }

    if ((a_Style & WS_SYSMENU) == 0)
    {
        flags |= WF_NOSYSMENU;
    }

    if ((a_StyleEx & WS_EX_TOOLWINDOW) != 0)
    {
        flags |= WF_WINDOWS_TOOL;
    }

    if ((a_StyleEx & WS_EX_TOPMOST) != 0)
    {
        flags |= WF_TOPMOST;
    }

    return flags;
}

I've had this bug for a while and mostly worked around it, but I really want to get rid of it.

Right now I just do as little as possible before creating the window and then hope it doesn't crash.

 


Unregistering Raw Input

17 August 2012 - 09:38 AM

So I am changing my input system from directinput to raw input, because I want multi mouse/keyboard support.
I've figured out most parts, but I have trouble getting one major part right.

I have 2 classes, an inputmanager and a window class.
The window class just creates a basic frame in which I can draw etc.
The inputmanager, as the name suggests, manages all the input.
Instances of the window class can be registered at the inputmanager, which will then register the raw input devices, and peek for input messages every frame.
A requirement for this is that the window class ignores all WM_INPUT messages (does not remove them from the message que).
If it does not do this, input messages sometimes leak through between the inputmanager peeking for messages and the processing of the window message que, even if they are called right after each other.
This is not acceptable for a game engine, so the window just ignores the WM_INPUT messages.

This is works fine and all, until I tell the input manager to stop tracking input on that window.
The window is still ignoring all the WM_INPUT messages, while the inputmanager does not pop them anymore.
So basically the message queue just starts filling up with WM_INPUT messages and no one takes them out.

Now the best solution of course would be to just unregister the devices so that they stop sending WM_INPUT messages and everything acts just like it did before I registered them, but this does not seem to be possible.
I am unable to find a function that does this.
The closest thing I could find was RIDEV_REMOVE, but this does not do anything related to the window, and I am uncertain how much it actually affects.

So what I need is:
Something to unregister raw input devices.
or
Some other solution to this problem that doesn't mess up the architecture without any leaks.

A requirement is that the window does not have to know if it is being tracked at the moment.

OS: Windows
Language: C++

Winsock Multiprocess Issues

04 April 2012 - 03:44 AM

So I have this really weird bug with I have been trying to fix for the past 3 days.

I basically have 2 applications, one is the game, the other one is an editor.
I connect them together so I can send data around.
The game has a listening socket and the editors just try to connect to it every once in a few seconds.

This works fine, but there is this really weird and specific bug.
I have the option to launch an instance of the editor from the game.
When I do this (using anything from sytem to CreateProcess, I tried them all), the editor launches and connects as expected.
When I then shut down the game the editor loses connection.

But here is where it gets weird.
For some reason the next time it tries to connect, it succeeds.
Even though the game is not running.
Then it disconnects because it doesn't receive any ping message (because there is no game to send them) and thinks that it has timed out.
After that, it reconnects again.
And it just keeps doing this over and over.
And this just happens when I start the process from the game.
When I launch the editor seperately, this does not happen, and everything works perfectly.

So I hope that any of you have any idea what is going on here, because I really don't know anymore.

Fastest way of getting image on screen

05 October 2011 - 04:05 PM

I am currently working on a software rasterizer as a school assignment.
I started with copying image buffers to the screen, but the performance is already terrible.
At the moment I tried both glDrawPixels and copying the data to a texture and then drawing a quad on screen with that texture.
Sending data to the GPU every frame is just so incredibly slow.
I've had this same problem before with a software raytracer and I'm getting tired of it.
Something so simple should not take up so much of your application's performance.

So here is my question: What is the fastest way of getting my image data on the screen?
I'm willing to go all out.
I don't care which API I have to use as long as it works on Windows.
So I don't mind whether it's OpenGL, DirectX or even the Windows API.

So the only restrictions are:
- Works on Windows
- Uses C++

So if you know a quick way of doing this, or even just an idea of something that might be worth a try, please tell me.

PARTNERS