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);
}
Esempio n. 4
0
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);
}