uint vogleditor_QProgramArbExplorer::set_program_objects(vogl::vector<vogl_context_snapshot*> sharingContexts) { clear(); m_pProgramEnvState = &(sharingContexts[0]->get_arb_program_environment_state()); m_maxEnvParameters = sharingContexts[0]->get_context_info().get_max_arb_vertex_program_env_params(); m_maxLocalParameters = (uint)sharingContexts[0]->get_general_state().get_value<int>(GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB); uint programCount = 0; for (uint c = 0; c < sharingContexts.size(); c++) { vogl_gl_object_state_ptr_vec programObjects; sharingContexts[c]->get_all_objects_of_category(cGLSTARBProgram, programObjects); programCount += add_program_objects(programObjects); } return programCount; }
// One multisampled source, multiple non-multisampled destinations created by method. bool vogl_msaa_texture_splitter::split(GLenum src_target, GLuint src_texture, vogl::vector<GLuint> &dest_textures) { dest_textures.resize(0); if (!m_valid) return false; if ((src_target != GL_TEXTURE_2D_MULTISAMPLE) && (src_target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) return false; GLenum dest_target = (src_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; GL_ENTRYPOINT(glBindTexture)(src_target, src_texture); VOGL_CHECK_GL_ERROR; GLint mip_level = 0, base_level = 0, max_level = 0; GLenum internal_fmt = 0; int base_width = 0, base_height = 0, base_depth = 0, samples = 0; GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, base_level, GL_TEXTURE_INTERNAL_FORMAT, reinterpret_cast<GLint *>(&internal_fmt)); GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, base_level, GL_TEXTURE_WIDTH, &base_width); GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, base_level, GL_TEXTURE_HEIGHT, &base_height); GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, base_level, GL_TEXTURE_DEPTH, &base_depth); GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, base_level, GL_TEXTURE_SAMPLES, &samples); VOGL_CHECK_GL_ERROR; if ((base_width < 1) || (base_height < 1) || (base_depth < 1) || (samples < 1)) return false; const vogl_internal_tex_format *pInternal_tex_fmt = vogl_find_internal_texture_format(internal_fmt); if ((!pInternal_tex_fmt) || (pInternal_tex_fmt->m_optimum_get_image_fmt == GL_NONE) || (pInternal_tex_fmt->m_optimum_get_image_type == GL_NONE)) return false; GLenum attachment_target = GL_COLOR_ATTACHMENT0; if ((pInternal_tex_fmt->m_comp_sizes[cTCDepth]) && (pInternal_tex_fmt->m_comp_sizes[cTCStencil])) attachment_target = GL_DEPTH_STENCIL_ATTACHMENT; else if (pInternal_tex_fmt->m_comp_sizes[cTCDepth]) attachment_target = GL_DEPTH_ATTACHMENT; else if (pInternal_tex_fmt->m_comp_sizes[cTCStencil]) return false; if (attachment_target == GL_COLOR_ATTACHMENT0) { GL_ENTRYPOINT(glDepthMask)(GL_FALSE); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glDisable)(GL_DEPTH_TEST); VOGL_CHECK_GL_ERROR; } else { GL_ENTRYPOINT(glDepthMask)(GL_TRUE); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glEnable)(GL_DEPTH_TEST); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glDepthFunc)(GL_ALWAYS); VOGL_CHECK_GL_ERROR; } GL_ENTRYPOINT(glDisable)(GL_STENCIL_TEST); VOGL_CHECK_GL_ERROR; uint32_t width = base_width << base_level; uint32_t height = base_height << base_level; uint32_t depth = base_depth; uint32_t max_possible_mip_levels = utils::compute_max_mips(width, height, depth); int num_actual_mip_levels = math::minimum<int>(max_possible_mip_levels, max_level + 1); for (int sample_index = 0; sample_index < samples; sample_index++) { m_read_color_program.set_uniform("tex_sample", sample_index); m_read_color_array_program.set_uniform("tex_sample", sample_index); m_read_depth_program.set_uniform("tex_sample", sample_index); m_read_depth_array_program.set_uniform("tex_sample", sample_index); GLuint dest_texture = 0; GL_ENTRYPOINT(glGenTextures)(1, &dest_texture); VOGL_CHECK_GL_ERROR; dest_textures.push_back(dest_texture); GL_ENTRYPOINT(glBindTexture)(dest_target, dest_texture); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glTexParameteri)(dest_target, GL_TEXTURE_BASE_LEVEL, base_level); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glTexParameteri)(dest_target, GL_TEXTURE_MAX_LEVEL, num_actual_mip_levels - 1); VOGL_CHECK_GL_ERROR; int mip_width = 0, mip_height = 0, mip_depth = 0; GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, mip_level, GL_TEXTURE_WIDTH, &mip_width); GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, mip_level, GL_TEXTURE_HEIGHT, &mip_height); GL_ENTRYPOINT(glGetTexLevelParameteriv)(src_target, mip_level, GL_TEXTURE_DEPTH, &mip_depth); if ((vogl_check_gl_error()) || (mip_width < 1) || (mip_height < 1) || (mip_depth < 1)) goto failure; VOGL_ASSERT(mip_depth == base_depth); VOGL_NOTE_UNUSED(mip_depth); vogl::vector<uint8_t> ones; ones.resize(static_cast<uint32_t>(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))); ones.set_all(255); if (src_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { GL_ENTRYPOINT(glTexImage3D)(dest_target, mip_level, internal_fmt, mip_width, mip_height, base_depth, 0, pInternal_tex_fmt->m_optimum_get_image_fmt, pInternal_tex_fmt->m_optimum_get_image_type, ones.get_ptr()); VOGL_CHECK_GL_ERROR; } else { GL_ENTRYPOINT(glTexImage2D)(dest_target, mip_level, internal_fmt, mip_width, mip_height, 0, pInternal_tex_fmt->m_optimum_get_image_fmt, pInternal_tex_fmt->m_optimum_get_image_type, ones.get_ptr()); VOGL_CHECK_GL_ERROR; } for (int layer = 0; layer < base_depth; layer++) { // Create FBO GLuint fbo_handle = 0; GL_ENTRYPOINT(glGenFramebuffers)(1, &fbo_handle); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, fbo_handle); VOGL_CHECK_GL_ERROR; if (dest_target == GL_TEXTURE_2D_ARRAY) { GL_ENTRYPOINT(glFramebufferTextureLayer)(GL_DRAW_FRAMEBUFFER, attachment_target, dest_texture, mip_level, layer); VOGL_CHECK_GL_ERROR; } else { GL_ENTRYPOINT(glFramebufferTexture2D)(GL_DRAW_FRAMEBUFFER, attachment_target, dest_target, dest_texture, mip_level); VOGL_CHECK_GL_ERROR; } if (attachment_target == GL_COLOR_ATTACHMENT0) { GLenum draw_buf = GL_COLOR_ATTACHMENT0; GL_ENTRYPOINT(glDrawBuffers)(1, &draw_buf); VOGL_CHECK_GL_ERROR; } else { GL_ENTRYPOINT(glDrawBuffer)(GL_NONE); VOGL_CHECK_GL_ERROR; } GLenum fbo_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER); VOGL_CHECK_GL_ERROR; bool status = false; if (fbo_status == GL_FRAMEBUFFER_COMPLETE) { // This method reads from a multisampled texture, which does NOT support GL_SKIP_DECODE_EXT on these targets. // 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. GL_ENTRYPOINT(glDisable)(GL_FRAMEBUFFER_SRGB); VOGL_CHECK_GL_ERROR; if (attachment_target == GL_COLOR_ATTACHMENT0) { GLint encoding = 0; GL_ENTRYPOINT(glGetFramebufferAttachmentParameteriv)(GL_DRAW_FRAMEBUFFER, attachment_target, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encoding); VOGL_CHECK_GL_ERROR; if (encoding == GL_SRGB) { GL_ENTRYPOINT(glEnable)(GL_FRAMEBUFFER_SRGB); VOGL_CHECK_GL_ERROR; } } // Render quad to FBO GL_ENTRYPOINT(glViewport)(0, 0, mip_width, mip_height); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glClearColor)(1.0f, 0.3f, 1.0f, 1.0f); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glClearDepth)(.25f); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glClearStencil)(64); VOGL_CHECK_GL_ERROR; if (attachment_target == GL_COLOR_ATTACHMENT0) { GL_ENTRYPOINT(glClear)(GL_COLOR_BUFFER_BIT); VOGL_CHECK_GL_ERROR; } else if (attachment_target == GL_DEPTH_ATTACHMENT) { GL_ENTRYPOINT(glClear)(GL_DEPTH_BUFFER_BIT); VOGL_CHECK_GL_ERROR; } else { GL_ENTRYPOINT(glClear)(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); VOGL_CHECK_GL_ERROR; } vogl_quad_vertex quad_tri_verts[3*2]; memcpy(quad_tri_verts, get_quad_tri_verts(), sizeof(quad_tri_verts)); for (uint32_t i = 0; i < 6; i++) { quad_tri_verts[i].m_uv0[0] *= mip_width; quad_tri_verts[i].m_uv0[1] *= mip_height; quad_tri_verts[i].m_uv0[2] = 1.0f * layer; } GL_ENTRYPOINT(glBufferData)(GL_ARRAY_BUFFER, sizeof(quad_tri_verts), quad_tri_verts, GL_STATIC_DRAW); VOGL_CHECK_GL_ERROR; if (attachment_target == GL_COLOR_ATTACHMENT0) { GL_ENTRYPOINT(glUseProgram)((src_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) ? m_read_color_array_program.get_handle() : m_read_color_program.get_handle()); VOGL_CHECK_GL_ERROR; } else { GL_ENTRYPOINT(glUseProgram)((src_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) ? m_read_depth_array_program.get_handle() : m_read_depth_program.get_handle()); VOGL_CHECK_GL_ERROR; } GL_ENTRYPOINT(glDrawArrays)(GL_TRIANGLES, 0, 6); VOGL_CHECK_GL_ERROR; status = true; } // fbo_status // Delete FBO GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glDeleteFramebuffers)(1, &fbo_handle); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glDrawBuffer)(GL_FRONT_LEFT); VOGL_CHECK_GL_ERROR; if (!status) goto failure; } // layer } // sample_index GL_ENTRYPOINT(glBindTexture)(src_target, 0); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glBindTexture)(dest_target, 0); VOGL_CHECK_GL_ERROR; return true; failure: GL_ENTRYPOINT(glBindTexture)(src_target, 0); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glBindTexture)(dest_target, 0); VOGL_CHECK_GL_ERROR; if (dest_textures.size()) { GL_ENTRYPOINT(glDeleteTextures)(dest_textures.size(), dest_textures.get_ptr()); VOGL_CHECK_GL_ERROR; dest_textures.resize(0); } return false; }