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;
}
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;
}
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;
}
&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);
#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)
{
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) {
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.
*/
}
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;
+}
bool yagl_gles2_get_array_param_count(GLenum pname, int *count);
+bool yagl_gles2_get_uniform_type_count(GLenum uniform_type, int *count);
+
#endif
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,
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_);