12 #include <osl/file.hxx>
13 #include <rtl/bootstrap.hxx>
14 #include <rtl/digest.h>
15 #include <rtl/strbuf.hxx>
16 #include <rtl/ustring.hxx>
19 #include <config_folders.h>
23 #include <officecfg/Office/Common.hxx>
24 #include <com/sun/star/util/XFlushable.hpp>
25 #include <com/sun/star/configuration/theDefaultProvider.hpp>
28 #include <string_view>
30 #include <unordered_map>
41 #if defined UNX && !defined MACOSX && !defined IOS && !defined ANDROID && !defined HAIKU
43 #elif defined (_WIN32)
55 OUString getShaderFolder()
57 OUString aUrl(
"$BRAND_BASE_DIR/" LIBO_ETC_FOLDER);
58 rtl::Bootstrap::expandMacros(aUrl);
60 return aUrl +
"/opengl/";
63 OString loadShader(std::u16string_view rFilename)
65 OUString aFileURL = getShaderFolder() + rFilename +
".glsl";
66 osl::File aFile(aFileURL);
67 if(aFile.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None)
71 std::unique_ptr<char[]> content(
new char[nSize+1]);
72 sal_uInt64 nBytesRead = 0;
73 aFile.read(content.get(), nSize, nBytesRead);
74 assert(nSize == nBytesRead);
75 content.get()[nBytesRead] = 0;
76 SAL_INFO(
"vcl.opengl",
"Read " << nBytesRead <<
" bytes from " << aFileURL);
81 SAL_WARN(
"vcl.opengl",
"Could not open " << aFileURL);
87 OString& getShaderSource(
const OUString& rFilename)
89 static std::unordered_map<OUString, OString>
aMap;
91 if (aMap.find(rFilename) == aMap.end())
93 aMap[rFilename] = loadShader(rFilename);
96 return aMap[rFilename];
102 int LogCompilerError(GLuint nId,
const OUString &rDetail,
103 const OUString &rName,
bool bShaderNotProgram)
107 int InfoLogLength = 0;
111 if (bShaderNotProgram)
112 glGetShaderiv (nId, GL_INFO_LOG_LENGTH, &InfoLogLength);
114 glGetProgramiv(nId, GL_INFO_LOG_LENGTH, &InfoLogLength);
118 if ( InfoLogLength > 0 )
120 std::vector<char> ErrorMessage(InfoLogLength+1);
121 if (bShaderNotProgram)
122 glGetShaderInfoLog (nId, InfoLogLength,
nullptr, ErrorMessage.data());
124 glGetProgramInfoLog(nId, InfoLogLength,
nullptr, ErrorMessage.data());
127 ErrorMessage.push_back(
'\0');
128 SAL_WARN(
"vcl.opengl", rDetail <<
" shader " << nId <<
" compile for " << rName <<
" failed : " << ErrorMessage.data());
131 SAL_WARN(
"vcl.opengl", rDetail <<
" shader: " << rName <<
" compile " << nId <<
" failed without error log");
140 static void addPreamble(OString& rShaderSource, std::string_view rPreamble)
142 if (rPreamble.empty())
145 int nVersionStrStartPos = rShaderSource.indexOf(
"#version");
147 if (nVersionStrStartPos == -1)
149 rShaderSource = OString::Concat(rPreamble) +
"\n" + rShaderSource;
153 int nVersionStrEndPos = rShaderSource.indexOf(
'\n', nVersionStrStartPos);
155 SAL_WARN_IF(nVersionStrEndPos == -1,
"vcl.opengl",
"syntax error in shader");
157 if (nVersionStrEndPos == -1)
158 nVersionStrEndPos = nVersionStrStartPos + 8;
160 OString aVersionLine = rShaderSource.copy(0, nVersionStrEndPos);
161 OString aShaderBody = rShaderSource.copy(nVersionStrEndPos + 1);
163 rShaderSource = aVersionLine +
"\n" + rPreamble +
"\n" + aShaderBody;
169 const sal_uInt32 GLenumSize =
sizeof(GLenum);
171 OString getHexString(
const sal_uInt8* pData, sal_uInt32 nLength)
173 static const char*
const pHexData =
"0123456789ABCDEF";
176 OStringBuffer aHexStr;
177 for(
size_t i = 0;
i < nLength; ++
i)
182 aHexStr.append( pHexData[ val & 0xf ] );
183 aHexStr.append( pHexData[ val >> 4 ] );
188 return aHexStr.makeStringAndClear();
191 OString generateMD5(
const void* pData,
size_t length)
193 sal_uInt8 pBuffer[RTL_DIGEST_LENGTH_MD5];
194 rtlDigestError aError = rtl_digest_MD5(pData, length,
195 pBuffer, RTL_DIGEST_LENGTH_MD5);
196 SAL_WARN_IF(aError != rtl_Digest_E_None,
"vcl.opengl",
"md5 generation failed");
198 return getHexString(pBuffer, RTL_DIGEST_LENGTH_MD5);
203 #if defined( SAL_UNX ) && !defined( MACOSX ) && !defined( IOS )&& !defined( ANDROID ) && !defined( HAIKU )
205 return aInfo.
GetOS() +
210 #elif defined( _WIN32 )
215 OString::number(DriverBlocklist::GetWindowsVersion());
217 return OString::Concat(reinterpret_cast<const char*>(glGetString(GL_VENDOR))) +
218 reinterpret_cast<const char*
>(glGetString(GL_RENDERER)) +
219 reinterpret_cast<const char*>(glGetString(GL_VERSION));
223 OString getStringDigest(
const OUString& rVertexShaderName,
224 const OUString& rFragmentShaderName,
225 std::string_view rPreamble )
228 OString aVertexShaderSource = getShaderSource( rVertexShaderName );
229 OString aFragmentShaderSource = getShaderSource( rFragmentShaderName );
234 OString aMessage = rPreamble +
235 aVertexShaderSource +
236 aFragmentShaderSource +
239 return generateMD5(aMessage.getStr(), aMessage.getLength());
242 OString getCacheFolder()
244 OUString url(
"${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE(
"bootstrap")
":UserInstallation}/cache/");
245 rtl::Bootstrap::expandMacros(url);
247 osl::Directory::create(url);
253 bool writeProgramBinary(
const OString& rBinaryFileName,
254 const std::vector<sal_uInt8>& rBinary )
256 osl::File aFile(OStringToOUString(rBinaryFileName, RTL_TEXTENCODING_UTF8));
257 osl::FileBase::RC eStatus = aFile.open(
258 osl_File_OpenFlag_Write | osl_File_OpenFlag_Create );
260 if( eStatus != osl::FileBase::E_None )
265 if( eStatus == osl::FileBase::E_EXIST )
268 "No binary program saved. A file with the same hash already exists: '" << rBinaryFileName <<
"'" );
274 sal_uInt64 nBytesWritten = 0;
275 aFile.write( rBinary.data(), rBinary.size(), nBytesWritten );
277 assert( rBinary.size() == nBytesWritten );
282 bool readProgramBinary(
const OString& rBinaryFileName,
283 std::vector<sal_uInt8>& rBinary )
285 osl::File aFile( OStringToOUString( rBinaryFileName, RTL_TEXTENCODING_UTF8 ) );
286 if(aFile.open( osl_File_OpenFlag_Read ) == osl::FileBase::E_None)
288 sal_uInt64 nSize = 0;
289 aFile.getSize( nSize );
290 rBinary.resize( nSize );
291 sal_uInt64 nBytesRead = 0;
292 aFile.read( rBinary.data(), nSize, nBytesRead );
293 assert( nSize == nBytesRead );
294 VCL_GL_INFO(
"Loading file: '" << rBinaryFileName <<
"': success" );
299 VCL_GL_INFO(
"Loading file: '" << rBinaryFileName <<
"': FAIL");
305 OString createFileName( std::u16string_view rVertexShaderName,
306 std::u16string_view rFragmentShaderName,
307 std::u16string_view rGeometryShaderName,
308 std::string_view rDigest )
310 OString aFileName = getCacheFolder() +
313 if (!rGeometryShaderName.empty())
314 aFileName +=
OUStringToOString( rGeometryShaderName, RTL_TEXTENCODING_UTF8 ) +
"-";
315 aFileName += OString::Concat(rDigest) +
".bin";
319 GLint loadProgramBinary( GLuint nProgramID,
const OString& rBinaryFileName )
321 GLint nResult = GL_FALSE;
322 GLenum nBinaryFormat;
323 std::vector<sal_uInt8> aBinary;
324 if( readProgramBinary( rBinaryFileName, aBinary ) && aBinary.size() > GLenumSize )
326 GLint nBinaryLength = aBinary.size() - GLenumSize;
330 for(
size_t i = 0;
i < GLenumSize; ++
i )
332 pBF[
i] = aBinary[nBinaryLength +
i];
336 glProgramBinary( nProgramID, nBinaryFormat, aBinary.data(), nBinaryLength );
339 glGetProgramiv(nProgramID, GL_LINK_STATUS, &nResult);
344 void saveProgramBinary( GLint nProgramID,
const OString& rBinaryFileName )
346 GLint nBinaryLength = 0;
347 GLenum nBinaryFormat = GL_NONE;
349 glGetProgramiv( nProgramID, GL_PROGRAM_BINARY_LENGTH, &nBinaryLength );
350 if( nBinaryLength <= 0 )
352 SAL_WARN(
"vcl.opengl",
"Binary size is zero" );
356 std::vector<sal_uInt8> aBinary( nBinaryLength + GLenumSize );
358 glGetProgramBinary( nProgramID, nBinaryLength,
nullptr, &nBinaryFormat, aBinary.data() );
361 aBinary.insert( aBinary.end(), pBF, pBF + GLenumSize );
363 SAL_INFO(
"vcl.opengl",
"Program id: " << nProgramID );
364 SAL_INFO(
"vcl.opengl",
"Binary length: " << nBinaryLength );
365 SAL_INFO(
"vcl.opengl",
"Binary format: " << nBinaryFormat );
367 if( !writeProgramBinary( rBinaryFileName, aBinary ) )
368 SAL_WARN(
"vcl.opengl",
"Writing binary file '" << rBinaryFileName <<
"': FAIL");
370 SAL_INFO(
"vcl.opengl",
"Writing binary file '" << rBinaryFileName <<
"': success");
375 const OUString& rFragmentShaderName,
376 std::string_view rPreamble )
378 return getStringDigest(rVertexShaderName, rFragmentShaderName, rPreamble);
382 const OUString& rFragmentShaderName,
383 const OUString& rGeometryShaderName,
384 std::string_view preamble,
385 std::string_view rDigest)
391 bool bHasGeometryShader = !rGeometryShaderName.isEmpty();
394 GLint ProgramID = glCreateProgram();
397 OString aVertexShaderSource = getShaderSource(rVertexShaderName);
398 OString aFragmentShaderSource = getShaderSource(rFragmentShaderName);
399 OString aGeometryShaderSource;
400 if (bHasGeometryShader)
401 aGeometryShaderSource = getShaderSource(rGeometryShaderName);
403 GLint bBinaryResult = GL_FALSE;
404 if (epoxy_has_gl_extension(
"GL_ARB_get_program_binary") && !rDigest.empty())
407 createFileName(rVertexShaderName, rFragmentShaderName, rGeometryShaderName, rDigest);
408 bBinaryResult = loadProgramBinary(ProgramID, aFileName);
412 if( bBinaryResult != GL_FALSE )
415 if (bHasGeometryShader)
416 VCL_GL_INFO(
"Load shader: vertex " << rVertexShaderName <<
" fragment " << rFragmentShaderName <<
" geometry " << rGeometryShaderName);
418 VCL_GL_INFO(
"Load shader: vertex " << rVertexShaderName <<
" fragment " << rFragmentShaderName);
420 GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
421 GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
422 GLuint GeometryShaderID = 0;
423 if (bHasGeometryShader)
424 GeometryShaderID = glCreateShader(GL_GEOMETRY_SHADER);
429 if( !preamble.empty())
431 char const * VertexSourcePointer = aVertexShaderSource.getStr();
432 glShaderSource(VertexShaderID, 1, &VertexSourcePointer ,
nullptr);
433 glCompileShader(VertexShaderID);
436 glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
438 return LogCompilerError(VertexShaderID,
"vertex",
439 rVertexShaderName,
true);
442 if( !preamble.empty())
444 char const * FragmentSourcePointer = aFragmentShaderSource.getStr();
445 glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer ,
nullptr);
446 glCompileShader(FragmentShaderID);
449 glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
451 return LogCompilerError(FragmentShaderID,
"fragment",
452 rFragmentShaderName,
true);
454 if (bHasGeometryShader)
457 if( !preamble.empty())
459 char const * GeometrySourcePointer = aGeometryShaderSource.getStr();
460 glShaderSource(GeometryShaderID, 1, &GeometrySourcePointer ,
nullptr);
461 glCompileShader(GeometryShaderID);
464 glGetShaderiv(GeometryShaderID, GL_COMPILE_STATUS, &Result);
466 return LogCompilerError(GeometryShaderID,
"geometry",
467 rGeometryShaderName,
true);
471 glAttachShader(ProgramID, VertexShaderID);
472 glAttachShader(ProgramID, FragmentShaderID);
473 if (bHasGeometryShader)
474 glAttachShader(ProgramID, GeometryShaderID);
476 if (epoxy_has_gl_extension(
"GL_ARB_get_program_binary") && !rDigest.empty())
478 glProgramParameteri(ProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
479 glLinkProgram(ProgramID);
480 glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
483 SAL_WARN(
"vcl.opengl",
"linking failed: " << Result );
484 return LogCompilerError(ProgramID,
"program",
"<both>",
false);
487 createFileName(rVertexShaderName, rFragmentShaderName, rGeometryShaderName, rDigest);
488 saveProgramBinary(ProgramID, aFileName);
492 glLinkProgram(ProgramID);
495 glDeleteShader(VertexShaderID);
496 glDeleteShader(FragmentShaderID);
497 if (bHasGeometryShader)
498 glDeleteShader(GeometryShaderID);
501 glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
503 return LogCompilerError(ProgramID,
"program",
"<both>",
false);
515 const OUString& rFragmentShaderName,
516 std::string_view preamble,
517 std::string_view rDigest)
519 return LoadShaders(rVertexShaderName, rFragmentShaderName, OUString(), preamble, rDigest);
523 const OUString& rFragmentShaderName,
524 const OUString& rGeometryShaderName)
526 return LoadShaders(rVertexShaderName, rFragmentShaderName, rGeometryShaderName, std::string_view(), std::string_view());
530 const OUString& rFragmentShaderName)
532 return LoadShaders(rVertexShaderName, rFragmentShaderName, OUString(),
"",
"");
539 std::unique_ptr<sal_uInt8[]> pBuffer(
new sal_uInt8[nWidth*nHeight*4]);
540 glReadPixels(0, 0, nWidth, nHeight, OptimalBufferFormat(), GL_UNSIGNED_BYTE, pBuffer.get());
541 BitmapEx aBitmap = ConvertBufferToBitmapEx(pBuffer.get(), nWidth, nHeight);
545 aWriter.
Write( sOutput );
548 SAL_WARN(
"vcl.opengl",
"Error writing png to " << rFileName);
595 *pScan++ = pBuffer[nCurPos];
596 *pScan++ = pBuffer[nCurPos+1];
597 *pScan++ = pBuffer[nCurPos+2];
600 *pAlphaScan++ =
static_cast<sal_uInt8>( 255 - pBuffer[nCurPos++] );
609 static const struct {
615 {GL_NO_ERROR,
"no error"},
616 {GL_INVALID_ENUM,
"invalid enumerant"},
617 {GL_INVALID_VALUE,
"invalid value"},
618 {GL_INVALID_OPERATION,
"invalid operation"},
619 {GL_STACK_OVERFLOW,
"stack overflow"},
620 {GL_STACK_UNDERFLOW,
"stack underflow"},
621 {GL_OUT_OF_MEMORY,
"out of memory"},
622 {GL_INVALID_FRAMEBUFFER_OPERATION,
"invalid framebuffer operation"},
629 for (i=0; errors[i].string; i++)
631 if (errors[i].
code == errorCode)
633 return errors[i].string;
640 std::ostream&
operator<<(std::ostream& rStrm,
const glm::vec4& rPos)
642 rStrm <<
"( " << rPos[0] <<
", " << rPos[1] <<
", " << rPos[2] <<
", " << rPos[3] <<
")";
646 std::ostream&
operator<<(std::ostream& rStrm,
const glm::vec3& rPos)
648 rStrm <<
"( " << rPos[0] <<
", " << rPos[1] <<
", " << rPos[2] <<
")";
652 std::ostream&
operator<<(std::ostream& rStrm,
const glm::mat4& rMatrix)
654 for(
int i = 0;
i < 4; ++
i)
657 for(
int j = 0; j < 4; ++j)
659 rStrm << rMatrix[j][
i];
668 GLuint& nRenderbufferDepthId, GLuint& nRenderbufferColorId)
673 glGenRenderbuffers(1, &nRenderbufferDepthId);
674 glBindRenderbuffer(GL_RENDERBUFFER, nRenderbufferDepthId);
675 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, nWidth, nHeight);
676 glBindRenderbuffer(GL_RENDERBUFFER, 0);
678 glGenTextures(1, &nRenderbufferColorId);
679 glBindTexture(GL_TEXTURE_2D, nRenderbufferColorId);
680 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
681 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
682 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
683 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
684 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, nWidth, nHeight, 0,
685 GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
686 glBindTexture(GL_TEXTURE_2D, 0);
688 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
689 GL_TEXTURE_2D, nRenderbufferColorId, 0);
692 glGenFramebuffers(1, &nFramebufferId);
693 glCheckFramebufferStatus(GL_FRAMEBUFFER);
694 glBindFramebuffer(GL_FRAMEBUFFER, nFramebufferId);
696 glBindRenderbuffer(GL_RENDERBUFFER, nRenderbufferColorId);
697 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, nRenderbufferColorId);
698 glCheckFramebufferStatus(GL_FRAMEBUFFER);
700 glBindRenderbuffer(GL_RENDERBUFFER, nRenderbufferDepthId);
701 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, nRenderbufferDepthId);
702 GLenum
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
703 if (status != GL_FRAMEBUFFER_COMPLETE)
705 SAL_WARN(
"vcl.opengl",
"invalid framebuffer status");
707 glBindRenderbuffer(GL_RENDERBUFFER, 0);
708 glBindFramebuffer(GL_FRAMEBUFFER, 0);
715 float fVersion = 1.0;
716 const GLubyte* aVersion = glGetString( GL_VERSION );
717 if( aVersion && aVersion[0] )
719 fVersion = aVersion[0] -
'0';
720 if( aVersion[1] ==
'.' && aVersion[2] )
722 fVersion += (aVersion[2] -
'0')/10.0;
737 GLenum glErr = glGetError();
738 if (glErr == GL_NO_ERROR)
744 sError =
"no message available";
746 SAL_WARN(
"vcl.opengl",
"GL Error " << std::hex << std::setw(4) << std::setfill(
'0') << glErr << std::dec << std::setw(0) << std::setfill(
' ') <<
" (" << sError <<
") in file " << pFile <<
" at line " << nLine);
751 SAL_WARN(
"vcl.opengl",
"Breaking potentially recursive glGetError loop");
759 static bool bSet =
false;
760 static bool bDenylisted =
true;
765 #if defined UNX && !defined MACOSX && !defined IOS && !defined ANDROID && !defined HAIKU
768 SAL_INFO(
"vcl.opengl",
"denylisted: " << bDenylisted);
769 #elif defined( _WIN32 )
773 if (DriverBlocklist::GetWindowsVersion() == 0x00060001 &&
776 SAL_INFO(
"vcl.opengl",
"Relaxing watchdog timings.");
790 if( getenv(
"SAL_DISABLEGL") !=
nullptr )
792 if( isDeviceDenylisted())
794 if( officecfg::Office::Common::VCL::DisableOpenGL::get())
809 class CrashWatchdogTimings
812 std::vector<CrashWatchdogTimingsValues> maTimingValues;
813 std::atomic<bool> mbRelaxed;
816 CrashWatchdogTimings();
818 void setRelax(
bool bRelaxed)
820 mbRelaxed = bRelaxed;
825 size_t index = (eMode == CrashWatchdogTimingMode::SHADER_COMPILE) ? 1 : 0;
826 index = mbRelaxed ? index + 2 : index;
828 return maTimingValues[index];
832 CrashWatchdogTimings gWatchdogTimings;
834 CrashWatchdogTimings::CrashWatchdogTimings()
836 {{6, 20} , {20, 120} ,
837 {60, 240} , {60, 240} }
852 static bool bDisabled =
false;
859 std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
861 officecfg::Office::Common::VCL::DisableOpenGL::set(
true, xChanges);
865 css::uno::Reference< css::util::XFlushable >(
866 css::configuration::theDefaultProvider::get(
868 css::uno::UNO_QUERY_THROW)->flush();
873 gWatchdogTimings.setRelax(
true);
878 SAL_INFO(
"vcl.watchdog",
"GL watchdog - unchanged "
879 << nUnchanged <<
" enter count " <<
enterCount() <<
" type "
889 return gWatchdogTimings.getWatchdogTimingsValues(eMode);
895 0,
"%" SAL_PRIxUINT32
": %s", osl_getThreadIdentifier(
nullptr), pStream.str().c_str());
901 1,
"%" SAL_PRIxUINT32
": %s", osl_getThreadIdentifier(
nullptr), pStream.str().c_str());
907 va_start (aArgs, pFormat);
911 #define vsnprintf _vsnprintf
913 vsnprintf(pStr,
sizeof(pStr), pFormat, aArgs);
914 pStr[
sizeof(pStr)-20] =
'\0';
918 strcat(pStr,
" (no GL context)");
933 if (epoxy_has_gl_extension(
"GL_KHR_debug"))
934 glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION,
938 GL_DEBUG_SEVERITY_LOW,
940 else if (epoxy_has_gl_extension(
"GL_AMD_debug_output"))
941 glDebugMessageInsertAMD(GL_DEBUG_CATEGORY_APPLICATION_AMD,
942 GL_DEBUG_SEVERITY_LOW_AMD,
std::ostream & operator<<(std::ostream &rStrm, const glm::vec4 &rPos)
exports com.sun.star.frame. status
static bool volatile gbInShaderCompile
const OString & GetOSRelease() const
static const AtomicCounter & enterCount()
static void debugMsgStreamWarn(std::ostringstream const &pStream)
static OString GetDigest(const OUString &rVertexShaderName, const OUString &rFragmentShaderName, std::string_view preamble)
const OUString & GetAdapterDeviceID() const
static void createFramebuffer(tools::Long nWidth, tools::Long nHeight, GLuint &nFramebufferId, GLuint &nRenderbufferDepthId, GLuint &nRenderbufferColorId)
The caller is responsible for deleting the buffer objects identified by nFramebufferId, nRenderbufferDepthId and nRenderbufferColorId.
OString getDeviceInfoString(cl_device_id aDeviceId, cl_device_info aDeviceInfo)
virtual bool isDeviceBlocked() override
static void checkGLError(const char *aFile, size_t nLine)
static bool isDeviceDenylisted()
checks if the device/driver pair is on our OpenGL denylist
static float getGLVersion()
Get OpenGL version (needs a context)
const OString & GetOS() const
static void addPreamble(OString &rShaderSource, std::string_view rPreamble)
static void relaxWatchdogTimings()
virtual bool isDeviceBlocked() override
const OString & GetVersion() const
HashMap_OWString_Interface aMap
static void debugMsgPrint(const int nType, const char *pFormat,...)
Insert a glDebugMessage into the queue - helpful for debugging with apitrace to annotate the output a...
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
static void debugMsgStream(std::ostringstream const &pStream)
Scanline GetScanline(tools::Long nY) const
static std::shared_ptr< ConfigurationChanges > create(css::uno::Reference< css::uno::XComponentContext > const &context=comphelper::getProcessComponentContext())
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
static const CrashWatchdogTimingsValues & getCrashWatchdogTimingsValues()
#define SAL_CONFIGFILE(name)
static void hardDisable()
Called from a signal handler or watchdog thread if we get a crash or hang in some GL code...
#define VCL_GL_INFO(stream)
Helper to do a SAL_INFO as well as a GL log.
ScanlineFormat GetScanlineFormat() const
const OUString & GetDriverVersion() const
static bool hasCurrent()
Is there a current GL context ?
const OString & GetRenderer() const
bool Write(SvStream &rStream)
static BitmapEx ConvertBufferToBitmapEx(const sal_uInt8 *const pBuffer, tools::Long nWidth, tools::Long nHeight)
The caller is responsible for allocating the memory for the buffer before calling this method...
static void checkDebug(int nUnchanged, const CrashWatchdogTimingsValues &aTimingValues)
We want to be able to detect if a given crash came from the OpenGL code, so use this helper to track ...
static GLint LoadShaders(const OUString &rVertexShaderName, const OUString &rFragmentShaderName, const OUString &rGeometryShaderName, std::string_view preamble, std::string_view rDigest)
#define SAL_WARN_IF(condition, area, stream)
static void renderToFile(tools::Long nWidth, tools::Long nHeight, const OUString &rFileName)
#define SAL_INFO(area, stream)
Reference< XComponentContext > getProcessComponentContext()
const OUString & GetAdapterVendorID() const
const OString & GetVendor() const
#define SAL_WARN(area, stream)
static bool supportsOpenGL()
checks if the system supports all features that are necessary for the OpenGL support ...
static const char * GLErrorString(GLenum errorCode)
static GLenum OptimalBufferFormat()
Returns the optimal buffer format for OpenGL (GL_BGRA or GL_RGBA).