1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
26 // File: vogl_msaa_texture.cpp
27 #include "vogl_msaa_texture.h"
29 #include "vogl_texture_format.h"
31 // Requires GL 3.2, GL_ARB_explicit_attrib_location, GL_ARB_separate_shader_objects, GL_ARB_sample_shading
33 // Passthrough vertex shader
35 // Requires GL 3.2, GL_ARB_explicit_attrib_location, GL_ARB_separate_shader_objects
36 static const char *g_passthrough_vert_shader =
38 "#extension GL_ARB_explicit_attrib_location : enable\n"
39 "#extension GL_ARB_separate_shader_objects : enable\n"
40 "layout(location = 0) in vec4 vVertex;\n"
41 "layout(location = 1) in vec3 vTexCoord0;\n"
42 "layout(location = 0) out vec3 vTex;\n"
44 "{ vTex = vTexCoord0;\n"
45 "gl_Position = vVertex;\n"
48 // Reading fragment shaders
50 static const char *g_read_color_frag_shader =
52 "#extension GL_ARB_explicit_attrib_location : enable\n"
53 "#extension GL_ARB_separate_shader_objects : enable\n"
54 "layout(location = 0) in vec3 vTex0;\n"
55 "layout(location = 0) out vec4 fragColor0;\n"
56 "uniform sampler2DMS tex;\n"
57 "uniform int tex_sample;\n"
58 "void main(void) { fragColor0 = texelFetch(tex, ivec2(int(vTex0.x), int(vTex0.y)), tex_sample); }";
60 static const char *g_read_color_array_frag_shader =
62 "#extension GL_ARB_explicit_attrib_location : enable\n"
63 "#extension GL_ARB_separate_shader_objects : enable\n"
64 "layout(location = 0) in vec3 vTex0;\n"
65 "layout(location = 0) out vec4 fragColor0;\n"
66 "uniform sampler2DMSArray tex;\n"
67 "uniform int tex_sample;\n"
68 "void main(void) { fragColor0 = texelFetch(tex, ivec3(int(vTex0.x), int(vTex0.y), int(vTex0.z)), tex_sample); }";
70 static const char *g_read_depth_frag_shader =
72 "#extension GL_ARB_explicit_attrib_location : enable\n"
73 "#extension GL_ARB_separate_shader_objects : enable\n"
74 "layout(location = 0) in vec3 vTex0;\n"
75 "layout(location = 0) out vec4 fragColor0;\n"
76 "uniform sampler2DMS tex;\n"
77 "uniform int tex_sample;\n"
78 "void main(void) { fragColor0 = vec4(0,0,0,0); gl_FragDepth = texelFetch(tex, ivec2(int(vTex0.x), int(vTex0.y)), tex_sample).x; }";
80 static const char *g_read_depth_array_frag_shader =
82 "#extension GL_ARB_explicit_attrib_location : enable\n"
83 "#extension GL_ARB_separate_shader_objects : enable\n"
84 "layout(location = 0) in vec3 vTex0;\n"
85 "layout(location = 0) out vec4 fragColor0;\n"
86 "uniform sampler2DMSArray tex;\n"
87 "uniform int tex_sample;\n"
88 "void main(void) { fragColor0 = vec4(0,0,0,1); gl_FragDepth = texelFetch(tex, ivec3(int(vTex0.x), int(vTex0.y), int(vTex0.z)), tex_sample).x; }";
90 // Writing fragment shaders
92 static const char *g_write_color_frag_shader =
94 "#extension GL_ARB_explicit_attrib_location : enable\n"
95 "#extension GL_ARB_separate_shader_objects : enable\n"
96 "#extension GL_ARB_sample_shading : enable\n"
97 "layout(location = 0) in vec3 vTex0;\n"
98 "layout(location = 0) out vec4 fragColor0;\n"
99 "uniform sampler2D tex;\n"
100 "uniform int sample_mask;\n"
103 "fragColor0 = texelFetch(tex, ivec2(int(vTex0.x), int(vTex0.y)), 0);\n"
104 "gl_SampleMask[0] = sample_mask;\n"
107 static const char *g_write_color_array_frag_shader =
108 "#version 150 core\n"
109 "#extension GL_ARB_explicit_attrib_location : enable\n"
110 "#extension GL_ARB_separate_shader_objects : enable\n"
111 "#extension GL_ARB_sample_shading : enable\n"
112 "layout(location = 0) in vec3 vTex0;\n"
113 "layout(location = 0) out vec4 fragColor0;\n"
114 "uniform sampler2DArray tex;\n"
115 "uniform int sample_mask;\n"
118 "fragColor0 = texelFetch(tex, ivec3(int(vTex0.x), int(vTex0.y), int(vTex0.z)), 0);\n"
119 "gl_SampleMask[0] = sample_mask;\n"
122 static const char *g_write_depth_frag_shader =
123 "#version 150 core\n"
124 "#extension GL_ARB_explicit_attrib_location : enable\n"
125 "#extension GL_ARB_separate_shader_objects : enable\n"
126 "#extension GL_ARB_sample_shading : enable\n"
127 "layout(location = 0) in vec3 vTex0;\n"
128 "layout(location = 0) out vec4 fragColor0;\n"
129 "uniform sampler2D tex;\n"
130 "uniform int sample_mask;\n"
133 "fragColor0 = vec4(0,0,0,1);\n"
134 "gl_FragDepth = texelFetch(tex, ivec2(int(vTex0.x), int(vTex0.y)), 0).x;\n"
135 "gl_SampleMask[0] = sample_mask;\n"
138 static const char *g_write_depth_array_frag_shader =
139 "#version 150 core\n"
140 "#extension GL_ARB_explicit_attrib_location : enable\n"
141 "#extension GL_ARB_separate_shader_objects : enable\n"
142 "#extension GL_ARB_sample_shading : enable\n"
143 "layout(location = 0) in vec3 vTex0;\n"
144 "layout(location = 0) out vec4 fragColor0;\n"
145 "uniform sampler2DArray tex;\n"
146 "uniform int sample_mask;\n"
149 "fragColor0 = vec4(0,0,0,1);\n"
150 "gl_FragDepth = texelFetch(tex, ivec3(int(vTex0.x), int(vTex0.y), int(vTex0.z)), 0).x;\n"
151 "gl_SampleMask[0] = sample_mask;\n"
154 static const char *g_const_color_frag_shader =
155 "#version 150 core\n"
156 "#extension GL_ARB_explicit_attrib_location : enable\n"
157 "#extension GL_ARB_separate_shader_objects : enable\n"
158 "#extension GL_ARB_sample_shading : enable\n"
159 "layout(location = 0) out vec4 fragColor0;\n"
160 "uniform vec4 color;\n"
163 "fragColor0 = color;\n"
166 static const char *g_write_stencil_frag_shader =
167 "#version 150 core\n"
168 "#extension GL_ARB_explicit_attrib_location : enable\n"
169 "#extension GL_ARB_separate_shader_objects : enable\n"
170 "#extension GL_ARB_sample_shading : enable\n"
171 "layout(location = 0) in vec3 vTex0;\n"
172 "layout(location = 0) out vec4 fragColor0;\n"
173 "uniform sampler2D tex;\n"
174 "uniform float stencil_comp_val;\n"
175 "uniform int sample_mask;\n"
178 "float stencil_val = texelFetch(tex, ivec2(int(vTex0.x), int(vTex0.y)), 0).x;\n"
179 "if (abs(stencil_val - stencil_comp_val) > 0.125/255.0) discard;\n"
180 "fragColor0 = vec4(0,0,0,1);\n"
181 "gl_SampleMask[0] = sample_mask;\n"
184 static const char *g_write_stencil_array_frag_shader =
185 "#version 150 core\n"
186 "#extension GL_ARB_explicit_attrib_location : enable\n"
187 "#extension GL_ARB_separate_shader_objects : enable\n"
188 "#extension GL_ARB_sample_shading : enable\n"
189 "layout(location = 0) in vec3 vTex0;\n"
190 "layout(location = 0) out vec4 fragColor0;\n"
191 "uniform sampler2DArray tex;\n"
192 "uniform float stencil_comp_val;\n"
193 "uniform int sample_mask;\n"
196 "float stencil_val = texelFetch(tex, ivec3(int(vTex0.x), int(vTex0.y), int(vTex0.z)), 0).x;\n"
197 "if (abs(stencil_val - stencil_comp_val) > 0.125/255.0) discard;\n"
198 "fragColor0 = vec4(0,0,0,1);\n"
199 "gl_SampleMask[0] = sample_mask;\n"
202 struct vogl_quad_vertex
207 vogl_quad_vertex() { }
209 vogl_quad_vertex(float x, float y, float z, float w, float u, float v, float q) :
210 m_pos(x, y, z, w), m_uv0(u, v, q)
215 static const vogl_quad_vertex g_quad_tri_verts[3*2] =
217 vogl_quad_vertex(-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f ), // top left
218 vogl_quad_vertex( 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f ), // top right
219 vogl_quad_vertex( 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f ), // bottom right
221 vogl_quad_vertex(-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f ), // top left
222 vogl_quad_vertex( 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f ), // bottom right
223 vogl_quad_vertex(-1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f ) // bottom left
226 vogl_msaa_texture_splitter::vogl_msaa_texture_splitter() :
238 bool vogl_msaa_texture_splitter::init()
242 // Create work context
243 m_orig_context = vogl_get_current_context();
244 m_cur_display = vogl_get_current_display();
245 m_cur_fb_config = vogl_get_current_fb_config();
246 m_cur_drawable = vogl_get_current_drawable();
248 vogl_context_desc context_desc;
249 m_work_context = vogl_create_context(m_cur_display, m_cur_fb_config, m_orig_context, 3, 2, eCHCDebugContextFlag | cCHCCoreProfileFlag, &context_desc);
252 vogl_error_printf("%s: Failed creating temporary context!\n", VOGL_METHOD_NAME);
256 vogl_make_current(m_cur_display, m_cur_drawable, m_work_context);
258 vogl_enable_generic_context_debug_messages();
260 m_context_info.init(context_desc);
262 GL_ENTRYPOINT(glGenVertexArrays)(1, &m_vao_handle);
265 GL_ENTRYPOINT(glBindVertexArray)(m_vao_handle);
271 if (!m_read_color_program.init(g_passthrough_vert_shader, g_read_color_frag_shader))
273 m_read_color_program.set_uniform("tex", 0);
275 if (!m_read_color_array_program.init(g_passthrough_vert_shader, g_read_color_array_frag_shader))
277 m_read_color_array_program.set_uniform("tex", 0);
279 if (!m_read_depth_program.init(g_passthrough_vert_shader, g_read_depth_frag_shader))
281 m_read_depth_program.set_uniform("tex", 0);
283 if (!m_read_depth_array_program.init(g_passthrough_vert_shader, g_read_depth_array_frag_shader))
285 m_read_depth_array_program.set_uniform("tex", 0);
288 if (!m_write_color_program.init(g_passthrough_vert_shader, g_write_color_frag_shader))
290 m_write_color_program.set_uniform("tex", 0);
292 if (!m_write_color_array_program.init(g_passthrough_vert_shader, g_write_color_array_frag_shader))
294 m_write_color_array_program.set_uniform("tex", 0);
296 if (!m_write_depth_program.init(g_passthrough_vert_shader, g_write_depth_frag_shader))
298 m_write_depth_program.set_uniform("tex", 0);
300 if (!m_write_depth_array_program.init(g_passthrough_vert_shader, g_write_depth_array_frag_shader))
302 m_write_depth_array_program.set_uniform("tex", 0);
304 // Copying stencil to color
305 if (!m_const_color_program.init(g_passthrough_vert_shader, g_const_color_frag_shader))
308 // Copying color to stencil
309 if (!m_write_stencil_program.init(g_passthrough_vert_shader, g_write_stencil_frag_shader))
311 m_write_stencil_program.set_uniform("tex", 0);
313 if (!m_write_stencil_array_program.init(g_passthrough_vert_shader, g_write_stencil_array_frag_shader))
315 m_write_stencil_array_program.set_uniform("tex", 0);
317 // Create vertex buffer and bind it
318 GL_ENTRYPOINT(glGenBuffers)(1, &m_vertex_buffer);
321 GL_ENTRYPOINT(glBindBuffer)(GL_ARRAY_BUFFER, m_vertex_buffer);
324 GL_ENTRYPOINT(glVertexAttribPointer)(0, 4, GL_FLOAT, GL_FALSE, sizeof(vogl_quad_vertex), (const GLvoid *)(uint64_t)VOGL_OFFSETOF(vogl_quad_vertex, m_pos));
327 GL_ENTRYPOINT(glVertexAttribPointer)(1, 3, GL_FLOAT, GL_FALSE, sizeof(vogl_quad_vertex), (const GLvoid *)(uint64_t)VOGL_OFFSETOF(vogl_quad_vertex, m_uv0));
330 GL_ENTRYPOINT(glEnableVertexAttribArray)(0);
333 GL_ENTRYPOINT(glEnableVertexAttribArray)(1);
336 vogl_reset_pixel_store_states();
338 // Set state (some of this is probably not necessary)
339 GL_ENTRYPOINT(glDisable)(GL_BLEND);
340 GL_ENTRYPOINT(glDisable)(GL_CULL_FACE);
341 GL_ENTRYPOINT(glDisable)(GL_DEPTH_TEST);
342 GL_ENTRYPOINT(glDisable)(GL_STENCIL_TEST);
343 GL_ENTRYPOINT(glDepthMask)(GL_FALSE);
344 GL_ENTRYPOINT(glStencilMask)(0);
345 GL_ENTRYPOINT(glActiveTexture)(GL_TEXTURE0);
353 void vogl_msaa_texture_splitter::deinit()
358 // We're switching contexts so serialize here (not sure if this is necessary, best to be safe).
359 GL_ENTRYPOINT(glFinish)();
362 GL_ENTRYPOINT(glBindVertexArray)(0);
365 GL_ENTRYPOINT(glUseProgram)(0);
368 GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D, 0);
371 GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D_MULTISAMPLE, 0);
374 GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
377 GL_ENTRYPOINT(glBindBuffer)(GL_ARRAY_BUFFER, 0);
382 GL_ENTRYPOINT(glDeleteVertexArrays)(1, &m_vao_handle);
390 GL_ENTRYPOINT(glDeleteBuffers)(1, &m_vertex_buffer);
396 m_read_color_program.deinit();
397 m_read_color_array_program.deinit();
398 m_read_depth_program.deinit();
399 m_read_depth_array_program.deinit();
401 m_write_color_program.deinit();
402 m_write_color_array_program.deinit();
403 m_write_depth_program.deinit();
404 m_write_depth_array_program.deinit();
406 m_const_color_program.deinit();
408 m_write_stencil_program.deinit();
409 m_write_stencil_array_program.deinit();
411 vogl_make_current(m_cur_display, m_cur_drawable, m_orig_context);
413 vogl_destroy_context(m_cur_display, m_work_context);
424 vogl_msaa_texture_splitter::~vogl_msaa_texture_splitter()
429 // One multisampled source, multiple non-multisampled destinations created by method.
430 bool vogl_msaa_texture_splitter::split(GLenum src_target, GLuint src_texture, vogl::vector<GLuint> &dest_textures)
432 dest_textures.resize(0);
437 if ((src_target != GL_TEXTURE_2D_MULTISAMPLE) && (src_target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY))
440 GLenum dest_target = (src_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
442 GL_ENTRYPOINT(glBindTexture)(src_target, src_texture);
445 GLint mip_level = 0, base_level = 0, max_level = 0;
447 GLenum internal_fmt = 0;
448 int base_width = 0, base_height = 0, base_depth = 0, samples = 0;
449 GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, base_level, GL_TEXTURE_INTERNAL_FORMAT, reinterpret_cast<GLint *>(&internal_fmt));
450 GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, base_level, GL_TEXTURE_WIDTH, &base_width);
451 GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, base_level, GL_TEXTURE_HEIGHT, &base_height);
452 GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, base_level, GL_TEXTURE_DEPTH, &base_depth);
453 GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, base_level, GL_TEXTURE_SAMPLES, &samples);
456 if ((base_width < 1) || (base_height < 1) || (base_depth < 1) || (samples < 1))
459 const vogl_internal_tex_format *pInternal_tex_fmt = vogl_find_internal_texture_format(internal_fmt);
460 if ((!pInternal_tex_fmt) || (pInternal_tex_fmt->m_optimum_get_image_fmt == GL_NONE) || (pInternal_tex_fmt->m_optimum_get_image_type == GL_NONE))
463 GLenum attachment_target = GL_COLOR_ATTACHMENT0;
465 if ((pInternal_tex_fmt->m_comp_sizes[cTCDepth]) && (pInternal_tex_fmt->m_comp_sizes[cTCStencil]))
466 attachment_target = GL_DEPTH_STENCIL_ATTACHMENT;
467 else if (pInternal_tex_fmt->m_comp_sizes[cTCDepth])
468 attachment_target = GL_DEPTH_ATTACHMENT;
469 else if (pInternal_tex_fmt->m_comp_sizes[cTCStencil])
472 if (attachment_target == GL_COLOR_ATTACHMENT0)
474 GL_ENTRYPOINT(glDepthMask)(GL_FALSE);
477 GL_ENTRYPOINT(glDisable)(GL_DEPTH_TEST);
482 GL_ENTRYPOINT(glDepthMask)(GL_TRUE);
485 GL_ENTRYPOINT(glEnable)(GL_DEPTH_TEST);
488 GL_ENTRYPOINT(glDepthFunc)(GL_ALWAYS);
492 GL_ENTRYPOINT(glDisable)(GL_STENCIL_TEST);
495 uint width = base_width << base_level;
496 uint height = base_height << base_level;
497 uint depth = base_depth;
499 uint max_possible_mip_levels = utils::compute_max_mips(width, height, depth);
500 int num_actual_mip_levels = math::minimum<int>(max_possible_mip_levels, max_level + 1);
502 for (int sample_index = 0; sample_index < samples; sample_index++)
504 m_read_color_program.set_uniform("tex_sample", sample_index);
505 m_read_color_array_program.set_uniform("tex_sample", sample_index);
506 m_read_depth_program.set_uniform("tex_sample", sample_index);
507 m_read_depth_array_program.set_uniform("tex_sample", sample_index);
509 GLuint dest_texture = 0;
510 GL_ENTRYPOINT(glGenTextures)(1, &dest_texture);
513 dest_textures.push_back(dest_texture);
515 GL_ENTRYPOINT(glBindTexture)(dest_target, dest_texture);
518 GL_ENTRYPOINT(glTexParameteri)(dest_target, GL_TEXTURE_BASE_LEVEL, base_level);
521 GL_ENTRYPOINT(glTexParameteri)(dest_target, GL_TEXTURE_MAX_LEVEL, num_actual_mip_levels - 1);
524 int mip_width = 0, mip_height = 0, mip_depth = 0;
525 GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, mip_level, GL_TEXTURE_WIDTH, &mip_width);
526 GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, mip_level, GL_TEXTURE_HEIGHT, &mip_height);
527 GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, mip_level, GL_TEXTURE_DEPTH, &mip_depth);
528 if ((vogl_check_gl_error()) || (mip_width < 1) || (mip_height < 1) || (mip_depth < 1))
531 VOGL_ASSERT(mip_depth == base_depth);
532 VOGL_NOTE_UNUSED(mip_depth);
534 vogl::vector<uint8> ones;
535 ones.resize(static_cast<uint>(vogl_get_image_size(pInternal_tex_fmt->m_optimum_get_image_fmt, pInternal_tex_fmt->m_optimum_get_image_type, mip_width, mip_height, mip_depth)));
538 if (src_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
540 GL_ENTRYPOINT(glTexImage3D)(dest_target,
547 pInternal_tex_fmt->m_optimum_get_image_fmt,
548 pInternal_tex_fmt->m_optimum_get_image_type,
554 GL_ENTRYPOINT(glTexImage2D)(dest_target,
560 pInternal_tex_fmt->m_optimum_get_image_fmt,
561 pInternal_tex_fmt->m_optimum_get_image_type,
566 for (int layer = 0; layer < base_depth; layer++)
569 GLuint fbo_handle = 0;
570 GL_ENTRYPOINT(glGenFramebuffers)(1, &fbo_handle);
573 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, fbo_handle);
576 if (dest_target == GL_TEXTURE_2D_ARRAY)
578 GL_ENTRYPOINT(glFramebufferTextureLayer)(GL_DRAW_FRAMEBUFFER, attachment_target, dest_texture, mip_level, layer);
583 GL_ENTRYPOINT(glFramebufferTexture2D)(GL_DRAW_FRAMEBUFFER, attachment_target, dest_target, dest_texture, mip_level);
587 if (attachment_target == GL_COLOR_ATTACHMENT0)
589 GLenum draw_buf = GL_COLOR_ATTACHMENT0;
590 GL_ENTRYPOINT(glDrawBuffers)(1, &draw_buf);
595 GL_ENTRYPOINT(glDrawBuffer)(GL_NONE);
599 GLenum fbo_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
604 if (fbo_status == GL_FRAMEBUFFER_COMPLETE)
606 // This method reads from a multisampled texture, which does NOT support GL_SKIP_DECODE_EXT on these targets.
607 // Instead, we enable sRGB writes to work around this. The source and dest use the same formats, and if the dest is not sRGB then the source shouldn't be.
608 GL_ENTRYPOINT(glDisable)(GL_FRAMEBUFFER_SRGB);
611 if (attachment_target == GL_COLOR_ATTACHMENT0)
614 GL_ENTRYPOINT(glGetFramebufferAttachmentParameteriv)(GL_DRAW_FRAMEBUFFER, attachment_target, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encoding);
617 if (encoding == GL_SRGB)
619 GL_ENTRYPOINT(glEnable)(GL_FRAMEBUFFER_SRGB);
624 // Render quad to FBO
625 GL_ENTRYPOINT(glViewport)(0, 0, mip_width, mip_height);
628 GL_ENTRYPOINT(glClearColor)(1.0f, 0.3f, 1.0f, 1.0f);
631 GL_ENTRYPOINT(glClearDepth)(.25f);
634 GL_ENTRYPOINT(glClearStencil)(64);
637 if (attachment_target == GL_COLOR_ATTACHMENT0)
639 GL_ENTRYPOINT(glClear)(GL_COLOR_BUFFER_BIT);
642 else if (attachment_target == GL_DEPTH_ATTACHMENT)
644 GL_ENTRYPOINT(glClear)(GL_DEPTH_BUFFER_BIT);
649 GL_ENTRYPOINT(glClear)(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
653 vogl_quad_vertex quad_tri_verts[3*2];
654 memcpy(quad_tri_verts, g_quad_tri_verts, sizeof(quad_tri_verts));
656 for (uint i = 0; i < 6; i++)
658 quad_tri_verts[i].m_uv0[0] *= mip_width;
659 quad_tri_verts[i].m_uv0[1] *= mip_height;
660 quad_tri_verts[i].m_uv0[2] = layer;
663 GL_ENTRYPOINT(glBufferData)(GL_ARRAY_BUFFER, sizeof(quad_tri_verts), quad_tri_verts, GL_STATIC_DRAW);
666 if (attachment_target == GL_COLOR_ATTACHMENT0)
668 GL_ENTRYPOINT(glUseProgram)((src_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) ? m_read_color_array_program.get_handle() : m_read_color_program.get_handle());
673 GL_ENTRYPOINT(glUseProgram)((src_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) ? m_read_depth_array_program.get_handle() : m_read_depth_program.get_handle());
677 GL_ENTRYPOINT(glDrawArrays)(GL_TRIANGLES, 0, 6);
684 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
687 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &fbo_handle);
690 GL_ENTRYPOINT(glDrawBuffer)(GL_FRONT_LEFT);
698 GL_ENTRYPOINT(glBindTexture)(src_target, 0);
701 GL_ENTRYPOINT(glBindTexture)(dest_target, 0);
707 GL_ENTRYPOINT(glBindTexture)(src_target, 0);
710 GL_ENTRYPOINT(glBindTexture)(dest_target, 0);
713 if (dest_textures.size())
715 GL_ENTRYPOINT(glDeleteTextures)(dest_textures.size(), dest_textures.get_ptr());
718 dest_textures.resize(0);
724 // Multiple sources, one multisampled destination. Caller creates destination.
725 bool vogl_msaa_texture_splitter::combine(GLuint src_texture, uint dest_sample_index, GLenum dest_target, GLuint dest_texture)
733 if ((dest_target != GL_TEXTURE_2D_MULTISAMPLE) && (dest_target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY))
739 m_write_color_program.set_uniform("sample_mask", static_cast<int>(1U << dest_sample_index));
740 m_write_color_array_program.set_uniform("sample_mask", static_cast<int>(1U << dest_sample_index));
741 m_write_depth_program.set_uniform("sample_mask", static_cast<int>(1U << dest_sample_index));
742 m_write_depth_array_program.set_uniform("sample_mask", static_cast<int>(1U << dest_sample_index));
744 const GLenum src_target = (dest_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
746 GL_ENTRYPOINT(glBindTexture)(src_target, src_texture);
749 GL_ENTRYPOINT(glBindTexture)(dest_target, dest_texture);
752 const int mip_level = 0;
754 GLenum internal_fmt = 0;
755 GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, mip_level, GL_TEXTURE_INTERNAL_FORMAT, reinterpret_cast<GLint *>(&internal_fmt));
757 int mip_width = 0, mip_height = 0, mip_depth = 0;
758 GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, mip_level, GL_TEXTURE_WIDTH, &mip_width);
759 GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, mip_level, GL_TEXTURE_HEIGHT, &mip_height);
760 GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, mip_level, GL_TEXTURE_DEPTH, &mip_depth);
762 if ((vogl_check_gl_error()) || (mip_width < 1) || (mip_height < 1) || (mip_depth < 1))
765 const vogl_internal_tex_format *pInternal_tex_fmt = vogl_find_internal_texture_format(internal_fmt);
766 if ((!pInternal_tex_fmt) || (pInternal_tex_fmt->m_optimum_get_image_fmt == GL_NONE) || (pInternal_tex_fmt->m_optimum_get_image_type == GL_NONE))
769 GLenum attachment_target = GL_COLOR_ATTACHMENT0;
770 if ((pInternal_tex_fmt->m_comp_sizes[cTCDepth]) && (pInternal_tex_fmt->m_comp_sizes[cTCStencil]))
771 attachment_target = GL_DEPTH_STENCIL_ATTACHMENT;
772 else if (pInternal_tex_fmt->m_comp_sizes[cTCDepth])
773 attachment_target = GL_DEPTH_ATTACHMENT;
774 else if (pInternal_tex_fmt->m_comp_sizes[cTCStencil])
777 if (attachment_target == GL_COLOR_ATTACHMENT0)
779 GL_ENTRYPOINT(glDepthMask)(GL_FALSE);
782 GL_ENTRYPOINT(glDisable)(GL_DEPTH_TEST);
787 GL_ENTRYPOINT(glDepthMask)(GL_TRUE);
790 GL_ENTRYPOINT(glEnable)(GL_DEPTH_TEST);
793 GL_ENTRYPOINT(glDepthFunc)(GL_ALWAYS);
797 GL_ENTRYPOINT(glDisable)(GL_STENCIL_TEST);
800 // This method disables sRGB reads and writes (we can do this because the source is non-multisampled and the dest is a multisampled render target.)
801 GLint orig_srgb_decode = 0;
802 if (m_context_info.supports_extension("GL_EXT_texture_sRGB_decode"))
804 GL_ENTRYPOINT(glGetTexParameteriv)(src_target, GL_TEXTURE_SRGB_DECODE_EXT, &orig_srgb_decode);
807 GL_ENTRYPOINT(glTexParameteri)(src_target, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
811 for (int layer = 0; layer < mip_depth; layer++)
814 GLuint fbo_handle = 0;
815 GL_ENTRYPOINT(glGenFramebuffers)(1, &fbo_handle);
818 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, fbo_handle);
821 if (dest_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
823 GL_ENTRYPOINT(glFramebufferTextureLayer)(GL_DRAW_FRAMEBUFFER, attachment_target, dest_texture, mip_level, layer);
828 GL_ENTRYPOINT(glFramebufferTexture2D)(GL_DRAW_FRAMEBUFFER, attachment_target, dest_target, dest_texture, mip_level);
832 if (attachment_target == GL_COLOR_ATTACHMENT0)
834 GLenum draw_buf = GL_COLOR_ATTACHMENT0;
835 GL_ENTRYPOINT(glDrawBuffers)(1, &draw_buf);
840 GL_ENTRYPOINT(glDrawBuffer)(GL_NONE);
844 GLenum fbo_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
849 if (fbo_status == GL_FRAMEBUFFER_COMPLETE)
851 // Render quad to FBO
852 GL_ENTRYPOINT(glViewport)(0, 0, mip_width, mip_height);
855 vogl_quad_vertex quad_tri_verts[3*2];
856 memcpy(quad_tri_verts, g_quad_tri_verts, sizeof(quad_tri_verts));
858 for (uint i = 0; i < 6; i++)
860 quad_tri_verts[i].m_uv0[0] *= mip_width;
861 quad_tri_verts[i].m_uv0[1] *= mip_height;
862 quad_tri_verts[i].m_uv0[2] = layer;
865 GL_ENTRYPOINT(glBufferData)(GL_ARRAY_BUFFER, sizeof(quad_tri_verts), quad_tri_verts, GL_STATIC_DRAW);
868 if (attachment_target == GL_COLOR_ATTACHMENT0)
870 GL_ENTRYPOINT(glUseProgram)((src_target == GL_TEXTURE_2D_ARRAY) ? m_write_color_array_program.get_handle() : m_write_color_program.get_handle());
875 GL_ENTRYPOINT(glUseProgram)((src_target == GL_TEXTURE_2D_ARRAY) ? m_write_depth_array_program.get_handle() : m_write_depth_program.get_handle());
879 GL_ENTRYPOINT(glDisable)(GL_FRAMEBUFFER_SRGB);
882 GL_ENTRYPOINT(glDrawArrays)(GL_TRIANGLES, 0, 6);
889 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
892 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &fbo_handle);
895 GL_ENTRYPOINT(glDrawBuffer)(GL_FRONT_LEFT);
902 GL_ENTRYPOINT(glBindTexture)(src_target, 0);
905 GL_ENTRYPOINT(glBindTexture)(dest_target, 0);
911 GL_ENTRYPOINT(glBindTexture)(src_target, 0);
914 GL_ENTRYPOINT(glBindTexture)(dest_target, 0);
917 if (m_context_info.supports_extension("GL_EXT_texture_sRGB_decode"))
919 GL_ENTRYPOINT(glTexParameteri)(src_target, GL_TEXTURE_SRGB_DECODE_EXT, orig_srgb_decode);
926 // How to retrieve MSAA stencil info:
927 // Step 1: Get MSAA depth/stencil texture info
928 // Step 2: Create new MSAA color texture - same res and # of samples, 32-bit RGBA format
929 // Step 3: Create new temp FBO, attach new MSAA color texture + MSAA depth/stencil texture
930 // Step 4: Clear FBO's color attachment
931 // Step 5: Disable depth mask, set depth func to always
932 // Step 6: For i = 0 to 255:
933 // Enable stencil testing, set ref to i, reject when stencil != i
934 // Draw a quad, have it output color value i
935 // Step 7: Now split this MSAA color texture into sep non-MSAA textures
936 // Step 8: Return these MSAA color textures to the caller
937 // Step 9: The caller now can combine the stencil data with the retrieved depth data
939 // Also see http://www.opengl.org/wiki/Texture#Stencil_texturing, but this is GL v4.3
941 bool vogl_msaa_texture_splitter::copy_stencil_samples_to_color(GLenum target, GLuint src_texture, GLuint &dest_texture)
951 if ((target != GL_TEXTURE_2D_MULTISAMPLE) && (target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY))
957 GL_ENTRYPOINT(glBindTexture)(target, src_texture);
960 const int mip_level = 0;
962 GLenum internal_fmt = 0;
963 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, mip_level, GL_TEXTURE_INTERNAL_FORMAT, reinterpret_cast<GLint *>(&internal_fmt));
965 int width = 0, height = 0, depth = 0, samples = 0;
966 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, mip_level, GL_TEXTURE_WIDTH, &width);
967 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, mip_level, GL_TEXTURE_HEIGHT, &height);
968 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, mip_level, GL_TEXTURE_DEPTH, &depth);
969 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, mip_level, GL_TEXTURE_SAMPLES, &samples);
971 if ((vogl_check_gl_error()) || (width < 1) || (height < 1) || (depth < 1) || (samples < 1))
974 const vogl_internal_tex_format *pInternal_tex_fmt = vogl_find_internal_texture_format(internal_fmt);
975 if ((!pInternal_tex_fmt) || (pInternal_tex_fmt->m_optimum_get_image_fmt == GL_NONE) || (pInternal_tex_fmt->m_optimum_get_image_type == GL_NONE))
978 if (!pInternal_tex_fmt->m_comp_sizes[cTCStencil])
981 GLenum fbo_attachment_target = GL_STENCIL_ATTACHMENT;
982 if (pInternal_tex_fmt->m_comp_sizes[cTCDepth])
983 fbo_attachment_target = GL_DEPTH_STENCIL_ATTACHMENT;
985 GL_ENTRYPOINT(glGenTextures)(1, &dest_texture);
988 GL_ENTRYPOINT(glBindTexture)(target, dest_texture);
991 const GLenum dest_internal_fmt = GL_RGBA;
992 const GLboolean fixed_sample_locations = GL_TRUE;
994 if (target == GL_TEXTURE_2D_MULTISAMPLE)
996 GL_ENTRYPOINT(glTexImage2DMultisample)(target, samples, dest_internal_fmt, width, height, fixed_sample_locations);
1001 GL_ENTRYPOINT(glTexImage3DMultisample)(target, samples, dest_internal_fmt, width, height, depth, fixed_sample_locations);
1002 VOGL_CHECK_GL_ERROR;
1005 GL_ENTRYPOINT(glUseProgram)(m_const_color_program.get_handle());
1006 VOGL_CHECK_GL_ERROR;
1008 for (int layer = 0; layer < depth; layer++)
1010 GLuint temp_fbo = 0;
1011 GL_ENTRYPOINT(glGenFramebuffers)(1, &temp_fbo);
1012 VOGL_CHECK_GL_ERROR;
1014 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, temp_fbo);
1015 VOGL_CHECK_GL_ERROR;
1017 if (target == GL_TEXTURE_2D_MULTISAMPLE)
1019 GL_ENTRYPOINT(glFramebufferTexture2D)(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, dest_texture, mip_level);
1020 VOGL_CHECK_GL_ERROR;
1022 GL_ENTRYPOINT(glFramebufferTexture2D)(GL_DRAW_FRAMEBUFFER, fbo_attachment_target, target, src_texture, mip_level);
1023 VOGL_CHECK_GL_ERROR;
1027 GL_ENTRYPOINT(glFramebufferTextureLayer)(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dest_texture, mip_level, layer);
1028 VOGL_CHECK_GL_ERROR;
1030 GL_ENTRYPOINT(glFramebufferTextureLayer)(GL_DRAW_FRAMEBUFFER, fbo_attachment_target, src_texture, mip_level, layer);
1031 VOGL_CHECK_GL_ERROR;
1034 GLenum draw_buf = GL_COLOR_ATTACHMENT0;
1035 GL_ENTRYPOINT(glDrawBuffers)(1, &draw_buf);
1036 VOGL_CHECK_GL_ERROR;
1038 GLenum fbo_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
1039 VOGL_CHECK_GL_ERROR;
1041 bool status = false;
1043 if (fbo_status == GL_FRAMEBUFFER_COMPLETE)
1045 GL_ENTRYPOINT(glDisable)(GL_FRAMEBUFFER_SRGB);
1046 VOGL_CHECK_GL_ERROR;
1048 GL_ENTRYPOINT(glViewport)(0, 0, width, height);
1049 VOGL_CHECK_GL_ERROR;
1051 GL_ENTRYPOINT(glClearColor)(0, 0, 0, 0);
1052 VOGL_CHECK_GL_ERROR;
1054 GL_ENTRYPOINT(glClear)(GL_COLOR_BUFFER_BIT);
1055 VOGL_CHECK_GL_ERROR;
1057 GL_ENTRYPOINT(glColorMask)(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1058 VOGL_CHECK_GL_ERROR;
1060 GL_ENTRYPOINT(glEnable)(GL_DEPTH_TEST);
1061 VOGL_CHECK_GL_ERROR;
1063 GL_ENTRYPOINT(glDepthMask)(GL_FALSE);
1064 VOGL_CHECK_GL_ERROR;
1066 GL_ENTRYPOINT(glDepthFunc)(GL_ALWAYS);
1067 VOGL_CHECK_GL_ERROR;
1069 GL_ENTRYPOINT(glEnable)(GL_STENCIL_TEST);
1070 VOGL_CHECK_GL_ERROR;
1072 GL_ENTRYPOINT(glStencilOp)(GL_KEEP, GL_KEEP, GL_REPLACE);
1073 VOGL_CHECK_GL_ERROR;
1075 vogl_quad_vertex quad_tri_verts[3*2];
1076 memcpy(quad_tri_verts, g_quad_tri_verts, sizeof(quad_tri_verts));
1078 for (uint i = 0; i < 6; i++)
1080 quad_tri_verts[i].m_uv0[0] *= width;
1081 quad_tri_verts[i].m_uv0[1] *= height;
1082 quad_tri_verts[i].m_uv0[2] = layer;
1085 GL_ENTRYPOINT(glBufferData)(GL_ARRAY_BUFFER, sizeof(quad_tri_verts), quad_tri_verts, GL_STATIC_DRAW);
1086 VOGL_CHECK_GL_ERROR;
1088 for (uint stencil_val = 0; stencil_val <= 255; stencil_val++)
1090 m_const_color_program.set_uniform("color", vec4F(stencil_val * (1.0f / 255.0f)));
1092 GL_ENTRYPOINT(glStencilFunc)(GL_EQUAL, stencil_val, 0xFF);
1093 VOGL_CHECK_GL_ERROR;
1095 GL_ENTRYPOINT(glDrawArrays)(GL_TRIANGLES, 0, 6);
1096 VOGL_CHECK_GL_ERROR;
1103 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
1104 VOGL_CHECK_GL_ERROR;
1106 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &temp_fbo);
1107 VOGL_CHECK_GL_ERROR;
1116 GL_ENTRYPOINT(glBindTexture)(target, 0);
1117 VOGL_CHECK_GL_ERROR;
1119 GL_ENTRYPOINT(glDisable)(GL_STENCIL_TEST);
1120 VOGL_CHECK_GL_ERROR;
1124 GL_ENTRYPOINT(glBindTexture)(target, 0);
1125 VOGL_CHECK_GL_ERROR;
1129 GL_ENTRYPOINT(glDeleteTextures)(1, &dest_texture);
1130 VOGL_CHECK_GL_ERROR;
1135 GL_ENTRYPOINT(glDisable)(GL_STENCIL_TEST);
1136 VOGL_CHECK_GL_ERROR;
1141 // Copies MSAA color samples from an MSAA 2D to 2D_ARRAY texture to the stencil buffer of a MSAA 2D or 2D_ARRAY depth/stencil texture.
1142 // Source is NOT multisampled, dest is multisampled.
1143 bool vogl_msaa_texture_splitter::copy_color_sample_to_stencil(
1144 GLuint src_texture, uint dest_sample_index, GLenum dest_target, GLuint dest_texture)
1146 bool exit_status = false;
1154 if ((dest_target != GL_TEXTURE_2D_MULTISAMPLE) && (dest_target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY))
1160 const GLenum src_target = (dest_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
1162 GL_ENTRYPOINT(glBindTexture)(src_target, src_texture);
1163 VOGL_CHECK_GL_ERROR;
1165 GL_ENTRYPOINT(glBindTexture)(dest_target, dest_texture);
1166 VOGL_CHECK_GL_ERROR;
1168 const int mip_level = 0;
1170 GLenum internal_fmt = 0;
1171 GL_ENTRYPOINT(glGetTexLevelParameteriv)(dest_target, mip_level, GL_TEXTURE_INTERNAL_FORMAT, reinterpret_cast<GLint *>(&internal_fmt));
1173 int width = 0, height = 0, depth = 0, samples = 0;
1174 GL_ENTRYPOINT(glGetTexLevelParameteriv)(dest_target, mip_level, GL_TEXTURE_WIDTH, &width);
1175 GL_ENTRYPOINT(glGetTexLevelParameteriv)(dest_target, mip_level, GL_TEXTURE_HEIGHT, &height);
1176 GL_ENTRYPOINT(glGetTexLevelParameteriv)(dest_target, mip_level, GL_TEXTURE_DEPTH, &depth);
1177 GL_ENTRYPOINT(glGetTexLevelParameteriv)(dest_target, mip_level, GL_TEXTURE_SAMPLES, &samples);
1179 GL_ENTRYPOINT(glBindTexture)(dest_target, 0);
1180 VOGL_CHECK_GL_ERROR;
1182 if ((vogl_check_gl_error()) || (width < 1) || (height < 1) || (depth < 1) || (samples < 1))
1185 const vogl_internal_tex_format *pInternal_tex_fmt = vogl_find_internal_texture_format(internal_fmt);
1186 if ((!pInternal_tex_fmt) || (pInternal_tex_fmt->m_optimum_get_image_fmt == GL_NONE) || (pInternal_tex_fmt->m_optimum_get_image_type == GL_NONE))
1189 if (!pInternal_tex_fmt->m_comp_sizes[cTCStencil])
1192 GLenum fbo_attachment_target = GL_STENCIL_ATTACHMENT;
1193 if (pInternal_tex_fmt->m_comp_sizes[cTCDepth])
1194 fbo_attachment_target = GL_DEPTH_STENCIL_ATTACHMENT;
1196 vogl_simple_gl_program &program = (dest_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) ? m_write_stencil_array_program : m_write_stencil_program;
1197 GL_ENTRYPOINT(glUseProgram)(program.get_handle());
1198 VOGL_CHECK_GL_ERROR;
1200 program.set_uniform("sample_mask", static_cast<int>(1 << dest_sample_index));
1202 GL_ENTRYPOINT(glColorMask)(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1203 VOGL_CHECK_GL_ERROR;
1205 GL_ENTRYPOINT(glStencilMask)(255);
1206 VOGL_CHECK_GL_ERROR;
1208 for (int layer = 0; layer < depth; layer++)
1211 GLuint fbo_handle = 0;
1212 GL_ENTRYPOINT(glGenFramebuffers)(1, &fbo_handle);
1213 VOGL_CHECK_GL_ERROR;
1215 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, fbo_handle);
1216 VOGL_CHECK_GL_ERROR;
1218 if (dest_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
1220 GL_ENTRYPOINT(glFramebufferTextureLayer)(GL_DRAW_FRAMEBUFFER, fbo_attachment_target, dest_texture, mip_level, layer);
1221 VOGL_CHECK_GL_ERROR;
1225 GL_ENTRYPOINT(glFramebufferTexture2D)(GL_DRAW_FRAMEBUFFER, fbo_attachment_target, dest_target, dest_texture, mip_level);
1226 VOGL_CHECK_GL_ERROR;
1229 GLenum draw_bufs[1] = { GL_NONE };
1230 GL_ENTRYPOINT(glDrawBuffers)(1, draw_bufs);
1231 VOGL_CHECK_GL_ERROR;
1233 GLenum fbo_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
1234 VOGL_CHECK_GL_ERROR;
1236 bool status = false;
1238 if (fbo_status == GL_FRAMEBUFFER_COMPLETE)
1240 // Render quad to FBO
1241 GL_ENTRYPOINT(glViewport)(0, 0, width, height);
1242 VOGL_CHECK_GL_ERROR;
1244 if (!dest_sample_index)
1246 GL_ENTRYPOINT(glClearStencil)(0);
1247 VOGL_CHECK_GL_ERROR;
1249 GL_ENTRYPOINT(glClear)(GL_STENCIL_BUFFER_BIT);
1250 VOGL_CHECK_GL_ERROR;
1253 vogl_quad_vertex quad_tri_verts[3*2];
1254 memcpy(quad_tri_verts, g_quad_tri_verts, sizeof(quad_tri_verts));
1256 for (uint i = 0; i < 6; i++)
1258 quad_tri_verts[i].m_uv0[0] *= width;
1259 quad_tri_verts[i].m_uv0[1] *= height;
1260 quad_tri_verts[i].m_uv0[2] = layer;
1263 GL_ENTRYPOINT(glBufferData)(GL_ARRAY_BUFFER, sizeof(quad_tri_verts), quad_tri_verts, GL_STATIC_DRAW);
1264 VOGL_CHECK_GL_ERROR;
1266 GL_ENTRYPOINT(glEnable)(GL_DEPTH_TEST);
1267 VOGL_CHECK_GL_ERROR;
1269 GL_ENTRYPOINT(glDepthMask)(GL_FALSE);
1270 VOGL_CHECK_GL_ERROR;
1272 GL_ENTRYPOINT(glDepthFunc)(GL_ALWAYS);
1273 VOGL_CHECK_GL_ERROR;
1275 GL_ENTRYPOINT(glEnable)(GL_STENCIL_TEST);
1276 VOGL_CHECK_GL_ERROR;
1278 GL_ENTRYPOINT(glStencilOp)(GL_KEEP, GL_KEEP, GL_REPLACE);
1279 VOGL_CHECK_GL_ERROR;
1281 for (uint stencil_val = 0; stencil_val <= 255; stencil_val++)
1283 program.set_uniform("stencil_comp_val", stencil_val / 255.0f);
1285 GL_ENTRYPOINT(glStencilFunc)(GL_ALWAYS, stencil_val, 0xFF);
1286 VOGL_CHECK_GL_ERROR;
1288 GL_ENTRYPOINT(glDrawArrays)(GL_TRIANGLES, 0, 6);
1289 VOGL_CHECK_GL_ERROR;
1297 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
1298 VOGL_CHECK_GL_ERROR;
1300 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &fbo_handle);
1301 VOGL_CHECK_GL_ERROR;
1303 GL_ENTRYPOINT(glDrawBuffer)(GL_FRONT_LEFT);
1304 VOGL_CHECK_GL_ERROR;
1314 GL_ENTRYPOINT(glBindTexture)(src_target, 0);
1315 VOGL_CHECK_GL_ERROR;
1317 GL_ENTRYPOINT(glBindTexture)(dest_target, 0);
1318 VOGL_CHECK_GL_ERROR;
1320 GL_ENTRYPOINT(glColorMask)(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1321 VOGL_CHECK_GL_ERROR;
1323 GL_ENTRYPOINT(glDisable)(GL_STENCIL_TEST);
1324 VOGL_CHECK_GL_ERROR;
1326 GL_ENTRYPOINT(glStencilMask)(0);
1327 VOGL_CHECK_GL_ERROR;