Browse Source

Create new CGImage for each draw

The system expects these to be immutable, so changing the data after
creation only works in some special cases. We need to recreate the
CGImage object each time we've changed something.
tags/v1.8.90
Pierre Ossman 7 years ago
parent
commit
3b347313f1
2 changed files with 46 additions and 36 deletions
  1. 0
    1
      vncviewer/Surface.h
  2. 46
    35
      vncviewer/Surface_OSX.cxx

+ 0
- 1
vncviewer/Surface.h View File

HBITMAP bitmap; HBITMAP bitmap;
#elif defined(__APPLE__) #elif defined(__APPLE__)
unsigned char* data; unsigned char* data;
CGImageRef image;
#else #else
Pixmap pixmap; Pixmap pixmap;
Picture picture; Picture picture;

+ 46
- 35
vncviewer/Surface_OSX.cxx View File



#include "Surface.h" #include "Surface.h"


static void render(CGContextRef gc, CGImageRef image,
static CGImageRef create_image(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)
throw rdr::Exception("CGDataProviderCreateWithData");

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");

return image;
}

static void render(CGContextRef gc,
const unsigned char* data,
CGBlendMode mode, CGFloat alpha, CGBlendMode mode, CGFloat alpha,
int src_x, int src_y,
int src_x, int src_y, int src_w, int src_h,
int x, int y, int w, int h) int x, int y, int w, int h)
{ {
CGRect rect; CGRect rect;
CGImageRef subimage;
CGImageRef image, subimage;

image = create_image(data, src_w, src_h);


rect.origin.x = src_x; rect.origin.x = src_x;
rect.origin.y = src_y; rect.origin.y = src_y;
CGContextRestoreGState(gc); CGContextRestoreGState(gc);


CGImageRelease(subimage); CGImageRelease(subimage);
CGImageRelease(image);
} }


static CGContextRef make_bitmap(int width, int height, unsigned char* data) static CGContextRef make_bitmap(int width, int height, unsigned char* data)
// macOS Coordinates are from bottom left, not top left // macOS Coordinates are from bottom left, not top left
y = Fl_Window::current()->h() - (y + h); y = Fl_Window::current()->h() - (y + h);


render(fl_gc, image, kCGBlendModeCopy, 1.0,
src_x, src_y, x, y, w, h);
render(fl_gc, data, kCGBlendModeCopy, 1.0,
src_x, src_y, width(), height(), x, y, w, h);


CGContextRestoreGState(fl_gc); CGContextRestoreGState(fl_gc);
} }
// macOS Coordinates are from bottom left, not top left // macOS Coordinates are from bottom left, not top left
y = dst->height() - (y + h); y = dst->height() - (y + h);


render(bitmap, image, kCGBlendModeCopy, 1.0,
src_x, src_y, x, y, w, h);
render(bitmap, data, kCGBlendModeCopy, 1.0,
src_x, src_y, width(), height(), x, y, w, h);


CGContextRelease(bitmap); CGContextRelease(bitmap);
} }
// macOS Coordinates are from bottom left, not top left // macOS Coordinates are from bottom left, not top left
y = Fl_Window::current()->h() - (y + h); y = Fl_Window::current()->h() - (y + h);


render(fl_gc, image, kCGBlendModeNormal, (CGFloat)a/255.0,
src_x, src_y, x, y, w, h);
render(fl_gc, data, kCGBlendModeNormal, (CGFloat)a/255.0,
src_x, src_y, width(), height(), x, y, w, h);


CGContextRestoreGState(fl_gc); CGContextRestoreGState(fl_gc);
} }
// macOS Coordinates are from bottom left, not top left // macOS Coordinates are from bottom left, not top left
y = dst->height() - (y + h); y = dst->height() - (y + h);


render(bitmap, image, kCGBlendModeNormal, (CGFloat)a/255.0,
src_x, src_y, x, y, w, h);
render(bitmap, data, kCGBlendModeNormal, (CGFloat)a/255.0,
src_x, src_y, width(), height(), x, y, w, h);


CGContextRelease(bitmap); CGContextRelease(bitmap);
} }


void Surface::alloc() void Surface::alloc()
{ {
CGColorSpaceRef lut;
CGDataProviderRef provider;

data = new unsigned char[width() * height() * 4]; data = new unsigned char[width() * height() * 4];

lut = CGDisplayCopyColorSpace(kCGDirectMainDisplay);
if (!lut) {
lut = CGColorSpaceCreateDeviceRGB();
if (!lut)
throw rdr::Exception("CGColorSpaceCreateDeviceRGB");
}

provider = CGDataProviderCreateWithData(NULL, data,
width() * height() * 4, NULL);
if (!provider)
throw rdr::Exception("CGDataProviderCreateWithData");

image = CGImageCreate(width(), height(), 8, 32, width() * 4, lut,
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little,
provider, NULL, false, kCGRenderingIntentDefault);
CGColorSpaceRelease(lut);
CGDataProviderRelease(provider);
if (!image)
throw rdr::Exception("CGImageCreate");
} }


void Surface::dealloc() void Surface::dealloc()
{ {
CGImageRelease(image);
delete [] data; delete [] data;
} }



Loading…
Cancel
Save