diff options
-rw-r--r-- | src/mesa/main/shaderapi.c | 66 |
1 files changed, 63 insertions, 3 deletions
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index 3c6fadae6ca..0d3c0de908e 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -3209,11 +3209,11 @@ _mesa_destroy_shader_includes(struct gl_shared_state *shared) } static bool -valid_path_format(const char *str) +valid_path_format(const char *str, bool relative_path) { int i = 0; - if (!str[i] || str[i] != '/') + if (!str[i] || (!relative_path && str[i] != '/')) return false; i++; @@ -3249,7 +3249,9 @@ validate_and_tokenise_sh_incl(struct gl_context *ctx, struct sh_incl_path_entry **path_list, char *full_path, bool error_check) { - if (!valid_path_format(full_path)) { + bool relative_path = ctx->Shared->ShaderIncludes->num_include_paths; + + if (!valid_path_format(full_path, relative_path)) { if (error_check) { _mesa_error(ctx, GL_INVALID_VALUE, "glNamedStringARB(invalid name %s)", full_path); @@ -3524,6 +3526,64 @@ GLvoid GLAPIENTRY _mesa_CompileShaderIncludeARB(GLuint shader, GLsizei count, const GLchar* const *path, const GLint *length) { + GET_CURRENT_CONTEXT(ctx); + const char *caller = "glCompileShaderIncludeARB"; + + if (count > 0 && path == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(count > 0 && path == NULL)", + caller); + return; + } + + void *mem_ctx = ralloc_context(NULL); + + mtx_lock(&ctx->Shared->ShaderIncludeMutex); + + ctx->Shared->ShaderIncludes->include_paths = + ralloc_array_size(mem_ctx, sizeof(struct sh_incl_path_entry *), count); + + for (size_t i = 0; i < count; i++) { + char *path_cp = copy_string(ctx, path[i], length ? length[i] : -1, + caller); + if (!path_cp) { + goto exit; + } + + struct sh_incl_path_entry *path_list; + + if (!validate_and_tokenise_sh_incl(ctx, mem_ctx, &path_list, path_cp, + true)) { + free(path_cp); + goto exit; + } + + ctx->Shared->ShaderIncludes->include_paths[i] = path_list; + + free(path_cp); + } + + /* We must set this *after* all calls to validate_and_tokenise_sh_incl() + * are done as we use this to decide if we need to check the start of the + * path for a '/' + */ + ctx->Shared->ShaderIncludes->num_include_paths = count; + + struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); + if (!sh) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(shader)", caller); + goto exit; + } + + _mesa_compile_shader(ctx, sh); + +exit: + ctx->Shared->ShaderIncludes->num_include_paths = 0; + ctx->Shared->ShaderIncludes->relative_path_cursor = 0; + ctx->Shared->ShaderIncludes->include_paths = NULL; + + mtx_unlock(&ctx->Shared->ShaderIncludeMutex); + + ralloc_free(mem_ctx); } GLboolean GLAPIENTRY |