From b2928461c5651cf3db4edcbce0256d98ee87925f Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Sun, 3 May 2026 17:35:11 +0800 Subject: [PATCH] OpenGL patch --- Rendering/OpenGL2/CMakeLists.txt | 4 + Rendering/OpenGL2/vtkCocoaGLView.mm | 36 ++--- Rendering/OpenGL2/vtkCocoaRenderWindow.mm | 96 ++++++++----- Rendering/OpenGL2/vtkOSOpenGLRenderWindow.cxx | 38 +++++- Rendering/OpenGL2/vtkOpenGLRenderWindow.cxx | 128 +++++++++++++++--- Rendering/OpenGL2/vtkXOpenGLRenderWindow.cxx | 38 +++++- 6 files changed, 260 insertions(+), 80 deletions(-) diff --git a/Rendering/OpenGL2/CMakeLists.txt b/Rendering/OpenGL2/CMakeLists.txt index 4098a99638..b8f1e10090 100644 --- a/Rendering/OpenGL2/CMakeLists.txt +++ b/Rendering/OpenGL2/CMakeLists.txt @@ -451,6 +451,10 @@ endif() if (VTK_USE_COCOA) vtk_module_link(VTK::RenderingOpenGL2 PUBLIC "-framework Cocoa") +elseif (VTK_USE_X) + # Link GL library explicitly for X11 backend (including macOS with XQuartz) + vtk_module_find_package(PACKAGE OpenGL COMPONENTS OpenGL) + vtk_module_link(VTK::RenderingOpenGL2 PUBLIC OpenGL::GL) elseif (VTK_USE_WIN32_OPENGL) # vtkWin32OpenGLDXRenderWindow requires D3D. vtk_module_find_package(PRIVATE_IF_SHARED diff --git a/Rendering/OpenGL2/vtkCocoaGLView.mm b/Rendering/OpenGL2/vtkCocoaGLView.mm index 007b6b50a4..03771a76f9 100644 --- a/Rendering/OpenGL2/vtkCocoaGLView.mm +++ b/Rendering/OpenGL2/vtkCocoaGLView.mm @@ -49,13 +49,13 @@ // on older versions of macOS. Conditionally using it would require conditionally // linking to that new framework, which just isn't worth the hassle when both // are just syntactic sugar for the string "public.file-url". -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + VTK_DIAG_OFF(deprecated-declarations) NSString* supportedDragType = (NSString*)kUTTypeFileURL; -#pragma clang diagnostic pop + VTK_DIAG_ON(deprecated-declarations) // Register the view for file drops. - [self registerForDraggedTypes:@[ supportedDragType ]]; + // Use explicit NSArray creation instead of @[] literal for gcc compatibility + [self registerForDraggedTypes:[NSArray arrayWithObject:supportedDragType]]; } //---------------------------------------------------------------------------- @@ -234,7 +234,7 @@ // first responder. NSPoint windowLoc = [[self window] mouseLocationOutsideOfEventStream]; NSPoint viewLoc = [self convertPoint:windowLoc fromView:nil]; - NSPoint backingLoc = [self convertPointToBacking:viewLoc]; + NSPoint backingLoc = vtkCocoaConvertPointToBacking(self, viewLoc); NSUInteger flags = [theEvent modifierFlags]; int shiftDown = ((flags & NSEventModifierFlagShift) != 0); @@ -353,7 +353,7 @@ // left corner. Since this is a mouse event, we can use locationInWindow. NSPoint windowLoc = [theEvent locationInWindow]; NSPoint viewLoc = [self convertPoint:windowLoc fromView:nil]; - NSPoint backingLoc = [self convertPointToBacking:viewLoc]; + NSPoint backingLoc = vtkCocoaConvertPointToBacking(self, viewLoc); NSUInteger flags = [theEvent modifierFlags]; int shiftDown = ((flags & NSEventModifierFlagShift) != 0); @@ -382,7 +382,7 @@ // left corner. Since this is a mouse event, we can use locationInWindow. NSPoint windowLoc = [theEvent locationInWindow]; NSPoint viewLoc = [self convertPoint:windowLoc fromView:nil]; - NSPoint backingLoc = [self convertPointToBacking:viewLoc]; + NSPoint backingLoc = vtkCocoaConvertPointToBacking(self, viewLoc); int clickCount = static_cast([theEvent clickCount]); int repeatCount = ((clickCount > 1) ? clickCount - 1 : 0); @@ -550,10 +550,9 @@ // on older versions of macOS. Conditionally using it would require conditionally // linking to that new framework, which just isn't worth the hassle when both // are just syntactic sugar for the string "public.file-url". -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + VTK_DIAG_OFF(deprecated-declarations) NSString* supportedDragType = (NSString*)kUTTypeFileURL; -#pragma clang diagnostic pop + VTK_DIAG_ON(deprecated-declarations) if ([types containsObject:supportedDragType]) { @@ -570,7 +569,7 @@ NSPoint pt = [sender draggingLocation]; NSPoint viewLoc = [self convertPoint:pt fromView:nil]; - NSPoint backingLoc = [self convertPointToBacking:viewLoc]; + NSPoint backingLoc = vtkCocoaConvertPointToBacking(self, viewLoc); double location[2]; location[0] = backingLoc.x; location[1] = backingLoc.y; @@ -578,10 +577,16 @@ vtkNew filePaths; NSPasteboard* pboard = [sender draggingPasteboard]; - NSArray* fileURLs = [pboard readObjectsForClasses:@[ [NSURL class] ] options:nil]; - for (NSURL* fileURL in fileURLs) - { - const char* filePath = [fileURL fileSystemRepresentation]; + // Use explicit NSArray creation instead of @[] literal for gcc compatibility + NSArray* fileURLs = [pboard readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] options:nil]; + // Use NSEnumerator instead of fast enumeration for gcc compatibility + NSEnumerator* urlEnumerator = [fileURLs objectEnumerator]; + NSURL* fileURL; + while ((fileURL = [urlEnumerator nextObject]) != nil) + { + // Use -path and UTF8String instead of -fileSystemRepresentation for 10.5/10.6 SDK compatibility + // (-fileSystemRepresentation was added in 10.9) + const char* filePath = [[fileURL path] UTF8String]; filePaths->InsertNextValue(filePath); } @@ -617,7 +622,7 @@ { // Convert from points to pixels. NSRect viewRect = [self frame]; - NSRect backingViewRect = [self convertRectToBacking:viewRect]; + NSRect backingViewRect = vtkCocoaConvertRectToBacking(self, viewRect); CGFloat viewHeight = NSHeight(viewRect); CGFloat backingViewHeight = NSHeight(backingViewRect); CGFloat backingScaleFactor = 1.0; @@ -629,7 +634,7 @@ else if (window) { // fall back to less reliable method - backingScaleFactor = [window backingScaleFactor]; + backingScaleFactor = vtkCocoaGetBackingScaleFactor(window); } assert(backingScaleFactor >= 1.0); @@ -653,13 +658,18 @@ } //---------------------------------------------------------------------------- -// Overridden (from NSView). +// Overridden (from NSView). Available in 10.7+. +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - (void)viewDidChangeBackingProperties { - [super viewDidChangeBackingProperties]; + if ([NSView instancesRespondToSelector:@selector(viewDidChangeBackingProperties)]) + { + [super viewDidChangeBackingProperties]; + } NSWindow* window = [self window]; [self modifyDPIForBackingScaleFactorOfWindow:window]; } +#endif @end diff --git a/Rendering/OpenGL2/vtkCocoaRenderWindow.mm b/Rendering/OpenGL2/vtkCocoaRenderWindow.mm index f941872365..17ce47388a 100644 --- a/Rendering/OpenGL2/vtkCocoaRenderWindow.mm +++ b/Rendering/OpenGL2/vtkCocoaRenderWindow.mm @@ -169,7 +169,7 @@ NSRect viewRect = [view frame]; // Convert from points to pixels. - NSRect backingViewRect = [view convertRectToBacking:viewRect]; + NSRect backingViewRect = vtkCocoaConvertRectToBacking(view, viewRect); int newWidth = static_cast(NSWidth(backingViewRect)); int newHeight = static_cast(NSHeight(backingViewRect)); @@ -401,12 +401,26 @@ << "\nOpenGL version string: " << glVersion << endl; strm << "OpenGL extensions: " << endl; - GLint n, i; - glGetIntegerv(GL_NUM_EXTENSIONS, &n); - for (i = 0; i < n; i++) + // glGetStringi and GL_NUM_EXTENSIONS are OpenGL 3.0+ + // For OpenGL 2.x, use the old glGetString(GL_EXTENSIONS) method + if (glGetStringi != nullptr) + { + GLint n, i; + glGetIntegerv(GL_NUM_EXTENSIONS, &n); + for (i = 0; i < n; i++) + { + const char* ext = (const char*)glGetStringi(GL_EXTENSIONS, i); + strm << " " << ext << endl; + } + } + else { - const char* ext = (const char*)glGetStringi(GL_EXTENSIONS, i); - strm << " " << ext << endl; + // Legacy OpenGL 2.x path + const char* extensions = (const char*)glGetString(GL_EXTENSIONS); + if (extensions) + { + strm << " " << extensions << endl; + } } // Obtain the OpenGL context in order to keep track of the current screen. @@ -439,11 +453,10 @@ // "NSOpenGLPFAStereo" is deprecated in the 10.12 SDK, suppress warning about its use. // No explanation is given for the deprecation, and no alternative is suggested. -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + VTK_DIAG_OFF(deprecated-declarations) [pixelFormat getValues:&pfd forAttribute:NSOpenGLPFAStereo forVirtualScreen:currentScreen]; strm << " stereo: " << (pfd == 0 ? "No" : "Yes") << endl; -#pragma clang diagnostic pop + VTK_DIAG_ON(deprecated-declarations) [pixelFormat getValues:&pfd forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:currentScreen]; strm << " stencil: " << pfd << endl; @@ -451,8 +464,14 @@ [pixelFormat getValues:&pfd forAttribute:NSOpenGLPFAAccelerated forVirtualScreen:currentScreen]; strm << " hardware acceleration: " << (pfd == 0 ? "No" : "Yes") << endl; - [pixelFormat getValues:&pfd forAttribute:NSOpenGLPFAOpenGLProfile forVirtualScreen:currentScreen]; - strm << " profile version: 0x" << std::hex << pfd << endl; + // NSOpenGLPFAOpenGLProfile is only available on 10.7+ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if ([pixelFormat respondsToSelector:@selector(getValues:forAttribute:forVirtualScreen:)]) + { + [pixelFormat getValues:&pfd forAttribute:NSOpenGLPFAOpenGLProfile forVirtualScreen:currentScreen]; + strm << " profile version: 0x" << std::hex << pfd << endl; + } +#endif delete[] this->Capabilities; @@ -497,7 +516,7 @@ // Convert the given new size from pixels to points. NSSize backingNewSize = NSMakeSize((CGFloat)width, (CGFloat)height); - NSSize newSize = [theView convertSizeFromBacking:backingNewSize]; + NSSize newSize = vtkCocoaConvertSizeFromBacking(theView, backingNewSize); // Test that there's actually a change so as not to recurse into viewFrameDidChange:. if (!NSEqualSizes(newSize, viewRect.size)) @@ -527,7 +546,7 @@ // Convert the given new size from pixels to points. NSRect backingNewRect = NSMakeRect(0.0, 0.0, (CGFloat)width, (CGFloat)height); - NSRect newRect = [window convertRectFromBacking:backingNewRect]; + NSRect newRect = vtkCocoaWindowConvertRectFromBacking(window, backingNewRect); // Test that there's actually a change so as not to recurse into viewFrameDidChange:. if (!NSEqualSizes(newRect.size, [window frame].size)) @@ -576,7 +595,7 @@ // Convert the given new position from pixels to points. NSPoint backingNewPosition = NSMakePoint((CGFloat)x, (CGFloat)y); - NSPoint newPosition = [theView convertPointFromBacking:backingNewPosition]; + NSPoint newPosition = vtkCocoaConvertPointFromBacking(theView, backingNewPosition); // Update the view's frameOrigin (in points) keeping the bottom-left // corner in the same place. @@ -608,7 +627,7 @@ // We use a dummy NSRect because NSWindow doesn't have convertPointFromBacking: before // macOS 10.14. NSRect backingNewPosition = NSMakeRect((CGFloat)x, (CGFloat)y, 0.0, 0.0); - NSRect newPosition = [window convertRectFromBacking:backingNewPosition]; + NSRect newPosition = vtkCocoaWindowConvertRectFromBacking(window, backingNewPosition); // Test that there's actually a change so as not to recurse into viewFrameDidChange:. if (!NSEqualPoints([window frame].origin, newPosition.origin)) @@ -709,7 +728,7 @@ NSRect screenRect = [screen frame]; // Convert from points to pixels. - NSRect backingScreenRect = [screen convertRectToBacking:screenRect]; + NSRect backingScreenRect = vtkCocoaConvertRectToBacking(screen, screenRect); if (this->FullScreen && screen) { @@ -744,15 +763,8 @@ (CGFloat)this->Size[0], (CGFloat)this->Size[1]); // Convert from pixels to points. - NSRect contentRect; - if (screen) - { - contentRect = [screen convertRectFromBacking:backingContentRect]; - } - else - { - contentRect = backingContentRect; - } + NSRect contentRect = screen ? vtkCocoaScreenConvertRectFromBacking(screen, backingContentRect) + : backingContentRect; NSWindowStyleMask styleMask = (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable); @@ -808,7 +820,7 @@ assert(window); NSRect backingViewRect = NSMakeRect((CGFloat)this->Position[0], (CGFloat)this->Position[1], (CGFloat)this->Size[0], (CGFloat)this->Size[1]); - NSRect viewRect = [window convertRectFromBacking:backingViewRect]; + NSRect viewRect = vtkCocoaWindowConvertRectFromBacking(window, backingViewRect); CGFloat width = NSWidth(viewRect); CGFloat height = NSHeight(viewRect); @@ -845,10 +857,7 @@ // SetParentId() was added for) then the Tk superview handles the events. NSRect glRect = NSMakeRect(x, y, width, height); NSView* glView = [[NSView alloc] initWithFrame:glRect]; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [glView setWantsBestResolutionOpenGLSurface:wantsBest]; -#pragma clang diagnostic pop + vtkCocoaSetWantsBestResolutionOpenGLSurface(glView, wantsBest); [parent addSubview:glView]; this->SetWindowId(glView); this->ViewCreated = 1; @@ -864,14 +873,11 @@ // Convert from points to pixels. NSWindow* window = (NSWindow*)this->GetRootWindow(); assert(window); - NSRect viewRect = [window convertRectFromBacking:backingViewRect]; + NSRect viewRect = vtkCocoaWindowConvertRectFromBacking(window, backingViewRect); // Create a vtkCocoaGLView. vtkCocoaGLView* glView = [[vtkCocoaGLView alloc] initWithFrame:viewRect]; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [glView setWantsBestResolutionOpenGLSurface:wantsBest]; -#pragma clang diagnostic pop + vtkCocoaSetWantsBestResolutionOpenGLSurface(glView, wantsBest); [window setContentView:glView]; // We have to set the frame's view rect again to work around rounding // that occurs when setting the window's content view. @@ -893,10 +899,9 @@ if (connectContextToNSView) { NSView* view = (NSView*)this->GetWindowId(); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + VTK_DIAG_OFF(deprecated-declarations) [context setView:view]; -#pragma clang diagnostic pop + VTK_DIAG_ON(deprecated-declarations) } // the error "invalid drawable" in the console from this call can appear @@ -933,12 +938,18 @@ { // If the deployment target is at least 10.10, prefer the 'OpenGL 4.1 Core // Implementation', otherwise we'll fall back to the 'OpenGL 3.2 Core - // Implementation' (available since 10.7). + // Implementation' (available since 10.7), or legacy OpenGL for pre-10.7. NSOpenGLPixelFormatAttribute profileVersion; + bool useProfile = true; // Whether to include NSOpenGLPFAOpenGLProfile #if MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 profileVersion = NSOpenGLProfileVersion4_1Core; -#else +#elif MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 profileVersion = NSOpenGLProfileVersion3_2Core; +#else + // For 10.5/10.6, start with legacy profile (no NSOpenGLPFAOpenGLProfile) + // and only try core profiles at runtime if the system supports them. + profileVersion = NSOpenGLProfileVersionLegacy; + useProfile = false; // Don't request a profile on legacy systems initially #endif // Prefer hardware acceleration @@ -951,8 +962,12 @@ int i = 0; NSOpenGLPixelFormatAttribute attribs[20]; - attribs[i++] = NSOpenGLPFAOpenGLProfile; - attribs[i++] = profileVersion; + // Only include OpenGL profile on 10.7+ systems + if (useProfile) + { + attribs[i++] = NSOpenGLPFAOpenGLProfile; + attribs[i++] = profileVersion; + } attribs[i++] = NSOpenGLPFADepthSize; attribs[i++] = (NSOpenGLPixelFormatAttribute)32; @@ -981,11 +996,16 @@ if (pixelFormat == nil) { - if (profileVersion != NSOpenGLProfileVersion3_2Core) + if (useProfile && profileVersion != NSOpenGLProfileVersion3_2Core) { // Try falling back to the 3.2 Core Profile profileVersion = NSOpenGLProfileVersion3_2Core; } + else if (useProfile && profileVersion == NSOpenGLProfileVersion3_2Core) + { + // Try falling back to legacy OpenGL (no profile specification) + useProfile = false; + } else if (hardware == NSOpenGLPFAAccelerated) { // Try falling back to the software renderer @@ -1018,10 +1038,9 @@ // This syncs the OpenGL context to the VBL to prevent tearing GLint one = 1; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + VTK_DIAG_OFF(deprecated-declarations) [context setValues:&one forParameter:NSOpenGLCPSwapInterval]; -#pragma clang diagnostic pop + VTK_DIAG_ON(deprecated-declarations) } this->SetPixelFormat((void*)pixelFormat); @@ -1060,10 +1079,9 @@ if (connectContextToNSView) { NSView* view = (NSView*)this->GetWindowId(); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + VTK_DIAG_OFF(deprecated-declarations) [context setView:view]; -#pragma clang diagnostic pop + VTK_DIAG_ON(deprecated-declarations) } // the error "invalid drawable" in the console from this call can appear @@ -1133,7 +1151,7 @@ NSRect viewRect = [view frame]; // Convert from points to pixels. - NSRect backingViewRect = [view convertRectToBacking:viewRect]; + NSRect backingViewRect = vtkCocoaConvertRectToBacking(view, viewRect); // Update the ivar. this->Size[0] = static_cast(NSWidth(backingViewRect)); @@ -1177,7 +1195,7 @@ NSRect screenRect = [screen frame]; // Convert from points to pixels. - NSRect backingScreenRect = [screen convertRectToBacking:screenRect]; + NSRect backingScreenRect = vtkCocoaConvertRectToBacking(screen, screenRect); this->ScreenSize[0] = static_cast(NSWidth(backingScreenRect)); this->ScreenSize[1] = static_cast(NSHeight(backingScreenRect)); @@ -1204,8 +1222,8 @@ NSRect viewRect = [view frame]; // Convert from points to pixels. - NSRect backingParentRect = [parent convertRectToBacking:parentRect]; - NSRect backingViewRect = [view convertRectToBacking:viewRect]; + NSRect backingParentRect = vtkCocoaConvertRectToBacking(parent, parentRect); + NSRect backingViewRect = vtkCocoaConvertRectToBacking(view, viewRect); this->Position[0] = static_cast(NSMinX(backingViewRect)); this->Position[1] = static_cast( @@ -1224,7 +1242,7 @@ NSRect windowRect = [window frame]; // Convert from points to pixels. - NSRect backingWindowRect = [window convertRectToBacking:windowRect]; + NSRect backingWindowRect = vtkCocoaWindowConvertRectToBacking(window, windowRect); this->Position[0] = static_cast(NSMinX(backingWindowRect)); this->Position[1] = static_cast(NSMinY(backingWindowRect)); diff --git a/Rendering/OpenGL2/vtkOSOpenGLRenderWindow.cxx b/Rendering/OpenGL2/vtkOSOpenGLRenderWindow.cxx index 649afafd11..0a72520126 100644 --- a/Rendering/OpenGL2/vtkOSOpenGLRenderWindow.cxx +++ b/Rendering/OpenGL2/vtkOSOpenGLRenderWindow.cxx @@ -548,13 +548,43 @@ const char* vtkOSOpenGLRenderWindow::ReportCapabilities() strm << "OpenGL vendor string: " << glVendor << endl; strm << "OpenGL renderer string: " << glRenderer << endl; strm << "OpenGL version string: " << glVersion << endl; - strm << "OpenGL extensions: " << endl; + strm << "OpenGL extensions:" << endl; + // Try GL 3.0+ method first (glGetStringi) int n = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &n); - for (int i = 0; i < n; i++) + if (glGetError() == GL_NO_ERROR && n > 0 && glGetStringi != nullptr) { - const char* ext = (const char*)glGetStringi(GL_EXTENSIONS, i); - strm << " " << ext << endl; + for (int i = 0; i < n; i++) + { + const char* ext = (const char*)glGetStringi(GL_EXTENSIONS, i); + if (ext) + { + strm << " " << ext << endl; + } + } + } + else + { + // Fallback for GL 2.x - use glGetString(GL_EXTENSIONS) + const char* extensions = (const char*)glGetString(GL_EXTENSIONS); + if (extensions) + { + std::string extStr(extensions); + size_t start = 0; + size_t end = 0; + while ((end = extStr.find(' ', start)) != std::string::npos) + { + if (end > start) + { + strm << " " << extStr.substr(start, end - start) << endl; + } + start = end + 1; + } + if (start < extStr.length()) + { + strm << " " << extStr.substr(start) << endl; + } + } } delete[] this->Capabilities; size_t len = strm.str().length(); diff --git a/Rendering/OpenGL2/vtkOpenGLRenderWindow.cxx b/Rendering/OpenGL2/vtkOpenGLRenderWindow.cxx index 5e45d57d89..7429251204 100644 --- a/Rendering/OpenGL2/vtkOpenGLRenderWindow.cxx +++ b/Rendering/OpenGL2/vtkOpenGLRenderWindow.cxx @@ -696,13 +696,43 @@ const char* vtkOpenGLRenderWindow::ReportCapabilities() strm << "OpenGL version string: " << glVersion << endl; } - strm << "OpenGL extensions: " << endl; - GLint n, i; + strm << "OpenGL extensions:" << endl; + // Try GL 3.0+ method first (glGetStringi) + GLint n = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &n); - for (i = 0; i < n; i++) + if (glGetError() == GL_NO_ERROR && n > 0 && glGetStringi != nullptr) { - const char* ext = (const char*)glGetStringi(GL_EXTENSIONS, i); - strm << " " << ext << endl; + for (GLint i = 0; i < n; i++) + { + const char* ext = (const char*)glGetStringi(GL_EXTENSIONS, i); + if (ext) + { + strm << " " << ext << endl; + } + } + } + else + { + // Fallback for GL 2.x - use glGetString(GL_EXTENSIONS) + const char* extensions = (const char*)glGetString(GL_EXTENSIONS); + if (extensions) + { + std::string extStr(extensions); + size_t start = 0; + size_t end = 0; + while ((end = extStr.find(' ', start)) != std::string::npos) + { + if (end > start) + { + strm << " " << extStr.substr(start, end - start) << endl; + } + start = end + 1; + } + if (start < extStr.length()) + { + strm << " " << extStr.substr(start) << endl; + } + } } delete[] this->Capabilities; @@ -872,6 +902,37 @@ int vtkOpenGLRenderWindow::GetDefaultTextureInternalFormat( vtktype, numComponents, needInt, needFloat, needSRGB); } +//------------------------------------------------------------------------------ +// Helper to parse GL version from GL_VERSION string (for GL 2.x) +static bool vtkParseOpenGLVersionString(const char* versionString, int& major, int& minor) +{ + if (!versionString) + { + return false; + } + const char* ptr = versionString; + // Skip "OpenGL ES " prefix if present + if (strncmp(ptr, "OpenGL ES ", 10) == 0) + { + ptr += 10; + } + char* endptr; + long majorVal = strtol(ptr, &endptr, 10); + if (endptr == ptr || *endptr != '.') + { + return false; + } + ptr = endptr + 1; + long minorVal = strtol(ptr, &endptr, 10); + if (endptr == ptr) + { + return false; + } + major = static_cast(majorVal); + minor = static_cast(minorVal); + return true; +} + //------------------------------------------------------------------------------ void vtkOpenGLRenderWindow::GetOpenGLVersion(int& major, int& minor) { @@ -880,8 +941,23 @@ void vtkOpenGLRenderWindow::GetOpenGLVersion(int& major, int& minor) if (this->Initialized) { + // Try GL 3.0+ method first this->GetState()->vtkglGetIntegerv(GL_MAJOR_VERSION, &glMajorVersion); - this->GetState()->vtkglGetIntegerv(GL_MINOR_VERSION, &glMinorVersion); + GLenum err = glGetError(); + if (err == GL_NO_ERROR) + { + this->GetState()->vtkglGetIntegerv(GL_MINOR_VERSION, &glMinorVersion); + } + else + { + // Fallback: parse GL_VERSION string for GL 2.x + const char* versionStr = (const char*)glGetString(GL_VERSION); + if (!vtkParseOpenGLVersionString(versionStr, glMajorVersion, glMinorVersion)) + { + glMajorVersion = 2; + glMinorVersion = 0; + } + } } major = glMajorVersion; @@ -921,23 +997,35 @@ void vtkOpenGLRenderWindow::OpenGLInitContext() } int major = 0; int minor = 0; + // Try GL 3.0+ method, fallback to parsing GL_VERSION glGetIntegerv(GL_MAJOR_VERSION, &major); - glGetIntegerv(GL_MINOR_VERSION, &minor); - // Require at least OpenGL 3.2 - if (major < 3 || (major == 3 && minor < 2)) - { - vtkWarningMacro(<< "Unable to find a valid OpenGL 3.2 or later implementation. " - << "(" << major << "." << minor - << " found). " - "Please update your video card driver to the latest version. " - "If you are using Mesa please make sure you have version 11.2 or " - "later and make sure your driver in Mesa supports OpenGL 3.2 such " - "as llvmpipe or openswr. If you are on windows and using Microsoft " - "remote desktop note that it only supports OpenGL 3.2 with nvidia " - "quadro cards. You can use other remoting software such as nomachine " - "to avoid this issue."); + if (glGetError() != GL_NO_ERROR) + { + const char* versionStr = (const char*)glGetString(GL_VERSION); + if (!vtkParseOpenGLVersionString(versionStr, major, minor)) + { + major = 2; + minor = 0; + } + } + else + { + glGetIntegerv(GL_MINOR_VERSION, &minor); + } + // Warn but don't fail for GL 2.x - some basic functionality may work + if (major < 2) + { + vtkErrorMacro(<< "OpenGL version " << major << "." << minor + << " is too old. VTK requires at least OpenGL 2.0."); return; } + else if (major < 3 || (major == 3 && minor < 2)) + { + vtkWarningMacro(<< "OpenGL " << major << "." << minor << " detected. " + << "VTK works best with OpenGL 3.2 or later. " + << "Some features may not work correctly."); + // Continue anyway for basic rendering support + } #else // gles this->Initialized = true; #endif diff --git a/Rendering/OpenGL2/vtkXOpenGLRenderWindow.cxx b/Rendering/OpenGL2/vtkXOpenGLRenderWindow.cxx index db5d836766..a7ba8b6c1a 100644 --- a/Rendering/OpenGL2/vtkXOpenGLRenderWindow.cxx +++ b/Rendering/OpenGL2/vtkXOpenGLRenderWindow.cxx @@ -1603,13 +1603,43 @@ const char* vtkXOpenGLRenderWindow::ReportCapabilities() strm << "OpenGL vendor string: " << glVendor << endl; strm << "OpenGL renderer string: " << glRenderer << endl; strm << "OpenGL version string: " << glVersion << endl; - strm << "OpenGL extensions: " << endl; + strm << "OpenGL extensions:" << endl; + // Try GL 3.0+ method first (glGetStringi) int n = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &n); - for (int i = 0; i < n; i++) + if (glGetError() == GL_NO_ERROR && n > 0 && glGetStringi != nullptr) + { + for (int i = 0; i < n; i++) + { + const char* ext = (const char*)glGetStringi(GL_EXTENSIONS, i); + if (ext) + { + strm << " " << ext << endl; + } + } + } + else { - const char* ext = (const char*)glGetStringi(GL_EXTENSIONS, i); - strm << " " << ext << endl; + // Fallback for GL 2.x - use glGetString(GL_EXTENSIONS) + const char* extensions = (const char*)glGetString(GL_EXTENSIONS); + if (extensions) + { + std::string extStr(extensions); + size_t start = 0; + size_t end = 0; + while ((end = extStr.find(' ', start)) != std::string::npos) + { + if (end > start) + { + strm << " " << extStr.substr(start, end - start) << endl; + } + start = end + 1; + } + if (start < extStr.length()) + { + strm << " " << extStr.substr(start) << endl; + } + } } strm << "X Extensions: "; diff --git a/ThirdParty/glad/vtkglad/CMakeLists.txt b/ThirdParty/glad/vtkglad/CMakeLists.txt index 4bb73ab9b3..5f4d293059 100644 --- a/ThirdParty/glad/vtkglad/CMakeLists.txt +++ b/ThirdParty/glad/vtkglad/CMakeLists.txt @@ -66,4 +66,7 @@ if (WIN32) elseif (VTK_OPENGL_USE_GLES) vtk_module_find_package(PACKAGE OpenGL COMPONENTS GLES3) vtk_module_link(VTK::glad PUBLIC OpenGL::GLES3) +elseif (VTK_USE_X AND NOT WIN32) + vtk_module_find_package(PACKAGE OpenGL COMPONENTS OpenGL) + vtk_module_link(VTK::glad PUBLIC OpenGL::GL) endif () --- a/Rendering/OpenGL2/vtkCocoaGLView.h 2026-05-16 04:34:56.000000000 +0800 +++ b/Rendering/OpenGL2/vtkCocoaGLView.h 2026-06-03 13:36:49.000000000 +0800 @@ -59,8 +59,14 @@ typedef void* vtkCocoaRenderWindowInteractorRef; #endif +// NSDraggingDestination was an informal protocol before 10.7 +// On older SDKs we don't declare conformance but still implement the methods VTKRENDERINGOPENGL2_EXPORT +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 @interface vtkCocoaGLView : NSView +#else +@interface vtkCocoaGLView : NSView +#endif { @private vtkCocoaRenderWindowRef _myVTKRenderWindow;