diff options
author | Lukasz Kostyra <l.kostyra@samsung.com> | 2020-07-23 16:11:40 +0200 |
---|---|---|
committer | Lukasz Kostyra <l.kostyra@samsung.com> | 2020-07-27 19:09:26 +0200 |
commit | f98a012c6b2d0760a5ee02c134a3e37b10bc2906 (patch) | |
tree | 6d334130aee0483799138e905becd9e62b0ed956 | |
parent | 552acc5e211eb1a2f1ce160a214211e5f3a2952b (diff) | |
download | emulator-yagl-f98a012c6b2d0760a5ee02c134a3e37b10bc2906.tar.gz emulator-yagl-f98a012c6b2d0760a5ee02c134a3e37b10bc2906.tar.bz2 emulator-yagl-f98a012c6b2d0760a5ee02c134a3e37b10bc2906.zip |
Implement thread safety when sharing EGL contextsubmit/tizen/20200729.080538accepted/tizen/unified/20200729.165549
- glGen* and associated calls now lock a sharegroup-global mutex.
- glGen* and glDeleteObjects host calls flush the transport
to ensure resource is created before recording more calls.
- Some instances of yagl_host_glDeleteObjects being called were removed
because they caused the same assertion to fail - these could remove
a texture which was next bound.
Change-Id: Iea1b71062f25bc48a6aa583f7074801d416574a8
-rw-r--r-- | EGL/yagl_egl_calls.c | 4 | ||||
-rw-r--r-- | EGL/yagl_host_egl_calls.c | 1 | ||||
-rw-r--r-- | EGL/yagl_sharegroup.c | 28 | ||||
-rw-r--r-- | EGL/yagl_transport.c | 1 | ||||
-rw-r--r-- | GLES_common/yagl_gles_calls.c | 62 | ||||
-rw-r--r-- | GLES_common/yagl_gles_texture.c | 4 | ||||
-rw-r--r-- | GLES_common/yagl_host_gles_calls.c | 7 | ||||
-rw-r--r-- | GLESv2/yagl_gles2_calls.c | 24 | ||||
-rw-r--r-- | include/yagl_client_context.h | 1 | ||||
-rw-r--r-- | include/yagl_sharegroup.h | 11 | ||||
-rw-r--r-- | include/yagl_transport.h | 1 |
11 files changed, 132 insertions, 12 deletions
diff --git a/EGL/yagl_egl_calls.c b/EGL/yagl_egl_calls.c index cabf163..db484df 100644 --- a/EGL/yagl_egl_calls.c +++ b/EGL/yagl_egl_calls.c @@ -1866,11 +1866,15 @@ YAGL_API EGLImageKHR eglCreateImageKHR(EGLDisplay dpy_, goto out; } + yagl_sharegroup_mutex_lock_if_shared(ctx->client_ctx->sg); + image = yagl_get_backend()->create_image_gl_texture_2d(dpy, ctx, (yagl_object_name)VOIDP2INT(buffer), iface); + yagl_sharegroup_mutex_unlock_if_shared(ctx->client_ctx->sg); + if (!image) { goto out; } diff --git a/EGL/yagl_host_egl_calls.c b/EGL/yagl_host_egl_calls.c index 766748a..654389b 100644 --- a/EGL/yagl_host_egl_calls.c +++ b/EGL/yagl_host_egl_calls.c @@ -497,6 +497,7 @@ EGLBoolean yagl_host_eglCreateImageYAGL(uint32_t texture, yagl_host_handle dpy, yagl_transport_put_in_EGLint(t, error); yagl_transport_put_in_EGLBoolean(t, &retval); yagl_transport_end(t); + yagl_transport_flush(t, NULL); return retval; } diff --git a/EGL/yagl_sharegroup.c b/EGL/yagl_sharegroup.c index 4e35831..45de196 100644 --- a/EGL/yagl_sharegroup.c +++ b/EGL/yagl_sharegroup.c @@ -34,6 +34,7 @@ #include "yagl_sharegroup.h" #include "yagl_object.h" #include "yagl_malloc.h" +#include "yagl_utils.h" static void yagl_sharegroup_destroy(struct yagl_ref *ref) { @@ -50,6 +51,8 @@ static void yagl_sharegroup_destroy(struct yagl_ref *ref) yagl_ref_cleanup(&sg->ref); + pthread_mutex_destroy(&sg->mutex); + yagl_free(sg); } @@ -58,6 +61,8 @@ struct yagl_sharegroup *yagl_sharegroup_create(void) struct yagl_sharegroup *sg = yagl_malloc0(sizeof(struct yagl_sharegroup)); int i; + yagl_mutex_init(&sg->mutex); + yagl_ref_init(&sg->ref, &yagl_sharegroup_destroy); for (i = 0; i < YAGL_NUM_NAMESPACES; ++i) { @@ -109,3 +114,26 @@ struct yagl_object *yagl_sharegroup_acquire_object(struct yagl_sharegroup *sg, { return yagl_namespace_acquire(&sg->namespaces[ns], local_name); } + +static __inline int yagl_sharegroup_is_shared(struct yagl_sharegroup *sg) +{ + pthread_mutex_lock(&sg->ref.mutex); + int res = (sg->ref.count > 1); + pthread_mutex_unlock(&sg->ref.mutex); + + return res; +} + +void yagl_sharegroup_mutex_lock_if_shared(struct yagl_sharegroup *sg) +{ + if (yagl_sharegroup_is_shared(sg)) { + pthread_mutex_lock(&sg->mutex); + } +} + +void yagl_sharegroup_mutex_unlock_if_shared(struct yagl_sharegroup *sg) +{ + if (yagl_sharegroup_is_shared(sg)) { + pthread_mutex_unlock(&sg->mutex); + } +} diff --git a/EGL/yagl_transport.c b/EGL/yagl_transport.c index fbd4bf2..598583b 100644 --- a/EGL/yagl_transport.c +++ b/EGL/yagl_transport.c @@ -35,6 +35,7 @@ #include "yagl_malloc.h" #include "yagl_log.h" #include "yagl_egl_fence.h" +#include "yagl_utils.h" #include <stdio.h> #include <stdlib.h> diff --git a/GLES_common/yagl_gles_calls.c b/GLES_common/yagl_gles_calls.c index a87f4c5..41e3368 100644 --- a/GLES_common/yagl_gles_calls.c +++ b/GLES_common/yagl_gles_calls.c @@ -420,6 +420,8 @@ YAGL_API void glBindBuffer(GLenum target, GLuint buffer) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg); + if (buffer != 0) { buffer_obj = (struct yagl_gles_buffer*)yagl_sharegroup_acquire_object(ctx->base.sg, YAGL_NS_BUFFER, buffer); @@ -441,6 +443,8 @@ YAGL_API void glBindBuffer(GLenum target, GLuint buffer) out: yagl_gles_buffer_release(buffer_obj); + yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -452,6 +456,8 @@ void glBindFramebuffer(GLenum target, GLuint framebuffer) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg); + if (framebuffer != 0) { framebuffer_obj = (struct yagl_gles_framebuffer*)yagl_namespace_acquire(&ctx->framebuffers, framebuffer); @@ -473,6 +479,8 @@ void glBindFramebuffer(GLenum target, GLuint framebuffer) out: yagl_gles_framebuffer_release(framebuffer_obj); + yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -484,6 +492,8 @@ void glBindRenderbuffer(GLenum target, GLuint renderbuffer) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg); + if (renderbuffer != 0) { renderbuffer_obj = (struct yagl_gles_renderbuffer*)yagl_sharegroup_acquire_object(ctx->base.sg, YAGL_NS_RENDERBUFFER, renderbuffer); @@ -505,6 +515,8 @@ void glBindRenderbuffer(GLenum target, GLuint renderbuffer) out: yagl_gles_renderbuffer_release(renderbuffer_obj); + yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -517,6 +529,8 @@ YAGL_API void glBindTexture(GLenum target, GLuint texture) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg); + if (!yagl_gles_context_validate_texture_target(ctx, target, &texture_target)) { YAGL_SET_ERR(GL_INVALID_ENUM); goto out; @@ -527,14 +541,8 @@ YAGL_API void glBindTexture(GLenum target, GLuint texture) YAGL_NS_TEXTURE, texture); if (!texture_obj) { - texture_obj = yagl_gles_texture_create(); - - if (!texture_obj) { - goto out; - } - - texture_obj = (struct yagl_gles_texture*)yagl_sharegroup_add_named(ctx->base.sg, - YAGL_NS_TEXTURE, texture, &texture_obj->base); + YAGL_SET_ERR(GL_INVALID_OPERATION); + goto out; } } @@ -543,6 +551,8 @@ YAGL_API void glBindTexture(GLenum target, GLuint texture) out: yagl_gles_texture_release(texture_obj); + yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -1029,6 +1039,8 @@ YAGL_API void glDeleteBuffers(GLsizei n, const GLuint *buffers) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg); + if (n < 0) { YAGL_SET_ERR(GL_INVALID_VALUE); goto out; @@ -1045,6 +1057,8 @@ YAGL_API void glDeleteBuffers(GLsizei n, const GLuint *buffers) } out: + yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -1056,6 +1070,8 @@ void glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg); + if (n < 0) { YAGL_SET_ERR(GL_INVALID_VALUE); goto out; @@ -1071,6 +1087,8 @@ void glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) } out: + yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -1082,6 +1100,8 @@ void glDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg); + if (n < 0) { YAGL_SET_ERR(GL_INVALID_VALUE); goto out; @@ -1098,6 +1118,8 @@ void glDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) } out: + yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -1109,6 +1131,8 @@ YAGL_API void glDeleteTextures(GLsizei n, const GLuint *textures) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg); + if (n < 0) { YAGL_SET_ERR(GL_INVALID_VALUE); goto out; @@ -1126,6 +1150,8 @@ YAGL_API void glDeleteTextures(GLsizei n, const GLuint *textures) } out: + yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -1411,6 +1437,8 @@ YAGL_API void glGenBuffers(GLsizei n, GLuint *buffer_names) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg); + if (n < 0) { YAGL_SET_ERR(GL_INVALID_VALUE); goto out; @@ -1442,6 +1470,8 @@ out: } yagl_free(buffers); + yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -1469,6 +1499,8 @@ void glGenFramebuffers(GLsizei n, GLuint *framebuffer_names) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg); + if (n < 0) { YAGL_SET_ERR(GL_INVALID_VALUE); goto out; @@ -1499,6 +1531,8 @@ out: } yagl_free(framebuffers); + yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -1511,6 +1545,8 @@ void glGenRenderbuffers(GLsizei n, GLuint *renderbuffer_names) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg); + if (n < 0) { YAGL_SET_ERR(GL_INVALID_VALUE); goto out; @@ -1542,6 +1578,8 @@ out: } yagl_free(renderbuffers); + yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -1554,6 +1592,8 @@ YAGL_API void glGenTextures(GLsizei n, GLuint *texture_names) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg); + if (n < 0) { YAGL_SET_ERR(GL_INVALID_VALUE); goto out; @@ -1585,6 +1625,8 @@ out: } yagl_free(textures); + yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -2432,6 +2474,8 @@ YAGL_API void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg); + switch (target) { case GL_TEXTURE_2D: texture_target = yagl_gles_texture_target_2d; @@ -2464,6 +2508,8 @@ YAGL_API void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) out: yagl_gles_image_release(image_obj); + yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg); + YAGL_LOG_FUNC_EXIT(NULL); } diff --git a/GLES_common/yagl_gles_texture.c b/GLES_common/yagl_gles_texture.c index e0f5e3d..e9a0580 100644 --- a/GLES_common/yagl_gles_texture.c +++ b/GLES_common/yagl_gles_texture.c @@ -266,8 +266,6 @@ void yagl_gles_texture_set_image(struct yagl_gles_texture *texture, if (texture->image) { yagl_gles_image_release(texture->image); - } else { - yagl_host_glDeleteObjects(&texture->global_name, 1); } texture->global_name = image->tex_global_name; @@ -314,8 +312,6 @@ void yagl_gles_texture_bind_tex_image(struct yagl_gles_texture *texture, if (texture->image) { yagl_gles_image_release(texture->image); - } else { - yagl_host_glDeleteObjects(&texture->global_name, 1); } texture->global_name = image->tex_global_name; diff --git a/GLES_common/yagl_host_gles_calls.c b/GLES_common/yagl_host_gles_calls.c index a810c02..df7a628 100644 --- a/GLES_common/yagl_host_gles_calls.c +++ b/GLES_common/yagl_host_gles_calls.c @@ -406,6 +406,7 @@ void yagl_host_glGenBuffers(const GLuint *buffers, int32_t buffers_count) yagl_transport_begin(t, yagl_api_id_gles, 27, 2 * 8, 0 * 8 + yagl_transport_array_size(buffers, buffers_count, sizeof(GLuint))); yagl_transport_put_out_array(t, buffers, buffers_count, sizeof(GLuint)); yagl_transport_end(t); + yagl_transport_flush(t, NULL); } /* @@ -519,6 +520,7 @@ void yagl_host_glGenTextures(const GLuint *textures, int32_t textures_count) yagl_transport_begin(t, yagl_api_id_gles, 35, 2 * 8, 0 * 8 + yagl_transport_array_size(textures, textures_count, sizeof(GLuint))); yagl_transport_put_out_array(t, textures, textures_count, sizeof(GLuint)); yagl_transport_end(t); + yagl_transport_flush(t, NULL); } /* @@ -976,6 +978,7 @@ void yagl_host_glGenFramebuffers(const GLuint *framebuffers, int32_t framebuffer yagl_transport_begin(t, yagl_api_id_gles, 63, 2 * 8, 0 * 8 + yagl_transport_array_size(framebuffers, framebuffers_count, sizeof(GLuint))); yagl_transport_put_out_array(t, framebuffers, framebuffers_count, sizeof(GLuint)); yagl_transport_end(t); + yagl_transport_flush(t, NULL); } /* @@ -1167,6 +1170,7 @@ void yagl_host_glGenRenderbuffers(const GLuint *renderbuffers, int32_t renderbuf yagl_transport_begin(t, yagl_api_id_gles, 76, 2 * 8, 0 * 8 + yagl_transport_array_size(renderbuffers, renderbuffers_count, sizeof(GLuint))); yagl_transport_put_out_array(t, renderbuffers, renderbuffers_count, sizeof(GLuint)); yagl_transport_end(t); + yagl_transport_flush(t, NULL); } /* @@ -1237,6 +1241,7 @@ void yagl_host_glCreateProgram(GLuint program) yagl_transport_begin(t, yagl_api_id_gles, 81, 1 * 8, 1 * 8); yagl_transport_put_out_GLuint(t, program); yagl_transport_end(t); + yagl_transport_flush(t, NULL); } /* @@ -1250,6 +1255,7 @@ void yagl_host_glCreateShader(GLuint shader, GLenum type) yagl_transport_put_out_GLuint(t, shader); yagl_transport_put_out_GLenum(t, type); yagl_transport_end(t); + yagl_transport_flush(t, NULL); } /* @@ -2644,6 +2650,7 @@ void yagl_host_glDeleteObjects(const GLuint *objects, int32_t objects_count) yagl_transport_begin(t, yagl_api_id_gles, 180, 2 * 8, 0 * 8 + yagl_transport_array_size(objects, objects_count, sizeof(GLuint))); yagl_transport_put_out_array(t, objects, objects_count, sizeof(GLuint)); yagl_transport_end(t); + yagl_transport_flush(t, NULL); } /* diff --git a/GLESv2/yagl_gles2_calls.c b/GLESv2/yagl_gles2_calls.c index 45befd7..72d27ba 100644 --- a/GLESv2/yagl_gles2_calls.c +++ b/GLESv2/yagl_gles2_calls.c @@ -198,6 +198,8 @@ YAGL_API void glAttachShader(GLuint program, GLuint shader) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->sg); + program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg, YAGL_NS_SHADER_PROGRAM, program); @@ -233,6 +235,8 @@ out: yagl_gles2_shader_release(shader_obj); yagl_gles2_program_release(program_obj); + yagl_sharegroup_mutex_unlock_if_shared(ctx->sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -339,6 +343,8 @@ YAGL_API GLuint glCreateProgram(void) YAGL_GET_CTX_RET(0); + yagl_sharegroup_mutex_lock_if_shared(ctx->sg); + program = yagl_gles2_program_create(ctx->gen_locations); if (!program) { @@ -351,6 +357,8 @@ YAGL_API GLuint glCreateProgram(void) out: yagl_gles2_program_release(program); + yagl_sharegroup_mutex_unlock_if_shared(ctx->sg); + YAGL_LOG_FUNC_EXIT_SPLIT(GLuint, res); return res; @@ -365,6 +373,8 @@ YAGL_API GLuint glCreateShader(GLenum type) YAGL_GET_CTX_RET(0); + yagl_sharegroup_mutex_lock_if_shared(ctx->sg); + if (yagl_gles2_is_shader_type_valid(type)) { shader = yagl_gles2_shader_create(type); @@ -381,6 +391,8 @@ YAGL_API GLuint glCreateShader(GLenum type) out: yagl_gles2_shader_release(shader); + yagl_sharegroup_mutex_unlock_if_shared(ctx->sg); + YAGL_LOG_FUNC_EXIT_SPLIT(GLuint, res); return res; @@ -394,6 +406,8 @@ YAGL_API void glDeleteProgram(GLuint program) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->sg); + if (program == 0) { goto out; } @@ -419,6 +433,8 @@ YAGL_API void glDeleteProgram(GLuint program) out: yagl_gles2_program_release(program_obj); + yagl_sharegroup_mutex_unlock_if_shared(ctx->sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -430,6 +446,8 @@ YAGL_API void glDeleteShader(GLuint shader) YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->sg); + if (shader == 0) { goto out; } @@ -453,6 +471,8 @@ YAGL_API void glDeleteShader(GLuint shader) out: yagl_gles2_shader_release(shader_obj); + yagl_sharegroup_mutex_unlock_if_shared(ctx->sg); + YAGL_LOG_FUNC_EXIT(NULL); } @@ -1347,6 +1367,8 @@ YAGL_API void glShaderSource(GLuint shader, GLsizei count, const GLchar * const YAGL_GET_CTX(); + yagl_sharegroup_mutex_lock_if_shared(ctx->sg); + if (count < 0) { YAGL_SET_ERR(GL_INVALID_VALUE); goto out; @@ -1439,6 +1461,8 @@ YAGL_API void glShaderSource(GLuint shader, GLsizei count, const GLchar * const out: yagl_gles2_shader_release(shader_obj); + yagl_sharegroup_mutex_unlock_if_shared(ctx->sg); + YAGL_LOG_FUNC_EXIT(NULL); } diff --git a/include/yagl_client_context.h b/include/yagl_client_context.h index 91057a5..25d73cf 100644 --- a/include/yagl_client_context.h +++ b/include/yagl_client_context.h @@ -36,6 +36,7 @@ #include "yagl_export.h" #include "yagl_types.h" +#include <pthread.h> struct yagl_sharegroup; struct yagl_client_image; diff --git a/include/yagl_sharegroup.h b/include/yagl_sharegroup.h index 868beb7..7dabd06 100644 --- a/include/yagl_sharegroup.h +++ b/include/yagl_sharegroup.h @@ -46,6 +46,7 @@ struct yagl_sharegroup { struct yagl_ref ref; + pthread_mutex_t mutex; struct yagl_namespace namespaces[YAGL_NUM_NAMESPACES]; @@ -111,4 +112,14 @@ YAGL_API struct yagl_object *yagl_sharegroup_acquire_object(struct yagl_sharegro int ns, yagl_object_name local_name); +/* + * Lock sharegroup's mutex if context is shared. + */ +YAGL_API void yagl_sharegroup_mutex_lock_if_shared(struct yagl_sharegroup *sg); + +/* + * Unlock sharegroup's mutex if context is shared. + */ +YAGL_API void yagl_sharegroup_mutex_unlock_if_shared(struct yagl_sharegroup *sg); + #endif diff --git a/include/yagl_transport.h b/include/yagl_transport.h index 62d4d6d..d69d228 100644 --- a/include/yagl_transport.h +++ b/include/yagl_transport.h @@ -39,6 +39,7 @@ #include <string.h> #include <assert.h> #include <limits.h> +#include <pthread.h> #define YAGL_TRANSPORT_MAX_IN_ARGS 8 #define YAGL_TRANSPORT_MAX_IN_ARRAYS 8 |