1 /*
2  * This software is licensed under the terms of the MIT License.
3  * See COPYING for further information.
4  * ---
5  * Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
6  * Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
7 */
8 
9 #include "taisei.h"
10 
11 #include "log.h"
12 #include "resource/postprocess.h"
13 #include "util/graphics.h"
14 #include "video.h"
15 #include "video_postprocess.h"
16 #include "util/fbmgr.h"
17 
18 struct VideoPostProcess {
19 	ManagedFramebufferGroup *mfb_group;
20 	FBPair framebuffers;
21 	PostprocessShader *pp_pipeline;
22 	int frames;
23 };
24 
video_postprocess_resize_strategy(void * userdata,IntExtent * fb_size,FloatRect * fb_viewport)25 static void video_postprocess_resize_strategy(void *userdata, IntExtent *fb_size, FloatRect *fb_viewport) {
26 	float w, h;
27 	video_get_viewport_size(&w, &h);
28 	*fb_size = (IntExtent) { w, h };
29 	*fb_viewport = (FloatRect) { 0, 0, w, h };
30 }
31 
video_postprocess_init(void)32 VideoPostProcess *video_postprocess_init(void) {
33 	PostprocessShader *pps = get_resource_data(RES_POSTPROCESS, "global", RESF_OPTIONAL | RESF_PERMANENT | RESF_PRELOAD);
34 
35 	if(!pps) {
36 		return NULL;
37 	}
38 
39 	VideoPostProcess *vpp = calloc(1, sizeof(*vpp));
40 	vpp->pp_pipeline = pps;
41 	vpp->mfb_group = fbmgr_group_create();
42 
43 	FBAttachmentConfig a = { 0 };
44 	a.attachment = FRAMEBUFFER_ATTACH_COLOR0;
45 	a.tex_params.anisotropy = 1;
46 	a.tex_params.filter.mag = TEX_FILTER_LINEAR;
47 	a.tex_params.filter.min = TEX_FILTER_LINEAR;
48 	a.tex_params.mipmap_mode = TEX_MIPMAP_MANUAL;
49 	a.tex_params.mipmaps = 1;
50 	a.tex_params.type = TEX_TYPE_RGB_8;
51 	a.tex_params.wrap.s = TEX_WRAP_MIRROR;
52 	a.tex_params.wrap.t = TEX_WRAP_MIRROR;
53 
54 	FramebufferConfig fbconf = { 0 };
55 	fbconf.num_attachments = 1;
56 	fbconf.attachments = &a;
57 	fbconf.resize_strategy.resize_func = video_postprocess_resize_strategy;
58 
59 	fbmgr_group_fbpair_create(vpp->mfb_group, "Global postprocess", &fbconf, &vpp->framebuffers);
60 	return vpp;
61 }
62 
video_postprocess_shutdown(VideoPostProcess * vpp)63 void video_postprocess_shutdown(VideoPostProcess *vpp) {
64 	if(vpp) {
65 		fbmgr_group_destroy(vpp->mfb_group);
66 		free(vpp);
67 	}
68 }
69 
video_postprocess_get_framebuffer(VideoPostProcess * vpp)70 Framebuffer *video_postprocess_get_framebuffer(VideoPostProcess *vpp) {
71 	return vpp ? vpp->framebuffers.front : NULL;
72 }
73 
postprocess_prepare(Framebuffer * fb,ShaderProgram * s,void * arg)74 static void postprocess_prepare(Framebuffer *fb, ShaderProgram *s, void *arg) {
75 	VideoPostProcess *vpp = arg;
76 	r_uniform_int("frames", vpp->frames);
77 	r_uniform_vec2("viewport", SCREEN_W, SCREEN_H);
78 }
79 
video_postprocess_render(VideoPostProcess * vpp)80 Framebuffer *video_postprocess_render(VideoPostProcess *vpp) {
81 	if(!vpp) {
82 		return NULL;
83 	}
84 
85 	postprocess(
86 		vpp->pp_pipeline,
87 		&vpp->framebuffers,
88 		postprocess_prepare,
89 		draw_framebuffer_tex,
90 		SCREEN_W,
91 		SCREEN_H,
92 		vpp
93 	);
94 
95 	++vpp->frames;
96 	return vpp->framebuffers.front;
97 }
98