summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/gtk/RedirectedXCompositeWindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/gtk/RedirectedXCompositeWindow.cpp')
-rw-r--r--Source/WebCore/platform/gtk/RedirectedXCompositeWindow.cpp151
1 files changed, 97 insertions, 54 deletions
diff --git a/Source/WebCore/platform/gtk/RedirectedXCompositeWindow.cpp b/Source/WebCore/platform/gtk/RedirectedXCompositeWindow.cpp
index 0d7bdba43..e9118c77e 100644
--- a/Source/WebCore/platform/gtk/RedirectedXCompositeWindow.cpp
+++ b/Source/WebCore/platform/gtk/RedirectedXCompositeWindow.cpp
@@ -27,45 +27,102 @@
#include "config.h"
#include "RedirectedXCompositeWindow.h"
-#if USE(GLX)
-#include "GLContextGLX.h"
-#include <GL/glx.h>
+#if PLATFORM(X11)
#include <X11/extensions/Xcomposite.h>
+#include <X11/extensions/Xdamage.h>
#include <cairo-xlib.h>
#include <gdk/gdkx.h>
#include <glib.h>
#include <gtk/gtk.h>
+#include <wtf/HashMap.h>
namespace WebCore {
+typedef HashMap<Window, RedirectedXCompositeWindow*> WindowHashMap;
+static WindowHashMap& getWindowHashMap()
+{
+ DEFINE_STATIC_LOCAL(WindowHashMap, windowHashMap, ());
+ return windowHashMap;
+}
+
+static int gDamageEventBase;
+static GdkFilterReturn filterXDamageEvent(GdkXEvent* gdkXEvent, GdkEvent* event, void*)
+{
+ XEvent* xEvent = static_cast<XEvent*>(gdkXEvent);
+ if (xEvent->type != gDamageEventBase + XDamageNotify)
+ return GDK_FILTER_CONTINUE;
+
+ XDamageNotifyEvent* damageEvent = reinterpret_cast<XDamageNotifyEvent*>(xEvent);
+ WindowHashMap& windowHashMap = getWindowHashMap();
+ WindowHashMap::iterator i = windowHashMap.find(damageEvent->drawable);
+ if (i == windowHashMap.end())
+ return GDK_FILTER_CONTINUE;
+
+ i->value->callDamageNotifyCallback();
+ XDamageSubtract(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), damageEvent->damage, None, None);
+ return GDK_FILTER_REMOVE;
+}
+
+static bool supportsXDamageAndXComposite()
+{
+ static bool initialized = false;
+ static bool hasExtensions = false;
+
+ if (initialized)
+ return hasExtensions;
+
+ initialized = true;
+
+ int errorBase;
+ Display* display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
+ if (!XDamageQueryExtension(display, &gDamageEventBase, &errorBase))
+ return false;
+
+ int eventBase;
+ if (!XCompositeQueryExtension(display, &eventBase, &errorBase))
+ return false;
+
+ // We need to support XComposite version 0.2.
+ int major, minor;
+ XCompositeQueryVersion(display, &major, &minor);
+ if (major < 0 || (!major && minor < 2))
+ return false;
+
+ hasExtensions = true;
+ return true;
+}
+
PassOwnPtr<RedirectedXCompositeWindow> RedirectedXCompositeWindow::create(const IntSize& size)
{
- return adoptPtr(new RedirectedXCompositeWindow(size));
+ return supportsXDamageAndXComposite() ? adoptPtr(new RedirectedXCompositeWindow(size)) : nullptr;
}
RedirectedXCompositeWindow::RedirectedXCompositeWindow(const IntSize& size)
- : m_usableSize(size)
+ : m_size(size)
, m_window(0)
, m_parentWindow(0)
, m_pixmap(0)
, m_surface(0)
- , m_pendingResizeSourceId(0)
, m_needsNewPixmapAfterResize(false)
+ , m_damage(0)
+ , m_damageNotifyCallback(0)
+ , m_damageNotifyData(0)
{
- Display* display = GLContextGLX::sharedDisplay();
+ Display* display = GLContext::sharedX11Display();
+ Screen* screen = DefaultScreenOfDisplay(display);
// This is based on code from Chromium: src/content/common/gpu/image_transport_surface_linux.cc
XSetWindowAttributes windowAttributes;
windowAttributes.override_redirect = True;
m_parentWindow = XCreateWindow(display,
- RootWindow(display, DefaultScreen(display)),
- -100, -100, 1, 1,
- 0,
- CopyFromParent,
- InputOutput,
- CopyFromParent,
- CWOverrideRedirect,
- &windowAttributes);
+ RootWindowOfScreen(screen),
+ WidthOfScreen(screen) + 1, 0, 1, 1,
+ 0,
+ CopyFromParent,
+ InputOutput,
+ CopyFromParent,
+ CWOverrideRedirect,
+ &windowAttributes);
XMapWindow(display, m_parentWindow);
windowAttributes.event_mask = StructureNotifyMask;
@@ -81,6 +138,10 @@ RedirectedXCompositeWindow::RedirectedXCompositeWindow(const IntSize& size)
&windowAttributes);
XMapWindow(display, m_window);
+ if (getWindowHashMap().isEmpty())
+ gdk_window_add_filter(0, reinterpret_cast<GdkFilterFunc>(filterXDamageEvent), 0);
+ getWindowHashMap().add(m_window, this);
+
while (1) {
XEvent event;
XWindowEvent(display, m_window, StructureNotifyMask, &event);
@@ -88,58 +149,34 @@ RedirectedXCompositeWindow::RedirectedXCompositeWindow(const IntSize& size)
break;
}
XSelectInput(display, m_window, NoEventMask);
-
XCompositeRedirectWindow(display, m_window, CompositeRedirectManual);
-
- resize(size);
+ m_damage = XDamageCreate(display, m_window, XDamageReportNonEmpty);
}
RedirectedXCompositeWindow::~RedirectedXCompositeWindow()
{
- Display* display = GLContextGLX::sharedDisplay();
- if (m_window)
- XDestroyWindow(display, m_window);
- if (m_parentWindow)
- XDestroyWindow(display, m_parentWindow);
- cleanupPixmapAndPixmapSurface();
-
- if (m_pendingResizeSourceId)
- g_source_remove(m_pendingResizeSourceId);
-}
+ ASSERT(m_damage);
+ ASSERT(m_window);
+ ASSERT(m_parentWindow);
-gboolean RedirectedXCompositeWindow::resizeLaterCallback(RedirectedXCompositeWindow* window)
-{
- window->resizeLater();
- return FALSE;
-}
+ getWindowHashMap().remove(m_window);
+ if (getWindowHashMap().isEmpty())
+ gdk_window_remove_filter(0, reinterpret_cast<GdkFilterFunc>(filterXDamageEvent), 0);
-void RedirectedXCompositeWindow::resizeLater()
-{
- m_usableSize = m_size;
- m_pendingResizeSourceId = 0;
+ Display* display = GLContext::sharedX11Display();
+ XDamageDestroy(display, m_damage);
+ XDestroyWindow(display, m_window);
+ XDestroyWindow(display, m_parentWindow);
+ cleanupPixmapAndPixmapSurface();
}
void RedirectedXCompositeWindow::resize(const IntSize& size)
{
- // When enlarging a redirected window, for the first render, the newly exposed areas seem
- // to contain uninitialized memory on Intel drivers. To avoid rendering artifacts while
- // resizing, we wait to render those new areas until after a short timeout. Thus, the
- // "usable size" of the window is smaller than the actual size of the window for the first
- // render.
- m_usableSize = size.shrunkTo(m_usableSize);
- if (m_usableSize.width() < size.width() || m_usableSize.height() < size.height()) { // The window is growing.
- // We're being very conservative here. Instead of risking drawing artifacts while doing continuous
- // opaque resizing, we err on the side of having more undrawn areas.
- if (m_pendingResizeSourceId)
- g_source_remove(m_pendingResizeSourceId);
- m_pendingResizeSourceId = g_timeout_add(0, reinterpret_cast<GSourceFunc>(resizeLaterCallback), this);
- }
-
- Display* display = GLContextGLX::sharedDisplay();
+ Display* display = GLContext::sharedX11Display();
XResizeWindow(display, m_window, size.width(), size.height());
XFlush(display);
- glXWaitX();
+ context()->waitNative();
// This swap is based on code in Chromium. It tries to work-around a bug in the Intel drivers
// where a swap is necessary to ensure the front and back buffers are properly resized.
@@ -216,6 +253,12 @@ cairo_surface_t* RedirectedXCompositeWindow::cairoSurfaceForWidget(GtkWidget* wi
return m_surface.get();
}
+void RedirectedXCompositeWindow::callDamageNotifyCallback()
+{
+ if (m_damageNotifyCallback)
+ m_damageNotifyCallback(m_damageNotifyData);
+}
+
} // namespace WebCore
-#endif // USE(GLX)
+#endif // PLATFORM(X11)