Commit 89d1b53d authored by FUJISAWA Tooru's avatar FUJISAWA Tooru Committed by Felix Paul Kühne

screen/mac: cursor rendering

Signed-off-by: default avatarFelix Paul Kühne <fkuehne@videolan.org>
parent 639c139e
...@@ -56,6 +56,11 @@ struct screen_data_t ...@@ -56,6 +56,11 @@ struct screen_data_t
int screen_height; int screen_height;
CGDirectDisplayID display_id; CGDirectDisplayID display_id;
CGContextRef offscreen_context;
CGRect offscreen_rect;
void *offscreen_bitmap;
size_t offscreen_bitmap_size;
}; };
int screen_InitCapture(demux_t *p_demux) int screen_InitCapture(demux_t *p_demux)
...@@ -63,7 +68,6 @@ int screen_InitCapture(demux_t *p_demux) ...@@ -63,7 +68,6 @@ int screen_InitCapture(demux_t *p_demux)
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
screen_data_t *p_data; screen_data_t *p_data;
CGLError returnedError; CGLError returnedError;
int i_bits_per_pixel, i_chroma = 0;
p_sys->p_data = p_data = calloc(1, sizeof(screen_data_t)); p_sys->p_data = p_data = calloc(1, sizeof(screen_data_t));
if (!p_data) if (!p_data)
...@@ -106,59 +110,17 @@ int screen_InitCapture(demux_t *p_demux) ...@@ -106,59 +110,17 @@ int screen_InitCapture(demux_t *p_demux)
p_data->height = p_data->screen_height; p_data->height = p_data->screen_height;
} }
CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(CGDisplayCopyDisplayMode(p_data->display_id));
int length = CFStringGetLength(pixelEncoding);
length++;
char *psz_name = (char *)malloc(length);
CFStringGetCString(pixelEncoding, psz_name, length, kCFStringEncodingUTF8);
msg_Dbg(p_demux, "pixel encoding is '%s'", psz_name);
CFRelease(pixelEncoding);
if (!strcmp(psz_name, IO32BitDirectPixels)) {
i_chroma = VLC_CODEC_RGB32;
i_bits_per_pixel = 32;
} else if (!strcmp(psz_name, IO16BitDirectPixels)) {
i_chroma = VLC_CODEC_RGB16;
i_bits_per_pixel = 16;
} else if (!strcmp(psz_name, IO8BitIndexedPixels)) {
i_chroma = VLC_CODEC_RGB8;
i_bits_per_pixel = 8;
} else {
msg_Err(p_demux, "unsupported pixel encoding");
free(p_data);
return VLC_EGENERIC;
}
free(psz_name);
/* setup format */ /* setup format */
es_format_Init(&p_sys->fmt, VIDEO_ES, i_chroma); es_format_Init(&p_sys->fmt, VIDEO_ES, VLC_CODEC_RGB32);
p_sys->fmt.video.i_visible_width = p_sys->fmt.video.i_visible_width =
p_sys->fmt.video.i_width = rect.size.width; p_sys->fmt.video.i_width = rect.size.width;
p_sys->fmt.video.i_visible_height = p_sys->fmt.video.i_visible_height =
p_sys->fmt.video.i_height = rect.size.height; p_sys->fmt.video.i_height = rect.size.height;
p_sys->fmt.video.i_bits_per_pixel = i_bits_per_pixel; p_sys->fmt.video.i_bits_per_pixel = 32;
p_sys->fmt.video.i_chroma = i_chroma; p_sys->fmt.video.i_chroma = VLC_CODEC_RGB32;
p_sys->fmt.video.i_rmask = 0x00ff0000;
switch (i_chroma) { p_sys->fmt.video.i_gmask = 0x0000ff00;
case VLC_CODEC_RGB15: p_sys->fmt.video.i_bmask = 0x000000ff;
p_sys->fmt.video.i_rmask = 0x7c00;
p_sys->fmt.video.i_gmask = 0x03e0;
p_sys->fmt.video.i_bmask = 0x001f;
break;
case VLC_CODEC_RGB24:
p_sys->fmt.video.i_rmask = 0x00ff0000;
p_sys->fmt.video.i_gmask = 0x0000ff00;
p_sys->fmt.video.i_bmask = 0x000000ff;
break;
case VLC_CODEC_RGB32:
p_sys->fmt.video.i_rmask = 0x00ff0000;
p_sys->fmt.video.i_gmask = 0x0000ff00;
p_sys->fmt.video.i_bmask = 0x000000ff;
break;
default:
msg_Warn( p_demux, "Unknown RGB masks" );
break;
}
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -168,6 +130,12 @@ int screen_CloseCapture(demux_t *p_demux) ...@@ -168,6 +130,12 @@ int screen_CloseCapture(demux_t *p_demux)
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
screen_data_t *p_data = p_sys->p_data; screen_data_t *p_data = p_sys->p_data;
if (p_data->offscreen_context)
CFRelease(p_data->offscreen_context);
if (p_data->offscreen_bitmap)
free(p_data->offscreen_bitmap);
if (p_data->p_block) if (p_data->p_block)
block_Release(p_data->p_block); block_Release(p_data->p_block);
...@@ -183,8 +151,6 @@ block_t *screen_Capture(demux_t *p_demux) ...@@ -183,8 +151,6 @@ block_t *screen_Capture(demux_t *p_demux)
block_t *p_block; block_t *p_block;
CGRect capture_rect; CGRect capture_rect;
CGImageRef image; CGImageRef image;
CGDataProviderRef dataProvider;
CFDataRef data;
/* forward cursor location */ /* forward cursor location */
CGPoint cursor_pos; CGPoint cursor_pos;
...@@ -204,37 +170,67 @@ block_t *screen_Capture(demux_t *p_demux) ...@@ -204,37 +170,67 @@ block_t *screen_Capture(demux_t *p_demux)
capture_rect.size.width = p_data->width; capture_rect.size.width = p_data->width;
capture_rect.size.height = p_data->height; capture_rect.size.height = p_data->height;
#if 0
// FIXME: actually plot cursor image into snapshot
/* fetch cursor image */
CGImageRef cursor_image;
int cid = CGSMainConnectionID();
CGPoint outHotSpot;
cursor_image = CGSCreateRegisteredCursorImage(cid, (char *)"com.apple.coregraphics.GlobalCurrent", &outHotSpot);
#endif
/* fetch image data */ /* fetch image data */
image = CGDisplayCreateImageForRect(p_data->display_id, capture_rect); image = CGDisplayCreateImageForRect(p_data->display_id, capture_rect);
if (image) { if (!image) {
/* build block */ msg_Warn(p_demux, "no image!");
int i_buffer = (p_sys->fmt.video.i_bits_per_pixel + 7) / 8 * p_sys->fmt.video.i_width * p_sys->fmt.video.i_height; return NULL;
p_block = block_Alloc(i_buffer); }
if (!p_block) {
msg_Warn(p_demux, "can't get block"); /* create offscreen context */
if (!p_data->offscreen_context) {
CGColorSpaceRef colorspace;
colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
p_data->offscreen_bitmap_size = p_sys->fmt.video.i_width * p_sys->fmt.video.i_height * 4;
p_data->offscreen_bitmap = calloc(1, p_data->offscreen_bitmap_size);
if (p_data->offscreen_bitmap == NULL) {
msg_Warn(p_demux, "can't allocate offscreen bitmap");
CFRelease(image);
return NULL; return NULL;
} }
dataProvider = CGImageGetDataProvider(image); p_data->offscreen_context = CGBitmapContextCreate(p_data->offscreen_bitmap, p_sys->fmt.video.i_width, p_sys->fmt.video.i_height, 8, p_sys->fmt.video.i_width * 4, colorspace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
data = CGDataProviderCopyData(dataProvider); if (!p_data->offscreen_context) {
CFDataGetBytes(data, CFRangeMake(0,CFDataGetLength(data)), p_block->p_buffer); msg_Warn(p_demux, "can't create offscreen bitmap context");
CFRelease(image);
return NULL;
}
CFRelease(data); CGColorSpaceRelease(colorspace);
CFRelease(dataProvider);
CFRelease(image);
return p_block; p_data->offscreen_rect = CGRectMake(0, 0, p_sys->fmt.video.i_width, p_sys->fmt.video.i_height);
} }
msg_Warn(p_demux, "no image!"); /* fetch cursor image */
return NULL; CGImageRef cursor_image;
int cid = CGSMainConnectionID();
CGPoint outHotSpot;
cursor_image = CGSCreateRegisteredCursorImage(cid, (char *)"com.apple.coregraphics.GlobalCurrent", &outHotSpot);
/* draw screen image and cursor image */
CGRect cursor_rect;
cursor_rect.size.width = CGImageGetWidth(cursor_image);
cursor_rect.size.height = CGImageGetHeight(cursor_image);
cursor_rect.origin.x = cursor_pos.x - p_sys->i_left - outHotSpot.x;
cursor_rect.origin.y = p_data->offscreen_rect.size.height
- (cursor_pos.y + cursor_rect.size.height - p_sys->i_top - outHotSpot.y);
CGContextDrawImage(p_data->offscreen_context, p_data->offscreen_rect, image);
CGContextDrawImage(p_data->offscreen_context, cursor_rect, cursor_image);
/* build block */
p_block = block_Alloc(p_data->offscreen_bitmap_size);
if (!p_block) {
msg_Warn(p_demux, "can't get block");
CFRelease(image);
return NULL;
}
memmove(p_block->p_buffer, p_data->offscreen_bitmap, p_data->offscreen_bitmap_size);
CFRelease(image);
return p_block;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment