Ejemplo n.º 1
0
SurfaceDescriptorX11::SurfaceDescriptorX11(gfxXlibSurface* aSurf)
  : mId(aSurf->XDrawable())
  , mSize(aSurf->GetSize())
{
  const XRenderPictFormat *pictFormat = aSurf->XRenderFormat();
  if (pictFormat) {
    mFormat = pictFormat->id;
  } else {
    mFormat = cairo_xlib_surface_get_visual(aSurf->CairoSurface())->visualid;
  }
}
Ejemplo n.º 2
0
PRBool
gfxXlibSurface::GetColormapAndVisual(Colormap* aColormap, Visual** aVisual)
{
    if (!mSurfaceValid)
        return PR_FALSE;

    XRenderPictFormat* format =
        cairo_xlib_surface_get_xrender_format(CairoSurface());
    Screen* screen = cairo_xlib_surface_get_screen(CairoSurface());
    Visual* visual = cairo_xlib_surface_get_visual(CairoSurface());

    return DisplayTable::GetColormapAndVisual(screen, format, visual,
                                              aColormap, aVisual);
}
Ejemplo n.º 3
0
SurfaceDescriptorX11::SurfaceDescriptorX11(gfxXlibSurface* aSurf,
                                           bool aForwardGLX)
  : mId(aSurf->XDrawable())
  , mSize(aSurf->GetSize())
  , mGLXPixmap(None)
{
  const XRenderPictFormat *pictFormat = aSurf->XRenderFormat();
  if (pictFormat) {
    mFormat = pictFormat->id;
  } else {
    mFormat = cairo_xlib_surface_get_visual(aSurf->CairoSurface())->visualid;
  }

#ifdef GL_PROVIDER_GLX
  if (aForwardGLX) {
    mGLXPixmap = aSurf->GetGLXPixmap();
  }
#endif
}
Ejemplo n.º 4
0
/* Vladimir Vukicevic reported that surfaces were being created with
 * mismatching Visuals and XRenderPictFormats.
 */
static cairo_bool_t
surface_compare_visual_and_format (cairo_surface_t *surface)
{
    Display *dpy;
    Visual *visual;
    XRenderPictFormat *format;

    dpy = cairo_xlib_surface_get_display (surface);

    visual = cairo_xlib_surface_get_visual (surface);
    if (visual == NULL)
        return TRUE;

    format = cairo_xlib_surface_get_xrender_format (surface);
    if (format == NULL)
        return TRUE;

    return format == XRenderFindVisualFormat (dpy, visual);

}
static cairo_bool_t
_draw_onto_temp_xlib_surface (cairo_surface_t *temp_xlib_surface,
                              cairo_xlib_drawing_callback callback,
                              void *closure,
                              double background_gray_value)
{
    Drawable d = cairo_xlib_surface_get_drawable (temp_xlib_surface);
    Screen *screen = cairo_xlib_surface_get_screen (temp_xlib_surface);
    Visual *visual = cairo_xlib_surface_get_visual (temp_xlib_surface);
    cairo_bool_t result;
    cairo_t *cr = cairo_create (temp_xlib_surface);
    cairo_set_source_rgb (cr, background_gray_value, background_gray_value,
                          background_gray_value);
    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
    cairo_paint (cr);
    cairo_destroy (cr);
    
    cairo_surface_flush (temp_xlib_surface);
    /* no clipping is needed because the callback can't draw outside the native
       surface anyway */
    result = callback (closure, screen, d, visual, 0, 0, NULL, 0);
    cairo_surface_mark_dirty (temp_xlib_surface);
    return result;
}
static already_AddRefed<gfxXlibSurface>
CreateTempXlibSurface (gfxASurface *destination, nsIntSize size,
                       bool canDrawOverBackground,
                       PRUint32 flags, Screen *screen, Visual *visual,
                       DrawingMethod *method)
{
    bool drawIsOpaque = (flags & gfxXlibNativeRenderer::DRAW_IS_OPAQUE) != 0;
    bool supportsAlternateVisual =
        (flags & gfxXlibNativeRenderer::DRAW_SUPPORTS_ALTERNATE_VISUAL) != 0;
    bool supportsAlternateScreen = supportsAlternateVisual &&
        (flags & gfxXlibNativeRenderer::DRAW_SUPPORTS_ALTERNATE_SCREEN);

    cairo_surface_t *target = destination->CairoSurface();
    cairo_surface_type_t target_type = cairo_surface_get_type (target);
    cairo_content_t target_content = cairo_surface_get_content (target);

    Screen *target_screen = target_type == CAIRO_SURFACE_TYPE_XLIB ?
        cairo_xlib_surface_get_screen (target) : screen;

    // When the background has an alpha channel, we need to draw with an alpha
    // channel anyway, so there is no need to copy the background.  If
    // doCopyBackground is set here, we'll also need to check below that the
    // background can copied without any loss in format conversions.
    bool doCopyBackground = !drawIsOpaque && canDrawOverBackground &&
        target_content == CAIRO_CONTENT_COLOR;

    if (supportsAlternateScreen && screen != target_screen && drawIsOpaque) {
        // Prefer a visual on the target screen.
        // (If !drawIsOpaque, we'll need doCopyBackground or an alpha channel.)
        visual = DefaultVisualOfScreen(target_screen);
        screen = target_screen;

    } else if (doCopyBackground || (supportsAlternateVisual && drawIsOpaque)) {
        // Analyse the pixel formats either to check whether we can
        // doCopyBackground or to see if we can find a better visual for
        // opaque drawing.
        Visual *target_visual = NULL;
        XRenderPictFormat *target_format = NULL;
        switch (target_type) {
        case CAIRO_SURFACE_TYPE_XLIB:
            target_visual = cairo_xlib_surface_get_visual (target);
            target_format = cairo_xlib_surface_get_xrender_format (target);
            break;
        case CAIRO_SURFACE_TYPE_IMAGE: {
            gfxASurface::gfxImageFormat imageFormat =
                static_cast<gfxImageSurface*>(destination)->Format();
            target_visual = gfxXlibSurface::FindVisual(screen, imageFormat);
            Display *dpy = DisplayOfScreen(screen);
            if (target_visual) {
                target_format = XRenderFindVisualFormat(dpy, target_visual);
            } else {
                target_format =
                    gfxXlibSurface::FindRenderFormat(dpy, imageFormat);
            }                
            break;
        }
        default:
            break;
        }

        if (supportsAlternateVisual &&
            (supportsAlternateScreen || screen == target_screen)) {
            if (target_visual) {
                visual = target_visual;
                screen = target_screen;
            }
        }
        // Could try harder to match formats across screens for background
        // copying when !supportsAlternateScreen, if we cared.  Preferably
        // we'll find a visual below with an alpha channel anyway; if so, the
        // background won't need to be copied.

        if (doCopyBackground && visual != target_visual &&
            !FormatConversionIsExact(screen, visual, target_format)) {
            doCopyBackground = false;
        }
    }

    if (supportsAlternateVisual && !drawIsOpaque &&
        (screen != target_screen ||
         !(doCopyBackground || VisualHasAlpha(screen, visual)))) {
        // Try to find a visual with an alpha channel.
        Screen *visualScreen =
            supportsAlternateScreen ? target_screen : screen;
        Visual *argbVisual =
            gfxXlibSurface::FindVisual(visualScreen,
                                       gfxASurface::ImageFormatARGB32);
        if (argbVisual) {
            visual = argbVisual;
            screen = visualScreen;
        } else if (!doCopyBackground &&
                   gfxXlibSurface::DepthOfVisual(screen, visual) != 24) {
            // Will need to do alpha extraction; prefer a 24-bit visual.
            // No advantage in using the target screen.
            Visual *rgb24Visual =
                gfxXlibSurface::FindVisual(screen,
                                           gfxASurface::ImageFormatRGB24);
            if (rgb24Visual) {
                visual = rgb24Visual;
            }
        }
    }

    Drawable drawable =
        (screen == target_screen && target_type == CAIRO_SURFACE_TYPE_XLIB) ?
        cairo_xlib_surface_get_drawable (target) : RootWindowOfScreen(screen);

    nsRefPtr<gfxXlibSurface> surface =
        gfxXlibSurface::Create(screen, visual,
                               gfxIntSize(size.width, size.height),
                               drawable);

    if (drawIsOpaque ||
        surface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
        NATIVE_DRAWING_NOTE(drawIsOpaque ?
                            ", SIMPLE OPAQUE\n" : ", SIMPLE WITH ALPHA");
        *method = eSimple;
    } else if (doCopyBackground) {
        NATIVE_DRAWING_NOTE(", COPY BACKGROUND\n");
        *method = eCopyBackground;
    } else {
        NATIVE_DRAWING_NOTE(", SLOW ALPHA EXTRACTION\n");
        *method = eAlphaExtraction;
    }

    return surface.forget();
}
/**
 * Try the direct path.
 * @return True if we took the direct path
 */
bool
gfxXlibNativeRenderer::DrawDirect(gfxContext *ctx, nsIntSize size,
                                  PRUint32 flags,
                                  Screen *screen, Visual *visual)
{
    cairo_t *cr = ctx->GetCairo();

    /* Check that the target surface is an xlib surface. */
    cairo_surface_t *target = cairo_get_group_target (cr);
    if (cairo_surface_get_type (target) != CAIRO_SURFACE_TYPE_XLIB) {
        NATIVE_DRAWING_NOTE("FALLBACK: non-X surface");
        return false;
    }
    
    cairo_matrix_t matrix;
    cairo_get_matrix (cr, &matrix);
    double device_offset_x, device_offset_y;
    cairo_surface_get_device_offset (target, &device_offset_x, &device_offset_y);

    /* Draw() checked that the matrix contained only a very-close-to-integer
       translation.  Here (and in several other places and thebes) device
       offsets are assumed to be integer. */
    NS_ASSERTION(PRInt32(device_offset_x) == device_offset_x &&
                 PRInt32(device_offset_y) == device_offset_y,
                 "Expected integer device offsets");
    nsIntPoint offset(NS_lroundf(matrix.x0 + device_offset_x),
                      NS_lroundf(matrix.y0 + device_offset_y));
    
    int max_rectangles = 0;
    if (flags & DRAW_SUPPORTS_CLIP_RECT) {
      max_rectangles = 1;
    }
    if (flags & DRAW_SUPPORTS_CLIP_LIST) {
      max_rectangles = MAX_STATIC_CLIP_RECTANGLES;
    }

    /* The client won't draw outside the surface so consider this when
       analysing clip rectangles. */
    nsIntRect bounds(offset, size);
    bounds.IntersectRect(bounds,
                         nsIntRect(0, 0,
                                   cairo_xlib_surface_get_width(target),
                                   cairo_xlib_surface_get_height(target)));

    bool needs_clip = true;
    nsIntRect rectangles[MAX_STATIC_CLIP_RECTANGLES];
    int rect_count = 0;

    /* Check that the clip is rectangular and aligned on unit boundaries. */
    /* Temporarily set the matrix for _get_rectangular_clip. It's basically
       the identity matrix, but we must adjust for the fact that our
       offset-rect is in device coordinates. */
    cairo_identity_matrix (cr);
    cairo_translate (cr, -device_offset_x, -device_offset_y);
    bool have_rectangular_clip =
        _get_rectangular_clip (cr, bounds, &needs_clip,
                               rectangles, max_rectangles, &rect_count);
    cairo_set_matrix (cr, &matrix);
    if (!have_rectangular_clip)
        return false;

    /* Stop now if everything is clipped out */
    if (needs_clip && rect_count == 0)
        return true;
      
    /* Check that the screen is supported.
       Visuals belong to screens, so, if alternate visuals are not supported,
       then alternate screens cannot be supported. */  
    bool supports_alternate_visual =
        (flags & DRAW_SUPPORTS_ALTERNATE_VISUAL) != 0;
    bool supports_alternate_screen = supports_alternate_visual &&
        (flags & DRAW_SUPPORTS_ALTERNATE_SCREEN);
    if (!supports_alternate_screen &&
        cairo_xlib_surface_get_screen (target) != screen) {
        NATIVE_DRAWING_NOTE("FALLBACK: non-default screen");
        return false;
    }
        
    /* Check that there is a visual */
    Visual *target_visual = cairo_xlib_surface_get_visual (target);
    if (!target_visual) {
        NATIVE_DRAWING_NOTE("FALLBACK: no Visual for surface");
        return false;
    }        
    /* Check that the visual is supported */
    if (!supports_alternate_visual && target_visual != visual) {
        // Only the format of the visual is important (not the GLX properties)
        // for Xlib or XRender drawing.
        XRenderPictFormat *target_format =
            cairo_xlib_surface_get_xrender_format (target);
        if (!target_format ||
            (target_format !=
             XRenderFindVisualFormat (DisplayOfScreen(screen), visual))) {
            NATIVE_DRAWING_NOTE("FALLBACK: unsupported Visual");
            return false;
        }
    }
  
    /* we're good to go! */
    NATIVE_DRAWING_NOTE("TAKING FAST PATH\n");
    cairo_surface_flush (target);
    nsRefPtr<gfxASurface> surface = gfxASurface::Wrap(target);
    nsresult rv = DrawWithXlib(static_cast<gfxXlibSurface*>(surface.get()),
                               offset, rectangles,
                               needs_clip ? rect_count : 0);
    if (NS_SUCCEEDED(rv)) {
        cairo_surface_mark_dirty (target);
        return true;
    }
    return false;
}
Ejemplo n.º 8
0
static cairo_test_status_t
test_cairo_xlib_surface_get_visual (cairo_surface_t *surface)
{
    Visual *visual = cairo_xlib_surface_get_visual (surface);
    return visual == NULL || surface_has_type (surface, CAIRO_SURFACE_TYPE_XLIB) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR;
}
/**
 * Try the direct path.
 * @param status the status returned by the callback, if we took the direct path
 * @return True if we took the direct path
 */
static cairo_bool_t
_draw_with_xlib_direct (cairo_t *cr,
                        Display *default_display,
                        cairo_xlib_drawing_callback callback,
                        void *closure,
                        int bounds_width, int bounds_height,
                        cairo_xlib_drawing_support_t capabilities)
{
    cairo_surface_t *target;
    Drawable d;
    cairo_matrix_t matrix;
    short offset_x, offset_y;
    cairo_bool_t needs_clip;
    XRectangle rectangles[MAX_STATIC_CLIP_RECTANGLES];
    int rect_count;
    double device_offset_x, device_offset_y;
    int max_rectangles;
    Screen *screen;
    Visual *visual;
    cairo_bool_t have_rectangular_clip;

    target = cairo_get_group_target (cr);
    cairo_surface_get_device_offset (target, &device_offset_x, &device_offset_y);
    d = cairo_xlib_surface_get_drawable (target);

    cairo_get_matrix (cr, &matrix);
    
    /* Check that the matrix is a pure translation */
    /* XXX test some approximation to == 1.0 here? */
    if (matrix.xx != 1.0 || matrix.yy != 1.0 || matrix.xy != 0.0 || matrix.yx != 0.0) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: matrix not a pure translation\n");
        return False;
    }
    /* Check that the matrix translation offsets (adjusted for
       device offset) are integers */
    if (!_convert_coord_to_short (matrix.x0 + device_offset_x, &offset_x) ||
        !_convert_coord_to_short (matrix.y0 + device_offset_y, &offset_y)) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-integer offset\n");
        return False;
    }
    
    max_rectangles = 0;
    if (capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_CLIP_RECT) {
      max_rectangles = 1;
    }
    if (capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_CLIP_LIST) {
      max_rectangles = MAX_STATIC_CLIP_RECTANGLES;
    }
    
    /* Check that the clip is rectangular and aligned on unit boundaries. */
    /* Temporarily set the matrix for _get_rectangular_clip. It's basically
       the identity matrix, but we must adjust for the fact that our
       offset-rect is in device coordinates. */
    cairo_identity_matrix (cr);
    cairo_translate (cr, -device_offset_x, -device_offset_y);
    have_rectangular_clip =
        _get_rectangular_clip (cr,
                               offset_x, offset_y, bounds_width, bounds_height,
                               &needs_clip,
                               rectangles, max_rectangles, &rect_count);
    cairo_set_matrix (cr, &matrix);
    if (!have_rectangular_clip) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: unsupported clip\n");
        return False;
    }

    /* Stop now if everything is clipped out */
    if (needs_clip && rect_count == 0) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING FAST PATH: all clipped\n");
        return True;
    }
      
    /* Check that the operator is OVER */
    if (cairo_get_operator (cr) != CAIRO_OPERATOR_OVER) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-OVER operator\n");
        return False;
    }
    
    /* Check that the offset is supported */  
    if (!(capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_OFFSET) &&
        (offset_x != 0 || offset_y != 0)) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: unsupported offset\n");
        return False;
    }
    
    /* Check that the target surface is an xlib surface. Do this late because
       we might complete early above when when the object to be drawn is
       completely clipped out. */
    if (!d) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-X surface\n");
        return False;
    }
    
    /* Check that the display is supported */  
    screen = cairo_xlib_surface_get_screen (target);
    if (!(capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_ALTERNATE_SCREEN) &&
        screen != DefaultScreenOfDisplay (default_display)) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-default display\n");
        return False;
    }
        
    /* Check that there is a visual */
    visual = cairo_xlib_surface_get_visual (target);
    if (!visual) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: no Visual for surface\n");
        return False;
    }        
    /* Check that the visual is supported */
    if (!(capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_NONDEFAULT_VISUAL) &&
        DefaultVisualOfScreen (screen) != visual) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-default visual\n");
        return False;
    }
  
    /* we're good to go! */
    CAIRO_XLIB_DRAWING_NOTE("TAKING FAST PATH\n");
    cairo_surface_flush (target);
    callback (closure, screen, d, visual, offset_x, offset_y, rectangles,
              needs_clip ? rect_count : 0);
    cairo_surface_mark_dirty (target);
    return True;
}