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