From 37e1e2b95793a8efbbc50fea4d1c1115a607c845 Mon Sep 17 00:00:00 2001 From: Stanislav Vorobiov Date: Wed, 7 Nov 2012 17:44:12 +0400 Subject: [PATCH] YaGL: Fix for khronos GLESv2 test: glGetUniform implemented appropriately YaGL: Fix for khronos GLESv2 test: number of texture units limited to 32 --- hw/yagl_apis/gles2/yagl_gles2_context.c | 14 +++- hw/yagl_apis/gles2/yagl_gles2_program.c | 93 +++++++++++++++++++++++++ hw/yagl_apis/gles2/yagl_gles2_program.h | 12 ++++ hw/yagl_apis/gles2/yagl_gles2_validate.c | 25 +++++++ hw/yagl_apis/gles2/yagl_gles2_validate.h | 2 + hw/yagl_apis/gles2/yagl_host_gles2_calls.c | 106 ++++++++++++++++++++++++++--- hw/yagl_apis/gles2/yagl_host_gles2_calls.h | 4 +- 7 files changed, 243 insertions(+), 13 deletions(-) diff --git a/hw/yagl_apis/gles2/yagl_gles2_context.c b/hw/yagl_apis/gles2/yagl_gles2_context.c index 6405291..d57ba73 100644 --- a/hw/yagl_apis/gles2/yagl_gles2_context.c +++ b/hw/yagl_apis/gles2/yagl_gles2_context.c @@ -167,6 +167,9 @@ static bool yagl_gles2_context_get_integerv(struct yagl_gles_context *ctx, case GL_RENDERBUFFER_BINDING: params[0] = ctx->rbo_local_name; break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: + params[0] = ctx->num_texture_units; + break; default: return false; } @@ -184,6 +187,7 @@ static bool yagl_gles2_context_get_booleanv(struct yagl_gles_context *ctx, case GL_CURRENT_PROGRAM: case GL_FRAMEBUFFER_BINDING: case GL_RENDERBUFFER_BINDING: + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: if (!yagl_gles2_context_get_integerv(ctx, pname, &tmp)) { return false; } @@ -206,6 +210,7 @@ static bool yagl_gles2_context_get_floatv(struct yagl_gles_context *ctx, case GL_CURRENT_PROGRAM: case GL_FRAMEBUFFER_BINDING: case GL_RENDERBUFFER_BINDING: + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: if (!yagl_gles2_context_get_integerv(ctx, pname, &tmp)) { return false; } @@ -394,9 +399,16 @@ static void yagl_gles2_context_prepare(struct yagl_gles2_context *gles2_ctx, &yagl_gles2_array_apply); } - gles_driver->GetIntegerv(gles_driver, GL_MAX_TEXTURE_IMAGE_UNITS, + gles_driver->GetIntegerv(gles_driver, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &num_texture_units); + /* + * We limit this by 32 for conformance. + */ + if (num_texture_units > 32) { + num_texture_units = 32; + } + yagl_gles_context_prepare(&gles2_ctx->base, ts, arrays, num_arrays, num_texture_units); diff --git a/hw/yagl_apis/gles2/yagl_gles2_program.c b/hw/yagl_apis/gles2/yagl_gles2_program.c index 6537e29..51fc1b4 100644 --- a/hw/yagl_apis/gles2/yagl_gles2_program.c +++ b/hw/yagl_apis/gles2/yagl_gles2_program.c @@ -2,6 +2,9 @@ #include "yagl_gles2_program.h" #include "yagl_gles2_shader.h" #include "yagl_gles2_driver.h" +#include "yagl_log.h" +#include "yagl_process.h" +#include "yagl_thread.h" static void yagl_gles2_program_destroy(struct yagl_ref *ref) { @@ -194,6 +197,96 @@ void yagl_gles2_program_validate(struct yagl_gles2_program *program) program->global_name); } +bool yagl_gles2_program_get_uniform_type(struct yagl_gles2_program *program, + GLint location, + GLenum *type) +{ + GLint link_status = GL_FALSE; + GLint i = 0, num_active_uniforms = 0; + GLint uniform_name_max_length = 0; + GLchar *uniform_name = NULL; + bool res = false; + + YAGL_LOG_FUNC_SET(0, 0, yagl_gles2_program_get_uniform_type); + + if (location < 0) { + return false; + } + + program->driver_ps->GetProgramiv(program->driver_ps, + program->global_name, + GL_LINK_STATUS, + &link_status); + + if (link_status == GL_FALSE) { + return false; + } + + program->driver_ps->GetProgramiv(program->driver_ps, + program->global_name, + GL_ACTIVE_UNIFORMS, + &num_active_uniforms); + + program->driver_ps->GetProgramiv(program->driver_ps, + program->global_name, + GL_ACTIVE_UNIFORM_MAX_LENGTH, + &uniform_name_max_length); + + uniform_name = g_malloc(uniform_name_max_length + 1); + + for (i = 0; i < num_active_uniforms; ++i) { + GLsizei length = 0; + GLint size = 0; + GLenum tmp_type = 0; + + program->driver_ps->GetActiveUniform(program->driver_ps, + program->global_name, + i, + uniform_name_max_length, + &length, + &size, + &tmp_type, + uniform_name); + + if (length == 0) { + YAGL_LOG_ERROR("Cannot get active uniform %d for program %d", i, program->global_name); + continue; + } + + if (program->driver_ps->GetUniformLocation(program->driver_ps, + program->global_name, + uniform_name) == location) { + *type = tmp_type; + res = true; + break; + } + } + + g_free(uniform_name); + + return res; +} + +void yagl_gles2_program_get_uniform_float(struct yagl_gles2_program *program, + GLint location, + GLfloat *params) +{ + program->driver_ps->GetUniformfv(program->driver_ps, + program->global_name, + location, + params); +} + +void yagl_gles2_program_get_uniform_int(struct yagl_gles2_program *program, + GLint location, + GLint *params) +{ + program->driver_ps->GetUniformiv(program->driver_ps, + program->global_name, + location, + params); +} + void yagl_gles2_program_acquire(struct yagl_gles2_program *program) { if (program) { diff --git a/hw/yagl_apis/gles2/yagl_gles2_program.h b/hw/yagl_apis/gles2/yagl_gles2_program.h index ccaca37..4bb0ef4 100644 --- a/hw/yagl_apis/gles2/yagl_gles2_program.h +++ b/hw/yagl_apis/gles2/yagl_gles2_program.h @@ -81,6 +81,18 @@ void yagl_gles2_program_get_info_log(struct yagl_gles2_program *program, void yagl_gles2_program_validate(struct yagl_gles2_program *program); +bool yagl_gles2_program_get_uniform_type(struct yagl_gles2_program *program, + GLint location, + GLenum *type); + +void yagl_gles2_program_get_uniform_float(struct yagl_gles2_program *program, + GLint location, + GLfloat *params); + +void yagl_gles2_program_get_uniform_int(struct yagl_gles2_program *program, + GLint location, + GLint *params); + /* * Passing NULL won't hurt, this is for convenience. */ diff --git a/hw/yagl_apis/gles2/yagl_gles2_validate.c b/hw/yagl_apis/gles2/yagl_gles2_validate.c index 8dc222c..454adc5 100644 --- a/hw/yagl_apis/gles2/yagl_gles2_validate.c +++ b/hw/yagl_apis/gles2/yagl_gles2_validate.c @@ -15,3 +15,28 @@ bool yagl_gles2_get_array_param_count(GLenum pname, int *count) } return true; } + +bool yagl_gles2_get_uniform_type_count(GLenum uniform_type, int *count) +{ + switch (uniform_type) { + case GL_FLOAT: *count = 1; break; + case GL_FLOAT_VEC2: *count = 2; break; + case GL_FLOAT_VEC3: *count = 3; break; + case GL_FLOAT_VEC4: *count = 4; break; + case GL_FLOAT_MAT2: *count = 2*2; break; + case GL_FLOAT_MAT3: *count = 3*3; break; + case GL_FLOAT_MAT4: *count = 4*4; break; + case GL_INT: *count = 1; break; + case GL_INT_VEC2: *count = 2; break; + case GL_INT_VEC3: *count = 3; break; + case GL_INT_VEC4: *count = 4; break; + case GL_BOOL: *count = 1; break; + case GL_BOOL_VEC2: *count = 2; break; + case GL_BOOL_VEC3: *count = 3; break; + case GL_BOOL_VEC4: *count = 4; break; + case GL_SAMPLER_2D: *count = 1; break; + case GL_SAMPLER_CUBE: *count = 1; break; + default: return false; + } + return true; +} diff --git a/hw/yagl_apis/gles2/yagl_gles2_validate.h b/hw/yagl_apis/gles2/yagl_gles2_validate.h index 8a26b3a..f51089c 100644 --- a/hw/yagl_apis/gles2/yagl_gles2_validate.h +++ b/hw/yagl_apis/gles2/yagl_gles2_validate.h @@ -5,4 +5,6 @@ bool yagl_gles2_get_array_param_count(GLenum pname, int *count); +bool yagl_gles2_get_uniform_type_count(GLenum uniform_type, int *count); + #endif diff --git a/hw/yagl_apis/gles2/yagl_host_gles2_calls.c b/hw/yagl_apis/gles2/yagl_host_gles2_calls.c index 240c10c..25ef824 100644 --- a/hw/yagl_apis/gles2/yagl_host_gles2_calls.c +++ b/hw/yagl_apis/gles2/yagl_host_gles2_calls.c @@ -1587,24 +1587,110 @@ out: bool yagl_host_glGetUniformfv(GLuint program, GLint location, - target_ulong /* GLfloat* */ params) + target_ulong /* GLfloat* */ params_) { - /* - * Currently I don't see how to implement this nicely... - */ + bool res = true; + struct yagl_gles2_program *program_obj = NULL; + GLenum type; + int count; + GLfloat params[100]; /* This fits all cases */ + + YAGL_GET_CTX(glGetUniformfv); + + program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg, + YAGL_NS_SHADER_PROGRAM, program); + + if (!program_obj) { + YAGL_SET_ERR(GL_INVALID_VALUE); + goto out; + } + + if (program_obj->is_shader) { + YAGL_SET_ERR(GL_INVALID_OPERATION); + goto out; + } - YAGL_UNIMPLEMENTED(glGetUniformfv); + if (!yagl_gles2_program_get_uniform_type(program_obj, + location, + &type)) { + YAGL_SET_ERR(GL_INVALID_OPERATION); + goto out; + } + + if (!yagl_gles2_get_uniform_type_count(type, &count)) { + YAGL_SET_ERR(GL_INVALID_OPERATION); + goto out; + } + + if (!yagl_mem_prepare(gles2_api_ts->ts->mt1, params_, count * sizeof(params[0]))) { + res = false; + goto out; + } + + yagl_gles2_program_get_uniform_float(program_obj, location, ¶ms[0]); + + if (params_) { + yagl_mem_put(gles2_api_ts->ts->mt1, ¶ms[0]); + } + +out: + yagl_gles2_program_release(program_obj); + + return res; } bool yagl_host_glGetUniformiv(GLuint program, GLint location, - target_ulong /* GLint* */ params) + target_ulong /* GLint* */ params_) { - /* - * Currently I don't see how to implement this nicely... - */ + bool res = true; + struct yagl_gles2_program *program_obj = NULL; + GLenum type; + int count; + GLint params[100]; /* This fits all cases */ + + YAGL_GET_CTX(glGetUniformiv); + + program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg, + YAGL_NS_SHADER_PROGRAM, program); + + if (!program_obj) { + YAGL_SET_ERR(GL_INVALID_VALUE); + goto out; + } + + if (program_obj->is_shader) { + YAGL_SET_ERR(GL_INVALID_OPERATION); + goto out; + } - YAGL_UNIMPLEMENTED(glGetUniformiv); + if (!yagl_gles2_program_get_uniform_type(program_obj, + location, + &type)) { + YAGL_SET_ERR(GL_INVALID_OPERATION); + goto out; + } + + if (!yagl_gles2_get_uniform_type_count(type, &count)) { + YAGL_SET_ERR(GL_INVALID_OPERATION); + goto out; + } + + if (!yagl_mem_prepare(gles2_api_ts->ts->mt1, params_, count * sizeof(params[0]))) { + res = false; + goto out; + } + + yagl_gles2_program_get_uniform_int(program_obj, location, ¶ms[0]); + + if (params_) { + yagl_mem_put(gles2_api_ts->ts->mt1, ¶ms[0]); + } + +out: + yagl_gles2_program_release(program_obj); + + return res; } bool yagl_host_glGetUniformLocation(int* retval, diff --git a/hw/yagl_apis/gles2/yagl_host_gles2_calls.h b/hw/yagl_apis/gles2/yagl_host_gles2_calls.h index 404f730..b7c09c5 100644 --- a/hw/yagl_apis/gles2/yagl_host_gles2_calls.h +++ b/hw/yagl_apis/gles2/yagl_host_gles2_calls.h @@ -111,10 +111,10 @@ bool yagl_host_glGetShaderSource(GLuint shader, target_ulong /* GLchar* */ source_); bool yagl_host_glGetUniformfv(GLuint program, GLint location, - target_ulong /* GLfloat* */ params); + target_ulong /* GLfloat* */ params_); bool yagl_host_glGetUniformiv(GLuint program, GLint location, - target_ulong /* GLint* */ params); + target_ulong /* GLint* */ params_); bool yagl_host_glGetUniformLocation(int* retval, GLuint program, target_ulong /* const GLchar* */ name_); -- 2.7.4