ENABLE_THUMBNAIL_GENERATOR -> Generate thumbnails using GLEW_EXT_framebuffer_object on graphic cards supporting it
This commit is contained in:
parent
d8dca69d60
commit
41dadfdfcf
4 changed files with 129 additions and 11 deletions
|
@ -1653,10 +1653,12 @@ void GLCanvas3D::render()
|
||||||
#if ENABLE_THUMBNAIL_GENERATOR
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background)
|
void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background)
|
||||||
{
|
{
|
||||||
if (GLCanvas3DManager::are_framebuffers_supported())
|
switch (GLCanvas3DManager::get_framebuffers_type())
|
||||||
_render_thumbnail_framebuffer(thumbnail_data, w, h, printable_only, parts_only, transparent_background);
|
{
|
||||||
else
|
case GLCanvas3DManager::FB_Arb: { _render_thumbnail_framebuffer(thumbnail_data, w, h, printable_only, parts_only, transparent_background); break; }
|
||||||
_render_thumbnail_legacy(thumbnail_data, w, h, printable_only, parts_only, transparent_background);
|
case GLCanvas3DManager::FB_Ext: { _render_thumbnail_framebuffer_ext(thumbnail_data, w, h, printable_only, parts_only, transparent_background); break; }
|
||||||
|
default: { _render_thumbnail_legacy(thumbnail_data, w, h, printable_only, parts_only, transparent_background); break; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
|
@ -3772,6 +3774,110 @@ void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, un
|
||||||
glsafe(::glDisable(GL_MULTISAMPLE));
|
glsafe(::glDisable(GL_MULTISAMPLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background)
|
||||||
|
{
|
||||||
|
thumbnail_data.set(w, h);
|
||||||
|
if (!thumbnail_data.is_valid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool multisample = m_multisample_allowed;
|
||||||
|
if (multisample)
|
||||||
|
glsafe(::glEnable(GL_MULTISAMPLE));
|
||||||
|
|
||||||
|
GLint max_samples;
|
||||||
|
glsafe(::glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_samples));
|
||||||
|
GLsizei num_samples = max_samples / 2;
|
||||||
|
|
||||||
|
GLuint render_fbo;
|
||||||
|
glsafe(::glGenFramebuffersEXT(1, &render_fbo));
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, render_fbo));
|
||||||
|
|
||||||
|
GLuint render_tex = 0;
|
||||||
|
GLuint render_tex_buffer = 0;
|
||||||
|
if (multisample)
|
||||||
|
{
|
||||||
|
// use renderbuffer instead of texture to avoid the need to use glTexImage2DMultisample which is available only since OpenGL 3.2
|
||||||
|
glsafe(::glGenRenderbuffersEXT(1, &render_tex_buffer));
|
||||||
|
glsafe(::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_tex_buffer));
|
||||||
|
glsafe(::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, num_samples, GL_RGBA8, w, h));
|
||||||
|
glsafe(::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, render_tex_buffer));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glsafe(::glGenTextures(1, &render_tex));
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, render_tex));
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, render_tex, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint render_depth;
|
||||||
|
glsafe(::glGenRenderbuffersEXT(1, &render_depth));
|
||||||
|
glsafe(::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_depth));
|
||||||
|
if (multisample)
|
||||||
|
glsafe(::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, num_samples, GL_DEPTH_COMPONENT24, w, h));
|
||||||
|
else
|
||||||
|
glsafe(::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, w, h));
|
||||||
|
|
||||||
|
glsafe(::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, render_depth));
|
||||||
|
|
||||||
|
GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 };
|
||||||
|
glsafe(::glDrawBuffers(1, drawBufs));
|
||||||
|
|
||||||
|
if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||||
|
{
|
||||||
|
render_volumes_in_thumbnail(m_shader, m_volumes.volumes, thumbnail_data, printable_only, parts_only, transparent_background);
|
||||||
|
|
||||||
|
if (multisample)
|
||||||
|
{
|
||||||
|
GLuint resolve_fbo;
|
||||||
|
glsafe(::glGenFramebuffersEXT(1, &resolve_fbo));
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, resolve_fbo));
|
||||||
|
|
||||||
|
GLuint resolve_tex;
|
||||||
|
glsafe(::glGenTextures(1, &resolve_tex));
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, resolve_tex));
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, resolve_tex, 0));
|
||||||
|
|
||||||
|
glsafe(::glDrawBuffers(1, drawBufs));
|
||||||
|
|
||||||
|
if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||||
|
{
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, render_fbo));
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, resolve_fbo));
|
||||||
|
glsafe(::glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR));
|
||||||
|
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, resolve_fbo));
|
||||||
|
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
glsafe(::glDeleteTextures(1, &resolve_tex));
|
||||||
|
glsafe(::glDeleteFramebuffersEXT(1, &resolve_fbo));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
debug_output_thumbnail(thumbnail_data);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
}
|
||||||
|
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||||
|
glsafe(::glDeleteRenderbuffersEXT(1, &render_depth));
|
||||||
|
if (render_tex_buffer != 0)
|
||||||
|
glsafe(::glDeleteRenderbuffersEXT(1, &render_tex_buffer));
|
||||||
|
if (render_tex != 0)
|
||||||
|
glsafe(::glDeleteTextures(1, &render_tex));
|
||||||
|
glsafe(::glDeleteFramebuffersEXT(1, &render_fbo));
|
||||||
|
|
||||||
|
if (multisample)
|
||||||
|
glsafe(::glDisable(GL_MULTISAMPLE));
|
||||||
|
}
|
||||||
|
|
||||||
void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background)
|
void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background)
|
||||||
{
|
{
|
||||||
// check that thumbnail size does not exceed the default framebuffer size
|
// check that thumbnail size does not exceed the default framebuffer size
|
||||||
|
|
|
@ -685,7 +685,9 @@ private:
|
||||||
#if ENABLE_THUMBNAIL_GENERATOR
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
// render thumbnail using an off-screen framebuffer
|
// render thumbnail using an off-screen framebuffer
|
||||||
void _render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background);
|
void _render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background);
|
||||||
// render thumbnail using the default framebuffer
|
// render thumbnail using an off-screen framebuffer when GLEW_EXT_framebuffer_object is supported
|
||||||
|
void _render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background);
|
||||||
|
// render thumbnail using the default framebuffer
|
||||||
void _render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background);
|
void _render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background);
|
||||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
|
|
|
@ -189,7 +189,7 @@ std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool exten
|
||||||
|
|
||||||
GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas3DManager::MS_Unknown;
|
GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas3DManager::MS_Unknown;
|
||||||
bool GLCanvas3DManager::s_compressed_textures_supported = false;
|
bool GLCanvas3DManager::s_compressed_textures_supported = false;
|
||||||
bool GLCanvas3DManager::s_framebuffers_supported = false;
|
GLCanvas3DManager::EFramebufferType GLCanvas3DManager::s_framebuffers_type = GLCanvas3DManager::FB_None;
|
||||||
GLCanvas3DManager::GLInfo GLCanvas3DManager::s_gl_info;
|
GLCanvas3DManager::GLInfo GLCanvas3DManager::s_gl_info;
|
||||||
|
|
||||||
GLCanvas3DManager::GLCanvas3DManager()
|
GLCanvas3DManager::GLCanvas3DManager()
|
||||||
|
@ -270,10 +270,12 @@ void GLCanvas3DManager::init_gl()
|
||||||
else
|
else
|
||||||
s_compressed_textures_supported = false;
|
s_compressed_textures_supported = false;
|
||||||
|
|
||||||
if (s_gl_info.is_version_greater_or_equal_to(3, 0) && GLEW_ARB_framebuffer_object)
|
if (GLEW_ARB_framebuffer_object)
|
||||||
s_framebuffers_supported = true;
|
s_framebuffers_type = FB_Arb;
|
||||||
|
else if (GLEW_EXT_framebuffer_object)
|
||||||
|
s_framebuffers_type = FB_Ext;
|
||||||
else
|
else
|
||||||
s_framebuffers_supported = false;
|
s_framebuffers_type = FB_None;
|
||||||
|
|
||||||
if (! s_gl_info.is_version_greater_or_equal_to(2, 0)) {
|
if (! s_gl_info.is_version_greater_or_equal_to(2, 0)) {
|
||||||
// Complain about the OpenGL version.
|
// Complain about the OpenGL version.
|
||||||
|
|
|
@ -30,6 +30,13 @@ struct Camera;
|
||||||
class GLCanvas3DManager
|
class GLCanvas3DManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum EFramebufferType : unsigned char
|
||||||
|
{
|
||||||
|
FB_None,
|
||||||
|
FB_Arb,
|
||||||
|
FB_Ext
|
||||||
|
};
|
||||||
|
|
||||||
class GLInfo
|
class GLInfo
|
||||||
{
|
{
|
||||||
mutable bool m_detected;
|
mutable bool m_detected;
|
||||||
|
@ -77,7 +84,7 @@ private:
|
||||||
bool m_gl_initialized;
|
bool m_gl_initialized;
|
||||||
static EMultisampleState s_multisample;
|
static EMultisampleState s_multisample;
|
||||||
static bool s_compressed_textures_supported;
|
static bool s_compressed_textures_supported;
|
||||||
static bool s_framebuffers_supported;
|
static EFramebufferType s_framebuffers_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLCanvas3DManager();
|
GLCanvas3DManager();
|
||||||
|
@ -98,7 +105,8 @@ public:
|
||||||
|
|
||||||
static bool can_multisample() { return s_multisample == MS_Enabled; }
|
static bool can_multisample() { return s_multisample == MS_Enabled; }
|
||||||
static bool are_compressed_textures_supported() { return s_compressed_textures_supported; }
|
static bool are_compressed_textures_supported() { return s_compressed_textures_supported; }
|
||||||
static bool are_framebuffers_supported() { return s_framebuffers_supported; }
|
static bool are_framebuffers_supported() { return (s_framebuffers_type != FB_None); }
|
||||||
|
static EFramebufferType get_framebuffers_type() { return s_framebuffers_type; }
|
||||||
|
|
||||||
static wxGLCanvas* create_wxglcanvas(wxWindow *parent);
|
static wxGLCanvas* create_wxglcanvas(wxWindow *parent);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue