Added a fix for mozbz#1127752 (rhbz#1256875) - Gtk3&OMTC crashes

This commit is contained in:
Martin Stransky 2015-08-26 14:22:17 +02:00
parent 40baf8ef48
commit 571fefe2c8
2 changed files with 947 additions and 1 deletions

View File

@ -91,7 +91,7 @@
Summary: Mozilla Firefox Web browser
Name: firefox
Version: 40.0
Release: 9%{?pre_tag}%{?dist}
Release: 10%{?pre_tag}%{?dist}
URL: http://www.mozilla.org/projects/firefox/
License: MPLv1.1 or GPLv2+ or LGPLv2+
Group: Applications/Internet
@ -138,6 +138,7 @@ Patch422: mozilla-1169232.patch
Patch423: mozilla-1129873-apppicker.patch
Patch424: mozilla-entry-padding.patch
Patch425: mozilla-1192243.patch
Patch426: mozilla-1127752.patch
# Fix Skia Neon stuff on AArch64
Patch500: aarch64-fix-skia.patch
@ -285,6 +286,7 @@ cd %{tarballdir}
%patch423 -p1 -b .1129873-apppicker
%patch424 -p2 -b .entry-padding
%patch425 -p1 -b .1192243
%patch426 -p2 -b .1127752
%endif
%patch500 -p1
@ -777,6 +779,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
#---------------------------------------------------------------------
%changelog
* Wed Aug 26 2015 Martin Stransky <stransky@redhat.com> - 40.0-10
- Added a fix for mozbz#1127752 (rhbz#1256875) - Gtk3&OMTC crashes
* Tue Aug 25 2015 Martin Stransky <stransky@redhat.com> - 40.0-9
- Enabled hardened builds

941
mozilla-1127752.patch Normal file
View File

@ -0,0 +1,941 @@
diff -up firefox-40.0/mozilla-release/gfx/2d/BorrowedContext.h.1127752 firefox-40.0/mozilla-release/gfx/2d/BorrowedContext.h
--- firefox-40.0/mozilla-release/gfx/2d/BorrowedContext.h.1127752 2015-08-07 17:54:22.000000000 +0200
+++ firefox-40.0/mozilla-release/gfx/2d/BorrowedContext.h 2015-08-26 14:07:24.666087911 +0200
@@ -8,6 +8,11 @@
#include "2D.h"
+#ifdef MOZ_X11
+#include <X11/extensions/Xrender.h>
+#include <X11/Xlib.h>
+#endif
+
struct _cairo;
typedef struct _cairo cairo_t;
@@ -69,6 +74,69 @@ private:
DrawTarget *mDT;
};
+#ifdef MOZ_X11
+/* This is a helper class that let's you borrow an Xlib drawable from
+ * a DrawTarget. This is used for drawing themed widgets.
+ *
+ * Callers should check the Xlib drawable after constructing the object
+ * to see if it succeeded. The DrawTarget should not be used while
+ * the drawable is borrowed. */
+class BorrowedXlibDrawable
+{
+public:
+ BorrowedXlibDrawable()
+ : mDT(nullptr),
+ mDisplay(nullptr),
+ mDrawable(None),
+ mScreen(nullptr),
+ mVisual(nullptr),
+ mXRenderFormat(nullptr)
+ {}
+
+ explicit BorrowedXlibDrawable(DrawTarget *aDT)
+ : mDT(nullptr),
+ mDisplay(nullptr),
+ mDrawable(None),
+ mScreen(nullptr),
+ mVisual(nullptr),
+ mXRenderFormat(nullptr)
+ {
+ Init(aDT);
+ }
+
+ // We can optionally Init after construction in
+ // case we don't know what the DT will be at construction
+ // time.
+ bool Init(DrawTarget *aDT);
+
+ // The caller needs to call Finish if drawable is non-zero when
+ // they are done with the context. This is currently explicit
+ // instead of happening implicitly in the destructor to make
+ // what's happening in the caller more clear. It also
+ // let's you resume using the DrawTarget in the same scope.
+ void Finish();
+
+ ~BorrowedXlibDrawable() {
+ MOZ_ASSERT(!mDrawable);
+ }
+
+ Display *GetDisplay() const { return mDisplay; }
+ Drawable GetDrawable() const { return mDrawable; }
+ Screen *GetScreen() const { return mScreen; }
+ Visual *GetVisual() const { return mVisual; }
+
+ XRenderPictFormat* GetXRenderFormat() const { return mXRenderFormat; }
+
+private:
+ DrawTarget *mDT;
+ Display *mDisplay;
+ Drawable mDrawable;
+ Screen *mScreen;
+ Visual *mVisual;
+ XRenderPictFormat *mXRenderFormat;
+};
+#endif
+
#ifdef XP_MACOSX
/* This is a helper class that let's you borrow a CGContextRef from a
* DrawTargetCG. This is used for drawing themed widgets.
diff -up firefox-40.0/mozilla-release/gfx/2d/DrawTargetCairo.cpp.1127752 firefox-40.0/mozilla-release/gfx/2d/DrawTargetCairo.cpp
--- firefox-40.0/mozilla-release/gfx/2d/DrawTargetCairo.cpp.1127752 2015-08-07 17:54:22.000000000 +0200
+++ firefox-40.0/mozilla-release/gfx/2d/DrawTargetCairo.cpp 2015-08-26 14:07:24.666087911 +0200
@@ -1714,5 +1714,50 @@ BorrowedCairoContext::ReturnCairoContext
cairoDT->mContext = aCairo;
}
+#ifdef MOZ_X11
+bool
+BorrowedXlibDrawable::Init(DrawTarget* aDT)
+{
+ MOZ_ASSERT(aDT, "Caller should check for nullptr");
+ MOZ_ASSERT(!mDT, "Can't initialize twice!");
+ mDT = aDT;
+ mDrawable = None;
+
+#ifdef CAIRO_HAS_XLIB_SURFACE
+ if (aDT->GetBackendType() != BackendType::CAIRO ||
+ aDT->IsDualDrawTarget() ||
+ aDT->IsTiledDrawTarget()) {
+ return false;
+ }
+
+ DrawTargetCairo* cairoDT = static_cast<DrawTargetCairo*>(aDT);
+ cairo_surface_t* surf = cairoDT->mSurface;
+ if (cairo_surface_get_type(surf) != CAIRO_SURFACE_TYPE_XLIB) {
+ return false;
+ }
+
+ cairoDT->WillChange();
+
+ mDisplay = cairo_xlib_surface_get_display(surf);
+ mDrawable = cairo_xlib_surface_get_drawable(surf);
+ mScreen = cairo_xlib_surface_get_screen(surf);
+ mVisual = cairo_xlib_surface_get_visual(surf);
+ mXRenderFormat = cairo_xlib_surface_get_xrender_format(surf);
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+void
+BorrowedXlibDrawable::Finish()
+{
+ if (mDrawable) {
+ mDrawable = None;
+ }
+}
+#endif
+
}
}
diff -up firefox-40.0/mozilla-release/gfx/2d/DrawTargetCairo.h.1127752 firefox-40.0/mozilla-release/gfx/2d/DrawTargetCairo.h
--- firefox-40.0/mozilla-release/gfx/2d/DrawTargetCairo.h.1127752 2015-08-07 17:54:22.000000000 +0200
+++ firefox-40.0/mozilla-release/gfx/2d/DrawTargetCairo.h 2015-08-26 14:07:24.666087911 +0200
@@ -54,6 +54,7 @@ class DrawTargetCairo final : public Dra
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetCairo, override)
friend class BorrowedCairoContext;
+ friend class BorrowedXlibDrawable;
DrawTargetCairo();
virtual ~DrawTargetCairo();
diff -up firefox-40.0/mozilla-release/gfx/2d/DrawTargetSkia.cpp.1127752 firefox-40.0/mozilla-release/gfx/2d/DrawTargetSkia.cpp
--- firefox-40.0/mozilla-release/gfx/2d/DrawTargetSkia.cpp.1127752 2015-08-07 17:54:22.000000000 +0200
+++ firefox-40.0/mozilla-release/gfx/2d/DrawTargetSkia.cpp 2015-08-26 14:07:24.667087889 +0200
@@ -148,6 +148,35 @@ DrawTargetSkia::Snapshot()
return snapshot.forget();
}
+bool
+DrawTargetSkia::LockBits(uint8_t** aData, IntSize* aSize,
+ int32_t* aStride, SurfaceFormat* aFormat)
+{
+ const SkBitmap &bitmap = mCanvas->getDevice()->accessBitmap(false);
+ if (!bitmap.lockPixelsAreWritable()) {
+ return false;
+ }
+
+ MarkChanged();
+
+ bitmap.lockPixels();
+ *aData = reinterpret_cast<uint8_t*>(bitmap.getPixels());
+ *aSize = IntSize(bitmap.width(), bitmap.height());
+ *aStride = int32_t(bitmap.rowBytes());
+ *aFormat = SkiaColorTypeToGfxFormat(bitmap.colorType());
+ return true;
+}
+
+void
+DrawTargetSkia::ReleaseBits(uint8_t* aData)
+{
+ const SkBitmap &bitmap = mCanvas->getDevice()->accessBitmap(false);
+ MOZ_ASSERT(bitmap.lockPixelsAreWritable());
+
+ bitmap.unlockPixels();
+ bitmap.notifyPixelsChanged();
+}
+
static void
SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, TempBitmap& aTmpBitmap,
Float aAlpha = 1.0)
@@ -688,10 +717,10 @@ DrawTargetSkia::CreateSourceSurfaceFromN
cairo_surface_t* surf = static_cast<cairo_surface_t*>(aSurface.mSurface);
return new SourceSurfaceCairo(surf, aSurface.mSize, aSurface.mFormat);
#if USE_SKIA_GPU
- } else if (aSurface.mType == NativeSurfaceType::OPENGL_TEXTURE) {
+ } else if (aSurface.mType == NativeSurfaceType::OPENGL_TEXTURE && UsingSkiaGPU()) {
RefPtr<SourceSurfaceSkia> newSurf = new SourceSurfaceSkia();
unsigned int texture = (unsigned int)((uintptr_t)aSurface.mSurface);
- if (UsingSkiaGPU() && newSurf->InitFromTexture((DrawTargetSkia*)this, texture, aSurface.mSize, aSurface.mFormat)) {
+ if (newSurf->InitFromTexture((DrawTargetSkia*)this, texture, aSurface.mSize, aSurface.mFormat)) {
return newSurf;
}
return nullptr;
diff -up firefox-40.0/mozilla-release/gfx/2d/DrawTargetSkia.h.1127752 firefox-40.0/mozilla-release/gfx/2d/DrawTargetSkia.h
--- firefox-40.0/mozilla-release/gfx/2d/DrawTargetSkia.h.1127752 2015-08-07 17:54:22.000000000 +0200
+++ firefox-40.0/mozilla-release/gfx/2d/DrawTargetSkia.h 2015-08-26 14:07:24.667087889 +0200
@@ -36,6 +36,9 @@ public:
virtual BackendType GetBackendType() const override { return BackendType::SKIA; }
virtual TemporaryRef<SourceSurface> Snapshot() override;
virtual IntSize GetSize() override { return mSize; }
+ virtual bool LockBits(uint8_t** aData, IntSize* aSize,
+ int32_t* aStride, SurfaceFormat* aFormat) override;
+ virtual void ReleaseBits(uint8_t* aData) override;
virtual void Flush() override;
virtual void DrawSurface(SourceSurface *aSurface,
const Rect &aDest,
diff -up firefox-40.0/mozilla-release/gfx/2d/moz.build.1127752 firefox-40.0/mozilla-release/gfx/2d/moz.build
--- firefox-40.0/mozilla-release/gfx/2d/moz.build.1127752 2015-08-07 17:54:22.000000000 +0200
+++ firefox-40.0/mozilla-release/gfx/2d/moz.build 2015-08-26 14:07:24.667087889 +0200
@@ -79,6 +79,7 @@ if CONFIG['MOZ_ENABLE_SKIA']:
'image_operations.cpp', # Uses _USE_MATH_DEFINES
]
EXPORTS.mozilla.gfx += [
+ 'HelpersCairo.h',
'HelpersSkia.h',
]
diff -up firefox-40.0/mozilla-release/gfx/layers/basic/BasicCompositor.cpp.1127752 firefox-40.0/mozilla-release/gfx/layers/basic/BasicCompositor.cpp
--- firefox-40.0/mozilla-release/gfx/layers/basic/BasicCompositor.cpp.1127752 2015-08-07 17:54:22.000000000 +0200
+++ firefox-40.0/mozilla-release/gfx/layers/basic/BasicCompositor.cpp 2015-08-26 14:07:24.667087889 +0200
@@ -523,7 +523,7 @@ BasicCompositor::BeginFrame(const nsIntR
RefPtr<CompositingRenderTarget> target = CreateRenderTarget(mInvalidRect, INIT_MODE_CLEAR);
if (!target) {
if (!mTarget) {
- mWidget->EndRemoteDrawing();
+ mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion);
}
return;
}
@@ -585,7 +585,7 @@ BasicCompositor::EndFrame()
IntPoint(r->x - offset.x, r->y - offset.y));
}
if (!mTarget) {
- mWidget->EndRemoteDrawing();
+ mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion);
}
mDrawTarget = nullptr;
diff -up firefox-40.0/mozilla-release/gfx/src/nsRegion.h.1127752 firefox-40.0/mozilla-release/gfx/src/nsRegion.h
--- firefox-40.0/mozilla-release/gfx/src/nsRegion.h.1127752 2015-08-07 17:54:05.000000000 +0200
+++ firefox-40.0/mozilla-release/gfx/src/nsRegion.h 2015-08-26 14:07:24.667087889 +0200
@@ -715,6 +715,12 @@ public:
return This();
}
+ Derived& ScaleInverseRoundOut (float aXScale, float aYScale)
+ {
+ mImpl.ScaleInverseRoundOut(aXScale, aYScale);
+ return This();
+ }
+
Derived& Transform (const gfx3DMatrix &aTransform)
{
mImpl.Transform(aTransform);
diff -up firefox-40.0/mozilla-release/gfx/thebes/gfxContext.cpp.1127752 firefox-40.0/mozilla-release/gfx/thebes/gfxContext.cpp
--- firefox-40.0/mozilla-release/gfx/thebes/gfxContext.cpp.1127752 2015-08-07 17:54:05.000000000 +0200
+++ firefox-40.0/mozilla-release/gfx/thebes/gfxContext.cpp 2015-08-26 14:07:24.668087868 +0200
@@ -619,6 +619,23 @@ gfxContext::GetClipExtents()
}
bool
+gfxContext::HasComplexClip() const
+{
+ for (int i = mStateStack.Length() - 1; i >= 0; i--) {
+ for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) {
+ const AzureState::PushedClip &clip = mStateStack[i].pushedClips[c];
+ if (clip.path || !clip.transform.IsRectilinear()) {
+ return true;
+ }
+ }
+ if (mStateStack[i].clipWasReset) {
+ break;
+ }
+ }
+ return false;
+}
+
+bool
gfxContext::ClipContainsRect(const gfxRect& aRect)
{
unsigned int lastReset = 0;
diff -up firefox-40.0/mozilla-release/gfx/thebes/gfxContext.h.1127752 firefox-40.0/mozilla-release/gfx/thebes/gfxContext.h
--- firefox-40.0/mozilla-release/gfx/thebes/gfxContext.h.1127752 2015-08-07 17:54:05.000000000 +0200
+++ firefox-40.0/mozilla-release/gfx/thebes/gfxContext.h 2015-08-26 14:07:24.668087868 +0200
@@ -446,6 +446,11 @@ public:
gfxRect GetClipExtents();
/**
+ * Whether the current clip is not a simple rectangle.
+ */
+ bool HasComplexClip() const;
+
+ /**
* Returns true if the given rectangle is fully contained in the current clip.
* This is conservative; it may return false even when the given rectangle is
* fully contained by the current clip.
diff -up firefox-40.0/mozilla-release/widget/gtk/nsNativeThemeGTK.cpp.1127752 firefox-40.0/mozilla-release/widget/gtk/nsNativeThemeGTK.cpp
--- firefox-40.0/mozilla-release/widget/gtk/nsNativeThemeGTK.cpp.1127752 2015-08-26 14:07:24.657088105 +0200
+++ firefox-40.0/mozilla-release/widget/gtk/nsNativeThemeGTK.cpp 2015-08-26 14:07:24.669087846 +0200
@@ -33,6 +33,18 @@
#include "gfxContext.h"
#include "gfxPlatformGtk.h"
#include "gfxGdkNativeRenderer.h"
+#include "mozilla/gfx/BorrowedContext.h"
+#include "mozilla/gfx/HelpersCairo.h"
+
+#ifdef MOZ_X11
+# ifdef CAIRO_HAS_XLIB_SURFACE
+# include "cairo-xlib.h"
+# endif
+# ifdef CAIRO_HAS_XLIB_XRENDER_SURFACE
+# include "cairo-xlib-xrender.h"
+# endif
+#endif
+
#include <algorithm>
#include <dlfcn.h>
@@ -706,6 +718,158 @@ ThemeRenderer::DrawWithGDK(GdkDrawable *
return NS_OK;
}
+#else
+static void
+DrawThemeWithCairo(gfxContext* aContext, DrawTarget* aDrawTarget,
+ GtkWidgetState aState, GtkThemeWidgetType aGTKWidgetType,
+ gint aFlags, GtkTextDirection aDirection, gint aScaleFactor,
+ bool aSnapped, const Point& aDrawOrigin, const nsIntSize& aDrawSize,
+ GdkRectangle& aGDKRect, nsITheme::Transparency aTransparency)
+{
+#ifndef MOZ_TREE_CAIRO
+ // Directly use the Cairo draw target to render the widget if using system Cairo everywhere.
+ BorrowedCairoContext borrow(aDrawTarget);
+ if (borrow.mCairo) {
+ if (aSnapped) {
+ cairo_identity_matrix(borrow.mCairo);
+ }
+ if (aDrawOrigin != Point(0, 0)) {
+ cairo_translate(borrow.mCairo, aDrawOrigin.x, aDrawOrigin.y);
+ }
+ if (aScaleFactor != 1) {
+ cairo_scale(borrow.mCairo, aScaleFactor, aScaleFactor);
+ }
+
+ moz_gtk_widget_paint(aGTKWidgetType, borrow.mCairo, &aGDKRect, &aState, aFlags, aDirection);
+
+ borrow.Finish();
+ return;
+ }
+#endif
+
+ // A direct Cairo draw target is not available, so we need to create a temporary one.
+ bool needClip = !aSnapped || aContext->HasComplexClip();
+#if defined(MOZ_X11) && defined(CAIRO_HAS_XLIB_SURFACE)
+ if (!needClip) {
+ // If using a Cairo xlib surface, then try to reuse it.
+ BorrowedXlibDrawable borrow(aDrawTarget);
+ if (borrow.GetDrawable()) {
+ nsIntSize size = aDrawTarget->GetSize();
+ cairo_surface_t* surf = nullptr;
+ // Check if the surface is using XRender.
+#ifdef CAIRO_HAS_XLIB_XRENDER_SURFACE
+ if (borrow.GetXRenderFormat()) {
+ surf = cairo_xlib_surface_create_with_xrender_format(
+ borrow.GetDisplay(), borrow.GetDrawable(), borrow.GetScreen(),
+ borrow.GetXRenderFormat(), size.width, size.height);
+ } else {
+#else
+ if (! borrow.GetXRenderFormat()) {
+#endif
+ surf = cairo_xlib_surface_create(
+ borrow.GetDisplay(), borrow.GetDrawable(), borrow.GetVisual(),
+ size.width, size.height);
+ }
+ if (!NS_WARN_IF(!surf)) {
+ cairo_t* cr = cairo_create(surf);
+ if (!NS_WARN_IF(!cr)) {
+ cairo_new_path(cr);
+ cairo_rectangle(cr, aDrawOrigin.x, aDrawOrigin.y, aDrawSize.width, aDrawSize.height);
+ cairo_clip(cr);
+ if (aDrawOrigin != Point(0, 0)) {
+ cairo_translate(cr, aDrawOrigin.x, aDrawOrigin.y);
+ }
+ if (aScaleFactor != 1) {
+ cairo_scale(cr, aScaleFactor, aScaleFactor);
+ }
+
+ moz_gtk_widget_paint(aGTKWidgetType, cr, &aGDKRect, &aState, aFlags, aDirection);
+
+ cairo_destroy(cr);
+ }
+ cairo_surface_destroy(surf);
+ }
+ borrow.Finish();
+ return;
+ }
+ }
+#endif
+
+ // Check if the widget requires complex masking that must be composited.
+ // Try to directly write to the draw target's pixels if possible.
+ uint8_t* data;
+ nsIntSize size;
+ int32_t stride;
+ SurfaceFormat format;
+ if (!needClip && aDrawTarget->LockBits(&data, &size, &stride, &format)) {
+ // Create a Cairo image surface context the device rectangle.
+ cairo_surface_t* surf =
+ cairo_image_surface_create_for_data(
+ data + int32_t(aDrawOrigin.y) * stride + int32_t(aDrawOrigin.x) * BytesPerPixel(format),
+ GfxFormatToCairoFormat(format), aDrawSize.width, aDrawSize.height, stride);
+ if (!NS_WARN_IF(!surf)) {
+ cairo_t* cr = cairo_create(surf);
+ if (!NS_WARN_IF(!cr)) {
+ if (aScaleFactor != 1) {
+ cairo_scale(cr, aScaleFactor, aScaleFactor);
+ }
+
+ moz_gtk_widget_paint(aGTKWidgetType, cr, &aGDKRect, &aState, aFlags, aDirection);
+
+ cairo_destroy(cr);
+ }
+ cairo_surface_destroy(surf);
+ }
+ aDrawTarget->ReleaseBits(data);
+ } else {
+ // If the widget has any transparency, make sure to choose an alpha format.
+ format = aTransparency != nsITheme::eOpaque ? SurfaceFormat::B8G8R8A8 : aDrawTarget->GetFormat();
+ // Create a temporary data surface to render the widget into.
+ RefPtr<DataSourceSurface> dataSurface =
+ Factory::CreateDataSourceSurface(aDrawSize, format, aTransparency != nsITheme::eOpaque);
+ DataSourceSurface::MappedSurface map;
+ if (!NS_WARN_IF(!(dataSurface && dataSurface->Map(DataSourceSurface::MapType::WRITE, &map)))) {
+ // Create a Cairo image surface wrapping the data surface.
+ cairo_surface_t* surf =
+ cairo_image_surface_create_for_data(map.mData, GfxFormatToCairoFormat(format),
+ aDrawSize.width, aDrawSize.height, map.mStride);
+ cairo_t* cr = nullptr;
+ if (!NS_WARN_IF(!surf)) {
+ cr = cairo_create(surf);
+ if (!NS_WARN_IF(!cr)) {
+ if (aScaleFactor != 1) {
+ cairo_scale(cr, aScaleFactor, aScaleFactor);
+ }
+
+ moz_gtk_widget_paint(aGTKWidgetType, cr, &aGDKRect, &aState, aFlags, aDirection);
+ }
+ }
+
+ // Unmap the surface before using it as a source
+ dataSurface->Unmap();
+
+ if (cr) {
+ if (needClip || aTransparency != nsITheme::eOpaque) {
+ // The widget either needs to be masked or has transparency, so use the slower drawing path.
+ aDrawTarget->DrawSurface(dataSurface,
+ Rect(aDrawOrigin, Size(aDrawSize)),
+ Rect(0, 0, aDrawSize.width, aDrawSize.height));
+ } else {
+ // The widget is a simple opaque rectangle, so just copy it out.
+ aDrawTarget->CopySurface(dataSurface,
+ IntRect(0, 0, aDrawSize.width, aDrawSize.height),
+ TruncatedToInt(aDrawOrigin));
+ }
+
+ cairo_destroy(cr);
+ }
+
+ if (surf) {
+ cairo_surface_destroy(surf);
+ }
+ }
+ }
+}
#endif
bool
@@ -800,10 +964,6 @@ nsNativeThemeGTK::DrawWidgetBackground(n
const nsRect& aRect,
const nsRect& aDirtyRect)
{
-#if (MOZ_WIDGET_GTK != 2)
- DrawTarget& aDrawTarget = *aContext->GetDrawTarget();
-#endif
-
GtkWidgetState state;
GtkThemeWidgetType gtkWidgetType;
GtkTextDirection direction = GetTextDirection(aFrame);
@@ -823,8 +983,8 @@ nsNativeThemeGTK::DrawWidgetBackground(n
// to provide crisper and faster drawing.
// Don't snap if it's a non-unit scale factor. We're going to have to take
// slow paths then in any case.
- bool snapXY = ctx->UserToDevicePixelSnapped(rect);
- if (snapXY) {
+ bool snapped = ctx->UserToDevicePixelSnapped(rect);
+ if (snapped) {
// Leave rect in device coords but make dirtyRect consistent.
dirtyRect = ctx->UserToDevice(dirtyRect);
}
@@ -853,23 +1013,6 @@ nsNativeThemeGTK::DrawWidgetBackground(n
|| !drawingRect.IntersectRect(overflowRect, drawingRect))
return NS_OK;
- // gdk rectangles are wrt the drawing rect.
-
- GdkRectangle gdk_rect = {-drawingRect.x/scaleFactor,
- -drawingRect.y/scaleFactor,
- widgetRect.width/scaleFactor,
- widgetRect.height/scaleFactor};
-
- // translate everything so (0,0) is the top left of the drawingRect
- gfxContextAutoSaveRestore autoSR(ctx);
- gfxMatrix tm;
- if (!snapXY) { // else rects are in device coords
- tm = ctx->CurrentMatrix();
- }
- tm.Translate(rect.TopLeft() + gfxPoint(drawingRect.x, drawingRect.y));
- tm.Scale(scaleFactor, scaleFactor); // Draw in GDK coords
- ctx->SetMatrix(tm);
-
NS_ASSERTION(!IsWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType),
"Trying to render an unsafe widget!");
@@ -879,7 +1022,27 @@ nsNativeThemeGTK::DrawWidgetBackground(n
gdk_error_trap_push ();
}
+ Transparency transparency = GetWidgetTransparency(aFrame, aWidgetType);
+
+ // gdk rectangles are wrt the drawing rect.
+ GdkRectangle gdk_rect = {-drawingRect.x/scaleFactor,
+ -drawingRect.y/scaleFactor,
+ widgetRect.width/scaleFactor,
+ widgetRect.height/scaleFactor};
+
+ // translate everything so (0,0) is the top left of the drawingRect
+ gfxPoint origin = rect.TopLeft() + drawingRect.TopLeft();
+
#if (MOZ_WIDGET_GTK == 2)
+ gfxContextAutoSaveRestore autoSR(ctx);
+ gfxMatrix matrix;
+ if (!snapped) { // else rects are in device coords
+ matrix = ctx->CurrentMatrix();
+ }
+ matrix.Translate(origin);
+ matrix.Scale(scaleFactor, scaleFactor); // Draw in GDK coords
+ ctx->SetMatrix(matrix);
+
// The gdk_clip is just advisory here, meaning "you don't
// need to draw outside this rect if you don't feel like it!"
GdkRectangle gdk_clip = {0, 0, drawingRect.width, drawingRect.height};
@@ -891,7 +1054,7 @@ nsNativeThemeGTK::DrawWidgetBackground(n
// clip rect we provide, so we cannot advertise support for clipping within
// the widget bounds.
uint32_t rendererFlags = 0;
- if (GetWidgetTransparency(aFrame, aWidgetType) == eOpaque) {
+ if (transparency == eOpaque) {
rendererFlags |= gfxGdkNativeRenderer::DRAW_IS_OPAQUE;
}
@@ -901,11 +1064,10 @@ nsNativeThemeGTK::DrawWidgetBackground(n
renderer.Draw(ctx, drawingRect.Size(), rendererFlags, colormap);
#else
- cairo_t *cairo_ctx =
- (cairo_t*)aDrawTarget.GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT);
- MOZ_ASSERT(cairo_ctx);
- moz_gtk_widget_paint(gtkWidgetType, cairo_ctx, &gdk_rect,
- &state, flags, direction);
+ DrawThemeWithCairo(ctx, aContext->GetDrawTarget(),
+ state, gtkWidgetType, flags, direction, scaleFactor,
+ snapped, ToPoint(origin), drawingRect.Size(),
+ gdk_rect, transparency);
#endif
if (!safeState) {
diff -up firefox-40.0/mozilla-release/widget/gtk/nsScreenGtk.cpp.1127752 firefox-40.0/mozilla-release/widget/gtk/nsScreenGtk.cpp
--- firefox-40.0/mozilla-release/widget/gtk/nsScreenGtk.cpp.1127752 2015-08-07 17:54:22.000000000 +0200
+++ firefox-40.0/mozilla-release/widget/gtk/nsScreenGtk.cpp 2015-08-26 14:07:24.669087846 +0200
@@ -12,6 +12,7 @@
#endif
#include <gtk/gtk.h>
#include <dlfcn.h>
+#include "gfxPlatformGtk.h"
static uint32_t sScreenId = 0;
diff -up firefox-40.0/mozilla-release/widget/gtk/nsWindow.cpp.1127752 firefox-40.0/mozilla-release/widget/gtk/nsWindow.cpp
--- firefox-40.0/mozilla-release/widget/gtk/nsWindow.cpp.1127752 2015-08-07 17:54:22.000000000 +0200
+++ firefox-40.0/mozilla-release/widget/gtk/nsWindow.cpp 2015-08-26 14:07:24.670087825 +0200
@@ -2050,71 +2050,52 @@ gdk_window_flash(GdkWindow * aGdkWind
#endif // DEBUG
#endif
-struct ExposeRegion
-{
- nsIntRegion mRegion;
-
#if (MOZ_WIDGET_GTK == 2)
- GdkRectangle *mRects;
- GdkRectangle *mRectsEnd;
-
- ExposeRegion() : mRects(nullptr)
- {
- }
- ~ExposeRegion()
- {
- g_free(mRects);
- }
- bool Init(GdkEventExpose *aEvent)
- {
- gint nrects;
- gdk_region_get_rectangles(aEvent->region, &mRects, &nrects);
-
- if (nrects > MAX_RECTS_IN_REGION) {
- // Just use the bounding box
- mRects[0] = aEvent->area;
- nrects = 1;
- }
+static bool
+ExtractExposeRegion(nsIntRegion& aRegion, GdkEventExpose* aEvent)
+{
+ GdkRectangle* rects;
+ gint nrects;
+ gdk_region_get_rectangles(aEvent->region, &rects, &nrects);
+
+ if (nrects > MAX_RECTS_IN_REGION) {
+ // Just use the bounding box
+ rects[0] = aEvent->area;
+ nrects = 1;
+ }
- mRectsEnd = mRects + nrects;
+ for (GdkRectangle* r = rects; r < rects + nrects; r++) {
+ aRegion.Or(aRegion, nsIntRect(r->x, r->y, r->width, r->height));
+ LOGDRAW(("\t%d %d %d %d\n", r->x, r->y, r->width, r->height));
+ }
- for (GdkRectangle *r = mRects; r < mRectsEnd; r++) {
- mRegion.Or(mRegion, nsIntRect(r->x, r->y, r->width, r->height));
- LOGDRAW(("\t%d %d %d %d\n", r->x, r->y, r->width, r->height));
- }
- return true;
- }
+ g_free(rects);
+ return true;
+}
#else
# ifdef cairo_copy_clip_rectangle_list
# error "Looks like we're including Mozilla's cairo instead of system cairo"
# endif
- cairo_rectangle_list_t *mRects;
+static bool
+ExtractExposeRegion(nsIntRegion& aRegion, cairo_t* cr)
+{
+ cairo_rectangle_list_t* rects = cairo_copy_clip_rectangle_list(cr);
+ if (rects->status != CAIRO_STATUS_SUCCESS) {
+ NS_WARNING("Failed to obtain cairo rectangle list.");
+ return false;
+ }
- ExposeRegion() : mRects(nullptr)
- {
- }
- ~ExposeRegion()
- {
- cairo_rectangle_list_destroy(mRects);
- }
- bool Init(cairo_t* cr)
- {
- mRects = cairo_copy_clip_rectangle_list(cr);
- if (mRects->status != CAIRO_STATUS_SUCCESS) {
- NS_WARNING("Failed to obtain cairo rectangle list.");
- return false;
- }
+ for (int i = 0; i < rects->num_rectangles; i++) {
+ const cairo_rectangle_t& r = rects->rectangles[i];
+ aRegion.Or(aRegion, nsIntRect(r.x, r.y, r.width, r.height));
+ LOGDRAW(("\t%d %d %d %d\n", r.x, r.y, r.width, r.height));
+ }
- for (int i = 0; i < mRects->num_rectangles; i++) {
- const cairo_rectangle_t& r = mRects->rectangles[i];
- mRegion.Or(mRegion, nsIntRect(r.x, r.y, r.width, r.height));
- LOGDRAW(("\t%d %d %d %d\n", r.x, r.y, r.width, r.height));
- }
- return true;
- }
+ cairo_rectangle_list_destroy(rects);
+ return true;
+}
#endif
-};
#if (MOZ_WIDGET_GTK == 2)
gboolean
@@ -2137,17 +2118,17 @@ nsWindow::OnExposeEvent(cairo_t *cr)
if (!listener)
return FALSE;
- ExposeRegion exposeRegion;
+ nsIntRegion exposeRegion;
#if (MOZ_WIDGET_GTK == 2)
- if (!exposeRegion.Init(aEvent)) {
+ if (!ExtractExposeRegion(exposeRegion, aEvent)) {
#else
- if (!exposeRegion.Init(cr)) {
+ if (!ExtractExposeRegion(exposeRegion, cr)) {
#endif
return FALSE;
}
gint scale = GdkScaleFactor();
- nsIntRegion& region = exposeRegion.mRegion;
+ nsIntRegion region = exposeRegion;
region.ScaleRoundOut(scale, scale);
ClientLayerManager *clientLayers =
@@ -2240,33 +2221,11 @@ nsWindow::OnExposeEvent(cairo_t *cr)
return TRUE;
}
- gfxASurface* surf;
-#if (MOZ_WIDGET_GTK == 2)
- surf = GetThebesSurface();
-#else
- surf = GetThebesSurface(cr);
-#endif
-
- nsRefPtr<gfxContext> ctx;
- if (gfxPlatform::GetPlatform()->
- SupportsAzureContentForType(BackendType::CAIRO)) {
- IntSize intSize(surf->GetSize().width, surf->GetSize().height);
- RefPtr<DrawTarget> dt =
- gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surf, intSize);
- ctx = new gfxContext(dt);
- } else if (gfxPlatform::GetPlatform()->
- SupportsAzureContentForType(BackendType::SKIA) &&
- surf->GetType() == gfxSurfaceType::Image) {
- gfxImageSurface* imgSurf = static_cast<gfxImageSurface*>(surf);
- SurfaceFormat format = ImageFormatToSurfaceFormat(imgSurf->Format());
- IntSize intSize(surf->GetSize().width, surf->GetSize().height);
- RefPtr<DrawTarget> dt =
- gfxPlatform::GetPlatform()->CreateDrawTargetForData(
- imgSurf->Data(), intSize, imgSurf->Stride(), format);
- ctx = new gfxContext(dt);
- } else {
- MOZ_CRASH("Unexpected content type");
+ RefPtr<DrawTarget> dt = StartRemoteDrawing();
+ if(!dt) {
+ return FALSE;
}
+ nsRefPtr<gfxContext> ctx = new gfxContext(dt);
#ifdef MOZ_X11
nsIntRect boundsRect; // for shaped only
@@ -2341,11 +2300,7 @@ nsWindow::OnExposeEvent(cairo_t *cr)
}
# ifdef MOZ_HAVE_SHMIMAGE
if (mShmImage && MOZ_LIKELY(!mIsDestroyed)) {
-#if (MOZ_WIDGET_GTK == 2)
- mShmImage->Put(mGdkWindow, exposeRegion.mRects, exposeRegion.mRectsEnd);
-#else
- mShmImage->Put(mGdkWindow, exposeRegion.mRects);
-#endif
+ mShmImage->Put(mGdkWindow, exposeRegion);
}
# endif // MOZ_HAVE_SHMIMAGE
#endif // MOZ_X11
@@ -6262,24 +6217,49 @@ nsWindow::StartRemoteDrawing()
return nullptr;
}
- IntSize size(surf->GetSize().width, surf->GetSize().height);
+ nsIntSize size = surf->GetSize();
if (size.width <= 0 || size.height <= 0) {
return nullptr;
}
- return gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surf, size);
+ gfxPlatform *platform = gfxPlatform::GetPlatform();
+ if (platform->SupportsAzureContentForType(BackendType::CAIRO) ||
+ surf->GetType() == gfxSurfaceType::Xlib) {
+ return platform->CreateDrawTargetForSurface(surf, size);
+ } else if (platform->SupportsAzureContentForType(BackendType::SKIA) &&
+ surf->GetType() == gfxSurfaceType::Image) {
+ gfxImageSurface* imgSurf = static_cast<gfxImageSurface*>(surf);
+ SurfaceFormat format = ImageFormatToSurfaceFormat(imgSurf->Format());
+ return platform->CreateDrawTargetForData(
+ imgSurf->Data(), size, imgSurf->Stride(), format);
+ } else {
+ return nullptr;
+ }
}
-// return the gfxASurface for rendering to this widget
-gfxASurface*
-nsWindow::GetThebesSurface()
-#if (MOZ_WIDGET_GTK == 3)
+void
+nsWindow::EndRemoteDrawingInRegion(DrawTarget* aDrawTarget, nsIntRegion& aInvalidRegion)
{
- return GetThebesSurface(nullptr);
+#ifdef MOZ_X11
+# ifdef MOZ_HAVE_SHMIMAGE
+ if (!mGdkWindow || mIsFullyObscured || !mHasMappedToplevel || mIsDestroyed ||
+ !mShmImage)
+ return;
+
+ gint scale = GdkScaleFactor();
+ if (scale != 1) {
+ aInvalidRegion.ScaleInverseRoundOut(scale, scale);
+ }
+
+ mShmImage->Put(mGdkWindow, aInvalidRegion);
+
+# endif // MOZ_HAVE_SHMIMAGE
+#endif // MOZ_X11
}
+
+// return the gfxASurface for rendering to this widget
gfxASurface*
-nsWindow::GetThebesSurface(cairo_t *cr)
-#endif
+nsWindow::GetThebesSurface()
{
if (!mGdkWindow)
return nullptr;
diff -up firefox-40.0/mozilla-release/widget/gtk/nsWindow.h.1127752 firefox-40.0/mozilla-release/widget/gtk/nsWindow.h
--- firefox-40.0/mozilla-release/widget/gtk/nsWindow.h.1127752 2015-08-07 17:54:22.000000000 +0200
+++ firefox-40.0/mozilla-release/widget/gtk/nsWindow.h 2015-08-26 14:07:24.671087803 +0200
@@ -194,7 +194,10 @@ public:
guint aTime,
gpointer aData);
- mozilla::TemporaryRef<mozilla::gfx::DrawTarget> StartRemoteDrawing() override;
+ virtual mozilla::TemporaryRef<mozilla::gfx::DrawTarget>
+ StartRemoteDrawing() override;
+ virtual void EndRemoteDrawingInRegion(mozilla::gfx::DrawTarget* aDrawTarget,
+ nsIntRegion& aInvalidRegion) override;
private:
void UpdateAlpha(gfxPattern* aPattern, nsIntRect aBoundsRect);
@@ -467,9 +470,6 @@ private:
LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE,
LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
bool* aAllowRetaining = nullptr) override;
-#if (MOZ_WIDGET_GTK == 3)
- gfxASurface* GetThebesSurface(cairo_t *cr);
-#endif
void CleanLayerManagerRecursive();
diff -up firefox-40.0/mozilla-release/widget/nsIWidget.h.1127752 firefox-40.0/mozilla-release/widget/nsIWidget.h
--- firefox-40.0/mozilla-release/widget/nsIWidget.h.1127752 2015-08-26 14:07:24.671087803 +0200
+++ firefox-40.0/mozilla-release/widget/nsIWidget.h 2015-08-26 14:07:59.529337002 +0200
@@ -1657,6 +1657,9 @@ class nsIWidget : public nsISupports {
* after each composition.
*/
virtual void EndRemoteDrawing() = 0;
+ virtual void EndRemoteDrawingInRegion(mozilla::gfx::DrawTarget* aDrawTarget, nsIntRegion& aInvalidRegion) {
+ EndRemoteDrawing();
+ }
/**
* A hook for the widget to prepare a Compositor, during the latter's initialization.
diff -up firefox-40.0/mozilla-release/widget/nsShmImage.cpp.1127752 firefox-40.0/mozilla-release/widget/nsShmImage.cpp
--- firefox-40.0/mozilla-release/widget/nsShmImage.cpp.1127752 2015-08-07 17:54:22.000000000 +0200
+++ firefox-40.0/mozilla-release/widget/nsShmImage.cpp 2015-08-26 14:07:24.672087781 +0200
@@ -121,7 +121,7 @@ nsShmImage::AsSurface()
#if (MOZ_WIDGET_GTK == 2)
void
-nsShmImage::Put(GdkWindow* aWindow, GdkRectangle* aRects, GdkRectangle* aEnd)
+nsShmImage::Put(GdkWindow* aWindow, const nsIntRegion& aRegion)
{
GdkDrawable* gd;
gint dx, dy;
@@ -131,7 +131,8 @@ nsShmImage::Put(GdkWindow* aWindow, GdkR
Drawable d = GDK_DRAWABLE_XID(gd);
GC gc = XCreateGC(dpy, d, 0, nullptr);
- for (GdkRectangle* r = aRects; r < aEnd; r++) {
+ nsIntRegionRectIterator iter(aRegion);
+ for (const nsIntRect *r = iter.Next(); r; r = iter.Next()) {
XShmPutImage(dpy, d, gc, mImage,
r->x, r->y,
r->x - dx, r->y - dy,
@@ -151,20 +152,19 @@ nsShmImage::Put(GdkWindow* aWindow, GdkR
#elif (MOZ_WIDGET_GTK == 3)
void
-nsShmImage::Put(GdkWindow* aWindow, cairo_rectangle_list_t* aRects)
+nsShmImage::Put(GdkWindow* aWindow, const nsIntRegion& aRegion)
{
Display* dpy = gdk_x11_get_default_xdisplay();
Drawable d = GDK_WINDOW_XID(aWindow);
int dx = 0, dy = 0;
GC gc = XCreateGC(dpy, d, 0, nullptr);
- cairo_rectangle_t r;
- for (int i = 0; i < aRects->num_rectangles; i++) {
- r = aRects->rectangles[i];
+ nsIntRegionRectIterator iter(aRegion);
+ for (const nsIntRect *r = iter.Next(); r; r = iter.Next()) {
XShmPutImage(dpy, d, gc, mImage,
- r.x, r.y,
- r.x - dx, r.y - dy,
- r.width, r.height,
+ r->x, r->y,
+ r->x - dx, r->y - dy,
+ r->width, r->height,
False);
}
diff -up firefox-40.0/mozilla-release/widget/nsShmImage.h.1127752 firefox-40.0/mozilla-release/widget/nsShmImage.h
--- firefox-40.0/mozilla-release/widget/nsShmImage.h.1127752 2015-08-07 17:54:22.000000000 +0200
+++ firefox-40.0/mozilla-release/widget/nsShmImage.h 2015-08-26 14:07:24.672087781 +0200
@@ -63,10 +63,8 @@ private:
public:
already_AddRefed<gfxASurface> AsSurface();
-#if (MOZ_WIDGET_GTK == 2)
- void Put(GdkWindow* aWindow, GdkRectangle* aRects, GdkRectangle* aEnd);
-#elif (MOZ_WIDGET_GTK == 3)
- void Put(GdkWindow* aWindow, cairo_rectangle_list_t* aRects);
+#ifdef MOZ_WIDGET_GTK
+ void Put(GdkWindow* aWindow, const nsIntRegion& aRegion);
#elif defined(MOZ_WIDGET_QT)
void Put(QWindow* aWindow, QRect& aRect);
#endif