std::unique_ptr<BackingStoreBackendCairo> BackingStore::createBackend() { #if PLATFORM(GTK) && PLATFORM(X11) const auto& sharedDisplay = PlatformDisplay::sharedDisplay(); if (is<PlatformDisplayX11>(sharedDisplay)) { GdkVisual* visual = gtk_widget_get_visual(m_webPageProxy.viewWidget()); GdkScreen* screen = gdk_visual_get_screen(visual); ASSERT(downcast<PlatformDisplayX11>(sharedDisplay).native() == GDK_SCREEN_XDISPLAY(screen)); return std::make_unique<BackingStoreBackendCairoX11>(downcast<PlatformDisplayX11>(sharedDisplay).native(), GDK_WINDOW_XID(gdk_screen_get_root_window(screen)), GDK_VISUAL_XVISUAL(visual), gdk_visual_get_depth(visual), m_size, m_deviceScaleFactor); } #endif IntSize scaledSize = m_size; scaledSize.scale(m_deviceScaleFactor); #if PLATFORM(GTK) RefPtr<cairo_surface_t> surface = adoptRef(gdk_window_create_similar_surface(gtk_widget_get_window(m_webPageProxy.viewWidget()), CAIRO_CONTENT_COLOR_ALPHA, scaledSize.width(), scaledSize.height())); #else RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, scaledSize.width(), scaledSize.height())); #endif cairoSurfaceSetDeviceScale(surface.get(), m_deviceScaleFactor, m_deviceScaleFactor); return std::make_unique<BackingStoreBackendCairoImpl>(surface.get(), m_size); }
BackingStoreBackendCairoX11::BackingStoreBackendCairoX11(unsigned long rootWindowID, Visual* visual, int depth, const IntSize& size, float deviceScaleFactor) : BackingStoreBackendCairo(size) { IntSize scaledSize = size; scaledSize.scale(deviceScaleFactor); auto* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native(); m_pixmap = XCreatePixmap(display, rootWindowID, scaledSize.width(), scaledSize.height(), depth); m_gc.reset(XCreateGC(display, m_pixmap.get(), 0, nullptr)); m_surface = adoptRef(cairo_xlib_surface_create(display, m_pixmap.get(), visual, scaledSize.width(), scaledSize.height())); cairoSurfaceSetDeviceScale(m_surface.get(), deviceScaleFactor, deviceScaleFactor); }
WidgetBackingStoreGtkX11::WidgetBackingStoreGtkX11(GtkWidget* widget, const IntSize& size, float deviceScaleFactor) : WidgetBackingStore(size, deviceScaleFactor) { IntSize scaledSize = size; scaledSize.scale(deviceScaleFactor); GdkVisual* visual = gtk_widget_get_visual(widget); GdkScreen* screen = gdk_visual_get_screen(visual); m_display = GDK_SCREEN_XDISPLAY(screen); m_pixmap = XCreatePixmap(m_display, GDK_WINDOW_XID(gdk_screen_get_root_window(screen)), scaledSize.width(), scaledSize.height(), gdk_visual_get_depth(visual)); m_gc = XCreateGC(m_display, m_pixmap, 0, 0); m_surface = adoptRef(cairo_xlib_surface_create(m_display, m_pixmap, GDK_VISUAL_XVISUAL(visual), scaledSize.width(), scaledSize.height())); cairoSurfaceSetDeviceScale(m_surface.get(), deviceScaleFactor, deviceScaleFactor); }
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); }