Delayed loading of the opengl texture for the G-code preview legend,

as the opengl context may not be ready on some platforms (Linux)
at the time the window gets its focus for the first time.

Changed the G-code preview invalidation to trigger when the print
gets invalidated. At that time the 3D path preview switches to the old
preview, if there is anything valid left.
This commit is contained in:
bubnikv 2018-02-15 14:37:53 +01:00
parent b5bdb46268
commit f9cdda7bfd
6 changed files with 68 additions and 79 deletions

View File

@ -1602,7 +1602,8 @@ sub draw_legend {
if ($self->_legend_enabled)
{
my $tex_id = Slic3r::GUI::_3DScene::get_legend_texture_id;
# If the legend texture has not been loaded into the GPU, do it now.
my $tex_id = Slic3r::GUI::_3DScene::finalize_legend_texture;
if ($tex_id > 0)
{
my $tex_w = Slic3r::GUI::_3DScene::get_legend_texture_width;

View File

@ -786,7 +786,6 @@ sub remove {
splice @{$self->{objects}}, $obj_idx, 1;
$self->{model}->delete_object($obj_idx);
$self->{print}->delete_object($obj_idx);
$self->{gcode_preview_data}->reset;
$self->{list}->DeleteItem($obj_idx);
$self->object_list_changed;
@ -807,7 +806,6 @@ sub reset {
@{$self->{objects}} = ();
$self->{model}->clear_objects;
$self->{print}->clear_objects;
$self->{gcode_preview_data}->reset;
$self->{list}->DeleteAllItems;
$self->object_list_changed;
@ -1161,6 +1159,7 @@ sub async_apply_config {
# Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared.
# Otherwise they will be just refreshed.
if ($invalidated) {
$self->{gcode_preview_data}->reset;
$self->{toolpaths2D}->reload_print if $self->{toolpaths2D};
$self->{preview3D}->reload_print if $self->{preview3D};
}
@ -1267,8 +1266,6 @@ sub reslice {
$self->stop_background_process;
# Rather perform one additional unnecessary update of the print object instead of skipping a pending async update.
$self->async_apply_config;
# Reset gcode data
$self->{gcode_preview_data}->reset;
$self->statusbar->SetCancelCallback(sub {
$self->stop_background_process;
$self->statusbar->SetStatusText("Slicing cancelled");

View File

@ -776,7 +776,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
_writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config.end_filament_gcode.get_at(m_writer.extruder()->id()), m_writer.extruder()->id()));
} else {
for (const std::string &end_gcode : print.config.end_filament_gcode.values)
_writeln(file, this->placeholder_parser_process("end_gcode", end_gcode, (unsigned int)(&end_gcode - &print.config.end_filament_gcode.values.front())));
_writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, (unsigned int)(&end_gcode - &print.config.end_filament_gcode.values.front())));
}
_writeln(file, this->placeholder_parser_process("end_gcode", print.config.end_gcode, m_writer.extruder()->id()));
_write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100%

View File

@ -1117,21 +1117,12 @@ const unsigned char _3DScene::LegendTexture::Squares_Border_Color[3] = { 64, 64,
const unsigned char _3DScene::LegendTexture::Background_Color[3] = { 9, 91, 134 };
const unsigned char _3DScene::LegendTexture::Opacity = 255;
_3DScene::LegendTexture::LegendTexture()
: m_tex_id(0)
, m_tex_width(0)
, m_tex_height(0)
// Generate a texture data, but don't load it into the GPU yet, as the GPU context may not yet be valid.
bool _3DScene::LegendTexture::generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
{
}
_3DScene::LegendTexture::~LegendTexture()
{
_destroy_texture();
}
bool _3DScene::LegendTexture::generate_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
{
_destroy_texture();
// Mark the texture as released, but don't release the texture from the GPU yet.
m_tex_width = m_tex_height = 0;
m_data.clear();
// collects items to render
const std::string& title = preview_data.get_legend_title();
@ -1241,64 +1232,45 @@ bool _3DScene::LegendTexture::generate_texture(const GCodePreviewData& preview_d
memDC.SelectObject(wxNullBitmap);
return _create_texture(preview_data, bitmap);
}
unsigned int _3DScene::LegendTexture::get_texture_id() const
{
return m_tex_id;
}
unsigned int _3DScene::LegendTexture::get_texture_width() const
{
return m_tex_width;
}
unsigned int _3DScene::LegendTexture::get_texture_height() const
{
return m_tex_height;
}
void _3DScene::LegendTexture::reset_texture()
{
_destroy_texture();
}
bool _3DScene::LegendTexture::_create_texture(const GCodePreviewData& preview_data, const wxBitmap& bitmap)
{
if ((m_tex_width == 0) || (m_tex_height == 0))
return false;
wxImage image = bitmap.ConvertToImage();
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
// prepare buffer
std::vector<unsigned char> buffer(4 * m_tex_width * m_tex_height, 0);
for (unsigned int h = 0; h < m_tex_height; ++h)
// Convert the bitmap into a linear data ready to be loaded into the GPU.
{
unsigned int hh = h * m_tex_width;
for (unsigned int w = 0; w < m_tex_width; ++w)
wxImage image = bitmap.ConvertToImage();
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
// prepare buffer
m_data.assign(4 * m_tex_width * m_tex_height, 0);
for (unsigned int h = 0; h < m_tex_height; ++h)
{
unsigned char* px_ptr = buffer.data() + 4 * (hh + w);
*px_ptr++ = image.GetRed(w, h);
*px_ptr++ = image.GetGreen(w, h);
*px_ptr++ = image.GetBlue(w, h);
*px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
unsigned int hh = h * m_tex_width;
unsigned char* px_ptr = m_data.data() + 4 * hh;
for (unsigned int w = 0; w < m_tex_width; ++w)
{
*px_ptr++ = image.GetRed(w, h);
*px_ptr++ = image.GetGreen(w, h);
*px_ptr++ = image.GetBlue(w, h);
*px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
}
}
}
// sends buffer to gpu
::glGenTextures(1, &m_tex_id);
::glBindTexture(GL_TEXTURE_2D, m_tex_id);
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)m_tex_width, (GLsizei)m_tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid*)buffer.data());
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
::glBindTexture(GL_TEXTURE_2D, 0);
return true;
}
unsigned int _3DScene::LegendTexture::finalize()
{
if (! m_data.empty()) {
// sends buffer to gpu
::glGenTextures(1, &m_tex_id);
::glBindTexture(GL_TEXTURE_2D, m_tex_id);
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)m_tex_width, (GLsizei)m_tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid*)m_data.data());
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
::glBindTexture(GL_TEXTURE_2D, 0);
m_data.clear();
}
return (m_tex_width > 0 && m_tex_height > 0) ? m_tex_id : 0;
}
void _3DScene::LegendTexture::_destroy_texture()
{
if (m_tex_id > 0)
@ -1308,6 +1280,7 @@ void _3DScene::LegendTexture::_destroy_texture()
m_tex_height = 0;
m_tex_width = 0;
}
m_data.clear();
}
void _3DScene::_glew_init()
@ -2267,7 +2240,12 @@ void _3DScene::_update_gcode_volumes_visibility(const GCodePreviewData& preview_
void _3DScene::_generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
{
s_legend_texture.generate_texture(preview_data, tool_colors);
s_legend_texture.generate(preview_data, tool_colors);
}
unsigned int _3DScene::finalize_legend_texture()
{
return s_legend_texture.finalize();
}
void _3DScene::_load_shells(const Print& print, GLVolumeCollection& volumes, bool use_VBOs)

View File

@ -421,20 +421,25 @@ class _3DScene
unsigned int m_tex_height;
public:
LegendTexture();
~LegendTexture();
LegendTexture() : m_tex_id(0), m_tex_width(0), m_tex_height(0) {}
~LegendTexture() { _destroy_texture(); }
bool generate_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
// Generate a texture data, but don't load it into the GPU yet, as the glcontext may not be valid yet.
bool generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
// If not loaded, load the texture data into the GPU. Return a texture ID or 0 if the texture has zero size.
unsigned int finalize();
unsigned int get_texture_id() const;
unsigned int get_texture_width() const;
unsigned int get_texture_height() const;
unsigned int get_texture_id() const { return m_tex_id; }
unsigned int get_texture_width() const { return m_tex_width; }
unsigned int get_texture_height() const { return m_tex_height; }
void reset_texture();
void reset_texture() { _destroy_texture(); }
private:
bool _create_texture(const GCodePreviewData& preview_data, const wxBitmap& bitmap);
void _destroy_texture();
// generate() fills in m_data with the pixels, while finalize() moves the data to the GPU before rendering.
std::vector<unsigned char> m_data;
};
static LegendTexture s_legend_texture;
@ -449,6 +454,7 @@ public:
static unsigned int get_legend_texture_height();
static void reset_legend_texture();
static unsigned int finalize_legend_texture();
static void _load_print_toolpaths(
const Print *print,

View File

@ -141,6 +141,13 @@ _glew_init()
CODE:
_3DScene::_glew_init();
unsigned int
finalize_legend_texture()
CODE:
RETVAL = _3DScene::finalize_legend_texture();
OUTPUT:
RETVAL
unsigned int
get_legend_texture_id()
CODE: