- Merge from trunk up to r45543
[reactos.git] / dll / directx / wine / wined3d / wined3d_main.c
index 5f19c26..39416e1 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 
+struct wined3d_wndproc
+{
+    HWND window;
+    WNDPROC proc;
+    IWineD3DDeviceImpl *device;
+};
+
+struct wined3d_wndproc_table
+{
+    struct wined3d_wndproc *entries;
+    unsigned int count;
+    unsigned int size;
+};
+
+static struct wined3d_wndproc_table wndproc_table;
+
 int num_lock = 0;
 void (*CDECL wine_tsx11_lock_ptr)(void) = NULL;
 void (*CDECL wine_tsx11_unlock_ptr)(void) = NULL;
@@ -325,6 +341,7 @@ static BOOL wined3d_init(HINSTANCE hInstDLL)
 static BOOL wined3d_destroy(HINSTANCE hInstDLL)
 {
     DWORD wined3d_context_tls_idx = context_get_tls_idx();
+    unsigned int i;
 
     if (!TlsFree(wined3d_context_tls_idx))
     {
@@ -332,6 +349,13 @@ static BOOL wined3d_destroy(HINSTANCE hInstDLL)
         ERR("Failed to free context TLS index, err %#x.\n", err);
     }
 
+    for (i = 0; i < wndproc_table.count; ++i)
+    {
+        struct wined3d_wndproc *entry = &wndproc_table.entries[i];
+        SetWindowLongPtrW(entry->window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
+    }
+    HeapFree(GetProcessHeap(), 0, wndproc_table.entries);
+
     HeapFree(GetProcessHeap(), 0, wined3d_settings.logo);
     UnregisterClassA(WINED3D_OPENGL_WINDOW_CLASS_NAME, hInstDLL);
 
@@ -348,6 +372,104 @@ void WINAPI wined3d_mutex_unlock(void)
     LeaveCriticalSection(&wined3d_cs);
 }
 
+static struct wined3d_wndproc *wined3d_find_wndproc(HWND window)
+{
+    unsigned int i;
+
+    for (i = 0; i < wndproc_table.count; ++i)
+    {
+        if (wndproc_table.entries[i].window == window)
+        {
+            return &wndproc_table.entries[i];
+        }
+    }
+
+    return NULL;
+}
+
+static LRESULT CALLBACK wined3d_wndproc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
+{
+    struct wined3d_wndproc *entry;
+    IWineD3DDeviceImpl *device;
+    WNDPROC proc;
+
+    wined3d_mutex_lock();
+    entry = wined3d_find_wndproc(window);
+
+    if (!entry)
+    {
+        wined3d_mutex_unlock();
+        ERR("Window %p is not registered with wined3d.\n", window);
+        return DefWindowProcW(window, message, wparam, lparam);
+    }
+
+    device = entry->device;
+    proc = entry->proc;
+    wined3d_mutex_unlock();
+
+    return device_process_message(device, window, message, wparam, lparam, proc);
+}
+
+BOOL wined3d_register_window(HWND window, IWineD3DDeviceImpl *device)
+{
+    struct wined3d_wndproc *entry;
+
+    wined3d_mutex_lock();
+
+    if (wndproc_table.size == wndproc_table.count)
+    {
+        unsigned int new_size = max(1, wndproc_table.size * 2);
+        struct wined3d_wndproc *new_entries;
+
+        if (!wndproc_table.entries) new_entries = HeapAlloc(GetProcessHeap(), 0, new_size * sizeof(*new_entries));
+        else new_entries = HeapReAlloc(GetProcessHeap(), 0, wndproc_table.entries, new_size * sizeof(*new_entries));
+
+        if (!new_entries)
+        {
+            wined3d_mutex_unlock();
+            ERR("Failed to grow table.\n");
+            return FALSE;
+        }
+
+        wndproc_table.entries = new_entries;
+        wndproc_table.size = new_size;
+    }
+
+    entry = &wndproc_table.entries[wndproc_table.count++];
+    entry->window = window;
+    entry->proc = (WNDPROC)SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc);
+    entry->device = device;
+
+    wined3d_mutex_unlock();
+
+    return TRUE;
+}
+
+void wined3d_unregister_window(HWND window)
+{
+    unsigned int i;
+
+    wined3d_mutex_lock();
+    for (i = 0; i < wndproc_table.count; ++i)
+    {
+        if (wndproc_table.entries[i].window == window)
+        {
+            struct wined3d_wndproc *entry = &wndproc_table.entries[i];
+            struct wined3d_wndproc *last = &wndproc_table.entries[--wndproc_table.count];
+
+            if (GetWindowLongPtrW(window, GWLP_WNDPROC) == (LONG_PTR)wined3d_wndproc)
+                SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
+            if (entry != last) *entry = *last;
+            wined3d_mutex_unlock();
+
+            return;
+        }
+    }
+    wined3d_mutex_unlock();
+
+    ERR("Window %p is not registered with wined3d.\n", window);
+}
+
 /* At process attach */
 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
 {