зеркало из https://github.com/mozilla/pjs.git
Bug 449959: gfxGdkNativeRenderer: look for GdkDrawable on group target,
use default display for fallback. r=vlad/karlt
This commit is contained in:
Родитель
d736c405df
Коммит
94e014face
|
@ -81,7 +81,7 @@ public:
|
|||
// visual passed in must be the default visual for dpy's default screen
|
||||
DRAW_SUPPORTS_NONDEFAULT_VISUAL = 0x10,
|
||||
// If set, then the Screen 'screen' in the callback can be different
|
||||
// from the default Screen of the display passed to 'Draw' and can be
|
||||
// from the default Screen of the default display and can be
|
||||
// on a different display.
|
||||
DRAW_SUPPORTS_ALTERNATE_SCREEN = 0x20
|
||||
};
|
||||
|
|
|
@ -80,7 +80,6 @@ _convert_coord_to_unsigned_short (double coord, unsigned short *v)
|
|||
|
||||
|
||||
void cairo_draw_with_gdk (cairo_t *cr,
|
||||
GdkDrawable * drawable,
|
||||
cairo_gdk_drawing_callback callback,
|
||||
void * closure,
|
||||
unsigned int width, unsigned int height,
|
||||
|
@ -101,7 +100,7 @@ void cairo_draw_with_gdk (cairo_t *cr,
|
|||
_convert_coord_to_short (matrix.y0 + device_offset_y, &offset_y);
|
||||
|
||||
cairo_surface_flush (target);
|
||||
callback (closure, drawable, offset_x, offset_y, NULL, 0);
|
||||
callback (closure, target, offset_x, offset_y, NULL, 0);
|
||||
cairo_surface_mark_dirty (target);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,11 +52,11 @@ CAIRO_BEGIN_DECLS
|
|||
* is composited if you call the callback multiple times with the same closure,
|
||||
* display and visual during a single cairo_draw_with_gdk call.
|
||||
*
|
||||
* @return True on success, False on non-recoverable error
|
||||
* @return True when able to draw, False otherwise
|
||||
*/
|
||||
typedef cairo_bool_t (* cairo_gdk_drawing_callback)
|
||||
(void *closure,
|
||||
GdkDrawable * drawable,
|
||||
cairo_surface_t *surface,
|
||||
short offset_x, short offset_y,
|
||||
GdkRectangle * clip_rects, unsigned int num_rects);
|
||||
|
||||
|
@ -136,7 +136,6 @@ typedef enum {
|
|||
* a surface for it.
|
||||
*/
|
||||
void cairo_draw_with_gdk (cairo_t *cr,
|
||||
GdkDrawable * drawable,
|
||||
cairo_gdk_drawing_callback callback,
|
||||
void * closure,
|
||||
unsigned int width, unsigned int height,
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* rocallahan@novell.com
|
||||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
* Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -204,6 +206,7 @@ _draw_with_xlib_direct (cairo_t *cr,
|
|||
Screen *screen;
|
||||
Visual *visual;
|
||||
cairo_bool_t have_rectangular_clip;
|
||||
cairo_bool_t ret;
|
||||
|
||||
target = cairo_get_group_target (cr);
|
||||
cairo_surface_get_device_offset (target, &device_offset_x, &device_offset_y);
|
||||
|
@ -301,11 +304,12 @@ _draw_with_xlib_direct (cairo_t *cr,
|
|||
/* we're good to go! */
|
||||
CAIRO_GDK_DRAWING_NOTE("TAKING FAST PATH\n");
|
||||
cairo_surface_flush (target);
|
||||
callback (closure, GDK_DRAWABLE(gdk_xid_table_lookup(d)),
|
||||
offset_x, offset_y, rectangles,
|
||||
ret = callback (closure, target, offset_x, offset_y, rectangles,
|
||||
needs_clip ? rect_count : 0);
|
||||
if (ret) {
|
||||
cairo_surface_mark_dirty (target);
|
||||
return True;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
|
@ -364,7 +368,6 @@ _draw_onto_temp_xlib_surface (cairo_surface_t *temp_xlib_surface,
|
|||
void *closure,
|
||||
double background_gray_value)
|
||||
{
|
||||
Drawable d = cairo_xlib_surface_get_drawable (temp_xlib_surface);
|
||||
cairo_bool_t result;
|
||||
|
||||
cairo_t *cr = cairo_create (temp_xlib_surface);
|
||||
|
@ -377,8 +380,7 @@ _draw_onto_temp_xlib_surface (cairo_surface_t *temp_xlib_surface,
|
|||
cairo_surface_flush (temp_xlib_surface);
|
||||
/* no clipping is needed because the callback can't draw outside the native
|
||||
surface anyway */
|
||||
result = callback (closure, GDK_DRAWABLE(gdk_xid_table_lookup(d)),
|
||||
0, 0, NULL, 0);
|
||||
result = callback (closure, temp_xlib_surface, 0, 0, NULL, 0);
|
||||
cairo_surface_mark_dirty (temp_xlib_surface);
|
||||
return result;
|
||||
}
|
||||
|
@ -492,7 +494,6 @@ _compute_alpha_values (uint32_t *black_data,
|
|||
|
||||
void
|
||||
cairo_draw_with_gdk (cairo_t *cr,
|
||||
GdkDrawable * drawable,
|
||||
cairo_gdk_drawing_callback callback,
|
||||
void * closure,
|
||||
unsigned int width, unsigned int height,
|
||||
|
@ -505,7 +506,7 @@ cairo_draw_with_gdk (cairo_t *cr,
|
|||
cairo_surface_t *white_image_surface;
|
||||
unsigned char *black_data;
|
||||
unsigned char *white_data;
|
||||
Display *dpy = gdk_x11_drawable_get_xdisplay(drawable);
|
||||
Display *dpy = gdk_x11_get_default_xdisplay();
|
||||
|
||||
if (result) {
|
||||
result->surface = NULL;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* rocallahan@novell.com
|
||||
* Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -50,11 +51,17 @@ typedef struct {
|
|||
|
||||
static cairo_bool_t
|
||||
NativeRendering(void *closure,
|
||||
GdkDrawable * drawable,
|
||||
cairo_surface_t *surface,
|
||||
short offset_x, short offset_y,
|
||||
GdkRectangle * rectangles, unsigned int num_rects)
|
||||
{
|
||||
NativeRenderingClosure* cl = (NativeRenderingClosure*)closure;
|
||||
nsRefPtr<gfxASurface> gfxSurface = gfxASurface::Wrap(surface);
|
||||
GdkDrawable *drawable =
|
||||
gfxPlatformGtk::GetPlatform()->GetGdkDrawable(gfxSurface);
|
||||
if (!drawable)
|
||||
return 0;
|
||||
|
||||
nsresult rv = cl->mRenderer->
|
||||
NativeDraw(drawable, offset_x, offset_y,
|
||||
rectangles, num_rects);
|
||||
|
@ -96,7 +103,6 @@ gfxGdkNativeRenderer::Draw(gfxContext* ctx, int width, int height,
|
|||
cairoFlags |= CAIRO_GDK_DRAWING_SUPPORTS_NONDEFAULT_VISUAL;
|
||||
}
|
||||
cairo_draw_with_gdk(ctx->GetCairo(),
|
||||
gfxPlatformGtk::GetPlatform()->GetGdkDrawable(ctx->OriginalSurface()),
|
||||
NativeRendering,
|
||||
&closure, width, height,
|
||||
(flags & DRAW_IS_OPAQUE) ? CAIRO_GDK_DRAWING_OPAQUE : CAIRO_GDK_DRAWING_TRANSPARENT,
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
* Masayuki Nakano <masayuki@d-toybox.com>
|
||||
* Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -61,6 +62,7 @@
|
|||
#ifdef MOZ_X11
|
||||
#include <gdk/gdkx.h>
|
||||
#include "gfxXlibSurface.h"
|
||||
#include "cairo-xlib.h"
|
||||
#endif /* MOZ_X11 */
|
||||
|
||||
#ifdef MOZ_DFB
|
||||
|
@ -90,8 +92,6 @@
|
|||
PRInt32 gfxPlatformGtk::sDPI = -1;
|
||||
gfxFontconfigUtils *gfxPlatformGtk::sFontconfigUtils = nsnull;
|
||||
|
||||
static cairo_user_data_key_t cairo_gdk_drawable_key;
|
||||
|
||||
#ifndef MOZ_PANGO
|
||||
typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
|
||||
static FontTable *gPlatformFonts = NULL;
|
||||
|
@ -99,12 +99,11 @@ static FontTable *gPlatformFontAliases = NULL;
|
|||
static FT_Library gPlatformFTLibrary = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
static cairo_user_data_key_t cairo_gdk_pixmap_key;
|
||||
static void do_gdk_pixmap_unref (void *data)
|
||||
static cairo_user_data_key_t cairo_gdk_drawable_key;
|
||||
static void do_gdk_drawable_unref (void *data)
|
||||
{
|
||||
GdkPixmap *pmap = (GdkPixmap*)data;
|
||||
gdk_pixmap_unref (pmap);
|
||||
GdkDrawable *d = (GdkDrawable*) data;
|
||||
g_object_unref (d);
|
||||
}
|
||||
|
||||
gfxPlatformGtk::gfxPlatformGtk()
|
||||
|
@ -212,17 +211,16 @@ gfxPlatformGtk::CreateOffscreenSurface(const gfxIntSize& size,
|
|||
if (newSurface && newSurface->CairoStatus() == 0) {
|
||||
// set up the surface to auto-unref the gdk pixmap when
|
||||
// the surface is released
|
||||
newSurface->SetData(&cairo_gdk_pixmap_key,
|
||||
pixmap,
|
||||
do_gdk_pixmap_unref);
|
||||
SetGdkDrawable(newSurface, GDK_DRAWABLE(pixmap));
|
||||
} else {
|
||||
// something went wrong with the surface creation.
|
||||
// Ignore and let's fall back to image surfaces.
|
||||
if (pixmap)
|
||||
gdk_pixmap_unref(pixmap);
|
||||
newSurface = nsnull;
|
||||
}
|
||||
|
||||
// always unref; SetGdkDrawable takes its own ref
|
||||
if (pixmap)
|
||||
g_object_unref(pixmap);
|
||||
}
|
||||
|
||||
if (!newSurface) {
|
||||
|
@ -722,18 +720,109 @@ gfxPlatformGtk::SetGdkDrawable(gfxASurface *target,
|
|||
if (target->CairoStatus())
|
||||
return;
|
||||
|
||||
gdk_drawable_ref(drawable);
|
||||
|
||||
cairo_surface_set_user_data (target->CairoSurface(),
|
||||
&cairo_gdk_drawable_key,
|
||||
drawable,
|
||||
NULL);
|
||||
do_gdk_drawable_unref);
|
||||
}
|
||||
|
||||
#ifdef MOZ_X11
|
||||
// Look for an existing Colormap that is known to be associated with visual.
|
||||
static GdkColormap *
|
||||
LookupGdkColormapForVisual(const Screen* screen, const Visual* visual)
|
||||
{
|
||||
Display* dpy = DisplayOfScreen(screen);
|
||||
GdkDisplay* gdkDpy = gdk_x11_lookup_xdisplay(dpy);
|
||||
if (!gdkDpy)
|
||||
return NULL;
|
||||
|
||||
// I wish there were a gdk_x11_display_lookup_screen.
|
||||
gint screen_num = 0;
|
||||
for (int s = 0; s < ScreenCount(dpy); ++s) {
|
||||
if (ScreenOfDisplay(dpy, s) == screen) {
|
||||
screen_num = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
GdkScreen* gdkScreen = gdk_display_get_screen(gdkDpy, screen_num);
|
||||
|
||||
// Common case: the display's default colormap
|
||||
if (visual ==
|
||||
GDK_VISUAL_XVISUAL(gdk_screen_get_system_visual(gdkScreen)))
|
||||
return gdk_screen_get_system_colormap(gdkScreen);
|
||||
|
||||
// widget/src/gtk2/mozcontainer.c uses gdk_rgb_get_colormap()
|
||||
// which is inherited by child widgets, so this is the visual
|
||||
// expected when drawing directly to widget surfaces or surfaces
|
||||
// created using cairo_surface_create_similar with
|
||||
// CAIRO_CONTENT_COLOR.
|
||||
// gdk_screen_get_rgb_colormap is the generalization of
|
||||
// gdk_rgb_get_colormap for any screen.
|
||||
if (visual ==
|
||||
GDK_VISUAL_XVISUAL(gdk_screen_get_rgb_visual(gdkScreen)))
|
||||
return gdk_screen_get_rgb_colormap(gdkScreen);
|
||||
|
||||
// This is the visual expected on displays with the Composite
|
||||
// extension enabled when the surface has been created using
|
||||
// cairo_surface_create_similar with CAIRO_CONTENT_COLOR_ALPHA,
|
||||
// as happens with non-unit opacity.
|
||||
if (visual ==
|
||||
GDK_VISUAL_XVISUAL(gdk_screen_get_rgba_visual(gdkScreen)))
|
||||
return gdk_screen_get_rgba_colormap(gdkScreen);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
GdkDrawable *
|
||||
gfxPlatformGtk::GetGdkDrawable(gfxASurface *target)
|
||||
{
|
||||
if (target->CairoStatus())
|
||||
return nsnull;
|
||||
|
||||
return (GdkDrawable*) cairo_surface_get_user_data (target->CairoSurface(),
|
||||
GdkDrawable *result;
|
||||
|
||||
result = (GdkDrawable*) cairo_surface_get_user_data (target->CairoSurface(),
|
||||
&cairo_gdk_drawable_key);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
if (target->GetType() == gfxASurface::SurfaceTypeXlib) {
|
||||
gfxXlibSurface *xs = (gfxXlibSurface*) target;
|
||||
|
||||
// try looking it up in gdk's table
|
||||
result = (GdkDrawable*) gdk_xid_table_lookup(xs->XDrawable());
|
||||
if (result) {
|
||||
SetGdkDrawable(target, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// If all else fails, try doing a foreign_new
|
||||
// but don't bother if we can't get a colormap.
|
||||
// Without a colormap GDK won't know how to draw.
|
||||
Screen *screen = cairo_xlib_surface_get_screen(xs->CairoSurface());
|
||||
Visual *visual = cairo_xlib_surface_get_visual(xs->CairoSurface());
|
||||
GdkColormap *cmap = LookupGdkColormapForVisual(screen, visual);
|
||||
if (cmap == None)
|
||||
return nsnull;
|
||||
|
||||
result = (GdkDrawable*) gdk_pixmap_foreign_new_for_display
|
||||
(gdk_display_get_default(), xs->XDrawable());
|
||||
if (result) {
|
||||
gdk_drawable_set_colormap(result, cmap);
|
||||
|
||||
SetGdkDrawable(target, result);
|
||||
// Release our ref. The object is held by target. Caller will
|
||||
// only need to ref if it wants to keep the drawable longer than
|
||||
// target.
|
||||
g_object_unref(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
|
|
@ -1730,7 +1730,8 @@ nsWindow::OnExposeEvent(GtkWidget *aWidget, GdkEventExpose *aEvent)
|
|||
// do double-buffering and clipping here
|
||||
nsRefPtr<gfxContext> ctx = rc->ThebesContext();
|
||||
|
||||
gfxPlatformGtk::GetPlatform()->SetGdkDrawable(ctx->OriginalSurface(), GDK_DRAWABLE(mDrawingarea->inner_window));
|
||||
gfxPlatformGtk::GetPlatform()->SetGdkDrawable(ctx->OriginalSurface(),
|
||||
GDK_DRAWABLE(mDrawingarea->inner_window));
|
||||
|
||||
// clip to the update region
|
||||
ctx->Save();
|
||||
|
@ -1800,6 +1801,7 @@ nsWindow::OnExposeEvent(GtkWidget *aWidget, GdkEventExpose *aEvent)
|
|||
gfxPlatformGtk::GetPlatform()->SetGdkDrawable(
|
||||
static_cast<gfxASurface *>(bufferPixmapSurface),
|
||||
GDK_DRAWABLE(bufferPixmap));
|
||||
|
||||
bufferPixmapSurface->SetDeviceOffset(gfxPoint(-boundsRect.x, -boundsRect.y));
|
||||
nsCOMPtr<nsIRenderingContext> newRC;
|
||||
nsresult rv = GetDeviceContext()->
|
||||
|
|
Загрузка…
Ссылка в новой задаче