bool vogl_sync_state::remap_handles(vogl_handle_remapper &remapper) { VOGL_FUNC_TRACER m_snapshot_handle = remapper.remap_handle(VOGL_NAMESPACE_SYNCS, m_snapshot_handle); return true; }
bool vogl_vao_state::remap_handles(vogl_handle_remapper &remapper) { VOGL_FUNC_TRACER m_snapshot_handle = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_VERTEX_ARRAYS, m_snapshot_handle)); if (m_element_array_binding) m_element_array_binding = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_BUFFERS, m_element_array_binding)); for (uint32_t i = 0; i < m_vertex_attribs.size(); i++) { if (m_vertex_attribs[i].m_array_binding) m_vertex_attribs[i].m_array_binding = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_BUFFERS, m_vertex_attribs[i].m_array_binding)); else if (m_vertex_attribs[i].m_pointer) m_vertex_attribs[i].m_pointer = remapper.remap_vertex_attrib_ptr(i, m_vertex_attribs[i].m_pointer); } return true; }
bool vogl_sync_state::restore(const vogl_context_info &context_info, vogl_handle_remapper &remapper, GLuint64 &handle) const { VOGL_FUNC_TRACER VOGL_NOTE_UNUSED(context_info); if (!m_is_valid) return false; VOGL_CHECK_GL_ERROR; if (!handle) { GLsync sync = GL_ENTRYPOINT(glFenceSync)(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); if ((vogl_check_gl_error()) || (!sync)) return false; handle = vogl_sync_to_handle(sync); remapper.declare_handle(VOGL_NAMESPACE_SYNCS, m_snapshot_handle, handle, GL_NONE); VOGL_ASSERT(remapper.remap_handle(VOGL_NAMESPACE_SYNCS, m_snapshot_handle) == handle); } return true; }
bool vogl_vao_state::restore(const vogl_context_info &context_info, vogl_handle_remapper &remapper, GLuint64 &handle) const { VOGL_FUNC_TRACER VOGL_CHECK_GL_ERROR; if (!m_is_valid) return false; vogl_scoped_binding_state orig_binding(GL_VERTEX_ARRAY, GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER); if ((!m_snapshot_handle) && (!handle)) { GL_ENTRYPOINT(glBindVertexArray)(0); VOGL_CHECK_GL_ERROR; } else { if (!handle) { GLuint handle32 = 0; GL_ENTRYPOINT(glGenVertexArrays)(1, &handle32); if ((vogl_check_gl_error()) || (!handle32)) return false; handle = handle32; if (m_snapshot_handle) { remapper.declare_handle(VOGL_NAMESPACE_VERTEX_ARRAYS, m_snapshot_handle, handle, GL_NONE); VOGL_ASSERT(remapper.remap_handle(VOGL_NAMESPACE_VERTEX_ARRAYS, m_snapshot_handle) == handle); } } if (m_has_been_bound) { GL_ENTRYPOINT(glBindVertexArray)(static_cast<GLuint>(handle)); VOGL_CHECK_GL_ERROR; } } if (m_has_been_bound) { GL_ENTRYPOINT(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_BUFFERS, m_element_array_binding))); VOGL_CHECK_GL_ERROR; if (m_vertex_attribs.size() > context_info.get_max_vertex_attribs()) { vogl_warning_printf("Saved VAO state has %u attribs, but context only allows %u attribs\n", m_vertex_attribs.size(), context_info.get_max_vertex_attribs()); } for (uint32_t i = 0; i < math::minimum<uint32_t>(context_info.get_max_vertex_attribs(), m_vertex_attribs.size()); i++) { const vogl_vertex_attrib_desc &desc = m_vertex_attribs[i]; GL_ENTRYPOINT(glBindBuffer)(GL_ARRAY_BUFFER, static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_BUFFERS, desc.m_array_binding))); VOGL_CHECK_GL_ERROR; vogl_trace_ptr_value trace_ptr_val = desc.m_pointer; vogl_trace_ptr_value restore_ptr_val = trace_ptr_val; if ((!desc.m_array_binding) && (trace_ptr_val) && (context_info.is_compatibility_profile())) restore_ptr_val = remapper.remap_vertex_attrib_ptr(i, trace_ptr_val); void *pRestore_ptr = reinterpret_cast<void *>(restore_ptr_val); if ((handle) && (desc.m_array_binding == 0)) { // If it's a non-default VAO, and there's no array binding, we can't call glVertexAttribPointer() because it's not allowed by AMD drivers (it thinks we're trying to set client side array data) // "OpenGL: glVertexAttribPointer failed because it is not allowed to specify a client-side vertex or element array when a non-default vertex array object is bound (GL_INVALID_OPERATION) [source=API type=ERROR severity=HIGH id=2100]" // Sanity checks. if ((pRestore_ptr != NULL) || (desc.m_stride) || (desc.m_enabled)) { vogl_warning_printf("Can't bind client side vertex array data on a non-default VAO, trace handle %u GL handle %u, restore ptr %p, size %i stride %i enabled %u\n", m_snapshot_handle, static_cast<uint32_t>(handle), pRestore_ptr, desc.m_size, desc.m_stride, desc.m_enabled); } } else { if (desc.m_integer) { GL_ENTRYPOINT(glVertexAttribIPointer)(i, desc.m_size, desc.m_type, desc.m_stride, pRestore_ptr); VOGL_CHECK_GL_ERROR; } else { GL_ENTRYPOINT(glVertexAttribPointer)(i, desc.m_size, desc.m_type, desc.m_normalized, desc.m_stride, pRestore_ptr); VOGL_CHECK_GL_ERROR; } } GL_ENTRYPOINT(glVertexAttribDivisor)(i, desc.m_divisor); VOGL_CHECK_GL_ERROR; if (desc.m_enabled) { GL_ENTRYPOINT(glEnableVertexAttribArray)(i); VOGL_CHECK_GL_ERROR; } else { GL_ENTRYPOINT(glDisableVertexAttribArray)(i); VOGL_CHECK_GL_ERROR; } } } return true; }
bool vogl_query_state::restore(const vogl_context_info &context_info, vogl_handle_remapper &remapper, GLuint64 &handle) const { VOGL_FUNC_TRACER VOGL_NOTE_UNUSED(context_info); if (!m_is_valid) return false; bool created_handle = false; if (!handle) { GLuint handle32 = 0; GL_ENTRYPOINT(glGenQueries)(1, &handle32); if ((vogl_check_gl_error()) || (!handle32)) return false; handle = handle32; remapper.declare_handle(VOGL_NAMESPACE_QUERIES, m_snapshot_handle, handle, m_target); VOGL_ASSERT(remapper.remap_handle(VOGL_NAMESPACE_QUERIES, m_snapshot_handle) == handle); created_handle = true; } // m_target will be GL_NONE if the query has been genned but not begun up to this point. if ((m_target != GL_NONE) && (m_has_been_begun)) { GLuint prev_query = 0; GL_ENTRYPOINT(glGetQueryiv)(m_target, GL_CURRENT_QUERY, reinterpret_cast<GLint *>(&prev_query)); VOGL_CHECK_GL_ERROR; VOGL_ASSERT(handle <= cUINT32_MAX); // Begin end the restore query, so it becomes a valid name. GL_ENTRYPOINT(glBeginQuery)(m_target, static_cast<GLuint>(handle)); if (vogl_check_gl_error()) goto handle_error; GL_ENTRYPOINT(glEndQuery)(m_target); if (vogl_check_gl_error()) goto handle_error; if (prev_query) { // Now begin/end the original query so it's active again. The query API sucks. GL_ENTRYPOINT(glBeginQuery)(m_target, prev_query); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glEndQuery)(m_target); VOGL_CHECK_GL_ERROR; } } return true; handle_error: if ((handle) && (created_handle)) { remapper.delete_handle_and_object(VOGL_NAMESPACE_QUERIES, m_snapshot_handle, handle); //GLuint handle32 = static_cast<GLuint>(handle); //GL_ENTRYPOINT(glDeleteQueries)(1, &handle32); //VOGL_CHECK_GL_ERROR; handle = 0; } return false; }
bool vogl_renderbuffer_state::restore(const vogl_context_info &context_info, vogl_handle_remapper &remapper, GLuint64 &handle) const { VOGL_FUNC_TRACER VOGL_ASSERT(context_info.get_version() >= VOGL_GL_VERSION_3_0); if (!m_is_valid) return false; vogl_scoped_binding_state orig_renderbuffer(GL_RENDERBUFFER); bool created_handle = false; if (!handle) { GLuint handle32 = 0; GL_ENTRYPOINT(glGenRenderbuffers)(1, &handle32); if ((vogl_check_gl_error()) || (!handle32)) return false; handle = handle32; remapper.declare_handle(VOGL_NAMESPACE_RENDER_BUFFERS, m_snapshot_handle, handle, GL_NONE); VOGL_ASSERT(remapper.remap_handle(VOGL_NAMESPACE_RENDER_BUFFERS, m_snapshot_handle) == handle); created_handle = true; } GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, static_cast<GLuint>(handle)); if (vogl_check_gl_error()) goto handle_error; if ((m_desc.m_width) && (m_desc.m_height) && (m_desc.m_internal_format)) { if (!m_desc.restore(context_info)) goto handle_error; if (m_texture.is_valid()) { GLenum attachment = GL_COLOR_ATTACHMENT0; GLenum draw_and_read_buf = GL_COLOR_ATTACHMENT0; GLenum blit_type = GL_COLOR_BUFFER_BIT; if ((m_desc.m_depth_size) && (m_desc.m_stencil_size)) { attachment = GL_DEPTH_STENCIL_ATTACHMENT; draw_and_read_buf = GL_NONE; blit_type = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; } else if (m_desc.m_depth_size) { attachment = GL_DEPTH_ATTACHMENT; draw_and_read_buf = GL_NONE; blit_type = GL_DEPTH_BUFFER_BIT; } else if (m_desc.m_stencil_size) { attachment = GL_STENCIL_ATTACHMENT; draw_and_read_buf = GL_NONE; blit_type = GL_STENCIL_BUFFER_BIT; } bool restore_status = false; GLuint64 tex_handle64 = 0; vogl_handle_remapper def_handle_remapper; if (m_texture.restore(context_info, def_handle_remapper, tex_handle64)) { GLuint tex_handle = static_cast<GLuint>(tex_handle64); const GLenum tex_target = (m_desc.m_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D; GLuint src_fbo_handle = 0, dst_fbo_handle = 0; // Source FBO GL_ENTRYPOINT(glGenFramebuffers)(1, &src_fbo_handle); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, src_fbo_handle); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glFramebufferTexture2D)(GL_READ_FRAMEBUFFER, attachment, tex_target, tex_handle, 0); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glReadBuffer)(draw_and_read_buf); VOGL_CHECK_GL_ERROR; // Dest FBO GL_ENTRYPOINT(glGenFramebuffers)(1, &dst_fbo_handle); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, dst_fbo_handle); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, attachment, GL_RENDERBUFFER, static_cast<GLuint>(handle)); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glDrawBuffers)(1, &draw_and_read_buf); VOGL_CHECK_GL_ERROR; GLenum read_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_READ_FRAMEBUFFER); VOGL_CHECK_GL_ERROR; GLenum draw_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER); VOGL_CHECK_GL_ERROR; if ((read_status = GL_FRAMEBUFFER_COMPLETE) && (draw_status == GL_FRAMEBUFFER_COMPLETE)) { #if 0 // HACK HACK HACK if (m_texture.get_num_samples() > 1) { uint base_level = m_texture.get_params().get_value<GLenum>(GL_TEXTURE_BASE_LEVEL); if (base_level < m_texture.get_num_levels()) { const vogl_state_vector &state_vec = m_texture.get_level_params(0, base_level); uint clear_mask = 0; if (state_vec.get_value<GLenum>(GL_TEXTURE_DEPTH_SIZE)) { clear_mask |= GL_DEPTH_BUFFER_BIT; } if (state_vec.get_value<GLenum>(GL_TEXTURE_STENCIL_SIZE)) { clear_mask |= GL_STENCIL_BUFFER_BIT; } if (state_vec.get_value<GLenum>(GL_TEXTURE_RED_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_GREEN_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_BLUE_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_ALPHA_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_INTENSITY_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_LUMINANCE_SIZE)) { clear_mask |= GL_COLOR_BUFFER_BIT; } GL_ENTRYPOINT(glClearColor)(1.0f, 0.0f, 1.0f, 1.0f); GL_ENTRYPOINT(glClearDepth)(.5f); GL_ENTRYPOINT(glClearStencil)(128); GL_ENTRYPOINT(glClear)(clear_mask); VOGL_CHECK_GL_ERROR; } } else #endif { GL_ENTRYPOINT(glBlitFramebuffer)( 0, 0, m_desc.m_width, m_desc.m_height, 0, 0, m_desc.m_width, m_desc.m_height, blit_type, GL_NEAREST); if (!vogl_check_gl_error_internal()) { restore_status = true; } } } // Delete FBO GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glDeleteFramebuffers)(1, &dst_fbo_handle); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, 0); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glDeleteFramebuffers)(1, &src_fbo_handle); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glDeleteTextures)(1, &tex_handle); VOGL_CHECK_GL_ERROR; } if (!restore_status) { vogl_error_printf("%s: Failed restoring contents of renderbuffer %u\n", VOGL_METHOD_NAME, static_cast<GLuint>(handle)); } } } return true; handle_error: if (created_handle) { GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, 0); VOGL_CHECK_GL_ERROR; remapper.delete_handle_and_object(VOGL_NAMESPACE_RENDER_BUFFERS, m_snapshot_handle, handle); //GLuint handle32 = static_cast<GLuint>(handle); //GL_ENTRYPOINT(glDeleteRenderbuffers)(1, &handle32); //VOGL_CHECK_GL_ERROR; handle = 0; } return false; }