This patch implements 'WGL_PBUFFER_LOST_ARB'. It creates a new field in
'X11DRV_PDEVICE' which is used to store flags (currently only one:
X11DRV_FLAG_DAMAGED). This flag indicates that the drawable (PBuffer) is
damaged and no longer valid. As soon as the x11 driver receives the
GLX_DAMAGED event it calls X11DRV_GLX_Event() which then set the flag.
wglQueryPbufferARB() uses ExtEscape() to retrieve this flag and can
decide whether the PBuffer is lost or not.

This patch depends on one I've sent earlier to the wine-patches mailing
list: '[x11drv] Move x11drv ExtEscape() codes to one common header
file.'. Please look through this patch and tell me if I've done
something horribly wrong or missed an important aspect. I'm very new to
wine and I don't know what I am allowed to touch and what not.

tom
diff --git a/dlls/opengl32/wgl_ext.c b/dlls/opengl32/wgl_ext.c
index ecefb7e..d11f4db 100644
--- a/dlls/opengl32/wgl_ext.c
+++ b/dlls/opengl32/wgl_ext.c
@@ -65,6 +65,16 @@ inline static void set_drawable( HDC hdc
     ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, 0, NULL );
 }
 
+inline static BOOL is_damaged( HDC hdc )
+{
+    long flags;
+    enum x11drv_escape_codes escape = X11DRV_GET_FLAGS;
+
+    if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
+                    sizeof(flags), (LPSTR)&flags )) return False;
+    return ((flags & X11DRV_FLAG_DAMAGED) == X11DRV_FLAG_DAMAGED);
+}
+
 /* Some WGL extensions... */
 static const char *WGL_extensions_base = "WGL_ARB_extensions_string WGL_EXT_extensions_string";
 static char *WGL_extensions = NULL;
@@ -1124,7 +1133,9 @@ GLboolean WINAPI wglQueryPbufferARB(HPBU
     break;
 
   case WGL_PBUFFER_LOST_ARB:
-    FIXME("unsupported WGL_PBUFFER_LOST_ARB (need glXSelectEvent/GLX_DAMAGED work)\n");
+   // FIXME("unsupported WGL_PBUFFER_LOST_ARB (need glXSelectEvent/GLX_DAMAGED work)\n");
+    *piValue = is_damaged(object->hdc);
+    TRACE("PBuffer is damaged: %d ?\n", *piValue);
     break;
 
   case WGL_TEXTURE_FORMAT_ARB:
diff --git a/dlls/x11drv/event.c b/dlls/x11drv/event.c
index 53c1a6a..e642fad 100644
--- a/dlls/x11drv/event.c
+++ b/dlls/x11drv/event.c
@@ -67,6 +67,15 @@ extern BOOL ximInComposeMode;
 
 #define DndURL          128   /* KDE drag&drop */
 
+/* GLX/PBuffer events */
+/* since we can't always include <GL/glx.h> and we need this in all cases
+ * we simply define 'GLX_DAMAGED' here.
+ * Why can't we use 'X11DRV_register_event_handler'? Because we need to make
+ * sure that this event passes 'filter_event' and we can't register event handlers
+ * that are always executed, no matter which events the application wants to recieve */
+#define GLX_DAMAGED                        0x8020
+extern void X11DRV_GLX_Event( HWND hwnd, XEvent *xev );
+
   /* Event handlers */
 static void EVENT_FocusIn( HWND hwnd, XEvent *event );
 static void EVENT_FocusOut( HWND hwnd, XEvent *event );
@@ -117,6 +126,7 @@ static struct event_handler handlers[MAX
     /* ColormapNotify */
     { ClientMessage,    EVENT_ClientMessage },
     { MappingNotify,    X11DRV_MappingNotify },
+    { GLX_DAMAGED,      X11DRV_GLX_Event },
 };
 
 static int nb_event_handlers = 18;  /* change this if you add handlers above */
@@ -224,6 +234,8 @@ static Bool filter_event( Display *displ
         return (mask & QS_PAINT) != 0;
     case ClientMessage:
         return (mask & QS_POSTMESSAGE) != 0;
+    case GLX_DAMAGED:
+        return 1;
     default:
         return (mask & QS_SENDMESSAGE) != 0;
     }
diff --git a/dlls/x11drv/init.c b/dlls/x11drv/init.c
index 9701266..f7d2b68 100644
--- a/dlls/x11drv/init.c
+++ b/dlls/x11drv/init.c
@@ -322,6 +322,20 @@ INT X11DRV_ExtEscape( X11DRV_PDEVICE *ph
                     return TRUE;
                 }
                 break;
+            case X11DRV_SET_FLAGS:
+                if (in_count >= sizeof(long))
+                {
+                    physDev->flags = *(long *)in_data;
+                    return TRUE;
+                }
+                break;
+            case X11DRV_GET_FLAGS:
+                if (out_count >= sizeof(long))
+                {
+                    *(long *)out_data = physDev->flags;
+                    return TRUE;
+                }
+                break;
             case X11DRV_SET_DRAWABLE:
                 if (in_count >= sizeof(struct x11drv_escape_set_drawable))
                 {
diff --git a/dlls/x11drv/opengl.c b/dlls/x11drv/opengl.c
index dd2017b..38d694b 100644
--- a/dlls/x11drv/opengl.c
+++ b/dlls/x11drv/opengl.c
@@ -28,6 +28,8 @@
 #include "wine/library.h"
 #include "wine/debug.h"
 
+#include "wine/x11drv_escape.h"
+
 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
 WINE_DECLARE_DEBUG_CHANNEL(opengl);
 
@@ -56,6 +58,34 @@ WINE_DECLARE_DEBUG_CHANNEL(opengl);
 #define WINAPI      __stdcall
 #define APIENTRY    WINAPI
 
+/* retrieve the GLX drawable to use on a given DC */
+inline static Drawable get_drawable( HDC hdc )
+{
+    GLXDrawable drawable;
+    enum x11drv_escape_codes escape = X11DRV_GET_GLX_DRAWABLE;
+
+    if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
+                    sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
+    return drawable;
+}
+
+/* mark the darwable in this DC as damaged, used for Pbuffers */
+inline static BOOL mark_damaged( HDC hdc )
+{
+    long flags;
+    enum x11drv_escape_codes escape = X11DRV_GET_FLAGS;
+
+    if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
+                    sizeof(flags), (LPSTR)&flags )) return False;
+
+    escape = X11DRV_SET_FLAGS;
+    flags |= X11DRV_FLAG_DAMAGED;
+    if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
+                    sizeof(flags), (LPSTR)&flags )) return False;
+
+    return True;
+}
+
 
 static void dump_PIXELFORMATDESCRIPTOR(const PIXELFORMATDESCRIPTOR *ppfd) {
   TRACE("  - size / version : %d / %d\n", ppfd->nSize, ppfd->nVersion);
@@ -614,6 +644,24 @@ BOOL destroy_glxpixmap(XID glxpixmap)
     return TRUE;
 }
 
+void X11DRV_GLX_Event( HWND hwnd, XEvent *xev )
+{
+    HDC hDC = GetDC(hwnd);
+
+    if (xev->type == GLX_DAMAGED) {
+        GLXDrawable drawable = get_drawable(hDC);
+
+        /* FIXME: is this check really necessary? */
+        if (drawable == xev->xany.window) {
+            if(!mark_damaged(hDC)) {
+                FIXME("Couldn't set the 'damaged' flag for GLXDrawable 0x%x\n", xev->xany.window);
+            }
+        } else {
+            FIXME("called with wrong hwnd: %p\n", hwnd);
+        }
+    }
+}
+
 #else  /* no OpenGL includes */
 
 void X11DRV_OpenGL_Init(Display *display)
@@ -686,4 +734,8 @@ BOOL destroy_glxpixmap(XID glxpixmap)
     return FALSE;
 }
 
+void X11DRV_GLX_Event( HWND hwnd, XEvent *xev )
+{
+}
+
 #endif /* defined(HAVE_OPENGL) */
diff --git a/dlls/x11drv/x11drv.h b/dlls/x11drv/x11drv.h
index 196d8c1..12011de 100644
--- a/dlls/x11drv/x11drv.h
+++ b/dlls/x11drv/x11drv.h
@@ -144,6 +144,7 @@ typedef struct
     struct dce   *dce;         /* opaque pointer to DCE */
     int           current_pf;
     XRENDERINFO   xrender;
+    long          flags;       /* X11DRV_FLAG_??? */
 } X11DRV_PDEVICE;
 
 
diff --git a/include/wine/x11drv_escape.h b/include/wine/x11drv_escape.h
index a19b551..af69ce0 100644
--- a/include/wine/x11drv_escape.h
+++ b/include/wine/x11drv_escape.h
@@ -21,18 +21,25 @@
 #ifndef __WINE_X11DRV_ESCAPE_H
 #define __WINE_X11DRV_ESCAPE_H
 
+#define X11DRV_FLAG_DAMAGED     ( 1 << 0 )
+
 #define X11DRV_ESCAPE 6789
 enum x11drv_escape_codes
 {
+    X11DRV_SET_DRAWABLE,        /* set current drawable for a DC */
+    X11DRV_SET_DCE,             /* set the DCE pointer */
+    X11DRV_SET_FLAGS,           /* set DC flags */
+
     X11DRV_GET_DISPLAY,         /* get X11 display for a DC */
     X11DRV_GET_DRAWABLE,        /* get current drawable for a DC */
+    X11DRV_GET_GLX_DRAWABLE,    /* get current glx drawable for a DC */
     X11DRV_GET_FONT,            /* get current X font for a DC */
-    X11DRV_SET_DRAWABLE,        /* set current drawable for a DC */
+    X11DRV_GET_DCE,             /* get the DCE pointer */
+    X11DRV_GET_FLAGS,           /* get DC flags */
+
     X11DRV_START_EXPOSURES,     /* start graphics exposures */
     X11DRV_END_EXPOSURES,       /* end graphics exposures */
-    X11DRV_GET_DCE,             /* get the DCE pointer */
-    X11DRV_SET_DCE,             /* set the DCE pointer */
-    X11DRV_GET_GLX_DRAWABLE,    /* get current glx drawable for a DC */
+
     X11DRV_SYNC_PIXMAP          /* sync the dibsection to its pixmap */
 };
 


Reply via email to