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/sk_app/unix/WindowContextFactory_unix.h>
23 #include <skia/utils.hxx>
24 #include <skia/zone.hxx>
26 #include <X11/Xutil.h>
28 using namespace SkiaHelper
;
30 X11SkiaSalGraphicsImpl::X11SkiaSalGraphicsImpl(X11SalGraphics
& rParent
)
31 : SkiaSalGraphicsImpl(rParent
, rParent
.GetGeometryProvider())
36 void X11SkiaSalGraphicsImpl::Init()
38 // The m_pFrame and m_pVDev pointers are updated late in X11
39 setProvider(mX11Parent
.GetGeometryProvider());
40 SkiaSalGraphicsImpl::Init();
43 void X11SkiaSalGraphicsImpl::createWindowSurfaceInternal(bool forceRaster
)
45 assert(!mWindowContext
);
47 assert(mX11Parent
.GetDrawable() != None
);
48 RenderMethod renderMethod
= forceRaster
? RenderRaster
: renderMethodToUse();
49 mScaling
= getWindowScaling();
50 mWindowContext
= createWindowContext(mX11Parent
.GetXDisplay(), mX11Parent
.GetDrawable(),
51 &mX11Parent
.GetVisual(), GetWidth() * mScaling
,
52 GetHeight() * mScaling
, renderMethod
, false);
55 // See flushSurfaceToWindowContext().
56 if (renderMethod
== RenderRaster
)
57 mSurface
= mWindowContext
->getBackbufferSurface();
59 mSurface
= createSkSurface(GetWidth(), GetHeight());
63 std::unique_ptr
<sk_app::WindowContext
>
64 X11SkiaSalGraphicsImpl::createWindowContext(Display
* display
, Drawable drawable
,
65 const XVisualInfo
* visual
, int width
, int height
,
66 RenderMethod renderMethod
, bool temporary
)
69 sk_app::DisplayParams displayParams
;
70 displayParams
.fColorType
= kN32_SkColorType
;
72 // WORKAROUND: VSync causes freezes that can even temporarily freeze the entire desktop.
73 // This happens even with the latest 450.66 drivers despite them claiming a fix for vsync.
74 // https://forums.developer.nvidia.com/t/hangs-freezes-when-vulkan-v-sync-vk-present-mode-fifo-khr-is-enabled/67751
75 if (getVendor() == DriverBlocklist::VendorNVIDIA
)
76 displayParams
.fDisableVsync
= true;
78 sk_app::window_context_factory::XlibWindowInfo winInfo
;
80 winInfo
.fDisplay
= display
;
81 winInfo
.fWindow
= drawable
;
82 winInfo
.fFBConfig
= nullptr; // not used
83 winInfo
.fVisualInfo
= const_cast<XVisualInfo
*>(visual
);
84 assert(winInfo
.fVisualInfo
->visual
!= nullptr); // make sure it's not an uninitialized SalVisual
85 winInfo
.fWidth
= width
;
86 winInfo
.fHeight
= height
;
87 #if defined DBG_UTIL && !defined NDEBUG
88 // Our patched Skia has VulkanWindowContext that shares grDirectContext, which requires
89 // that the X11 visual is always the same. Ensure it is so.
90 static VisualID checkVisualID
= -1U;
91 // Exception is for the temporary case during startup, when SkiaHelper's
92 // checkDeviceDenylisted() needs a WindowContext and may be called before SalVisual
96 assert(checkVisualID
== -1U || winInfo
.fVisualInfo
->visualid
== checkVisualID
);
97 checkVisualID
= winInfo
.fVisualInfo
->visualid
;
102 switch (renderMethod
)
105 // Make sure we ask for color type that matches the X11 visual. If red mask
106 // is larger value than blue mask, then on little endian this means blue is first.
107 // This should also preferably match SK_R32_SHIFT set in config_skia.h, as that
108 // improves performance, the common setup seems to be BGRA (possibly because of
109 // choosing OpenGL-capable visual).
110 displayParams
.fColorType
111 = (visual
->red_mask
> visual
->blue_mask
? kBGRA_8888_SkColorType
112 : kRGBA_8888_SkColorType
);
113 return sk_app::window_context_factory::MakeRasterForXlib(winInfo
, displayParams
);
115 return sk_app::window_context_factory::MakeVulkanForXlib(winInfo
, displayParams
);
123 bool X11SkiaSalGraphicsImpl::avoidRecreateByResize() const
125 if (SkiaSalGraphicsImpl::avoidRecreateByResize())
127 if (!mSurface
|| isOffscreen())
129 // Skia's WindowContext uses actual dimensions of the X window, which due to X11 being
130 // asynchronous may be temporarily different from what VCL thinks are the dimensions.
131 // That can lead to us repeatedly calling recreateSurface() because of "incorrect"
132 // size, and we otherwise need to check for size changes, because VCL does not inform us.
133 // Avoid the problem here by checking the size of the X window and bail out if Skia
134 // would just return the same size as it is now.
137 unsigned int w
, h
, border
, depth
;
138 XGetGeometry(mX11Parent
.GetXDisplay(), mX11Parent
.GetDrawable(), &r
, &x
, &y
, &w
, &h
, &border
,
140 return mSurface
->width() == int(w
) && mSurface
->height() == int(h
);
143 void X11SkiaSalGraphicsImpl::freeResources() {}
145 void X11SkiaSalGraphicsImpl::Flush() { performFlush(); }
147 std::unique_ptr
<sk_app::WindowContext
> createVulkanWindowContext(bool temporary
)
149 SalDisplay
* salDisplay
= vcl_sal::getSalDisplay(GetGenericUnixSalData());
150 const XVisualInfo
* visual
;
151 XVisualInfo
* visuals
= nullptr;
153 visual
= &salDisplay
->GetVisual(salDisplay
->GetDefaultXScreen());
156 // SalVisual from salDisplay may not be setup yet at this point, get
157 // info for the default visual.
159 search
.visualid
= XVisualIDFromVisual(
160 DefaultVisual(salDisplay
->GetDisplay(), salDisplay
->GetDefaultXScreen().getXScreen()));
162 visuals
= XGetVisualInfo(salDisplay
->GetDisplay(), VisualIDMask
, &search
, &count
);
166 std::unique_ptr
<sk_app::WindowContext
> ret
= X11SkiaSalGraphicsImpl::createWindowContext(
167 salDisplay
->GetDisplay(), None
, visual
, 1, 1, RenderVulkan
, temporary
);
173 void X11SkiaSalGraphicsImpl::prepareSkia() { SkiaHelper::prepareSkia(createVulkanWindowContext
); }
175 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */