diff options
Diffstat (limited to 'texture_share_vk.lua')
| -rw-r--r-- | texture_share_vk.lua | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/texture_share_vk.lua b/texture_share_vk.lua new file mode 100644 index 0000000..b8e2523 --- /dev/null +++ b/texture_share_vk.lua @@ -0,0 +1,172 @@ +local ffi = require 'ffi' + +ffi.cdef [[ +// GL/gl.h +typedef int GLint; +typedef unsigned int GLuint; +typedef unsigned int GLenum; + +void glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, + GLenum pname, GLint *params); + +// texture_share_ipc/texture_share_ipc.h +typedef enum ImgFormat { + R8G8B8A8, + R8G8B8, + B8G8R8A8, + B8G8R8, + Undefined, +} ImgFormat; + +// texture_share_gl_client/texture_share_gl_client.h +typedef enum ImageLookupResult { + Error = -1, + NotFound = 0, + Found = 1, + RequiresUpdate = 2, +} ImageLookupResult; + +typedef struct ClientImageDataGuard ClientImageDataGuard; + +typedef struct GlClient GlClient; + +typedef struct GlImageExtent { + GLint top_left[2]; + GLint bottom_right[2]; +} GlImageExtent; + +bool gl_client_initialize_external_gl(void); + +struct GlClient *gl_client_new(const char *socket_path, uint64_t timeout_in_millis); +struct GlClient *gl_client_new_with_server_launch(const char *socket_path, + uint64_t client_timeout_in_millis, + const char *server_program, + const char *server_lock_path, + const char *server_socket_path, + const char *shmem_prefix, + uint64_t server_socket_timeout_in_millis, + uint64_t server_connection_wait_timeout_in_millis, + uint64_t server_ipc_timeout_in_millis, + uint64_t server_lockfile_timeout_in_millis, + uint64_t server_spawn_timeout_in_millis); + +void gl_client_destroy(struct GlClient *gl_client); + +enum ImageLookupResult gl_client_init_image(struct GlClient *gl_client, + const char *image_name, + uint32_t width, + uint32_t height, + ImgFormat format, + bool overwrite_existing); + +int gl_client_send_image(struct GlClient *gl_client, + const char *image_name, + GLuint src_texture_id, + GLenum src_texture_target, + bool invert, + GLuint prev_fbo, + const struct GlImageExtent *extents); +]] + +-- from texture_share_vk/config.h +local VK_SERVER_EXECUTABLE = "/usr/bin/texture-share-vk-server" +local VK_SERVER_DEFAULT_LOCKFILE_PATH = "/tmp/vk_server/vk_server.lock" +local VK_SERVER_DEFAULT_SOCKET_PATH = "/tmp/vk_server/vk_server.sock" +local VK_SERVER_DEFAULT_SHMEM_PREFIX = "shmem_img_" + +-- from GL/gl.h +local GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1 +local GL_COLOR_ATTACHMENT0 = 0x8CE0 +local GL_FRAMEBUFFER = 0x8D40 +local GL_TEXTURE_2D = 0x0DE1 + +local IMAGE_FORMATS = { + rgba8 = ffi.C.R8G8B8A8, + rgb8 = ffi.C.R8G8B8, +} + +local tvs = ffi.load("texture_share_gl_client") +local gl = ffi.load("GL") + +local Client, Canvas = {}, {} +Client.__index = Client + +function Client.new() + assert(tvs.gl_client_initialize_external_gl(), "failed to init tsv OpenGL") + local client = assert(tvs.gl_client_new_with_server_launch( + VK_SERVER_DEFAULT_SOCKET_PATH, + 1000, + VK_SERVER_EXECUTABLE, + VK_SERVER_DEFAULT_LOCKFILE_PATH, + VK_SERVER_DEFAULT_SOCKET_PATH, + VK_SERVER_DEFAULT_SHMEM_PREFIX, + 2000, + 2000, + 2000, + 2000, + 2000 + ), "failed to connect or launch tsv server") + + return setmetatable({ client = client }, Client) +end + +function Client:newSharedCanvas(name, ...) + local canvas = love.graphics.newCanvas(...) + local width, height = canvas:getDimensions() + local format = assert(IMAGE_FORMATS[canvas:getFormat()], "unsupported Texture format") + assert( + tvs.gl_client_init_image(self.client, name, width, height, format, true) > 0, + "failed to init image" + ) + + local last_canvas = love.graphics.getCanvas() + love.graphics.setCanvas(canvas) + + local name_ptr = ffi.typeof('GLint[1]')() + gl.glGetFramebufferAttachmentParameteriv( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + name_ptr + ) + love.graphics.setCanvas(last_canvas) + + return setmetatable({ + name = name, + canvas = canvas, + client = self, + texture_id = name_ptr[0] + }, Canvas) +end + +function Client:__gc() + tvs.gl_client_destroy(self) +end + +function Canvas:send() + tvs.gl_client_send_image( + self.client.client, + self.name, + self.texture_id, + GL_TEXTURE_2D, + false, + 0, + nil + ) +end + +function Canvas:__index(key) + local val = Canvas[key] + if val then return val end + + val = self.canvas[key] + if val then + Canvas[key] = function (shared, ...) + return val(shared.canvas, ...) + end + + return Canvas[key] + end +end + +return Client |
