Skip to content

Commit

Permalink
Mac: fix BOINC graphics library libboinc_graphics2.a built with Xcode…
Browse files Browse the repository at this point in the history
… 11 to properly display graphics apps when invoked from "Show graphics" button on BOINC Manager.
  • Loading branch information
Charlie Fenton committed May 1, 2020
1 parent 21b99d6 commit e091b98
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 87 deletions.
84 changes: 80 additions & 4 deletions api/macglutfix.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
// int set_realtime(int period, int computation, int constraint);
void MacGLUTFix(bool isScreenSaver);
void BringAppToFront(void);
int compareOSVersionTo(int toMajor, int toMinor);

// The standard ScreenSaverView class actually sets the window
// level to 2002, not the 1000 defined by NSScreenSaverWindowLevel
Expand All @@ -59,11 +60,15 @@
#define SAVERDELAY 30

void MacGLUTFix(bool isScreenSaver) {
static bool done = false;
static NSMenu * emptyMenu;
NSOpenGLContext * myContext = nil;
NSView *myView = nil;
NSWindow* myWindow = nil;

if (done) return;
done = true;

if (! boinc_is_standalone()) {
if (emptyMenu == nil) {
emptyMenu = [ NSMenu alloc ];
Expand All @@ -74,15 +79,42 @@ void MacGLUTFix(bool isScreenSaver) {
myContext = [ NSOpenGLContext currentContext ];
if (myContext)
myView = [ myContext view ];
if (myView)
if (myView) {
#ifdef __MAC_10_15 // Do this only if built under OS 10.15 or later
// OpenGL apps built under Xcode 11 apparently use window dimensions based
// on the number of backing store pixels. That is, they double the window
// dimensions for Retina displays (which have 2X2 pixels per point.) But
// OpenGL apps built under earlier versions of Xcode don't.
// Catalina assumes OpenGL apps work as built under Xcode 11, so it displays
// older builds at half width and height, unless we compensate in our code.
// This code is part of my attempt to ensure that BOINC graphics apps built on
// all versions of Xcode work properly on different versions of OS X. See also
// [BOINC_Saver_ModuleView initWithFrame:] in clientscr/Mac_Saver_ModuleCiew.m
// and MacPassOffscreenBufferToScreenSaver()
//
// NOTES:
// * Graphics apps must be linked with the IOSurface framework
// * The libboinc_graphics2.a library and the graphics app must be built
// with the same version of Xcode
//
if (compareOSVersionTo(10, 15) >= 0) {
int w = (int)[myView bounds].size.width;
int h = (int)[myView bounds].size.height;
NSArray *allScreens = [ NSScreen screens ];
int DPI_multiplier = [((NSScreen*)allScreens[0]) backingScaleFactor];
glViewport(0, 0, w*DPI_multiplier, h*DPI_multiplier);
}
#endif
myWindow = [ myView window ];
}
if (myWindow == nil)
return;

if (!isScreenSaver) {
NSButton *closeButton = [myWindow standardWindowButton:NSWindowCloseButton ];
[closeButton setEnabled:YES];
[myWindow setDocumentEdited: NO];

return;
}

Expand Down Expand Up @@ -294,13 +326,19 @@ - (void)sendIOSurfaceMachPortToClients:(uint32_t)index withMachPort:(mach_port_t

// OpenGL apps built under Xcode 11 apparently use window dimensions based
// on the number of backing store pixels. That is, they double the window
// dimensiona for Retina displays (which have two pixels per point.) But
// dimensions for Retina displays (which have 2X2 pixels per point.) But
// OpenGL apps built under earlier versions of Xcode don't.
// Catalina assumes OpenGL apps work as built under Xcode 11, so it displays
// older builds at half width and height, unless we compensate in our code.
// This code is part of my attempt to ensure that BOINC graphics apps built on
// all versions of Xcode work proprly on different versions of OS X. See also
// all versions of Xcode work properly on different versions of OS X. See also
// [BOINC_Saver_ModuleView initWithFrame:] in clientscr/Mac_Saver_ModuleCiew.m
// and MacGLUTFix(bool isScreenSaver) above.
//
// NOTES:
// * Graphics apps must be linked with the IOSurface framework
// * The libboinc_graphics2.a library and the graphics app must be built
// with the same version of Xcode
//
void MacPassOffscreenBufferToScreenSaver() {
NSOpenGLContext * myContext = [ NSOpenGLContext currentContext ];
Expand Down Expand Up @@ -389,6 +427,44 @@ void MacPassOffscreenBufferToScreenSaver() {
currentFrameIndex = (currentFrameIndex + 1) % NUM_IOSURFACE_BUFFERS;
}

// Test OS version number on all versions of OS X without using deprecated Gestalt
// compareOSVersionTo(x, y) returns:
// -1 if the OS version we are running on is less than x.y
// 0 if the OS version we are running on is equal to x.y
// +1 if the OS version we are running on is lgreater than x.y
int compareOSVersionTo(int toMajor, int toMinor) {
static SInt32 major = -1;
static SInt32 minor = -1;

if (major < 0) {
char vers[100], *p1 = NULL;
FILE *f;
vers[0] = '\0';
f = popen("sw_vers -productVersion", "r");
if (f) {
fscanf(f, "%s", vers);
pclose(f);
}
if (vers[0] == '\0') {
fprintf(stderr, "popen(\"sw_vers -productVersion\" failed\n");
fflush(stderr);
return 0;
}
// Extract the major system version number
major = atoi(vers);
// Extract the minor system version number
p1 = strchr(vers, '.');
minor = atoi(p1+1);
}

if (major < toMajor) return -1;
if (major > toMajor) return 1;
// if (major == toMajor) compare minor version numbers
if (minor < toMinor) return -1;
if (minor > toMinor) return 1;
return 0;
}

// Code for debugging:

#if CREATE_LOG
Expand Down
19 changes: 14 additions & 5 deletions clientscr/Mac_Saver_ModuleView.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2020 University of California
// Copyright (C) 2019 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
Expand Down Expand Up @@ -206,6 +206,10 @@ - (id)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview {
gIsHighSierra = (compareOSVersionTo(10, 13) >= 0);
gIsMojave = (compareOSVersionTo(10, 14) >= 0);
gIsCatalina = (compareOSVersionTo(10, 15) >= 0);

// MIN_OS_TO_USE_SCREENSAVER_LAUNCH_AGENT is defined in mac_util.h
gUseLaunchAgent = (compareOSVersionTo(10, MIN_OS_TO_USE_SCREENSAVER_LAUNCH_AGENT) >= 0);

if (gIsCatalina) {
// Under OS 10.15, isPreview is often true even when it shouldn't be
// so we use this hack instead
Expand All @@ -216,13 +220,19 @@ - (id)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview {

// OpenGL apps built under Xcode 11 apparently use window dimensions based
// on the number of backing store pixels. That is, they double the window
// dimensions for Retina displays (which have two pixels per point.) But
// dimensions for Retina displays (which have 2X2 pixels per point.) But
// OpenGL apps built under earlier versions of Xcode don't.
// Catalina assumes OpenGL apps work as built under Xcode 11, so it displays
// older builds at half width and height, unless we compensate in our code.
// This code is part of my attempt to ensure that BOINC graphics apps built on
// all versions of Xcode work proprly on different versions of OS X. See also
// MacPassOffscreenBufferToScreenSaver() in lib/magglutfix.m for more info.
// all versions of Xcode work properly on different versions of OS X. See also
// MacPassOffscreenBufferToScreenSaver() and MacGLUTFix(bool isScreenSaver)
// in lib/macglutfix.m and for more info.
//
// NOTES:
// * Graphics apps must be linked with the IOSurface framework
// * The libboinc_graphics2.a library and the graphics app must be built
// with the same version of Xcode
//
if (gIsCatalina) {
NSArray *allScreens = [ NSScreen screens ];
Expand Down Expand Up @@ -387,7 +397,6 @@ - (void)stopAnimation {
[imageView removeFromSuperview]; // Releases imageView
imageView = nil;
}

if (!myIsPreview) {
closeBOINCSaver();
}
Expand Down
Loading

0 comments on commit e091b98

Please sign in to comment.