From 74aa1c466b03fb831d15a2d986e4acdf48a2dfc9 Mon Sep 17 00:00:00 2001 From: Palana Date: Mon, 23 Dec 2013 16:34:56 +0100 Subject: [PATCH] add osx iosurface opengl integration --- libobs-opengl/CMakeLists.txt | 5 ++ libobs-opengl/gl-cocoa.m | 103 ++++++++++++++++++++++++++++ libobs-opengl/gl-exports.h | 5 ++ libobs-opengl/makefile.am | 1 + libobs/graphics/graphics-imports.c | 4 ++ libobs/graphics/graphics-internal.h | 4 ++ libobs/graphics/graphics.c | 22 ++++++ libobs/graphics/graphics.h | 5 ++ 8 files changed, 149 insertions(+) diff --git a/libobs-opengl/CMakeLists.txt b/libobs-opengl/CMakeLists.txt index a01442246..732e18fe3 100644 --- a/libobs-opengl/CMakeLists.txt +++ b/libobs-opengl/CMakeLists.txt @@ -6,9 +6,14 @@ elseif(APPLE AND UNIX) set_source_files_properties(${libobs_opengl_platform_objc_src} PROPERTIES LANGUAGE C) set(libobs_opengl_platform_src ${libobs_opengl_platform_objc_src}) + find_library(COCOA Cocoa) include_directories(${COCOA}) link_libraries(${COCOA}) + + find_library(IOSURF IOSurface) + include_directories(${IOSURF}) + link_libraries(${IOSURF}) else() endif() diff --git a/libobs-opengl/gl-cocoa.m b/libobs-opengl/gl-cocoa.m index b88a2fcef..bf80b4fc0 100644 --- a/libobs-opengl/gl-cocoa.m +++ b/libobs-opengl/gl-cocoa.m @@ -252,3 +252,106 @@ void gl_getclientsize(struct gs_swap_chain *swap, uint32_t *width, if(width) *width = swap->info.cx; if(height) *height = swap->info.cy; } + +texture_t texture_create_from_iosurface(device_t device, void *iosurf) +{ + IOSurfaceRef ref = (IOSurfaceRef)iosurf; + struct gs_texture_2d *tex = bmalloc(sizeof(struct gs_texture_2d)); + memset(tex, 0, sizeof(struct gs_texture_2d)); + + const enum gs_color_format color_format = GS_BGRA; + + tex->base.device = device; + tex->base.type = GS_TEXTURE_2D; + tex->base.format = GS_BGRA; + tex->base.levels = 1; + tex->base.gl_format = convert_gs_format(color_format); + tex->base.gl_internal_format = convert_gs_internal_format(color_format); + tex->base.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; + tex->base.gl_target = GL_TEXTURE_RECTANGLE; + tex->base.is_dynamic = false; + tex->base.is_render_target = false; + tex->base.gen_mipmaps = false; + tex->width = IOSurfaceGetWidth(ref); + tex->height = IOSurfaceGetHeight(ref); + + if (!gl_gen_textures(1, &tex->base.texture)) + goto fail; + + if (!gl_bind_texture(tex->base.gl_target, tex->base.texture)) + goto fail; + + CGLError err = CGLTexImageIOSurface2D( + [[NSOpenGLContext currentContext] CGLContextObj], + tex->base.gl_target, + tex->base.gl_internal_format, + tex->width, tex->height, + tex->base.gl_format, + tex->base.gl_type, + ref, 0); + + if(err != kCGLNoError) { + blog(LOG_ERROR, "CGLTexImageIOSurface2D: %u, %s" + " (texture_create_from_iosurface)", + err, CGLErrorString(err)); + + gl_success("CGLTexImageIOSurface2D"); + goto fail; + } + + if (!gl_tex_param_i(tex->base.gl_target, + GL_TEXTURE_MAX_LEVEL, 0)) + goto fail; + + if (!gl_bind_texture(tex->base.gl_target, 0)) + goto fail; + + return (texture_t)tex; + +fail: + texture_destroy((texture_t)tex); + blog(LOG_ERROR, "texture_create_from_iosurface (GL) failed"); + return NULL; +} + +bool texture_rebind_iosurface(texture_t texture, void *iosurf) +{ + if (!texture) + return false; + + if (!iosurf) + return false; + + struct gs_texture_2d *tex = (struct gs_texture_2d*)texture; + IOSurfaceRef ref = (IOSurfaceRef)iosurf; + + if (tex->width != IOSurfaceGetWidth(ref) || + tex->height != IOSurfaceGetHeight(ref)) + return false; + + if (!gl_bind_texture(tex->base.gl_target, tex->base.texture)) + return false; + + CGLError err = CGLTexImageIOSurface2D( + [[NSOpenGLContext currentContext] CGLContextObj], + tex->base.gl_target, + tex->base.gl_internal_format, + tex->width, tex->height, + tex->base.gl_format, + tex->base.gl_type, + ref, 0); + + if(err != kCGLNoError) { + blog(LOG_ERROR, "CGLTexImageIOSurface2D: %u, %s" + " (texture_rebind_iosurface)", + err, CGLErrorString(err)); + + gl_success("CGLTexImageIOSurface2D"); + return false; + } + + if (!gl_bind_texture(tex->base.gl_target, 0)) + return false; + + return true; +} diff --git a/libobs-opengl/gl-exports.h b/libobs-opengl/gl-exports.h index acc91f2e6..bc9d4b5b3 100644 --- a/libobs-opengl/gl-exports.h +++ b/libobs-opengl/gl-exports.h @@ -188,3 +188,8 @@ EXPORT void shader_settexture(shader_t shader, sparam_t param, texture_t val); EXPORT void shader_setval(shader_t shader, sparam_t param, const void *val, size_t size); EXPORT void shader_setdefault(shader_t shader, sparam_t param); + +#ifdef __APPLE__ +EXPORT texture_t texture_create_from_iosurface(device_t device, void *iosurf); +EXPORT bool texture_rebind_iosurface(texture_t texture, void *iosurf); +#endif diff --git a/libobs-opengl/makefile.am b/libobs-opengl/makefile.am index 2b8489937..d248ab219 100644 --- a/libobs-opengl/makefile.am +++ b/libobs-opengl/makefile.am @@ -33,6 +33,7 @@ libobs_opengl_la_SOURCES = gl-helpers.c \ if OS_OSX libobs_opengl_la_SOURCES += gl-cocoa.m +libobs_opengl_la_LDFLAGS += -framework Cocoa -framework IOSurface endif if OS_WIN diff --git a/libobs/graphics/graphics-imports.c b/libobs/graphics/graphics-imports.c index 3b55171f4..8b1da5f21 100644 --- a/libobs/graphics/graphics-imports.c +++ b/libobs/graphics/graphics-imports.c @@ -165,5 +165,9 @@ bool load_graphics_imports(struct gs_exports *exports, void *module, GRAPHICS_IMPORT(shader_setval); GRAPHICS_IMPORT(shader_setdefault); + /* OSX/Cocoa specific functions */ + GRAPHICS_IMPORT_OPTIONAL(texture_create_from_iosurface); + GRAPHICS_IMPORT_OPTIONAL(texture_rebind_iosurface); + return success; } diff --git a/libobs/graphics/graphics-internal.h b/libobs/graphics/graphics-internal.h index 4c6e168bf..7286f232e 100644 --- a/libobs/graphics/graphics-internal.h +++ b/libobs/graphics/graphics-internal.h @@ -201,6 +201,10 @@ struct gs_exports { void (*shader_setval)(shader_t shader, sparam_t param, const void *val, size_t size); void (*shader_setdefault)(shader_t shader, sparam_t param); + + /* OSX/Cocoa specific functions */ + texture_t (*texture_create_from_iosurface)(device_t dev, void *iosurf); + bool (*texture_rebind_iosurface)(texture_t texture, void *iosurf); }; struct graphics_subsystem { diff --git a/libobs/graphics/graphics.c b/libobs/graphics/graphics.c index 7d30d45dc..2226b5215 100644 --- a/libobs/graphics/graphics.c +++ b/libobs/graphics/graphics.c @@ -1589,3 +1589,25 @@ enum gs_index_type indexbuffer_gettype(indexbuffer_t indexbuffer) { return thread_graphics->exports.indexbuffer_gettype(indexbuffer); } + +/** Platform specific functions */ +texture_t gs_create_texture_from_iosurface(void *iosurf) +{ + graphics_t graphics = thread_graphics; + if (!graphics->exports.texture_create_from_iosurface) + return NULL; + + return graphics->exports.texture_create_from_iosurface( + graphics->device, iosurf); +} + +bool texture_rebind_iosurface(texture_t texture, void *iosurf) +{ + graphics_t graphics = thread_graphics; + if (!graphics->exports.texture_rebind_iosurface) + return false; + + return graphics->exports.texture_rebind_iosurface(texture, iosurf); +} + + diff --git a/libobs/graphics/graphics.h b/libobs/graphics/graphics.h index 87e584c38..f972b9838 100644 --- a/libobs/graphics/graphics.h +++ b/libobs/graphics/graphics.h @@ -678,6 +678,11 @@ EXPORT void *indexbuffer_getdata(indexbuffer_t indexbuffer); EXPORT size_t indexbuffer_numindices(indexbuffer_t indexbuffer); EXPORT enum gs_index_type indexbuffer_gettype(indexbuffer_t indexbuffer); +/** platform specific function for creating (GL_TEXTURE_RECTANGLE) textures + * from shared surface resources */ +EXPORT texture_t gs_create_texture_from_iosurface(void *iosurf); +EXPORT bool texture_rebind_iosurface(texture_t texture, void *iosurf); + /* inline functions used by modules */ static inline uint32_t gs_get_format_bpp(enum gs_color_format format)