tdf#165005 Fix URL to community forum in readme
[LibreOffice.git] / vcl / skia / x11 / gdiimpl.cxx
blob34df45fa7d09049e48ac2e0e6df4eb0a497b5cff
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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())
34 , mX11Parent(rParent)
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);
47 assert(!mSurface);
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);
54 if (mWindowContext)
56 // See flushSurfaceToWindowContext().
57 if (renderMethod == RenderRaster)
58 mSurface = mWindowContext->getBackbufferSurface();
59 else
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)
69 SkiaZone zone;
70 skwindow::DisplayParams displayParams;
71 displayParams.fColorType = kN32_SkColorType;
72 #if defined LINUX
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;
78 #endif
79 skwindow::XlibWindowInfo winInfo;
80 assert(display);
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
94 // is ready.
95 if (!temporary)
97 assert(checkVisualID == -1U || winInfo.fVisualInfo->visualid == checkVisualID);
98 checkVisualID = winInfo.fVisualInfo->visualid;
100 #else
101 (void)temporary;
102 #endif
103 switch (renderMethod)
105 case RenderRaster:
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);
115 case RenderVulkan:
116 return skwindow::MakeGaneshVulkanForXlib(winInfo, displayParams);
117 case RenderMetal:
118 abort();
119 break;
121 abort();
124 bool X11SkiaSalGraphicsImpl::avoidRecreateByResize() const
126 if (SkiaSalGraphicsImpl::avoidRecreateByResize())
127 return true;
128 if (!mSurface || isOffscreen())
129 return false;
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.
136 Window r;
137 int x, y;
138 unsigned int w, h, border, depth;
139 XGetGeometry(mX11Parent.GetXDisplay(), mX11Parent.GetDrawable(), &r, &x, &y, &w, &h, &border,
140 &depth);
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;
151 if (!temporary)
152 visual = &salDisplay->GetVisual(salDisplay->GetDefaultXScreen());
153 else
155 // SalVisual from salDisplay may not be setup yet at this point, get
156 // info for the default visual.
157 XVisualInfo search;
158 search.visualid = XVisualIDFromVisual(
159 DefaultVisual(salDisplay->GetDisplay(), salDisplay->GetDefaultXScreen().getXScreen()));
160 int count;
161 visuals = XGetVisualInfo(salDisplay->GetDisplay(), VisualIDMask, &search, &count);
162 assert(count == 1);
163 visual = visuals;
165 std::unique_ptr<skwindow::WindowContext> ret = X11SkiaSalGraphicsImpl::createWindowContext(
166 salDisplay->GetDisplay(), None, visual, 1, 1, RenderVulkan, temporary);
167 if (temporary)
168 XFree(visuals);
169 return ret;
172 void X11SkiaSalGraphicsImpl::prepareSkia() { SkiaHelper::prepareSkia(createVulkanWindowContext); }
174 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */