cairo_surface_t* RedirectedXCompositeWindow::cairoSurfaceForWidget(GtkWidget* widget) { if (!m_needsNewPixmapAfterResize && m_surface) return m_surface.get(); m_needsNewPixmapAfterResize = false; // It's important that the new pixmap be created with the same Display pointer as the target // widget or else drawing speed can be 100x slower. Display* newPixmapDisplay = GDK_DISPLAY_XDISPLAY(gtk_widget_get_display(widget)); Pixmap newPixmap = XCompositeNameWindowPixmap(newPixmapDisplay, m_window); if (!newPixmap) { cleanupPixmapAndPixmapSurface(); return 0; } XWindowAttributes windowAttributes; if (!XGetWindowAttributes(newPixmapDisplay, m_window, &windowAttributes)) { cleanupPixmapAndPixmapSurface(); XFreePixmap(newPixmapDisplay, newPixmap); return 0; } RefPtr<cairo_surface_t> newSurface = adoptRef(cairo_xlib_surface_create(newPixmapDisplay, newPixmap, windowAttributes.visual, m_size.width(), m_size.height())); // Nvidia drivers seem to prepare their redirected window pixmap asynchronously, so for a few fractions // of a second after each resize, while doing continuous resizing (which constantly destroys and creates // pixmap window-backings), the pixmap memory is uninitialized. To work around this issue, paint the old // pixmap to the new one to properly initialize it. if (m_surface) { RefPtr<cairo_t> cr = adoptRef(cairo_create(newSurface.get())); cairo_set_source_rgb(cr.get(), 1, 1, 1); cairo_paint(cr.get()); cairo_set_source_surface(cr.get(), m_surface.get(), 0, 0); cairo_paint(cr.get()); } cleanupPixmapAndPixmapSurface(); m_pixmap = newPixmap; m_surface = newSurface; return m_surface.get(); }
cairo_surface_t* RedirectedXCompositeWindow::surface() { // This should never be called with an empty size (not in Accelerated Compositing mode). ASSERT(!m_size.isEmpty()); if (!m_needsNewPixmapAfterResize && m_surface) return m_surface.get(); m_needsNewPixmapAfterResize = false; Pixmap newPixmap = XCompositeNameWindowPixmap(m_display, m_window); if (!newPixmap) { cleanupPixmapAndPixmapSurface(); return nullptr; } XWindowAttributes windowAttributes; if (!XGetWindowAttributes(m_display, m_window, &windowAttributes)) { cleanupPixmapAndPixmapSurface(); XFreePixmap(m_display, newPixmap); return nullptr; } RefPtr<cairo_surface_t> newSurface = adoptRef(cairo_xlib_surface_create(m_display, newPixmap, windowAttributes.visual, m_size.width(), m_size.height())); // Nvidia drivers seem to prepare their redirected window pixmap asynchronously, so for a few fractions // of a second after each resize, while doing continuous resizing (which constantly destroys and creates // pixmap window-backings), the pixmap memory is uninitialized. To work around this issue, paint the old // pixmap to the new one to properly initialize it. if (m_surface) { RefPtr<cairo_t> cr = adoptRef(cairo_create(newSurface.get())); cairo_set_source_rgb(cr.get(), 1, 1, 1); cairo_paint(cr.get()); cairo_set_source_surface(cr.get(), m_surface.get(), 0, 0); cairo_paint(cr.get()); } cleanupPixmapAndPixmapSurface(); m_pixmap = newPixmap; m_surface = newSurface; return m_surface.get(); }
void RedirectedXCompositeWindow::createNewPixampAndPixampSurface() { // This should never be called with an empty size (not in Accelerated Compositing mode). ASSERT(!m_size.isEmpty()); XUniquePixmap newPixmap(XCompositeNameWindowPixmap(m_display, m_window.get())); if (!newPixmap) { cleanupPixmapAndPixmapSurface(); return; } XWindowAttributes windowAttributes; if (!XGetWindowAttributes(m_display, m_window.get(), &windowAttributes)) { cleanupPixmapAndPixmapSurface(); return; } RefPtr<cairo_surface_t> newSurface = adoptRef(cairo_xlib_surface_create(m_display, newPixmap.get(), windowAttributes.visual, m_size.width(), m_size.height())); cairoSurfaceSetDeviceScale(newSurface.get(), m_webPage.deviceScaleFactor(), m_webPage.deviceScaleFactor()); RefPtr<cairo_t> cr = adoptRef(cairo_create(newSurface.get())); if (!m_webPage.drawsBackground()) cairo_set_operator(cr.get(), CAIRO_OPERATOR_CLEAR); else setSourceRGBAFromColor(cr.get(), m_webPage.backgroundColor()); cairo_paint(cr.get()); // Nvidia drivers seem to prepare their redirected window pixmap asynchronously, so for a few fractions // of a second after each resize, while doing continuous resizing (which constantly destroys and creates // pixmap window-backings), the pixmap memory is uninitialized. To work around this issue, paint the old // pixmap to the new one to properly initialize it. if (m_surface) { cairo_set_operator(cr.get(), CAIRO_OPERATOR_OVER); cairo_set_source_surface(cr.get(), m_surface.get(), 0, 0); cairo_paint(cr.get()); } cleanupPixmapAndPixmapSurface(); m_pixmap = WTFMove(newPixmap); m_surface = WTFMove(newSurface); }
void RedirectedXCompositeWindow::resize(const IntSize& size) { if (size == m_size) return; // Resize the window to at last 1x1 since X doesn't allow to create empty windows. XResizeWindow(m_display, m_window, std::max(1, size.width()), std::max(1, size.height())); XFlush(m_display); m_size = size; m_needsNewPixmapAfterResize = true; if (m_size.isEmpty()) cleanupPixmapAndPixmapSurface(); }
RedirectedXCompositeWindow::~RedirectedXCompositeWindow() { ASSERT(m_display); ASSERT(m_damage); ASSERT(m_window); ASSERT(m_parentWindow); xDamageNotifier().remove(m_window); XDamageDestroy(m_display, m_damage); XDestroyWindow(m_display, m_window); XDestroyWindow(m_display, m_parentWindow); cleanupPixmapAndPixmapSurface(); }
RedirectedXCompositeWindow::~RedirectedXCompositeWindow() { ASSERT(m_damage); ASSERT(m_window); ASSERT(m_parentWindow); getWindowHashMap().remove(m_window); if (getWindowHashMap().isEmpty()) gdk_window_remove_filter(0, reinterpret_cast<GdkFilterFunc>(filterXDamageEvent), 0); Display* display = GLContext::sharedX11Display(); XDamageDestroy(display, m_damage); XDestroyWindow(display, m_window); XDestroyWindow(display, m_parentWindow); cleanupPixmapAndPixmapSurface(); }
void RedirectedXCompositeWindow::resize(const IntSize& size) { IntSize scaledSize(size); scaledSize.scale(m_webPage.deviceScaleFactor()); if (scaledSize == m_size) return; // Resize the window to at last 1x1 since X doesn't allow to create empty windows. XResizeWindow(m_display, m_window.get(), std::max(1, scaledSize.width()), std::max(1, scaledSize.height())); XFlush(m_display); m_size = scaledSize; if (m_size.isEmpty()) cleanupPixmapAndPixmapSurface(); else createNewPixampAndPixampSurface(); }