Bug 1478661 - Replace IsComposited() with explicit alpha visual state, r?jhorak
IsComposited() does not reflect Visual selected by GLContextGLX::FindVisual()
which is used by WebRender which leads to shaped window rendering with WebRender.
IsComposited() is replaced by mHasAlphaVisual variable which is explicitly
set when we have an alpha visual and we don't need to use shape X11 extension.
MozReview-Commit-ID: 1kDLwkUyHte
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -477,16 +477,18 @@ nsWindow::nsWindow()
mTransparencyBitmapHeight = 0;
#if GTK_CHECK_VERSION(3,4,0)
mLastScrollEventTime = GDK_CURRENT_TIME;
#endif
mPendingConfigures = 0;
mCSDSupportLevel = CSD_SUPPORT_NONE;
mDrawInTitlebar = false;
+
+ mHasAlphaVisual = false;
}
nsWindow::~nsWindow()
{
LOG(("nsWindow::~nsWindow() [%p]\n", (void *)this));
delete[] mTransparencyBitmap;
mTransparencyBitmap = nullptr;
@@ -2129,17 +2131,17 @@ nsWindow::OnExposeEvent(cairo_t *cr)
// Our bounds may have changed after calling WillPaintWindow. Clip
// to the new bounds here. The region is relative to this
// window.
region.And(region, LayoutDeviceIntRect(0, 0, mBounds.width, mBounds.height));
bool shaped = false;
if (eTransparencyTransparent == GetTransparencyMode()) {
- if (IsComposited()) {
+ if (mHasAlphaVisual) {
// Remove possible shape mask from when window manger was not
// previously compositing.
static_cast<nsWindow*>(GetTopLevelWidget())->
ClearTransparencyBitmap();
} else {
shaped = true;
}
}
@@ -2232,17 +2234,17 @@ nsWindow::OnExposeEvent(cairo_t *cr)
#endif // MOZ_X11
bool painted = false;
{
if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) {
if (GetTransparencyMode() == eTransparencyTransparent &&
layerBuffering == BufferMode::BUFFER_NONE &&
- IsComposited()) {
+ mHasAlphaVisual) {
// If our draw target is unbuffered and we use an alpha channel,
// clear the image beforehand to ensure we don't get artifacts from a
// reused SHM image. See bug 1258086.
dt->ClearRect(Rect(boundsRect));
}
AutoLayerManagerSetup setupLayerManager(this, ctx, layerBuffering);
painted = listener->PaintWindow(this, region);
@@ -3656,18 +3658,18 @@ nsWindow::Create(nsIWidget* aParent,
// figure out our parent window
GtkWidget *parentMozContainer = nullptr;
GtkContainer *parentGtkContainer = nullptr;
GdkWindow *parentGdkWindow = nullptr;
GtkWindow *topLevelParent = nullptr;
nsWindow *parentnsWindow = nullptr;
GtkWidget *eventWidget = nullptr;
bool drawToContainer = false;
- bool useAlphaVisual = (mWindowType == eWindowType_popup &&
- aInitData->mSupportTranslucency);
+ bool needsAlphaVisual = (mWindowType == eWindowType_popup &&
+ aInitData->mSupportTranslucency);
if (aParent) {
parentnsWindow = static_cast<nsWindow*>(aParent);
parentGdkWindow = parentnsWindow->mGdkWindow;
} else if (aNativeParent && GDK_IS_WINDOW(aNativeParent)) {
parentGdkWindow = GDK_WINDOW(aNativeParent);
parentnsWindow = get_window_for_gdk_window(parentGdkWindow);
if (!parentnsWindow)
@@ -3726,32 +3728,38 @@ nsWindow::Create(nsIWidget* aParent,
// before the widget is realized.
if (mIsX11Display && useWebRender) {
auto display =
GDK_DISPLAY_XDISPLAY(gtk_widget_get_display(mShell));
auto screen = gtk_widget_get_screen(mShell);
int screenNumber = GDK_SCREEN_XNUMBER(screen);
int visualId = 0;
if (GLContextGLX::FindVisual(display, screenNumber,
- useWebRender, useAlphaVisual,
+ useWebRender, needsAlphaVisual,
&visualId)) {
// If we're using CSD, rendering will go through mContainer, but
// it will inherit this visual as it is a child of mShell.
gtk_widget_set_visual(mShell,
gdk_x11_screen_lookup_visual(screen,
visualId));
+ mHasAlphaVisual = true;
+ } else {
+ NS_WARNING("We're missing X11 Visual for WebRender!");
}
} else
#endif // MOZ_X11
{
- if (useAlphaVisual) {
+ if (needsAlphaVisual) {
GdkScreen *screen = gtk_widget_get_screen(mShell);
if (gdk_screen_is_composited(screen)) {
GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
- gtk_widget_set_visual(mShell, visual);
+ if (visual) {
+ gtk_widget_set_visual(mShell, visual);
+ mHasAlphaVisual = true;
+ }
}
}
}
// We only move a general managed toplevel window if someone has
// actually placed the window somewhere. If no placement has taken
// place, we just let the window manager Do The Right Thing.
NativeResize();
@@ -4125,17 +4133,17 @@ nsWindow::Create(nsIWidget* aParent,
#ifdef MOZ_X11
if (mIsX11Display && mGdkWindow) {
mXDisplay = GDK_WINDOW_XDISPLAY(mGdkWindow);
mXWindow = gdk_x11_window_get_xid(mGdkWindow);
GdkVisual* gdkVisual = gdk_window_get_visual(mGdkWindow);
mXVisual = gdk_x11_visual_get_xvisual(gdkVisual);
mXDepth = gdk_visual_get_depth(gdkVisual);
- bool shaped = useAlphaVisual && !IsComposited();
+ bool shaped = needsAlphaVisual && !mHasAlphaVisual;
mSurfaceProvider.Initialize(mXDisplay, mXWindow, mXVisual, mXDepth,
shaped);
}
#ifdef MOZ_WAYLAND
else if (!mIsX11Display) {
mSurfaceProvider.Initialize(this);
}
@@ -7185,34 +7193,20 @@ nsWindow::RoundsWidgetCoordinatesTo()
return GdkScaleFactor();
}
void nsWindow::GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData)
{
*aInitData = mozilla::widget::GtkCompositorWidgetInitData(
(mXWindow != X11None) ? mXWindow : (uintptr_t)nullptr,
mXDisplay ? nsCString(XDisplayString(mXDisplay)) : nsCString(),
- mIsTransparent && !IsComposited(),
+ mIsTransparent && !mHasAlphaVisual,
GetClientSize());
}
-bool
-nsWindow::IsComposited() const
-{
- if (!mGdkWindow) {
- NS_WARNING("nsWindow::HasARGBVisual called before realization!");
- return false;
- }
-
- GdkScreen* gdkScreen = gdk_window_get_screen(mGdkWindow);
- return gdk_screen_is_composited(gdkScreen) &&
- (gdk_window_get_visual(mGdkWindow)
- == gdk_screen_get_rgba_visual(gdkScreen));
-}
-
#ifdef MOZ_WAYLAND
wl_display*
nsWindow::GetWaylandDisplay()
{
// Available as of GTK 3.8+
static auto sGdkWaylandDisplayGetWlDisplay =
(wl_display *(*)(GdkDisplay *))
dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display");
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -486,17 +486,16 @@ private:
CheckForRollup(0, 0, false, true);
}
bool GetDragInfo(mozilla::WidgetMouseEvent* aMouseEvent,
GdkWindow** aWindow, gint* aButton,
gint* aRootX, gint* aRootY);
void ClearCachedResources();
nsIWidgetListener* GetListener();
- bool IsComposited() const;
void UpdateClientOffsetForCSDWindow();
nsWindow* GetTransientForWindowIfPopup();
bool IsHandlingTouchSequence(GdkEventSequence* aSequence);
#ifdef MOZ_X11
typedef enum { GTK_WIDGET_COMPOSIDED_DEFAULT = 0,
@@ -604,16 +603,19 @@ private:
static GdkCursor *gsGtkCursorCache[eCursorCount];
// Transparency
bool mIsTransparent;
// This bitmap tracks which pixels are transparent. We don't support
// full translucency at this time; each pixel is either fully opaque
// or fully transparent.
gchar* mTransparencyBitmap;
+ // True when we're on compositing window manager and this
+ // window is using visual with alpha channel.
+ bool mHasAlphaVisual;
// all of our DND stuff
void InitDragEvent(mozilla::WidgetDragEvent& aEvent);
float mLastMotionPressure;
// Remember the last sizemode so that we can restore it when
// leaving fullscreen