Example #1
0
static bool load_vb_buffer(struct shader_attrib *attrib,
                           struct gs_vertex_buffer *vb, GLint id)
{
    GLenum type;
    GLint width;
    GLuint buffer;
    bool success = true;

    buffer = get_vb_buffer(vb, attrib->type, attrib->index, &width, &type);
    if (!buffer) {
        blog(LOG_ERROR, "Vertex buffer does not have the required "
             "inputs for vertex shader");
        return false;
    }

    if (!gl_bind_buffer(GL_ARRAY_BUFFER, buffer))
        return false;

    glVertexAttribPointer(id, width, type, GL_TRUE, 0, 0);
    if (!gl_success("glVertexAttribPointer"))
        success = false;

    glEnableVertexAttribArray(id);
    if (!gl_success("glEnableVertexAttribArray"))
        success = false;

    if (!gl_bind_buffer(GL_ARRAY_BUFFER, 0))
        success = false;

    return success;
}
Example #2
0
device_t device_create(struct gs_init_data *info)
{
	struct gs_device *device = bmalloc(sizeof(struct gs_device));
	memset(device, 0, sizeof(struct gs_device));

	device->plat = gl_platform_create(device, info);
	if (!device->plat)
		goto fail;

	if (!gl_init_extensions(device))
		goto fail;
	
	gl_enable(GL_CULL_FACE);
	
	glGenProgramPipelines(1, &device->pipeline);
	if (!gl_success("glGenProgramPipelines"))
		goto fail;

	glBindProgramPipeline(device->pipeline);
	if (!gl_success("glBindProgramPipeline"))
		goto fail;

	device_leavecontext(device);
	device->cur_swap = gl_platform_getswap(device->plat);

	return device;

fail:
	blog(LOG_ERROR, "device_create (GL) failed");
	bfree(device);
	return NULL;
}
Example #3
0
device_t device_create(struct gs_init_data *info)
{
	struct gs_device *device = bmalloc(sizeof(struct gs_device));
	memset(device, 0, sizeof(struct gs_device));

	device->plat = gl_platform_create(device, info);
	if (!device->plat)
		goto fail;

	glGenProgramPipelines(1, &device->pipeline);
	if (!gl_success("glGenProgramPipelines"))
		goto fail;

	glBindProgramPipeline(device->pipeline);
	if (!gl_success("glBindProgramPipeline"))
		goto fail;

#ifdef _DEBUG
	glEnable(GL_DEBUG_OUTPUT);
	if (glGetError() == GL_INVALID_ENUM)
		blog(LOG_DEBUG, "OpenGL debug information not available");
#endif

	gl_enable(GL_CULL_FACE);

	device_leavecontext(device);
	device->cur_swap = gl_platform_getswap(device->plat);

	return device;

fail:
	blog(LOG_ERROR, "device_create (GL) failed");
	bfree(device);
	return NULL;
}
void device_draw(gs_device_t *device, enum gs_draw_mode draw_mode,
		uint32_t start_vert, uint32_t num_verts)
{
	struct gs_index_buffer *ib = device->cur_index_buffer;
	GLenum  topology = convert_gs_topology(draw_mode);
	gs_effect_t *effect = gs_get_effect();
	struct gs_program *program;

	if (!can_render(device))
		goto fail;

	if (effect)
		gs_effect_update_params(effect);

	program = get_shader_program(device);
	if (!program)
		goto fail;

	load_vb_buffers(program, device->cur_vertex_buffer);

	if (program != device->cur_program && device->cur_program) {
		glUseProgram(0);
		gl_success("glUseProgram (zero)");
	}

	if (program != device->cur_program) {
		device->cur_program = program;

		glUseProgram(program->obj);
		if (!gl_success("glUseProgram"))
			goto fail;
	}

	update_viewproj_matrix(device);

	program_update_params(program);

	if (ib) {
		if (num_verts == 0)
			num_verts = (uint32_t)device->cur_index_buffer->num;
		glDrawElements(topology, num_verts, ib->gl_type,
				(const GLvoid*)(start_vert * ib->width));
		if (!gl_success("glDrawElements"))
			goto fail;

	} else {
		if (num_verts == 0)
			num_verts = (uint32_t)device->cur_vertex_buffer->num;
		glDrawArrays(topology, start_vert, num_verts);
		if (!gl_success("glDrawArrays"))
			goto fail;
	}

	return;

fail:
	blog(LOG_ERROR, "device_draw (GL) failed");
}
Example #5
0
struct gl_platform *gl_platform_create(device_t device,
		struct gs_init_data *info)
{
	struct gl_platform *plat = bmalloc(sizeof(struct gl_platform));
	struct dummy_context dummy;
	int pixel_format;
	PIXELFORMATDESCRIPTOR pfd;

	memset(plat, 0, sizeof(struct gl_platform));
	memset(&dummy, 0, sizeof(struct dummy_context));

	if (!gl_dummy_context_init(&dummy))
		goto fail;
	if (!gl_init_extensions(device))
		goto fail;

	/* you have to have a dummy context open before you can actually
	 * use wglChoosePixelFormatARB */
	if (!gl_getpixelformat(dummy.hdc, info, &pixel_format, &pfd))
		goto fail;

	gl_dummy_context_free(&dummy);

	if (!init_default_swap(plat, device, pixel_format, &pfd, info))
		goto fail;

	plat->hrc = gl_init_context(plat->swap.wi->hdc);
	if (!plat->hrc)
		goto fail;

	if (GLEW_ARB_seamless_cube_map) {
		glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
		gl_success("GL_TEXTURE_CUBE_MAP_SEAMLESS");
	}

#ifdef _DEBUG
	if (GLEW_AMD_debug_output) {
		glDebugMessageEnableAMD(0, 0, 0, NULL, true);
		glDebugMessageCallbackAMD(gl_debug_message_amd, device);
		gl_success("glDebugMessageCallback");
	}
#endif

	return plat;

fail:
	blog(LOG_ERROR, "gl_platform_create failed");
	gl_platform_destroy(plat);
	gl_dummy_context_free(&dummy);
	return NULL;
}
Example #6
0
void shader_setfloat(shader_t shader, sparam_t param, float val)
{
	if (matching_shader(shader, param)) {
		glProgramUniform1f(shader->program, param->param, val);
		gl_success("glProgramUniform1f");
	}
}
Example #7
0
void shader_setbool(shader_t shader, sparam_t param, bool val)
{
	if (matching_shader(shader, param)) {
		glProgramUniform1i(shader->program, param->param, (GLint)val);
		gl_success("glProgramUniform1i");
	}
}
static void update_viewproj_matrix(struct gs_device *device)
{
	struct gs_shader *vs = device->cur_vertex_shader;
	struct matrix4 cur_proj;

	gs_matrix_get(&device->cur_view);
	matrix4_copy(&cur_proj, &device->cur_proj);

	if (device->cur_fbo) {
		cur_proj.x.y = -cur_proj.x.y;
		cur_proj.y.y = -cur_proj.y.y;
		cur_proj.z.y = -cur_proj.z.y;
		cur_proj.t.y = -cur_proj.t.y;

		glFrontFace(GL_CW);
	} else {
		glFrontFace(GL_CCW);
	}

	gl_success("glFrontFace");

	matrix4_mul(&device->cur_viewproj, &device->cur_view, &cur_proj);
	matrix4_transpose(&device->cur_viewproj, &device->cur_viewproj);

	if (vs->viewproj)
		gs_shader_set_matrix4(vs->viewproj, &device->cur_viewproj);
}
Example #9
0
void device_stage_texture(device_t device, stagesurf_t dst, texture_t src)
{
	struct gs_texture_2d *tex2d = (struct gs_texture_2d*)src;
	if (!can_stage(dst, tex2d))
		goto failed;

	if (!gl_copy_texture(device, dst->texture, GL_TEXTURE_2D,
				tex2d->base.texture, GL_TEXTURE_2D,
				dst->width, dst->height))
		goto failed;

	if (!gl_bind_texture(GL_TEXTURE_2D, dst->texture))
		goto failed;
	if (!gl_bind_buffer(GL_PIXEL_PACK_BUFFER, dst->pack_buffer))
		goto failed;

	glGetTexImage(GL_TEXTURE_2D, 0, dst->gl_format, dst->gl_type, 0);
	if (!gl_success("glGetTexImage"))
		goto failed;

	gl_bind_buffer(GL_PIXEL_PACK_BUFFER, 0);
	gl_bind_texture(GL_TEXTURE_2D, 0);
	return;

failed:
	gl_bind_buffer(GL_PIXEL_PACK_BUFFER, 0);
	gl_bind_texture(GL_TEXTURE_2D, 0);
	blog(LOG_ERROR, "device_stage_texture (GL) failed");
}
Example #10
0
void device_setscissorrect(device_t device, struct gs_rect *rect)
{
	UNUSED_PARAMETER(device);
	glScissor(rect->x, rect->y, rect->cx, rect->cy);
	if (!gl_success("glScissor"))
		blog(LOG_ERROR, "device_setscissorrect (GL) failed");
}
Example #11
0
void shader_setint(shader_t shader, sparam_t param, int val)
{
	if (matching_shader(shader, param)) {
		glProgramUniform1i(shader->program, param->param, val);
		gl_success("glProgramUniform1i");
	}
}
Example #12
0
static bool attach_rendertarget(struct fbo_info *fbo, gs_texture_t tex,
		int side)
{
	if (fbo->cur_render_target == tex)
		return true;

	fbo->cur_render_target = tex;

	if (tex->type == GS_TEXTURE_2D) {
		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
				GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
				tex->texture, 0);

	} else if (tex->type == GS_TEXTURE_CUBE) {
		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
				GL_COLOR_ATTACHMENT0,
				GL_TEXTURE_CUBE_MAP_POSITIVE_X + side,
				tex->texture, 0);

	} else {
		return false;
	}

	return gl_success("glFramebufferTexture2D");
}
Example #13
0
void device_load_pixelshader(device_t device, shader_t pixelshader)
{
	GLuint program = 0;
	if (device->cur_pixel_shader == pixelshader)
		return;

	if (pixelshader && pixelshader->type != SHADER_PIXEL) {
		blog(LOG_ERROR, "Specified shader is not a pixel shader");
		goto fail;
	}

	device->cur_pixel_shader = pixelshader;

	if (pixelshader)
		program = pixelshader->program;

	glUseProgramStages(device->pipeline, GL_FRAGMENT_SHADER_BIT, program);
	if (!gl_success("glUseProgramStages"))
		goto fail;

	clear_textures(device);

	if (pixelshader)
		load_default_pixelshader_samplers(device, pixelshader);
	return;

fail:
	blog(LOG_ERROR, "device_load_pixelshader (GL) failed");
}
Example #14
0
void device_clear(gs_device_t device, uint32_t clear_flags,
		struct vec4 *color, float depth, uint8_t stencil)
{
	GLbitfield gl_flags = 0;

	if (clear_flags & GS_CLEAR_COLOR) {
		glClearColor(color->x, color->y, color->z, color->w);
		gl_flags |= GL_COLOR_BUFFER_BIT;
	}

	if (clear_flags & GS_CLEAR_DEPTH) {
		glClearDepth(depth);
		gl_flags |= GL_DEPTH_BUFFER_BIT;
	}

	if (clear_flags & GS_CLEAR_STENCIL) {
		glClearStencil(stencil);
		gl_flags |= GL_STENCIL_BUFFER_BIT;
	}

	glClear(gl_flags);
	if (!gl_success("glClear"))
		blog(LOG_ERROR, "device_clear (GL) failed");

	UNUSED_PARAMETER(device);
}
Example #15
0
/*
 * This automatically manages FBOs so that render targets are always given
 * an FBO that matches their width/height/format to maximize optimization
 */
static struct fbo_info *get_fbo(struct gs_device *device, texture_t tex)
{
	size_t i;
	uint32_t width, height;
	GLuint fbo;
	struct fbo_info *ptr;

	if (!get_tex_dimensions(tex, &width, &height))
		return NULL;

	for (i = 0; i < device->fbos.num; i++) {
		ptr = device->fbos.array[i];

		if (ptr->width  == width && ptr->height == height &&
		    ptr->format == tex->format)
			return ptr;
	}

	glGenFramebuffers(1, &fbo);
	if (!gl_success("glGenFramebuffers"))
		return NULL;

	ptr = bmalloc(sizeof(struct fbo_info));
	ptr->fbo                 = fbo;
	ptr->width               = width;
	ptr->height              = height;
	ptr->format              = tex->format;
	ptr->cur_render_target   = NULL;
	ptr->cur_render_side     = 0;
	ptr->cur_zstencil_buffer = NULL;

	da_push_back(device->fbos, &ptr);
	return ptr;
}
Example #16
0
/*
 * This automatically manages FBOs so that render targets are always given
 * an FBO that matches their width/height/format to maximize optimization
 */
struct fbo_info *get_fbo(struct gs_device *device,
		uint32_t width, uint32_t height, enum gs_color_format format)
{
	size_t i;
	GLuint fbo;
	struct fbo_info *ptr;

	for (i = 0; i < device->fbos.num; i++) {
		ptr = device->fbos.array[i];

		if (ptr->width  == width && ptr->height == height &&
		    ptr->format == format)
			return ptr;
	}

	glGenFramebuffers(1, &fbo);
	if (!gl_success("glGenFramebuffers"))
		return NULL;

	ptr = bmalloc(sizeof(struct fbo_info));
	ptr->fbo                 = fbo;
	ptr->width               = width;
	ptr->height              = height;
	ptr->format              = format;
	ptr->cur_render_target   = NULL;
	ptr->cur_render_side     = 0;
	ptr->cur_zstencil_buffer = NULL;

	da_push_back(device->fbos, &ptr);
	return ptr;
}
Example #17
0
void device_load_vertexshader(device_t device, shader_t vertshader)
{
	GLuint program = 0;
	vertbuffer_t cur_vb = device->cur_vertex_buffer;

	if (device->cur_vertex_shader == vertshader)
		return;

	if (vertshader && vertshader->type != SHADER_VERTEX) {
		blog(LOG_ERROR, "Specified shader is not a vertex shader");
		goto fail;
	}

	/* unload and reload the vertex buffer to sync the buffers up with
	 * the specific shader */
	if (cur_vb && !vertexbuffer_load(device, NULL))
		goto fail;

	device->cur_vertex_shader = vertshader;

	if (vertshader)
		program = vertshader->program;

	glUseProgramStages(device->pipeline, GL_VERTEX_SHADER_BIT, program);
	if (!gl_success("glUseProgramStages"))
		goto fail;

	if (cur_vb && !vertexbuffer_load(device, cur_vb))
		goto fail;

	return;

fail:
	blog(LOG_ERROR, "device_load_vertexshader (GL) failed");
}
Example #18
0
void convert_sampler_info(struct gs_sampler_state *sampler,
		struct gs_sampler_info *info)
{
	GLint max_anisotropy_max;
	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;

	max_anisotropy_max = 1;
	glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy_max);
	gl_success("glGetIntegerv(GL_MAX_TEXTURE_ANISOTROPY_MAX)");

	if (1 <= sampler->max_anisotropy &&
	    sampler->max_anisotropy <= max_anisotropy_max)
		return;

	if (sampler->max_anisotropy < 1)
		sampler->max_anisotropy = 1;
	else if (sampler->max_anisotropy > max_anisotropy_max)
		sampler->max_anisotropy = max_anisotropy_max;

	blog(LOG_INFO, "convert_sampler_info: 1 <= max_anisotropy <= "
	               "%d violated, selected: %d, set: %d",
	               max_anisotropy_max,
	               info->max_anisotropy, sampler->max_anisotropy);
}
Example #19
0
static bool gl_init_zsbuffer(struct gs_zstencil_buffer *zs, uint32_t width,
		uint32_t height)
{
	glGenRenderbuffers(1, &zs->buffer);
	if (!gl_success("glGenRenderbuffers"))
		return false;

	if (!gl_bind_renderbuffer(GL_RENDERBUFFER, zs->buffer))
		return false;

	glRenderbufferStorage(GL_RENDERBUFFER, zs->format, width, height);
	if (!gl_success("glRenderbufferStorage"))
		return false;

	gl_bind_renderbuffer(GL_RENDERBUFFER, 0);
	return true;
}
Example #20
0
void device_depthfunction(device_t device, enum gs_depth_test test)
{
	GLenum gl_test = convert_gs_depth_test(test);

	glDepthFunc(gl_test);
	if (!gl_success("glDepthFunc"))
		blog(LOG_ERROR, "device_depthfunction (GL) failed");
}
Example #21
0
void shader_setvec4(shader_t shader, sparam_t param,
		const struct vec4 *val)
{
	if (matching_shader(shader, param)) {
		glProgramUniform4fv(shader->program, param->param, 1, val->ptr);
		gl_success("glProgramUniform4fv");
	}
}
Example #22
0
static inline bool check_shader_pipeline_validity(device_t device)
{
	int valid = false;

	glValidateProgramPipeline(device->pipeline);
	if (!gl_success("glValidateProgramPipeline"))
		return false;

	glGetProgramPipelineiv(device->pipeline, GL_VALIDATE_STATUS, &valid);
	if (!gl_success("glGetProgramPipelineiv"))
		return false;

	if (!valid)
		blog(LOG_ERROR, "Shader pipeline appears to be invalid");

	return valid != 0;
}
Example #23
0
void shader_setmatrix4(shader_t shader, sparam_t param,
		const struct matrix4 *val)
{
	if (matching_shader(shader, param)) {
		glProgramUniformMatrix4fv(shader->program, param->param, 1,
				false, val->x.ptr);
		gl_success("glProgramUniformMatrix4fv");
	}
}
Example #24
0
void device_draw(device_t device, enum gs_draw_mode draw_mode,
		uint32_t start_vert, uint32_t num_verts)
{
	struct gs_index_buffer *ib = device->cur_index_buffer;
	GLenum  topology = convert_gs_topology(draw_mode);
	effect_t effect = gs_geteffect();

	if (!can_render(device))
		goto fail;

	if (effect)
		effect_updateparams(effect);

	shader_update_textures(device->cur_pixel_shader);

	update_viewproj_matrix(device);


#ifdef _DEBUG
	if (!check_shader_pipeline_validity(device))
		goto fail;
#endif

	if (ib) {
		if (num_verts == 0)
			num_verts = (uint32_t)device->cur_index_buffer->num;
		glDrawElements(topology, num_verts, ib->gl_type,
				(const GLvoid*)(start_vert * ib->width));
		if (!gl_success("glDrawElements"))
			goto fail;

	} else {
		if (num_verts == 0)
			num_verts = (uint32_t)device->cur_vertex_buffer->num;
		glDrawArrays(topology, start_vert, num_verts);
		if (!gl_success("glDrawArrays"))
			goto fail;
	}

	return;

fail:
	blog(LOG_ERROR, "device_draw (GL) failed");
}
Example #25
0
void device_blendfunction(device_t device, enum gs_blend_type src,
		enum gs_blend_type dest)
{
	GLenum gl_src = convert_gs_blend_type(src);
	GLenum gl_dst = convert_gs_blend_type(dest);

	glBlendFunc(gl_src, gl_dst);
	if (!gl_success("glBlendFunc"))
		blog(LOG_ERROR, "device_blendfunction (GL) failed");
}
void device_depth_function(gs_device_t *device, enum gs_depth_test test)
{
	GLenum gl_test = convert_gs_depth_test(test);

	glDepthFunc(gl_test);
	if (!gl_success("glDepthFunc"))
		blog(LOG_ERROR, "device_depth_function (GL) failed");

	UNUSED_PARAMETER(device);
}
Example #27
0
void stagesurface_unmap(stagesurf_t stagesurf)
{
	if (!gl_bind_buffer(GL_PIXEL_PACK_BUFFER, stagesurf->pack_buffer))
		return;

	glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
	gl_success("glUnmapBuffer");

	gl_bind_buffer(GL_PIXEL_PACK_BUFFER, 0);
}
Example #28
0
void device_stencilfunction(device_t device, enum gs_stencil_side side,
		enum gs_depth_test test)
{
	GLenum gl_side = convert_gs_stencil_side(side);
	GLenum gl_test = convert_gs_depth_test(test);

	glStencilFuncSeparate(gl_side, gl_test, 0, 0xFFFFFFFF);
	if (!gl_success("glStencilFuncSeparate"))
		blog(LOG_ERROR, "device_stencilfunction (GL) failed");
}
Example #29
0
/* Apparently for mac, PBOs won't do an asynchronous transfer unless you use
 * FBOs aong with glReadPixels, which is really dumb. */
void device_stage_texture(device_t device, stagesurf_t dst, texture_t src)
{
	struct gs_texture_2d *tex2d = (struct gs_texture_2d*)src;
	struct fbo_info *fbo;
	GLint last_fbo;
	bool success = false;

	if (!can_stage(dst, tex2d))
		goto failed;

	if (!gl_bind_buffer(GL_PIXEL_PACK_BUFFER, dst->pack_buffer))
		goto failed;

	fbo = get_fbo(device, dst->width, dst->height, dst->format);

	if (!gl_get_integer_v(GL_READ_FRAMEBUFFER_BINDING, &last_fbo))
		goto failed_unbind_buffer;
	if (!gl_bind_framebuffer(GL_READ_FRAMEBUFFER, fbo->fbo))
		goto failed_unbind_buffer;

	glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 0,
			src->gl_target, src->texture, 0);
	if (!gl_success("glFrameBufferTexture2D"))
		goto failed_unbind_all;

	glReadPixels(0, 0, dst->width, dst->height, dst->gl_format,
			dst->gl_type, 0);
	if (!gl_success("glReadPixels"))
		goto failed_unbind_all;

	success = true;

failed_unbind_all:
	gl_bind_framebuffer(GL_READ_FRAMEBUFFER, last_fbo);

failed_unbind_buffer:
	gl_bind_buffer(GL_PIXEL_PACK_BUFFER, 0);

failed:
	if (!success)
		blog(LOG_ERROR, "device_stage_texture (GL) failed");
}
Example #30
0
void gs_zstencil_destroy(gs_zstencil_t zs)
{
	if (zs) {
		if (zs->buffer) {
			glDeleteRenderbuffers(1, &zs->buffer);
			gl_success("glDeleteRenderbuffers");
		}

		bfree(zs);
	}
}