From 5da019ad6bc54e10930b846f796851200e662783 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 28 Apr 2017 11:37:12 +0200 Subject: [PATCH] Use correct color space for current monitor We won't always be on the primary monitor, so check which color space we're actually using right now. For offscreen stuff we assume a standard sRGB color space. (cherry picked from commit 1669a2d5a15aa39313cb74eff4f62dfe14d136cd) --- tests/CMakeLists.txt | 5 ++++- vncviewer/Surface_OSX.cxx | 46 +++++++++++++++++---------------------- vncviewer/cocoa.h | 4 ++++ vncviewer/cocoa.mm | 22 +++++++++++++++++++ 4 files changed, 50 insertions(+), 27 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8ea99255..60edb013 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -27,7 +27,10 @@ set(FBPERF_SOURCES if(WIN32) set(FBPERF_SOURCES ${FBPERF_SOURCES} ../vncviewer/Surface_Win32.cxx) elseif(APPLE) - set(FBPERF_SOURCES ${FBPERF_SOURCES} ../vncviewer/Surface_OSX.cxx) + set(FBPERF_SOURCES + ${FBPERF_SOURCES} ../vncviewer/Surface_OSX.cxx + ${FBPERF_SOURCES} ../vncviewer/keysym2ucs.c + ${FBPERF_SOURCES} ../vncviewer/cocoa.mm) else() set(FBPERF_SOURCES ${FBPERF_SOURCES} ../vncviewer/Surface_X11.cxx) endif() diff --git a/vncviewer/Surface_OSX.cxx b/vncviewer/Surface_OSX.cxx index 10d1e3e2..3313ae3b 100644 --- a/vncviewer/Surface_OSX.cxx +++ b/vncviewer/Surface_OSX.cxx @@ -26,23 +26,19 @@ #include +#include "cocoa.h" #include "Surface.h" -static CGImageRef create_image(const unsigned char* data, +static CGColorSpaceRef srgb = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); + +static CGImageRef create_image(CGColorSpaceRef lut, + const unsigned char* data, int w, int h) { - CGColorSpaceRef lut; CGDataProviderRef provider; CGImageRef image; - lut = CGDisplayCopyColorSpace(kCGDirectMainDisplay); - if (!lut) { - lut = CGColorSpaceCreateDeviceRGB(); - if (!lut) - throw rdr::Exception("CGColorSpaceCreateDeviceRGB"); - } - provider = CGDataProviderCreateWithData(NULL, data, w * h * 4, NULL); if (!provider) @@ -51,7 +47,6 @@ static CGImageRef create_image(const unsigned char* data, image = CGImageCreate(w, h, 8, 32, w * 4, lut, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little, provider, NULL, false, kCGRenderingIntentDefault); - CGColorSpaceRelease(lut); CGDataProviderRelease(provider); if (!image) throw rdr::Exception("CGImageCreate"); @@ -59,7 +54,7 @@ static CGImageRef create_image(const unsigned char* data, return image; } -static void render(CGContextRef gc, +static void render(CGContextRef gc, CGColorSpaceRef lut, const unsigned char* data, CGBlendMode mode, CGFloat alpha, int src_x, int src_y, int src_w, int src_h, @@ -68,7 +63,7 @@ static void render(CGContextRef gc, CGRect rect; CGImageRef image, subimage; - image = create_image(data, src_w, src_h); + image = create_image(lut, data, src_w, src_h); rect.origin.x = src_x; rect.origin.y = src_y; @@ -99,19 +94,10 @@ static void render(CGContextRef gc, static CGContextRef make_bitmap(int width, int height, unsigned char* data) { - CGColorSpaceRef lut; CGContextRef bitmap; - lut = CGDisplayCopyColorSpace(kCGDirectMainDisplay); - if (!lut) { - lut = CGColorSpaceCreateDeviceRGB(); - if (!lut) - throw rdr::Exception("CGColorSpaceCreateDeviceRGB"); - } - - bitmap = CGBitmapContextCreate(data, width, height, 8, width*4, lut, + bitmap = CGBitmapContextCreate(data, width, height, 8, width*4, srgb, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little); - CGColorSpaceRelease(lut); if (!bitmap) throw rdr::Exception("CGBitmapContextCreate"); @@ -140,6 +126,8 @@ void Surface::clear(unsigned char r, unsigned char g, unsigned char b, unsigned void Surface::draw(int src_x, int src_y, int x, int y, int w, int h) { + CGColorSpaceRef lut; + CGContextSaveGState(fl_gc); // Reset the transformation matrix back to the default identity @@ -149,8 +137,10 @@ void Surface::draw(int src_x, int src_y, int x, int y, int w, int h) // macOS Coordinates are from bottom left, not top left y = Fl_Window::current()->h() - (y + h); - render(fl_gc, data, kCGBlendModeCopy, 1.0, + lut = cocoa_win_color_space(Fl_Window::current()); + render(fl_gc, lut, data, kCGBlendModeCopy, 1.0, src_x, src_y, width(), height(), x, y, w, h); + CGColorSpaceRelease(lut); CGContextRestoreGState(fl_gc); } @@ -164,7 +154,7 @@ void Surface::draw(Surface* dst, int src_x, int src_y, int x, int y, int w, int // macOS Coordinates are from bottom left, not top left y = dst->height() - (y + h); - render(bitmap, data, kCGBlendModeCopy, 1.0, + render(bitmap, srgb, data, kCGBlendModeCopy, 1.0, src_x, src_y, width(), height(), x, y, w, h); CGContextRelease(bitmap); @@ -172,6 +162,8 @@ void Surface::draw(Surface* dst, int src_x, int src_y, int x, int y, int w, int void Surface::blend(int src_x, int src_y, int x, int y, int w, int h, int a) { + CGColorSpaceRef lut; + CGContextSaveGState(fl_gc); // Reset the transformation matrix back to the default identity @@ -181,8 +173,10 @@ void Surface::blend(int src_x, int src_y, int x, int y, int w, int h, int a) // macOS Coordinates are from bottom left, not top left y = Fl_Window::current()->h() - (y + h); - render(fl_gc, data, kCGBlendModeNormal, (CGFloat)a/255.0, + lut = cocoa_win_color_space(Fl_Window::current()); + render(fl_gc, lut, data, kCGBlendModeNormal, (CGFloat)a/255.0, src_x, src_y, width(), height(), x, y, w, h); + CGColorSpaceRelease(lut); CGContextRestoreGState(fl_gc); } @@ -196,7 +190,7 @@ void Surface::blend(Surface* dst, int src_x, int src_y, int x, int y, int w, int // macOS Coordinates are from bottom left, not top left y = dst->height() - (y + h); - render(bitmap, data, kCGBlendModeNormal, (CGFloat)a/255.0, + render(bitmap, srgb, data, kCGBlendModeNormal, (CGFloat)a/255.0, src_x, src_y, width(), height(), x, y, w, h); CGContextRelease(bitmap); diff --git a/vncviewer/cocoa.h b/vncviewer/cocoa.h index e9101f34..0c3ac82f 100644 --- a/vncviewer/cocoa.h +++ b/vncviewer/cocoa.h @@ -22,6 +22,10 @@ int cocoa_capture_display(Fl_Window *win, bool all_displays); void cocoa_release_display(Fl_Window *win); +typedef struct CGColorSpace *CGColorSpaceRef; + +CGColorSpaceRef cocoa_win_color_space(Fl_Window *win); + int cocoa_is_keyboard_event(const void *event); int cocoa_is_key_press(const void *event); diff --git a/vncviewer/cocoa.mm b/vncviewer/cocoa.mm index fc3b5bcf..85b736ba 100644 --- a/vncviewer/cocoa.mm +++ b/vncviewer/cocoa.mm @@ -110,6 +110,28 @@ void cocoa_release_display(Fl_Window *win) [nsw setLevel:newlevel]; } +CGColorSpaceRef cocoa_win_color_space(Fl_Window *win) +{ + NSWindow *nsw; + NSColorSpace *nscs; + + nsw = (NSWindow*)fl_xid(win); + + nscs = [nsw colorSpace]; + if (nscs == nil) { + // Offscreen, so return standard SRGB color space + assert(false); + return CGColorSpaceCreateWithName(kCGColorSpaceSRGB); + } + + CGColorSpaceRef lut = [nscs CGColorSpace]; + + // We want a permanent reference, not an autorelease + CGColorSpaceRetain(lut); + + return lut; +} + int cocoa_is_keyboard_event(const void *event) { NSEvent *nsevent; -- 2.39.5