Browse Source

added initial GL shader code

jp9000 12 years ago
parent
commit
fda2ee1147

+ 292 - 0
libobs-opengl/gl-shader.c

@@ -0,0 +1,292 @@
+/******************************************************************************
+    Copyright (C) 2013 by Hugh Bailey <[email protected]>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+#include <assert.h>
+#include "gl-subsystem.h"
+#include "gl-shaderparser.h"
+
+static inline void shader_param_init(struct shader_param *param)
+{
+	memset(param, 0, sizeof(struct shader_param));
+}
+
+
+static inline void shader_param_free(struct shader_param *param)
+{
+	bfree(param->name);
+	da_free(param->cur_value);
+	da_free(param->def_value);
+}
+
+static void gl_get_program_info(GLuint program, char **error_string)
+{
+	char    *errors;
+	GLint   info_len = 0;
+	GLsizei chars_written = 0;
+
+	glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_len);
+	if (!gl_success("glGetProgramiv") || !info_len)
+		return;
+
+	errors = bmalloc(info_len+1);
+	memset(errors, 0, info_len+1);
+	glGetProgramInfoLog(program, info_len, &chars_written, errors);
+
+	*error_string = errors;
+}
+
+static bool gl_add_param(struct gs_shader *shader, struct shader_var *var,
+		GLint *texture_id)
+{
+	struct shader_param param = {0};
+
+	param.array_count = var->array_count;
+	param.name        = bstrdup(var->name);
+	param.type        = get_shader_param_type(var->type);
+
+	if (param.type == SHADER_PARAM_TEXTURE) {
+		param.sampler_id  = var->gl_sampler_id;
+		param.texture_id  = (*texture_id)++;
+	} else {
+		param.changed = true;
+	}
+
+	da_move(param.def_value, var->default_val);
+	da_copy(param.cur_value, param.def_value);
+
+	param.param = glGetUniformLocation(shader->program, param.name);
+	if (!gl_success("glGetUniformLocation"))
+		return false;
+
+	return true;
+}
+
+static inline bool gl_add_params(struct gs_shader *shader,
+		struct gl_shader_parser *glsp)
+{
+	size_t i;
+	GLint tex_id = 0;
+
+	for (i = 0; i < glsp->parser.params.num; i++)
+		if (!gl_add_param(shader, glsp->parser.params.array+i, &tex_id))
+			return false;
+
+	return true;
+}
+
+static void gl_add_sampler(struct gs_shader *shader,
+		struct shader_sampler *sampler)
+{
+	struct gs_sampler new_sampler = {0};
+	struct gs_sampler_info info;
+
+	shader_sampler_convert(sampler, &info);
+	convert_sampler_info(&new_sampler, &info);
+	da_push_back(shader->samplers, &new_sampler);
+}
+
+static inline void gl_add_samplers(struct gs_shader *shader,
+		struct gl_shader_parser *glsp)
+{
+	size_t i;
+
+	for (i = 0; i < glsp->parser.samplers.num; i++) {
+		struct shader_sampler *sampler = glsp->parser.samplers.array+i;
+		gl_add_sampler(shader, sampler);
+	}
+}
+
+static bool gl_shader_init(struct gs_shader *shader,
+		struct gl_shader_parser *glsp,
+		const char *file, char **error_string)
+{
+	GLenum type = convert_shader_type(shader->type);
+	int compiled = 0;
+	bool success = true;
+
+	shader->program = glCreateShaderProgramv(type, 1,
+			&glsp->gl_string.array);
+	gl_success("glCreateShaderProgramv");
+	if (!shader->program)
+		return false;
+
+	glGetProgramiv(shader->program, GL_VALIDATE_STATUS, &compiled);
+	if (!gl_success("glGetProgramiv"))
+		return false;
+
+	if (!compiled)
+		success = false;
+
+	gl_get_program_info(shader->program, error_string);
+
+	if (success)
+		success = gl_add_params(shader, glsp);
+	if (success)
+		gl_add_samplers(shader, glsp);
+
+	return success;
+}
+
+static struct gs_shader *shader_create(device_t device, enum shader_type type,
+		const char *shader_str, const char *file, char **error_string)
+{
+	struct gs_shader *shader = bmalloc(sizeof(struct gs_shader));
+	struct gl_shader_parser glsp;
+	bool success = true;
+
+	memset(shader, 0, sizeof(struct gs_shader));
+	shader->type = type;
+
+	gl_shader_parser_init(&glsp);
+	if (!gl_shader_parse(&glsp, shader_str, file))
+		success = false;
+	else
+		success = gl_shader_init(shader, &glsp, file, error_string);
+
+	if (!success) {
+		shader_destroy(shader);
+		shader = NULL;
+	}
+
+	gl_shader_parser_free(&glsp);
+	return shader;
+}
+
+shader_t device_create_vertexshader(device_t device,
+		const char *shader, const char *file,
+		char **error_string)
+{
+	return shader_create(device, SHADER_VERTEX, shader, file, error_string);
+}
+
+shader_t device_create_pixelshader(device_t device,
+		const char *shader, const char *file,
+		char **error_string)
+{
+	return shader_create(device, SHADER_PIXEL, shader, file, error_string);
+}
+
+void shader_destroy(shader_t shader)
+{
+	size_t i;
+
+	if (!shader)
+		return;
+
+	for (i = 0; i < shader->params.num; i++)
+		shader_param_free(shader->params.array+i);
+
+	if (shader->program) {
+		glDeleteProgram(shader->program);
+		gl_success("glDeleteProgram");
+	}
+
+	da_free(shader->samplers);
+	da_free(shader->params);
+	bfree(shader);
+}
+
+int shader_numparams(shader_t shader)
+{
+	return (int)shader->params.num;
+}
+
+sparam_t shader_getparambyidx(shader_t shader, int param)
+{
+	assert(param < shader->params.num);
+	return shader->params.array+param;
+}
+
+sparam_t shader_getparambyname(shader_t shader, const char *name)
+{
+	size_t i;
+	for (i = 0; i < shader->params.num; i++) {
+		struct shader_param *param = shader->params.array+i;
+
+		if (strcmp(param->name, name) == 0)
+			return param;
+	}
+
+	return NULL;
+}
+
+void shader_getparaminfo(shader_t shader, sparam_t param,
+		struct shader_param_info *info)
+{
+	info->type = param->type;
+	info->name = param->name;
+}
+
+sparam_t shader_getviewprojmatrix(shader_t shader)
+{
+	return shader->viewproj;
+}
+
+sparam_t shader_getworldmatrix(shader_t shader)
+{
+	return shader->world;
+}
+
+void shader_setbool(shader_t shader, sparam_t param, bool val)
+{
+}
+
+void shader_setfloat(shader_t shader, sparam_t param, float val)
+{
+}
+
+void shader_setint(shader_t shader, sparam_t param, int val)
+{
+}
+
+void shader_setmatrix3(shader_t shader, sparam_t param,
+		const struct matrix3 *val)
+{
+}
+
+void shader_setmatrix4(shader_t shader, sparam_t param,
+		const struct matrix4 *val)
+{
+}
+
+void shader_setvec2(shader_t shader, sparam_t param,
+		const struct vec2 *val)
+{
+}
+
+void shader_setvec3(shader_t shader, sparam_t param,
+		const struct vec3 *val)
+{
+}
+
+void shader_setvec4(shader_t shader, sparam_t param,
+		const struct vec4 *val)
+{
+}
+
+void shader_settexture(shader_t shader, sparam_t param, texture_t val)
+{
+}
+
+void shader_setval(shader_t shader, sparam_t param, const void *val,
+		size_t size)
+{
+}
+
+void shader_setdefault(shader_t shader, sparam_t param)
+{
+}

+ 36 - 15
libobs-opengl/gl-shaderparser.c

@@ -21,6 +21,32 @@
 static void gl_write_function_contents(struct gl_shader_parser *glsp,
 		struct cf_token **p_token, const char *end);
 
+static inline struct shader_var *sp_getparam(struct gl_shader_parser *glsp,
+		struct cf_token *token)
+{
+	size_t i;
+	for (i = 0; i < glsp->parser.params.num; i++) {
+		struct shader_var *param = glsp->parser.params.array+i;
+		if (strref_cmp(&token->str, param->name) == 0)
+			return param;
+	}
+
+	return NULL;
+}
+
+static inline size_t sp_getsampler(struct gl_shader_parser *glsp,
+		struct cf_token *token)
+{
+	size_t i;
+	for (i = 0; i < glsp->parser.samplers.num; i++) {
+		struct shader_sampler *sampler = glsp->parser.samplers.array+i;
+		if (strref_cmp(&token->str, sampler->name) == 0)
+			return i;
+	}
+
+	return -1;
+}
+
 static bool gl_write_type_n(struct gl_shader_parser *glsp,
 		const char *type, size_t len)
 {
@@ -251,8 +277,16 @@ static inline bool gl_write_texture_call(struct gl_shader_parser *glsp,
 		struct shader_var *var, const char *call)
 {
 	struct cf_parser *cfp = &glsp->parser.cfp;
-	if (!go_to_token(cfp, ",", NULL))
-		return false;
+	size_t sampler_id = -1;
+
+	if (!next_token(cfp))    return false;
+	if (!token_is(cfp, "(")) return false;
+	if (!next_token(cfp))    return false;
+
+	sampler_id = sp_getsampler(glsp, cfp->cur_token);
+	if (sampler_id == -1) return false;
+
+	var->gl_sampler_id = sampler_id;
 
 	dstr_cat(&glsp->gl_string, call);
 	dstr_cat(&glsp->gl_string, "(");
@@ -294,19 +328,6 @@ static bool gl_write_texture_code(struct gl_shader_parser *glsp,
 	return true;
 }
 
-static inline struct shader_var *sp_getparam(struct gl_shader_parser *glsp,
-		struct cf_token *token)
-{
-	size_t i;
-	for (i = 0; i < glsp->parser.params.num; i++) {
-		struct shader_var *param = glsp->parser.params.array+i;
-		if (strref_cmp(&token->str, param->name) == 0)
-			return param;
-	}
-
-	return NULL;
-}
-
 static bool gl_write_intrinsic(struct gl_shader_parser *glsp,
 		struct cf_token **p_token)
 {

+ 2 - 0
libobs-opengl/gl-shaderparser.h

@@ -30,6 +30,8 @@
 struct gl_shader_parser {
 	struct dstr          gl_string;
 	struct shader_parser parser;
+
+	DARRAY(uint32_t)     texture_samplers;
 };
 
 static inline void gl_shader_parser_init(struct gl_shader_parser *glsp)

+ 11 - 91
libobs-opengl/gl-subsystem.c

@@ -17,6 +17,17 @@
 
 #include "gl-subsystem.h"
 
+void convert_sampler_info(struct gs_sampler *sampler,
+		struct gs_sampler_info *info)
+{
+	convert_filter(info->filter, &sampler->min_filter,
+			&sampler->mag_filter);
+	sampler->address_u      = convert_address_mode(info->address_u);
+	sampler->address_v      = convert_address_mode(info->address_v);
+	sampler->address_w      = convert_address_mode(info->address_w);
+	sampler->max_anisotropy = info->max_anisotropy;
+}
+
 device_t device_create(struct gs_init_data *info)
 {
 	struct gs_device *device = bmalloc(sizeof(struct gs_device));
@@ -104,18 +115,6 @@ samplerstate_t device_create_samplerstate(device_t device,
 {
 }
 
-shader_t device_create_vertexshader(device_t device,
-		const char *shader, const char *file,
-		char **error_string)
-{
-}
-
-shader_t device_create_pixelshader(device_t device,
-		const char *shader, const char *file,
-		char **error_string)
-{
-}
-
 vertbuffer_t device_create_vertexbuffer(device_t device,
 		struct vb_data *data, uint32_t flags)
 {
@@ -433,82 +432,3 @@ size_t indexbuffer_numindices(indexbuffer_t indexbuffer)
 enum gs_index_type indexbuffer_gettype(indexbuffer_t indexbuffer)
 {
 }
-
-void shader_destroy(shader_t shader)
-{
-}
-
-int shader_numparams(shader_t shader)
-{
-}
-
-sparam_t shader_getparambyidx(shader_t shader, int param)
-{
-}
-
-sparam_t shader_getparambyname(shader_t shader, const char *name)
-{
-}
-
-void shader_getparaminfo(shader_t shader, sparam_t param,
-		struct shader_param_info *info)
-{
-}
-
-sparam_t shader_getviewprojmatrix(shader_t shader)
-{
-}
-
-sparam_t shader_getworldmatrix(shader_t shader)
-{
-}
-
-void shader_setbool(shader_t shader, sparam_t param, bool val)
-{
-}
-
-void shader_setfloat(shader_t shader, sparam_t param, float val)
-{
-}
-
-void shader_setint(shader_t shader, sparam_t param, int val)
-{
-}
-
-void shader_setmatrix3(shader_t shader, sparam_t param,
-		const struct matrix3 *val)
-{
-}
-
-void shader_setmatrix4(shader_t shader, sparam_t param,
-		const struct matrix4 *val)
-{
-}
-
-void shader_setvec2(shader_t shader, sparam_t param,
-		const struct vec2 *val)
-{
-}
-
-void shader_setvec3(shader_t shader, sparam_t param,
-		const struct vec3 *val)
-{
-}
-
-void shader_setvec4(shader_t shader, sparam_t param,
-		const struct vec4 *val)
-{
-}
-
-void shader_settexture(shader_t shader, sparam_t param, texture_t val)
-{
-}
-
-void shader_setval(shader_t shader, sparam_t param, const void *val,
-		size_t size)
-{
-}
-
-void shader_setdefault(shader_t shader, sparam_t param)
-{
-}

+ 103 - 0
libobs-opengl/gl-subsystem.h

@@ -18,6 +18,7 @@
 #ifndef GL_SUBSYSTEM_H
 #define GL_SUBSYSTEM_H
 
+#include "util/darray.h"
 #include "graphics/graphics.h"
 #include "glew/include/GL/glew.h"
 #include "gl-helpers.h"
@@ -85,6 +86,108 @@ static inline GLint convert_zstencil_format(enum gs_zstencil_format format)
 	}
 }
 
+static inline GLenum convert_shader_type(enum shader_type type)
+{
+	switch (type) {
+	default:
+	case SHADER_VERTEX: return GL_VERTEX_SHADER;
+	case SHADER_PIXEL:  return GL_FRAGMENT_SHADER;
+	}
+}
+
+static inline void convert_filter(enum gs_sample_filter filter,
+		GLint *min_filter, GLint *mag_filter)
+{
+	switch (filter) {
+	case GS_FILTER_ANISOTROPIC:
+		*min_filter = GL_LINEAR_MIPMAP_LINEAR;
+		*mag_filter = GL_LINEAR;
+		break;
+	default:
+	case GS_FILTER_POINT:
+		*min_filter = GL_NEAREST_MIPMAP_NEAREST;
+		*mag_filter = GL_NEAREST;
+		break;
+	case GS_FILTER_LINEAR:
+		*min_filter = GL_LINEAR_MIPMAP_LINEAR;
+		*mag_filter = GL_LINEAR;
+		break;
+	case GS_FILTER_MIN_MAG_POINT_MIP_LINEAR:
+		*min_filter = GL_NEAREST_MIPMAP_LINEAR;
+		*mag_filter = GL_NEAREST;
+		break;
+	case GS_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT:
+		*min_filter = GL_NEAREST_MIPMAP_NEAREST;
+		*mag_filter = GL_LINEAR;
+		break;
+	case GS_FILTER_MIN_POINT_MAG_MIP_LINEAR:
+		*min_filter = GL_NEAREST_MIPMAP_LINEAR;
+		*mag_filter = GL_LINEAR;
+		break;
+	case GS_FILTER_MIN_LINEAR_MAG_MIP_POINT:
+		*min_filter = GL_LINEAR_MIPMAP_NEAREST;
+		*mag_filter = GL_NEAREST;
+		break;
+	case GS_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR:
+		*min_filter = GL_LINEAR_MIPMAP_LINEAR;
+		*mag_filter = GL_NEAREST;
+		break;
+	case GS_FILTER_MIN_MAG_LINEAR_MIP_POINT:
+		*min_filter = GL_LINEAR_MIPMAP_NEAREST;
+		*mag_filter = GL_LINEAR;
+		break;
+	}
+}
+
+static inline GLint convert_address_mode(enum gs_address_mode mode)
+{
+	switch (mode) {
+	default:
+	case GS_ADDRESS_WRAP:       return GL_REPEAT;
+	case GS_ADDRESS_CLAMP:      return GL_CLAMP;
+	case GS_ADDRESS_MIRROR:     return GL_MIRRORED_REPEAT;
+	case GS_ADDRESS_BORDER:     return GL_CLAMP_TO_BORDER;
+	case GS_ADDRESS_MIRRORONCE: return GL_MIRROR_CLAMP_EXT;
+	}
+}
+
+extern void convert_sampler_info(struct gs_sampler *sampler,
+		struct gs_sampler_info *info);
+
+struct gs_sampler {
+	GLint min_filter;
+	GLint mag_filter;
+	GLint address_u;
+	GLint address_v;
+	GLint address_w;
+	GLint max_anisotropy;
+};
+
+struct shader_param {
+	char                   *name;
+	enum shader_param_type type;
+	GLint                  param;
+	GLint                  texture_id;
+	size_t                 sampler_id;
+	int                    array_count;
+
+	DARRAY(uint8_t)        cur_value;
+	DARRAY(uint8_t)        def_value;
+	bool                   changed;
+};
+
+struct gs_shader {
+	device_t         device;
+	enum shader_type type;
+	GLuint           program;
+
+	struct shader_param *viewproj;
+	struct shader_param *world;
+
+	DARRAY(struct gs_sampler)   samplers;
+	DARRAY(struct shader_param) params;
+};
+
 struct gs_texture {
 	device_t             device;
 	enum gs_texture_type type;

+ 1 - 0
libobs/graphics/shader-parser.h

@@ -49,6 +49,7 @@ struct shader_var {
 	char *mapping;
 	enum shader_var_type var_type;
 	int array_count;
+	size_t gl_sampler_id; /* optional: used/parsed by GL */
 
 	DARRAY(uint8_t) default_val;
 };

+ 1 - 0
vs/2010/libobs-opengl/libobs-opengl.vcxproj

@@ -162,6 +162,7 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\libobs-opengl\gl-helpers.c" />
+    <ClCompile Include="..\..\..\libobs-opengl\gl-shader.c" />
     <ClCompile Include="..\..\..\libobs-opengl\gl-shaderparser.c" />
     <ClCompile Include="..\..\..\libobs-opengl\gl-subsystem.c" />
     <ClCompile Include="..\..\..\libobs-opengl\gl-texture2d.c" />

+ 3 - 0
vs/2010/libobs-opengl/libobs-opengl.vcxproj.filters

@@ -47,5 +47,8 @@
     <ClCompile Include="..\..\..\libobs-opengl\gl-shaderparser.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\libobs-opengl\gl-shader.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>