1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * Some of this code is based on Skia source code, covered by the following
10 * license notice (see readlicense_oo for the full license):
12 * Copyright 2016 Google Inc.
14 * Use of this source code is governed by a BSD-style license that can be
15 * found in the LICENSE file.
19 #include <skia/x11/gdiimpl.hxx>
21 #include <tools/window/unix/RasterWindowContext_unix.h>
22 #include <tools/window/unix/GaneshVulkanWindowContext_unix.h>
23 #include <tools/window/unix/XlibWindowInfo.h>
25 #include <skia/utils.hxx>
26 #include <skia/zone.hxx>
28 #include <X11/Xutil.h>
30 using namespace SkiaHelper
;
32 X11SkiaSalGraphicsImpl::X11SkiaSalGraphicsImpl(X11SalGraphics
& rParent
)
33 : SkiaSalGraphicsImpl(rParent
, rParent
.GetGeometryProvider())
38 void X11SkiaSalGraphicsImpl::UpdateX11GeometryProvider()
40 // The m_pFrame and m_pVDev pointers are updated late in X11
41 setProvider(mX11Parent
.GetGeometryProvider());
44 void X11SkiaSalGraphicsImpl::createWindowSurfaceInternal(bool forceRaster
)
46 assert(!mWindowContext
);
48 assert(mX11Parent
.GetDrawable() != None
);
49 RenderMethod renderMethod
= forceRaster
? RenderRaster
: renderMethodToUse();
50 mScaling
= getWindowScaling();
51 mWindowContext
= createWindowContext(mX11Parent
.GetXDisplay(), mX11Parent
.GetDrawable(),
52 &mX11Parent
.GetVisual(), GetWidth() * mScaling
,
53 GetHeight() * mScaling
, renderMethod
, false);
56 // See flushSurfaceToWindowContext().
57 if (renderMethod
== RenderRaster
)
58 mSurface
= mWindowContext
->getBackbufferSurface();
60 mSurface
= createSkSurface(GetWidth(), GetHeight());
64 std::unique_ptr
<skwindow::WindowContext
>
65 X11SkiaSalGraphicsImpl::createWindowContext(Display
* display
, Drawable drawable
,
66 const XVisualInfo
* visual
, int width
, int height
,
67 RenderMethod renderMethod
, bool temporary
)
70 skwindow::DisplayParams displayParams
;
71 displayParams
.fColorType
= kN32_SkColorType
;
73 // WORKAROUND: VSync causes freezes that can even temporarily freeze the entire desktop.
74 // This happens even with the latest 450.66 drivers despite them claiming a fix for vsync.
75 // https://forums.developer.nvidia.com/t/hangs-freezes-when-vulkan-v-sync-vk-present-mode-fifo-khr-is-enabled/67751
76 if (getVendor() == DriverBlocklist::VendorNVIDIA
)
77 displayParams
.fDisableVsync
= true;
79 skwindow::XlibWindowInfo winInfo
;
81 winInfo
.fDisplay
= display
;
82 winInfo
.fWindow
= drawable
;
83 winInfo
.fFBConfig
= nullptr; // not used
84 winInfo
.fVisualInfo
= const_cast<XVisualInfo
*>(visual
);
85 assert(winInfo
.fVisualInfo
->visual
!= nullptr); // make sure it's not an uninitialized SalVisual
86 winInfo
.fWidth
= width
;
87 winInfo
.fHeight
= height
;
88 #if defined DBG_UTIL && !defined NDEBUG
89 // Our patched Skia has VulkanWindowContext that shares grDirectContext, which requires
90 // that the X11 visual is always the same. Ensure it is so.
91 static VisualID checkVisualID
= -1U;
92 // Exception is for the temporary case during startup, when SkiaHelper's
93 // checkDeviceDenylisted() needs a WindowContext and may be called before SalVisual
97 assert(checkVisualID
== -1U || winInfo
.fVisualInfo
->visualid
== checkVisualID
);
98 checkVisualID
= winInfo
.fVisualInfo
->visualid
;
103 switch (renderMethod
)
106 // Make sure we ask for color type that matches the X11 visual. If red mask
107 // is larger value than blue mask, then on little endian this means blue is first.
108 // This should also preferably match SK_R32_SHIFT set in config_skia.h, as that
109 // improves performance, the common setup seems to be BGRA (possibly because of
110 // choosing OpenGL-capable visual).
111 displayParams
.fColorType
112 = (visual
->red_mask
> visual
->blue_mask
? kBGRA_8888_SkColorType
113 : kRGBA_8888_SkColorType
);
114 return skwindow::MakeRasterForXlib(winInfo
, displayParams
);
116 return skwindow::MakeGaneshVulkanForXlib(winInfo
, displayParams
);
124 bool X11SkiaSalGraphicsImpl::avoidRecreateByResize() const
126 if (SkiaSalGraphicsImpl::avoidRecreateByResize())
128 if (!mSurface
|| isOffscreen())
130 // Skia's WindowContext uses actual dimensions of the X window, which due to X11 being
131 // asynchronous may be temporarily different from what VCL thinks are the dimensions.
132 // That can lead to us repeatedly calling recreateSurface() because of "incorrect"
133 // size, and we otherwise need to check for size changes, because VCL does not inform us.
134 // Avoid the problem here by checking the size of the X window and bail out if Skia
135 // would just return the same size as it is now.
138 unsigned int w
, h
, border
, depth
;
139 XGetGeometry(mX11Parent
.GetXDisplay(), mX11Parent
.GetDrawable(), &r
, &x
, &y
, &w
, &h
, &border
,
141 return mSurface
->width() == int(w
) && mSurface
->height() == int(h
);
144 void X11SkiaSalGraphicsImpl::Flush() { performFlush(); }
146 std::unique_ptr
<skwindow::WindowContext
> createVulkanWindowContext(bool temporary
)
148 SalDisplay
* salDisplay
= vcl_sal::getSalDisplay(GetGenericUnixSalData());
149 const XVisualInfo
* visual
;
150 XVisualInfo
* visuals
= nullptr;
152 visual
= &salDisplay
->GetVisual(salDisplay
->GetDefaultXScreen());
155 // SalVisual from salDisplay may not be setup yet at this point, get
156 // info for the default visual.
158 search
.visualid
= XVisualIDFromVisual(
159 DefaultVisual(salDisplay
->GetDisplay(), salDisplay
->GetDefaultXScreen().getXScreen()));
161 visuals
= XGetVisualInfo(salDisplay
->GetDisplay(), VisualIDMask
, &search
, &count
);
165 std::unique_ptr
<skwindow::WindowContext
> ret
= X11SkiaSalGraphicsImpl::createWindowContext(
166 salDisplay
->GetDisplay(), None
, visual
, 1, 1, RenderVulkan
, temporary
);
172 void X11SkiaSalGraphicsImpl::prepareSkia() { SkiaHelper::prepareSkia(createVulkanWindowContext
); }
174 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */