Bug Summary

File:root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp
Warning:line 347, column 29
Called C++ object pointer is uninitialized

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name GLContextProviderGLX.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/gl -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/gl -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/gfx/gl -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/gl -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/gfx/skia -I /root/firefox-clang/gfx/skia/skia -I /root/firefox-clang/gfx/cairo/cairo/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gtk-3.0/unix-print -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-26-231904-1820671-1 -x c++ /root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp
1/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6#ifdef MOZ_WIDGET_GTK1
7# include <gdk/gdk.h>
8# include <gdk/gdkx.h>
9# define GET_NATIVE_WINDOW(aWidget)(gdk_x11_window_get_xid ((GdkWindow*)aWidget->GetNativeData
(0)))
\
10 GDK_WINDOW_XID((GdkWindow*)aWidget->GetNativeData(NS_NATIVE_WINDOW))(gdk_x11_window_get_xid ((GdkWindow*)aWidget->GetNativeData
(0)))
11#endif
12
13#include <X11/Xlib.h>
14#include <X11/Xutil.h>
15#include "X11UndefineNone.h"
16
17#include "mozilla/MathAlgorithms.h"
18#include "mozilla/StaticPtr.h"
19#include "mozilla/layers/CompositorOptions.h"
20#include "mozilla/Range.h"
21#include "mozilla/ScopeExit.h"
22#include "mozilla/Sprintf.h"
23#include "mozilla/StaticPrefs_gfx.h"
24#include "mozilla/StaticPrefs_layout.h"
25#include "mozilla/widget/CompositorWidget.h"
26#include "mozilla/widget/GtkCompositorWidget.h"
27#include "mozilla/Unused.h"
28
29#include "prenv.h"
30#include "GLContextProvider.h"
31#include "GLLibraryLoader.h"
32#include "nsDebug.h"
33#include "nsIWidget.h"
34#include "GLXLibrary.h"
35#include "gfxContext.h"
36#include "gfxEnv.h"
37#include "gfxPlatform.h"
38#include "GLContextGLX.h"
39#include "gfxUtils.h"
40#include "gfx2DGlue.h"
41#include "GLScreenBuffer.h"
42
43#include "gfxCrashReporterUtils.h"
44
45#ifdef MOZ_WIDGET_GTK1
46# include "gfxPlatformGtk.h"
47#endif
48
49namespace mozilla::gl {
50
51using namespace mozilla::gfx;
52using namespace mozilla::widget;
53
54MOZ_RUNINIT GLXLibrary sGLXLibrary;
55
56static inline bool HasExtension(const char* aExtensions,
57 const char* aRequiredExtension) {
58 return GLContext::ListHasExtension(
59 reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension);
60}
61
62bool GLXLibrary::EnsureInitialized(Display* aDisplay) {
63 if (mInitialized) {
64 return true;
65 }
66
67 // Don't repeatedly try to initialize.
68 if (mTriedInitializing) {
69 return false;
70 }
71 mTriedInitializing = true;
72
73 MOZ_ASSERT(aDisplay)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDisplay)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDisplay))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aDisplay", "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 73); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplay" ")"
); do { MOZ_CrashSequence(__null, 73); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
74 if (!aDisplay) {
75 return false;
76 }
77
78 // Force enabling s3 texture compression. (Bug 774134)
79 PR_SetEnv("force_s3tc_enable=true");
80
81 if (!mOGLLibrary) {
82 // see e.g. bug 608526: it is intrinsically interesting to know whether we
83 // have dynamically linked to libGL.so.1 because at least the NVIDIA
84 // implementation requires an executable stack, which causes mprotect calls,
85 // which trigger glibc bug
86 // http://sourceware.org/bugzilla/show_bug.cgi?id=12225
87 const char* libGLfilename = "libGL.so.1";
88#if defined(__OpenBSD__) || defined(__NetBSD__)
89 libGLfilename = "libGL.so";
90#endif
91
92 const bool forceFeatureReport = false;
93 ScopedGfxFeatureReporter reporter(libGLfilename, forceFeatureReport);
94 mOGLLibrary = PR_LoadLibrary(libGLfilename);
95 if (!mOGLLibrary) {
96 NS_WARNING("Couldn't load OpenGL shared library.")NS_DebugBreak(NS_DEBUG_WARNING, "Couldn't load OpenGL shared library."
, nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 96)
;
97 return false;
98 }
99 reporter.SetSuccessful();
100 }
101
102 if (gfxEnv::MOZ_GLX_DEBUG()) {
103 mDebug = true;
104 }
105
106#define SYMBOL(X){ (PRFuncPtr*)&mSymbols.fX, { { "glX" "X" } } } \
107 { \
108 (PRFuncPtr*)&mSymbols.f##X, { \
109 { \
110 "glX" #X \
111 } \
112 } \
113 }
114#define END_OF_SYMBOLS{ nullptr, {} } \
115 { \
116 nullptr, {} \
117 }
118
119 const SymLoadStruct symbols[] = {
120 /* functions that were in GLX 1.0 */
121 SYMBOL(DestroyContext){ (PRFuncPtr*)&mSymbols.fDestroyContext, { { "glX" "DestroyContext"
} } }
,
122 SYMBOL(MakeCurrent){ (PRFuncPtr*)&mSymbols.fMakeCurrent, { { "glX" "MakeCurrent"
} } }
,
123 SYMBOL(SwapBuffers){ (PRFuncPtr*)&mSymbols.fSwapBuffers, { { "glX" "SwapBuffers"
} } }
,
124 SYMBOL(QueryVersion){ (PRFuncPtr*)&mSymbols.fQueryVersion, { { "glX" "QueryVersion"
} } }
,
125 SYMBOL(GetConfig){ (PRFuncPtr*)&mSymbols.fGetConfig, { { "glX" "GetConfig"
} } }
,
126 SYMBOL(GetCurrentContext){ (PRFuncPtr*)&mSymbols.fGetCurrentContext, { { "glX" "GetCurrentContext"
} } }
,
127 SYMBOL(WaitGL){ (PRFuncPtr*)&mSymbols.fWaitGL, { { "glX" "WaitGL" } } },
128 SYMBOL(WaitX){ (PRFuncPtr*)&mSymbols.fWaitX, { { "glX" "WaitX" } } },
129
130 /* functions introduced in GLX 1.1 */
131 SYMBOL(QueryExtensionsString){ (PRFuncPtr*)&mSymbols.fQueryExtensionsString, { { "glX"
"QueryExtensionsString" } } }
,
132 SYMBOL(GetClientString){ (PRFuncPtr*)&mSymbols.fGetClientString, { { "glX" "GetClientString"
} } }
,
133 SYMBOL(QueryServerString){ (PRFuncPtr*)&mSymbols.fQueryServerString, { { "glX" "QueryServerString"
} } }
,
134
135 /* functions introduced in GLX 1.3 */
136 SYMBOL(ChooseFBConfig){ (PRFuncPtr*)&mSymbols.fChooseFBConfig, { { "glX" "ChooseFBConfig"
} } }
,
137 SYMBOL(ChooseVisual){ (PRFuncPtr*)&mSymbols.fChooseVisual, { { "glX" "ChooseVisual"
} } }
,
138 SYMBOL(GetFBConfigAttrib){ (PRFuncPtr*)&mSymbols.fGetFBConfigAttrib, { { "glX" "GetFBConfigAttrib"
} } }
,
139 SYMBOL(GetFBConfigs){ (PRFuncPtr*)&mSymbols.fGetFBConfigs, { { "glX" "GetFBConfigs"
} } }
,
140 SYMBOL(CreatePixmap){ (PRFuncPtr*)&mSymbols.fCreatePixmap, { { "glX" "CreatePixmap"
} } }
,
141 SYMBOL(DestroyPixmap){ (PRFuncPtr*)&mSymbols.fDestroyPixmap, { { "glX" "DestroyPixmap"
} } }
,
142 SYMBOL(CreateNewContext){ (PRFuncPtr*)&mSymbols.fCreateNewContext, { { "glX" "CreateNewContext"
} } }
,
143
144 // Core in GLX 1.4, ARB extension before.
145 {(PRFuncPtr*)&mSymbols.fGetProcAddress,
146 {{"glXGetProcAddress", "glXGetProcAddressARB"}}},
147 END_OF_SYMBOLS{ nullptr, {} }};
148
149 {
150 const SymbolLoader libLoader(*mOGLLibrary);
151 if (!libLoader.LoadSymbols(symbols)) {
152 NS_WARNING("Couldn't load required GLX symbols.")NS_DebugBreak(NS_DEBUG_WARNING, "Couldn't load required GLX symbols."
, nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 152)
;
153 return false;
154 }
155 }
156 const SymbolLoader pfnLoader(mSymbols.fGetProcAddress);
157
158 int screen = DefaultScreen(aDisplay)(((_XPrivDisplay)(aDisplay))->default_screen);
159
160 {
161 int major, minor;
162 if (!fQueryVersion(aDisplay, &major, &minor) || major != 1 || minor < 3) {
163 NS_ERROR("GLX version older than 1.3. (released in 1998)")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "GLX version older than 1.3. (released in 1998)"
, "Error", "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 163); MOZ_PretendNoReturn(); } while (0)
;
164 return false;
165 }
166 }
167
168 const SymLoadStruct symbols_createcontext[] = {
169 SYMBOL(CreateContextAttribsARB){ (PRFuncPtr*)&mSymbols.fCreateContextAttribsARB, { { "glX"
"CreateContextAttribsARB" } } }
, END_OF_SYMBOLS{ nullptr, {} }};
170
171 const SymLoadStruct symbols_videosync[] = {
172 SYMBOL(GetVideoSyncSGI){ (PRFuncPtr*)&mSymbols.fGetVideoSyncSGI, { { "glX" "GetVideoSyncSGI"
} } }
, SYMBOL(WaitVideoSyncSGI){ (PRFuncPtr*)&mSymbols.fWaitVideoSyncSGI, { { "glX" "WaitVideoSyncSGI"
} } }
, END_OF_SYMBOLS{ nullptr, {} }};
173
174 const SymLoadStruct symbols_swapcontrol[] = {SYMBOL(SwapIntervalEXT){ (PRFuncPtr*)&mSymbols.fSwapIntervalEXT, { { "glX" "SwapIntervalEXT"
} } }
,
175 END_OF_SYMBOLS{ nullptr, {} }};
176
177 const SymLoadStruct symbols_querydrawable[] = {SYMBOL(QueryDrawable){ (PRFuncPtr*)&mSymbols.fQueryDrawable, { { "glX" "QueryDrawable"
} } }
,
178 END_OF_SYMBOLS{ nullptr, {} }};
179
180 const auto fnLoadSymbols = [&](const SymLoadStruct* symbols) {
181 if (pfnLoader.LoadSymbols(symbols)) return true;
182
183 ClearSymbols(symbols);
184 return false;
185 };
186
187 const char* clientVendor = fGetClientString(aDisplay, LOCAL_GLX_VENDOR0x1);
188 const char* serverVendor =
189 fQueryServerString(aDisplay, screen, LOCAL_GLX_VENDOR0x1);
190 const char* extensionsStr = fQueryExtensionsString(aDisplay, screen);
191
192 if (HasExtension(extensionsStr, "GLX_ARB_create_context") &&
193 HasExtension(extensionsStr, "GLX_ARB_create_context_profile") &&
194 fnLoadSymbols(symbols_createcontext)) {
195 mHasCreateContextAttribs = true;
196 }
197
198 if (HasExtension(extensionsStr, "GLX_ARB_create_context_robustness")) {
199 mHasRobustness = true;
200 }
201
202 if (HasExtension(extensionsStr, "GLX_NV_robustness_video_memory_purge")) {
203 mHasVideoMemoryPurge = true;
204 }
205
206 if (HasExtension(extensionsStr, "GLX_SGI_video_sync") &&
207 fnLoadSymbols(symbols_videosync)) {
208 mHasVideoSync = true;
209 }
210
211 if (!HasExtension(extensionsStr, "GLX_EXT_swap_control") ||
212 !fnLoadSymbols(symbols_swapcontrol)) {
213 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "GLX_swap_control unsupported, ASAP mode may still block on buffer "
"swaps.", nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 215)
214 "GLX_swap_control unsupported, ASAP mode may still block on buffer "NS_DebugBreak(NS_DEBUG_WARNING, "GLX_swap_control unsupported, ASAP mode may still block on buffer "
"swaps.", nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 215)
215 "swaps.")NS_DebugBreak(NS_DEBUG_WARNING, "GLX_swap_control unsupported, ASAP mode may still block on buffer "
"swaps.", nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 215)
;
216 }
217
218 if (HasExtension(extensionsStr, "GLX_EXT_buffer_age") &&
219 fnLoadSymbols(symbols_querydrawable)) {
220 mHasBufferAge = true;
221 }
222
223 mIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI");
224 mIsNVIDIA =
225 serverVendor && DoesStringMatch(serverVendor, "NVIDIA Corporation");
226 mClientIsMesa = clientVendor && DoesStringMatch(clientVendor, "Mesa");
227
228 mInitialized = true;
229
230 // This needs to be after `fQueryServerString` is called so that the
231 // driver is loaded.
232 MesaMemoryLeakWorkaround();
233
234 return true;
235}
236
237bool GLXLibrary::SupportsVideoSync(Display* aDisplay) {
238 if (!EnsureInitialized(aDisplay)) {
239 return false;
240 }
241
242 return mHasVideoSync;
243}
244
245static int (*sOldErrorHandler)(Display*, XErrorEvent*);
246static XErrorEvent sErrorEvent = {};
247
248static int GLXErrorHandler(Display* display, XErrorEvent* ev) {
249 if (!sErrorEvent.error_code) {
250 sErrorEvent = *ev;
251 }
252 return 0;
253}
254
255GLXLibrary::WrapperScope::WrapperScope(const GLXLibrary& glx,
256 const char* const funcName,
257 Display* aDisplay)
258 : mGlx(glx), mFuncName(funcName), mDisplay(aDisplay) {
259 if (mGlx.mDebug) {
260 sOldErrorHandler = XSetErrorHandler(GLXErrorHandler);
261 }
262}
263
264GLXLibrary::WrapperScope::~WrapperScope() {
265 if (mGlx.mDebug) {
266 if (mDisplay) {
267 FinishX(mDisplay);
268 }
269 if (sErrorEvent.error_code) {
270 char buffer[100] = {};
271 if (mDisplay) {
272 XGetErrorText(mDisplay, sErrorEvent.error_code, buffer, sizeof(buffer));
273 } else {
274 SprintfLiteral(buffer, "%d", sErrorEvent.error_code);
275 }
276 printf_stderr("X ERROR after %s: %s (%i) - Request: %i.%i, Serial: %lu",
277 mFuncName, buffer, sErrorEvent.error_code,
278 sErrorEvent.request_code, sErrorEvent.minor_code,
279 sErrorEvent.serial);
280 MOZ_ASSERT_UNREACHABLE("AfterGLXCall sErrorEvent")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"AfterGLXCall sErrorEvent" ")", "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 280); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "AfterGLXCall sErrorEvent" ")"); do
{ MOZ_CrashSequence(__null, 280); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
281 }
282 const auto was = XSetErrorHandler(sOldErrorHandler);
283 if (was != GLXErrorHandler) {
284 NS_WARNING("Concurrent XSetErrorHandlers")NS_DebugBreak(NS_DEBUG_WARNING, "Concurrent XSetErrorHandlers"
, nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 284)
;
285 }
286 }
287}
288
289// Returns the GTK display if available; otherwise, if a display was
290// previously opened by this method and is still open, returns a
291// reference to it; otherwise, opens a new connection. (The non-GTK
292// cases are similar to what we do for EGL.)
293std::shared_ptr<XlibDisplay> GLXLibrary::GetDisplay() {
294 std::shared_ptr<XlibDisplay> display;
295
296#ifdef MOZ_WIDGET_GTK1
297 static const bool kHaveGtk = !!gdk_display_get_default();
298 if (kHaveGtk) {
299 display = XlibDisplay::Borrow(DefaultXDisplay());
300 }
301#endif
302 if (display) {
303 return display;
304 }
305
306 auto ownDisplay = mOwnDisplay.Lock();
307 display = ownDisplay->lock();
308 if (display) {
309 return display;
310 }
311
312 display = XlibDisplay::Open(nullptr);
313 if (NS_WARN_IF(!display)NS_warn_if_impl(!display, "!display", "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 313)
) {
314 return nullptr;
315 }
316 *ownDisplay = display;
317 return display;
318}
319
320already_AddRefed<GLContextGLX> GLContextGLX::CreateGLContext(
321 const GLContextDesc& desc, std::shared_ptr<XlibDisplay> display,
322 GLXDrawable drawable, GLXFBConfig cfg, Drawable ownedPixmap) {
323 GLXLibrary& glx = sGLXLibrary;
324
325 int isDoubleBuffered = 0;
326 int err = glx.fGetFBConfigAttrib(*display, cfg, LOCAL_GLX_DOUBLEBUFFER5,
327 &isDoubleBuffered);
328 if (LOCAL_GLX_BAD_ATTRIBUTE2 != err) {
9
Assuming 'err' is equal to LOCAL_GLX_BAD_ATTRIBUTE
10
Taking false branch
329 if (ShouldSpew()) {
330 printf("[GLX] FBConfig is %sdouble-buffered\n",
331 isDoubleBuffered ? "" : "not ");
332 }
333 }
334
335 if (!glx.HasCreateContextAttribs()) {
11
Assuming the condition is false
12
Taking false branch
336 NS_WARNING("Cannot create GLContextGLX without glxCreateContextAttribs")NS_DebugBreak(NS_DEBUG_WARNING, "Cannot create GLContextGLX without glxCreateContextAttribs"
, nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 336)
;
337 return nullptr;
338 }
339
340 // -
341
342 const auto CreateWithAttribs =
343 [&](const std::vector<int>& attribs) -> RefPtr<GLContextGLX> {
344 auto terminated = attribs;
345 terminated.push_back(0);
346
347 const auto glxContext = glx.fCreateContextAttribs(
21
Called C++ object pointer is uninitialized
348 *display, cfg, nullptr, X11True1, terminated.data());
349 if (!glxContext) return nullptr;
350 const RefPtr<GLContextGLX> ret = new GLContextGLX(
351 desc, display, drawable, glxContext, isDoubleBuffered, ownedPixmap);
352
353 if (!ret->Init()) return nullptr;
354
355 return ret;
356 };
357
358 // -
359
360 RefPtr<GLContextGLX> glContext;
361
362 std::vector<int> attribs;
363 attribs.insert(attribs.end(), {
364 LOCAL_GLX_RENDER_TYPE0x8011,
365 LOCAL_GLX_RGBA_TYPE0x8014,
366 });
367 if (glx.HasVideoMemoryPurge()) {
13
Assuming the condition is false
14
Taking false branch
368 attribs.insert(attribs.end(),
369 {
370 LOCAL_GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV0x20F7,
371 LOCAL_GL_TRUE1,
372 });
373 }
374 const bool useCore =
375 !(desc.flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE);
376 if (useCore
14.1
'useCore' is false
) {
15
Taking false branch
377 attribs.insert(attribs.end(), {
378 LOCAL_GLX_CONTEXT_MAJOR_VERSION_ARB0x2091,
379 3,
380 LOCAL_GLX_CONTEXT_MINOR_VERSION_ARB0x2092,
381 2,
382 LOCAL_GLX_CONTEXT_PROFILE_MASK_ARB0x9126,
383 LOCAL_GLX_CONTEXT_CORE_PROFILE_BIT_ARB0x00000001,
384 });
385 }
386
387 if (glx.HasRobustness()) {
16
Uninitialized value stored to 'glx'
17
Assuming the condition is false
18
Taking false branch
388 auto withRobustness = attribs;
389 withRobustness.insert(withRobustness.end(),
390 {
391 LOCAL_GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB0x8256,
392 LOCAL_GLX_LOSE_CONTEXT_ON_RESET_ARB0x8252,
393 });
394
395 {
396 auto withRBAB = withRobustness;
397 withRBAB.insert(withRBAB.end(),
398 {
399 LOCAL_GLX_CONTEXT_FLAGS_ARB0x2094,
400 LOCAL_GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB0x00000004,
401 });
402 if (!glContext) {
403 glContext = CreateWithAttribs(withRBAB);
404 if (!glContext) {
405 NS_WARNING("Failed to create+init GLContextGLX with RBAB")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to create+init GLContextGLX with RBAB"
, nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 405)
;
406 }
407 }
408 }
409
410 if (!glContext) {
411 glContext = CreateWithAttribs(withRobustness);
412 if (!glContext) {
413 NS_WARNING("Failed to create+init GLContextGLX with Robustness")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to create+init GLContextGLX with Robustness"
, nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 413)
;
414 }
415 }
416 }
417
418 if (!glContext) {
19
Taking true branch
419 glContext = CreateWithAttribs(attribs);
20
Calling 'operator()'
420 if (!glContext) {
421 NS_WARNING("Failed to create+init GLContextGLX with required attribs")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to create+init GLContextGLX with required attribs"
, nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 421)
;
422 }
423 }
424
425 return glContext.forget();
426}
427
428GLContextGLX::~GLContextGLX() {
429 MarkDestroyed();
430
431 // Wrapped context should not destroy glxContext/Surface
432 if (!mOwnsContext) {
433 return;
434 }
435
436 // see bug 659842 comment 76
437 bool success = mGLX->fMakeCurrent(*mDisplay, X11None0L, nullptr);
438 if (!success) {
439 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "glXMakeCurrent failed to release GL context before we call "
"glXDestroyContext!", nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 441)
440 "glXMakeCurrent failed to release GL context before we call "NS_DebugBreak(NS_DEBUG_WARNING, "glXMakeCurrent failed to release GL context before we call "
"glXDestroyContext!", nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 441)
441 "glXDestroyContext!")NS_DebugBreak(NS_DEBUG_WARNING, "glXMakeCurrent failed to release GL context before we call "
"glXDestroyContext!", nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 441)
;
442 }
443
444 mGLX->fDestroyContext(*mDisplay, mContext);
445
446 // If we own the enclosed X pixmap, then free it after we free the enclosing
447 // GLX pixmap.
448 if (mOwnedPixmap) {
449 mGLX->fDestroyPixmap(*mDisplay, mDrawable);
450 XFreePixmap(*mDisplay, mOwnedPixmap);
451 }
452}
453
454bool GLContextGLX::Init() {
455 if (!GLContext::Init()) {
456 return false;
457 }
458
459 // EXT_framebuffer_object is not supported on Core contexts
460 // so we'll also check for ARB_framebuffer_object
461 if (!IsExtensionSupported(EXT_framebuffer_object) &&
462 !IsSupported(GLFeature::framebuffer_object))
463 return false;
464
465 return true;
466}
467
468bool GLContextGLX::MakeCurrentImpl() const {
469 if (mGLX->IsMesa()) {
470 // Read into the event queue to ensure that Mesa receives a
471 // DRI2InvalidateBuffers event before drawing. See bug 1280653.
472 Unused << XPending(*mDisplay);
473 }
474
475 const bool succeeded = mGLX->fMakeCurrent(*mDisplay, mDrawable, mContext);
476 if (!succeeded) {
477 NS_WARNING("Failed to make GL context current!")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to make GL context current!"
, nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 477)
;
478 }
479
480 if (!IsOffscreen() && mGLX->SupportsSwapControl()) {
481 // Many GLX implementations default to blocking until the next
482 // VBlank when calling glXSwapBuffers. We want to run unthrottled
483 // in ASAP mode. See bug 1280744.
484 const bool swapInterval = gfxVars::SwapIntervalGLX();
485 const bool isASAP = (StaticPrefs::layout_frame_rate() == 0);
486 const int interval = (swapInterval && !isASAP) ? 1 : 0;
487 mGLX->fSwapInterval(*mDisplay, mDrawable, interval);
488 }
489 return succeeded;
490}
491
492bool GLContextGLX::IsCurrentImpl() const {
493 return mGLX->fGetCurrentContext() == mContext;
494}
495
496Maybe<SymbolLoader> GLContextGLX::GetSymbolLoader() const {
497 const auto pfn = sGLXLibrary.GetGetProcAddress();
498 return Some(SymbolLoader(pfn));
499}
500
501bool GLContextGLX::IsDoubleBuffered() const { return mDoubleBuffered; }
502
503bool GLContextGLX::SwapBuffers() {
504 if (!mDoubleBuffered) return false;
505 mGLX->fSwapBuffers(*mDisplay, mDrawable);
506 return true;
507}
508
509GLint GLContextGLX::GetBufferAge() const {
510 if (!sGLXLibrary.SupportsBufferAge()) {
511 return 0;
512 }
513
514 GLuint result = 0;
515 mGLX->fQueryDrawable(*mDisplay, mDrawable, LOCAL_GLX_BACK_BUFFER_AGE_EXT0x20F4,
516 &result);
517 if (result > INT32_MAX(2147483647)) {
518 // If the result can't fit, just assume the buffer cannot be reused.
519 return 0;
520 }
521 return result;
522}
523
524void GLContextGLX::GetWSIInfo(nsCString* const out) const {
525 int screen = DefaultScreen(mDisplay->get())(((_XPrivDisplay)(mDisplay->get()))->default_screen);
526
527 int majorVersion, minorVersion;
528 sGLXLibrary.fQueryVersion(*mDisplay, &majorVersion, &minorVersion);
529
530 out->Append(nsPrintfCString("GLX %u.%u", majorVersion, minorVersion));
531
532 out->AppendLiteral("\nGLX_VENDOR(client): ");
533 out->Append(sGLXLibrary.fGetClientString(*mDisplay, LOCAL_GLX_VENDOR0x1));
534
535 out->AppendLiteral("\nGLX_VENDOR(server): ");
536 out->Append(
537 sGLXLibrary.fQueryServerString(*mDisplay, screen, LOCAL_GLX_VENDOR0x1));
538
539 out->AppendLiteral("\nExtensions: ");
540 out->Append(sGLXLibrary.fQueryExtensionsString(*mDisplay, screen));
541}
542
543bool GLContextGLX::OverrideDrawable(GLXDrawable drawable) {
544 return mGLX->fMakeCurrent(*mDisplay, drawable, mContext);
545}
546
547bool GLContextGLX::RestoreDrawable() {
548 return mGLX->fMakeCurrent(*mDisplay, mDrawable, mContext);
549}
550
551GLContextGLX::GLContextGLX(const GLContextDesc& desc,
552 std::shared_ptr<XlibDisplay> aDisplay,
553 GLXDrawable aDrawable, GLXContext aContext,
554 bool aDoubleBuffered, Drawable aOwnedPixmap)
555 : GLContext(desc, nullptr),
556 mContext(aContext),
557 mDisplay(aDisplay),
558 mDrawable(aDrawable),
559 mOwnedPixmap(aOwnedPixmap),
560 mDoubleBuffered(aDoubleBuffered),
561 mGLX(&sGLXLibrary) {}
562
563static bool AreCompatibleVisuals(Visual* one, Visual* two) {
564 if (one->c_class != two->c_class) {
565 return false;
566 }
567
568 if (one->red_mask != two->red_mask || one->green_mask != two->green_mask ||
569 one->blue_mask != two->blue_mask) {
570 return false;
571 }
572
573 if (one->bits_per_rgb != two->bits_per_rgb) {
574 return false;
575 }
576
577 return true;
578}
579
580already_AddRefed<GLContext> CreateForWidget(Display* aXDisplay, Window aXWindow,
581 bool aHardwareWebRender,
582 bool aForceAccelerated) {
583 if (!sGLXLibrary.EnsureInitialized(aXDisplay)) {
584 return nullptr;
585 }
586
587 // Currently, we take whatever Visual the window already has, and
588 // try to create an fbconfig for that visual. This isn't
589 // necessarily what we want in the long run; an fbconfig may not
590 // be available for the existing visual, or if it is, the GL
591 // performance might be suboptimal. But using the existing visual
592 // is a relatively safe intermediate step.
593
594 if (!aXDisplay) {
595 NS_ERROR("X Display required for GLX Context provider")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "X Display required for GLX Context provider"
, "Error", "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 595); MOZ_PretendNoReturn(); } while (0)
;
596 return nullptr;
597 }
598
599 if (!aXWindow) {
600 NS_ERROR("X window required for GLX Context provider")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "X window required for GLX Context provider"
, "Error", "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 600); MOZ_PretendNoReturn(); } while (0)
;
601 return nullptr;
602 }
603
604 int xscreen = DefaultScreen(aXDisplay)(((_XPrivDisplay)(aXDisplay))->default_screen);
605
606 GLXFBConfig config;
607 int visid;
608 if (!GLContextGLX::FindFBConfigForWindow(
609 aXDisplay, xscreen, aXWindow, &config, &visid, aHardwareWebRender)) {
610 return nullptr;
611 }
612
613 CreateContextFlags flags;
614 if (aHardwareWebRender) {
615 flags = CreateContextFlags::NONE; // WR needs GL3.2+
616 } else {
617 flags = CreateContextFlags::REQUIRE_COMPAT_PROFILE;
618 }
619 return GLContextGLX::CreateGLContext(
620 {{flags}, false}, XlibDisplay::Borrow(aXDisplay), aXWindow, config);
621}
622
623already_AddRefed<GLContext> GLContextProviderGLX::CreateForCompositorWidget(
624 CompositorWidget* aCompositorWidget, bool aHardwareWebRender,
625 bool aForceAccelerated) {
626 if (!aCompositorWidget) {
627 MOZ_ASSERT(false)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false", "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ")");
do { MOZ_CrashSequence(__null, 627); __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
;
628 return nullptr;
629 }
630 GtkCompositorWidget* compWidget = aCompositorWidget->AsGTK();
631 MOZ_ASSERT(compWidget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(compWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(compWidget))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("compWidget", "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 631); AnnotateMozCrashReason("MOZ_ASSERT" "(" "compWidget" ")"
); do { MOZ_CrashSequence(__null, 631); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
632
633 return CreateForWidget(DefaultXDisplay(), compWidget->XWindow(),
634 aHardwareWebRender, aForceAccelerated);
635}
636
637static bool ChooseConfig(GLXLibrary* glx, Display* display, int screen,
638 GLXFBConfig* const out_config, int* const out_visid) {
639 const int attribs[] = {
640 LOCAL_GLX_RENDER_TYPE0x8011,
641 LOCAL_GLX_RGBA_BIT0x00000001,
642 LOCAL_GLX_DRAWABLE_TYPE0x8010,
643 LOCAL_GLX_PIXMAP_BIT0x00000002,
644 LOCAL_GLX_X_RENDERABLE0x8012,
645 X11True1,
646 LOCAL_GLX_RED_SIZE8,
647 8,
648 LOCAL_GLX_GREEN_SIZE9,
649 8,
650 LOCAL_GLX_BLUE_SIZE10,
651 8,
652 LOCAL_GLX_ALPHA_SIZE11,
653 8,
654 LOCAL_GLX_DEPTH_SIZE12,
655 0,
656 LOCAL_GLX_STENCIL_SIZE13,
657 0,
658 0,
659 };
660
661 int numConfigs = 0;
662 const auto scopedConfigArr =
663 glx->fChooseFBConfig(display, screen, attribs, &numConfigs);
664 const auto freeConfigList = MakeScopeExit([&]() {
665 if (scopedConfigArr) {
666 XFree(scopedConfigArr);
667 }
668 });
669 if (!scopedConfigArr || !numConfigs) return false;
670
671 // Issues with glxChooseFBConfig selection and sorting:
672 // * ALPHA_SIZE is sorted as 'largest total RGBA bits first'. If we don't
673 // request
674 // alpha bits, we'll probably get RGBA anyways, since 32 is more than 24.
675 // * DEPTH_SIZE is sorted largest first, including for `0` inputs.
676 // * STENCIL_SIZE is smallest first, but it might return `8` even though we
677 // ask for
678 // `0`.
679
680 // For now, we don't care about these. We *will* care when we do XPixmap
681 // sharing.
682
683 for (int i = 0; i < numConfigs; ++i) {
684 GLXFBConfig curConfig = scopedConfigArr[i];
685
686 int visid;
687 if (glx->fGetFBConfigAttrib(display, curConfig, LOCAL_GLX_VISUAL_ID0x800B,
688 &visid) != Success0) {
689 continue;
690 }
691
692 if (!visid) continue;
693
694 *out_config = curConfig;
695 *out_visid = visid;
696 return true;
697 }
698
699 return false;
700}
701
702bool GLContextGLX::FindVisual(Display* display, int screen,
703 int* const out_visualId) {
704 if (!sGLXLibrary.EnsureInitialized(display)) {
705 return false;
706 }
707
708 XVisualInfo visualTemplate;
709 visualTemplate.screen = screen;
710
711 // Get all visuals of screen
712
713 int visualsLen = 0;
714 XVisualInfo* xVisuals =
715 XGetVisualInfo(display, VisualScreenMask0x2, &visualTemplate, &visualsLen);
716 if (!xVisuals) {
717 return false;
718 }
719 const Range<XVisualInfo> visualInfos(xVisuals, visualsLen);
720 auto cleanupVisuals = MakeScopeExit([&] { XFree(xVisuals); });
721
722 // Get default visual info
723
724 Visual* defaultVisual = DefaultVisual(display, screen)((&((_XPrivDisplay)(display))->screens[screen])->root_visual
)
;
725 const auto defaultVisualInfo = [&]() -> const XVisualInfo* {
726 for (const auto& cur : visualInfos) {
727 if (cur.visual == defaultVisual) {
728 return &cur;
729 }
730 }
731 return nullptr;
732 }();
733 if (!defaultVisualInfo) {
734 MOZ_ASSERT(false)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false", "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ")");
do { MOZ_CrashSequence(__null, 734); __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
;
735 return false;
736 }
737
738 const int bpp = 32;
739
740 for (auto& cur : visualInfos) {
741 const auto fnConfigMatches = [&](const int pname, const int expected) {
742 int actual;
743 if (sGLXLibrary.fGetConfig(display, &cur, pname, &actual)) {
744 return false;
745 }
746 return actual == expected;
747 };
748
749 // Check if visual is compatible.
750 if (cur.depth != bpp || cur.c_class != defaultVisualInfo->c_class) {
751 continue;
752 }
753
754 // Check if visual is compatible to GL requests.
755 if (fnConfigMatches(LOCAL_GLX_USE_GL1, 1) &&
756 fnConfigMatches(LOCAL_GLX_DOUBLEBUFFER5, 1) &&
757 fnConfigMatches(LOCAL_GLX_RED_SIZE8, 8) &&
758 fnConfigMatches(LOCAL_GLX_GREEN_SIZE9, 8) &&
759 fnConfigMatches(LOCAL_GLX_BLUE_SIZE10, 8) &&
760 fnConfigMatches(LOCAL_GLX_ALPHA_SIZE11, 8)) {
761 *out_visualId = cur.visualid;
762 return true;
763 }
764 }
765
766 return false;
767}
768
769bool GLContextGLX::FindFBConfigForWindow(Display* display, int screen,
770 Window window,
771 GLXFBConfig* const out_config,
772 int* const out_visid,
773 bool aWebRender) {
774 // XXX the visual ID is almost certainly the LOCAL_GLX_FBCONFIG_ID, so
775 // we could probably do this first and replace the glXGetFBConfigs
776 // with glXChooseConfigs. Docs are sparklingly clear as always.
777 XWindowAttributes windowAttrs;
778 if (!XGetWindowAttributes(display, window, &windowAttrs)) {
779 NS_WARNING("[GLX] XGetWindowAttributes() failed")NS_DebugBreak(NS_DEBUG_WARNING, "[GLX] XGetWindowAttributes() failed"
, nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 779)
;
780 return false;
781 }
782
783 GLXFBConfig* cfgs = nullptr;
784 const auto freeConfigList = MakeScopeExit([&]() {
785 if (cfgs) {
786 XFree(cfgs);
787 }
788 });
789 int numConfigs;
790 const int webrenderAttribs[] = {LOCAL_GLX_ALPHA_SIZE11,
791 windowAttrs.depth == 32 ? 8 : 0,
792 LOCAL_GLX_DOUBLEBUFFER5, X11True1, 0};
793
794 if (aWebRender) {
795 cfgs = sGLXLibrary.fChooseFBConfig(display, screen, webrenderAttribs,
796 &numConfigs);
797 } else {
798 cfgs = sGLXLibrary.fGetFBConfigs(display, screen, &numConfigs);
799 }
800
801 if (!cfgs) {
802 NS_WARNING("[GLX] glXGetFBConfigs() failed")NS_DebugBreak(NS_DEBUG_WARNING, "[GLX] glXGetFBConfigs() failed"
, nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 802)
;
803 return false;
804 }
805 NS_ASSERTION(numConfigs > 0, "No FBConfigs found!")do { if (!(numConfigs > 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "No FBConfigs found!", "numConfigs > 0", "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 805); MOZ_PretendNoReturn(); } } while (0)
;
806
807 const VisualID windowVisualID = XVisualIDFromVisual(windowAttrs.visual);
808#ifdef DEBUG1
809 printf("[GLX] window %lx has VisualID 0x%lx\n", window, windowVisualID);
810#endif
811
812 for (int i = 0; i < numConfigs; i++) {
813 int visid = X11None0L;
814 sGLXLibrary.fGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID0x800B,
815 &visid);
816 if (visid) {
817 // WebRender compatible GLX visual is configured
818 // at nsWindow::Create() by GLContextGLX::FindVisual(),
819 // just reuse it here.
820 if (windowVisualID == static_cast<VisualID>(visid)) {
821 *out_config = cfgs[i];
822 *out_visid = visid;
823 return true;
824 }
825 }
826 }
827
828 // We don't have a frame buffer visual which matches the GLX visual
829 // from GLContextGLX::FindVisual(). Let's try to find a near one and hope
830 // we're not on NVIDIA (Bug 1478454) as it causes X11 BadMatch error there.
831 for (int i = 0; i < numConfigs; i++) {
832 int visid = X11None0L;
833 sGLXLibrary.fGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID0x800B,
834 &visid);
835 if (visid) {
836 int depth;
837 Visual* visual;
838 FindVisualAndDepth(display, visid, &visual, &depth);
839 if (depth == windowAttrs.depth &&
840 AreCompatibleVisuals(windowAttrs.visual, visual)) {
841 *out_config = cfgs[i];
842 *out_visid = visid;
843 return true;
844 }
845 }
846 }
847
848 NS_WARNING("[GLX] Couldn't find a FBConfig matching window visual")NS_DebugBreak(NS_DEBUG_WARNING, "[GLX] Couldn't find a FBConfig matching window visual"
, nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 848)
;
849 return false;
850}
851
852static already_AddRefed<GLContextGLX> CreateOffscreenPixmapContext(
853 const GLContextCreateDesc& desc, const IntSize& size,
854 nsACString* const out_failureId) {
855 GLXLibrary* glx = &sGLXLibrary;
856 auto display = glx->GetDisplay();
857
858 if (!display || !glx->EnsureInitialized(*display)) return nullptr;
2
Taking false branch
859
860 int screen = DefaultScreen(display->get())(((_XPrivDisplay)(display->get()))->default_screen);
861
862 GLXFBConfig config;
863 int visid;
864 if (!ChooseConfig(glx, *display, screen, &config, &visid)) {
3
Taking false branch
865 NS_WARNING("Failed to find a compatible config.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to find a compatible config."
, nullptr, "/root/firefox-clang/gfx/gl/GLContextProviderGLX.cpp"
, 865)
;
866 return nullptr;
867 }
868
869 Visual* visual;
870 int depth;
871 FindVisualAndDepth(*display, visid, &visual, &depth);
872
873 gfx::IntSize dummySize(16, 16);
874 const auto drawable =
875 XCreatePixmap(*display, DefaultRootWindow(display->get())((&((_XPrivDisplay)(display->get()))->screens[(((_XPrivDisplay
)(display->get()))->default_screen)])->root)
,
876 dummySize.width, dummySize.height, depth);
877 if (!drawable) {
4
Assuming 'drawable' is not equal to 0
5
Taking false branch
878 return nullptr;
879 }
880
881 // Handle slightly different signature between glXCreatePixmap and
882 // its pre-GLX-1.3 extension equivalent (though given the ABI, we
883 // might not need to).
884 const auto pixmap = glx->fCreatePixmap(*display, config, drawable, nullptr);
885 if (pixmap == 0) {
6
Assuming 'pixmap' is not equal to 0
7
Taking false branch
886 XFreePixmap(*display, drawable);
887 return nullptr;
888 }
889
890 auto fullDesc = GLContextDesc{desc};
891 fullDesc.isOffscreen = true;
892
893 return GLContextGLX::CreateGLContext(fullDesc, display, pixmap, config,
8
Calling 'GLContextGLX::CreateGLContext'
894 drawable);
895}
896
897/*static*/
898already_AddRefed<GLContext> GLContextProviderGLX::CreateHeadless(
899 const GLContextCreateDesc& desc, nsACString* const out_failureId) {
900 IntSize dummySize = IntSize(16, 16);
901 return CreateOffscreenPixmapContext(desc, dummySize, out_failureId);
1
Calling 'CreateOffscreenPixmapContext'
902}
903
904/*static*/
905GLContext* GLContextProviderGLX::GetGlobalContext() {
906 // Context sharing not supported.
907 return nullptr;
908}
909
910/*static*/
911void GLContextProviderGLX::Shutdown() {}
912
913} // namespace mozilla::gl