YaGL: Fix for khronos GLESv2 test: glGetUniform implemented appropriately
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Wed, 7 Nov 2012 13:44:12 +0000 (17:44 +0400)
committerEvgeny Voevodin <e.voevodin@samsung.com>
Mon, 26 Nov 2012 09:25:32 +0000 (13:25 +0400)
YaGL: Fix for khronos GLESv2 test: number of texture units limited to 32

hw/yagl_apis/gles2/yagl_gles2_context.c
hw/yagl_apis/gles2/yagl_gles2_program.c
hw/yagl_apis/gles2/yagl_gles2_program.h
hw/yagl_apis/gles2/yagl_gles2_validate.c
hw/yagl_apis/gles2/yagl_gles2_validate.h
hw/yagl_apis/gles2/yagl_host_gles2_calls.c
hw/yagl_apis/gles2/yagl_host_gles2_calls.h

index 6405291..d57ba73 100644 (file)
@@ -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);
 
index 6537e29..51fc1b4 100644 (file)
@@ -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) {
index ccaca37..4bb0ef4 100644 (file)
@@ -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.
  */
index 8dc222c..454adc5 100644 (file)
@@ -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;
+}
index 8a26b3a..f51089c 100644 (file)
@@ -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
index 240c10c..25ef824 100644 (file)
@@ -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, &params[0]);
+
+    if (params_) {
+        yagl_mem_put(gles2_api_ts->ts->mt1, &params[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, &params[0]);
+
+    if (params_) {
+        yagl_mem_put(gles2_api_ts->ts->mt1, &params[0]);
+    }
+
+out:
+    yagl_gles2_program_release(program_obj);
+
+    return res;
 }
 
 bool yagl_host_glGetUniformLocation(int* retval,
index 404f730..b7c09c5 100644 (file)
@@ -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_);