diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index b2b02b643..38df46e41 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -53,8 +53,10 @@ #define ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL (1 && ENABLE_2_5_0_ALPHA1) // Enable removal of legacy OpenGL calls #define ENABLE_LEGACY_OPENGL_REMOVAL (1 && ENABLE_2_5_0_ALPHA1) +// Enable OpenGL ES +#define ENABLE_OPENGL_ES (1 && ENABLE_LEGACY_OPENGL_REMOVAL) // Enable OpenGL core profile context (tested against Mesa 20.1.8 on Windows) -#define ENABLE_GL_CORE_PROFILE (1 && ENABLE_LEGACY_OPENGL_REMOVAL) +#define ENABLE_GL_CORE_PROFILE (1 && ENABLE_LEGACY_OPENGL_REMOVAL && !ENABLE_OPENGL_ES) // Enable OpenGL debug messages using debug context #define ENABLE_OPENGL_DEBUG_OPTION (1 && ENABLE_GL_CORE_PROFILE) // Shows an imgui dialog with GLModel statistics data diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 83b8cae63..863062211 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -916,13 +916,25 @@ void GLVolumeCollection::load_object_auxiliary( #if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL +#if ENABLE_OPENGL_ES +int GLVolumeCollection::load_wipe_tower_preview( + float pos_x, float pos_y, float width, float depth, float height, + float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh) +#else int GLVolumeCollection::load_wipe_tower_preview( float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width) +#endif // ENABLE_OPENGL_ES +#else +#if ENABLE_OPENGL_ES +int GLVolumeCollection::load_wipe_tower_preview( + int obj_idx, float pos_x, float pos_y, float width, float depth, float height, + float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh) #else int GLVolumeCollection::load_wipe_tower_preview( int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width) +#endif // ENABLE_OPENGL_ES #endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL #else #if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL @@ -1183,6 +1195,10 @@ int GLVolumeCollection::load_wipe_tower_preview( volumes.emplace_back(new GLVolume(color)); GLVolume& v = *volumes.back(); #if ENABLE_LEGACY_OPENGL_REMOVAL +#if ENABLE_OPENGL_ES + if (out_mesh != nullptr) + *out_mesh = mesh; +#endif // ENABLE_OPENGL_ES v.model.init_from(mesh); v.model.set_color(color); #if ENABLE_RAYCAST_PICKING diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index a47c8d05d..ad79485a4 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -675,11 +675,21 @@ public: size_t timestamp); #if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL +#if ENABLE_OPENGL_ES + int load_wipe_tower_preview( + float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh = nullptr); +#else int load_wipe_tower_preview( float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width); +#endif // ENABLE_OPENGL_ES +#else +#if ENABLE_OPENGL_ES + int load_wipe_tower_preview( + int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh = nullptr); #else int load_wipe_tower_preview( int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width); +#endif // ENABLE_OPENGL_ES #endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL #else std::vector load_object( diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index bf5443b03..35cac1d8c 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1220,9 +1220,16 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const // get vertices/normals data from vertex buffers on gpu for (size_t i = 0; i < t_buffer.vertices.vbos.size(); ++i) { const size_t floats_count = t_buffer.vertices.sizes[i] / sizeof(float); - VertexBuffer vertices(floats_count); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, t_buffer.vertices.vbos[i])); +#if ENABLE_OPENGL_ES + const VertexBuffer vertices = *static_cast(::glMapBufferRange(GL_ARRAY_BUFFER, 0, + static_cast(t_buffer.vertices.sizes[i]), GL_MAP_READ_BIT)); + glcheck(); + glsafe(::glUnmapBuffer(GL_ARRAY_BUFFER)); +#else + VertexBuffer vertices(floats_count); glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, 0, static_cast(t_buffer.vertices.sizes[i]), static_cast(vertices.data()))); +#endif // ENABLE_OPENGL_ES glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); const size_t vertices_count = floats_count / floats_per_vertex; for (size_t j = 0; j < vertices_count; ++j) { @@ -1270,9 +1277,17 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const // get indices data from index buffer on gpu glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuffer.ibo)); for (size_t j = 0; j < render_path.sizes.size(); ++j) { +#if ENABLE_OPENGL_ES + const IndexBuffer indices = *static_cast(::glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, + static_cast(render_path.offsets[j]), static_cast(render_path.sizes[j] * sizeof(IBufferType)), + GL_MAP_READ_BIT)); + glcheck(); + glsafe(::glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER)); +#else IndexBuffer indices(render_path.sizes[j]); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast(render_path.offsets[j]), static_cast(render_path.sizes[j] * sizeof(IBufferType)), static_cast(indices.data()))); +#endif // ENABLE_OPENGL_ES const size_t triangles_count = render_path.sizes[j] / 3; for (size_t k = 0; k < triangles_count; ++k) { @@ -2688,14 +2703,30 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool // gets the vertex index from the index buffer on gpu const IBuffer& i_buffer = buffer.indices[sub_path.first.b_id]; - IBufferType index = 0; glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); +#if ENABLE_OPENGL_ES + IBufferType index = *static_cast(::glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, + static_cast(offset * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), + GL_MAP_READ_BIT)); + glcheck(); + glsafe(::glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER)); +#else + IBufferType index = 0; glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast(offset * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&index))); +#endif // ENABLE_OPENGL_ES glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); // gets the position from the vertices buffer on gpu glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); +#if ENABLE_OPENGL_ES + sequential_view->current_position = *static_cast(::glMapBufferRange(GL_ARRAY_BUFFER, + static_cast(index * buffer.vertices.vertex_size_bytes()), + static_cast(buffer.vertices.position_size_bytes()), GL_MAP_READ_BIT)); + glcheck(); + glsafe(::glUnmapBuffer(GL_ARRAY_BUFFER)); +#else glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(index * buffer.vertices.vertex_size_bytes()), static_cast(3 * sizeof(float)), static_cast(sequential_view->current_position.data()))); +#endif // ENABLE_OPENGL_ES glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); sequential_view->current_offset = Vec3f::Zero(); @@ -2903,10 +2934,22 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool // extract indices from index buffer std::array indices{ 0, 0, 0, 0, 0, 0 }; glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); +#if ENABLE_OPENGL_ES + IBufferType* index_ptr = static_cast(::glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, + static_cast(offset * sizeof(IBufferType)), static_cast(14 * sizeof(IBufferType)), + GL_MAP_READ_BIT)); + glcheck(); + indices[0] = *(index_ptr + 0); + indices[1] = *(index_ptr + 7); + indices[2] = *(index_ptr + 1); + indices[4] = *(index_ptr + 13); + glsafe(::glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER)); +#else glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 0) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[0]))); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 7) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[1]))); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 1) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[2]))); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 13) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[4]))); +#endif // ENABLE_OPENGL_ES glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); indices[3] = indices[0]; indices[5] = indices[1]; @@ -2952,10 +2995,22 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool // extract indices from index buffer std::array indices{ 0, 0, 0, 0, 0, 0 }; glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); +#if ENABLE_OPENGL_ES + IBufferType* index_ptr = static_cast(::glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, + static_cast(offset * sizeof(IBufferType)), static_cast(17 * sizeof(IBufferType)), + GL_MAP_READ_BIT)); + glcheck(); + indices[0] = *(index_ptr + 2); + indices[1] = *(index_ptr + 4); + indices[2] = *(index_ptr + 10); + indices[5] = *(index_ptr + 16); + glsafe(::glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER)); +#else glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 2) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[0]))); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 4) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[1]))); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 10) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[2]))); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 16) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[5]))); +#endif // ENABLE_OPENGL_ES glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); indices[3] = indices[0]; indices[4] = indices[2]; @@ -3037,7 +3092,13 @@ void GCodeViewer::render_toolpaths() shader.set_uniform("gap_size", 0.0f); #endif // ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_ES + for (size_t i = 0; i < path.sizes.size(); ++i) { + glsafe(::glDrawElements(GL_LINES, (GLsizei)path.sizes[i], GL_UNSIGNED_SHORT, (const void*)path.offsets[i])); + } +#else glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); +#endif // ENABLE_OPENGL_ES #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_multi_lines_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -3055,7 +3116,13 @@ void GCodeViewer::render_toolpaths() assert(! path.sizes.empty()); assert(! path.offsets.empty()); shader.set_uniform(uniform_color, path.color); +#if ENABLE_OPENGL_ES + for (size_t i = 0; i < path.sizes.size(); ++i) { + glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)path.sizes[i], GL_UNSIGNED_SHORT, (const void*)path.offsets[i])); + } +#else glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); +#endif // ENABLE_OPENGL_ES #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_multi_triangles_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 6c924f1fa..6435c5463 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1215,7 +1215,11 @@ bool GLCanvas3D::init() return false; glsafe(::glClearColor(1.0f, 1.0f, 1.0f, 1.0f)); +#if ENABLE_OPENGL_ES + glsafe(::glClearDepthf(1.0f)); +#else glsafe(::glClearDepth(1.0f)); +#endif // ENABLE_OPENGL_ES glsafe(::glDepthFunc(GL_LESS)); @@ -2075,6 +2079,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re if (volume->is_wipe_tower) { // There is only one wipe tower. assert(volume_idx_wipe_tower_old == -1); +#if ENABLE_OPENGL_ES + m_wipe_tower_mesh.clear(); +#endif // ENABLE_OPENGL_ES volume_idx_wipe_tower_old = (int)volume_id; } if (!m_reload_delayed) { @@ -2323,13 +2330,25 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re #if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL +#if ENABLE_OPENGL_ES + int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( + x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower), + brim_width, &m_wipe_tower_mesh); +#else int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower), brim_width); +#endif // ENABLE_OPENGL_ES +#else +#if ENABLE_OPENGL_ES + int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( + 1000, x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower), + brim_width, &m_wipe_tower_mesh); #else int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( 1000, x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower), brim_width); +#endif // ENABLE_OPENGL_ES #endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL #else #if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL @@ -5639,7 +5658,11 @@ void GLCanvas3D::_rectangular_selection_picking_pass() glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, render_tex, 0)); glsafe(::glGenRenderbuffers(1, &render_depth)); glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, render_depth)); +#if ENABLE_OPENGL_ES + glsafe(::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height)); +#else glsafe(::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height)); +#endif // ENABLE_OPENGL_ES glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, render_depth)); } else { diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index e556c582e..d5e3d32d9 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -517,6 +517,9 @@ private: bool m_event_handlers_bound{ false }; GLVolumeCollection m_volumes; +#if ENABLE_OPENGL_ES + TriangleMesh m_wipe_tower_mesh; +#endif // ENABLE_OPENGL_ES GCodeViewer m_gcode_viewer; RenderTimer m_render_timer; diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index c8ffa71d1..4eb7d4f41 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -125,6 +125,22 @@ void GLModel::Geometry::add_vertex(const Vec3f& position, const Vec3f& normal, c vertices.emplace_back(tex_coord.y()); } +#if ENABLE_OPENGL_ES +void GLModel::Geometry::add_vertex(const Vec3f& position, const Vec3f& normal, const Vec3f& extra) +{ + assert(format.vertex_layout == EVertexLayout::P3N3E3); + vertices.emplace_back(position.x()); + vertices.emplace_back(position.y()); + vertices.emplace_back(position.z()); + vertices.emplace_back(normal.x()); + vertices.emplace_back(normal.y()); + vertices.emplace_back(normal.z()); + vertices.emplace_back(extra.x()); + vertices.emplace_back(extra.y()); + vertices.emplace_back(extra.z()); +} +#endif // ENABLE_OPENGL_ES + void GLModel::Geometry::add_vertex(const Vec4f& position) { assert(format.vertex_layout == EVertexLayout::P4); @@ -272,6 +288,9 @@ size_t GLModel::Geometry::vertex_stride_floats(const Format& format) case EVertexLayout::P3T2: { return 5; } case EVertexLayout::P3N3: { return 6; } case EVertexLayout::P3N3T2: { return 8; } +#if ENABLE_OPENGL_ES + case EVertexLayout::P3N3E3: { return 9; } +#endif // ENABLE_OPENGL_ES case EVertexLayout::P4: { return 4; } default: { assert(false); return 0; } }; @@ -286,7 +305,12 @@ size_t GLModel::Geometry::position_stride_floats(const Format& format) case EVertexLayout::P3: case EVertexLayout::P3T2: case EVertexLayout::P3N3: +#if ENABLE_OPENGL_ES + case EVertexLayout::P3N3T2: + case EVertexLayout::P3N3E3: { return 3; } +#else case EVertexLayout::P3N3T2: { return 3; } +#endif // ENABLE_OPENGL_ES case EVertexLayout::P4: { return 4; } default: { assert(false); return 0; } }; @@ -302,6 +326,9 @@ size_t GLModel::Geometry::position_offset_floats(const Format& format) case EVertexLayout::P3T2: case EVertexLayout::P3N3: case EVertexLayout::P3N3T2: +#if ENABLE_OPENGL_ES + case EVertexLayout::P3N3E3: +#endif // ENABLE_OPENGL_ES case EVertexLayout::P4: { return 0; } default: { assert(false); return 0; } }; @@ -312,7 +339,12 @@ size_t GLModel::Geometry::normal_stride_floats(const Format& format) switch (format.vertex_layout) { case EVertexLayout::P3N3: +#if ENABLE_OPENGL_ES + case EVertexLayout::P3N3T2: + case EVertexLayout::P3N3E3: { return 3; } +#else case EVertexLayout::P3N3T2: { return 3; } +#endif // ENABLE_OPENGL_ES default: { assert(false); return 0; } }; } @@ -322,7 +354,12 @@ size_t GLModel::Geometry::normal_offset_floats(const Format& format) switch (format.vertex_layout) { case EVertexLayout::P3N3: +#if ENABLE_OPENGL_ES + case EVertexLayout::P3N3T2: + case EVertexLayout::P3N3E3: { return 3; } +#else case EVertexLayout::P3N3T2: { return 3; } +#endif // ENABLE_OPENGL_ES default: { assert(false); return 0; } }; } @@ -349,6 +386,26 @@ size_t GLModel::Geometry::tex_coord_offset_floats(const Format& format) }; } +#if ENABLE_OPENGL_ES +size_t GLModel::Geometry::extra_stride_floats(const Format& format) +{ + switch (format.vertex_layout) + { + case EVertexLayout::P3N3E3: { return 3; } + default: { assert(false); return 0; } + }; +} + +size_t GLModel::Geometry::extra_offset_floats(const Format& format) +{ + switch (format.vertex_layout) + { + case EVertexLayout::P3N3E3: { return 6; } + default: { assert(false); return 0; } + }; +} +#endif // ENABLE_OPENGL_ES + size_t GLModel::Geometry::index_stride_bytes(const Geometry& data) { switch (data.index_type) @@ -370,6 +427,9 @@ bool GLModel::Geometry::has_position(const Format& format) case EVertexLayout::P3T2: case EVertexLayout::P3N3: case EVertexLayout::P3N3T2: +#if ENABLE_OPENGL_ES + case EVertexLayout::P3N3E3: +#endif // ENABLE_OPENGL_ES case EVertexLayout::P4: { return true; } default: { assert(false); return false; } }; @@ -385,7 +445,12 @@ bool GLModel::Geometry::has_normal(const Format& format) case EVertexLayout::P3T2: case EVertexLayout::P4: { return false; } case EVertexLayout::P3N3: +#if ENABLE_OPENGL_ES + case EVertexLayout::P3N3T2: + case EVertexLayout::P3N3E3: { return true; } +#else case EVertexLayout::P3N3T2: { return true; } +#endif // ENABLE_OPENGL_ES default: { assert(false); return false; } }; } @@ -400,10 +465,31 @@ bool GLModel::Geometry::has_tex_coord(const Format& format) case EVertexLayout::P2: case EVertexLayout::P3: case EVertexLayout::P3N3: +#if ENABLE_OPENGL_ES + case EVertexLayout::P3N3E3: +#endif // ENABLE_OPENGL_ES case EVertexLayout::P4: { return false; } default: { assert(false); return false; } }; } + +#if ENABLE_OPENGL_ES +bool GLModel::Geometry::has_extra(const Format& format) +{ + switch (format.vertex_layout) + { + case EVertexLayout::P3N3E3: { return true; } + case EVertexLayout::P2: + case EVertexLayout::P2T2: + case EVertexLayout::P3: + case EVertexLayout::P3T2: + case EVertexLayout::P3N3: + case EVertexLayout::P3N3T2: + case EVertexLayout::P4: { return false; } + default: { assert(false); return false; } + }; +} +#endif // ENABLE_OPENGL_ES #else size_t GLModel::Geometry::vertices_count() const { @@ -890,6 +976,9 @@ void GLModel::render(const std::pair& range) const bool position = Geometry::has_position(data.format); const bool normal = Geometry::has_normal(data.format); const bool tex_coord = Geometry::has_tex_coord(data.format); +#if ENABLE_OPENGL_ES + const bool extra = Geometry::has_extra(data.format); +#endif // ENABLE_OPENGL_ES #if ENABLE_GL_CORE_PROFILE if (OpenGLManager::get_gl_info().is_version_greater_or_equal_to(3, 0)) @@ -898,9 +987,12 @@ void GLModel::render(const std::pair& range) #endif // ENABLE_GL_CORE_PROFILE glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_render_data.vbo_id)); - int position_id = -1; - int normal_id = -1; + int position_id = -1; + int normal_id = -1; int tex_coord_id = -1; +#if ENABLE_OPENGL_ES + int extra_id = -1; +#endif // ENABLE_OPENGL_ES if (position) { position_id = shader->get_attrib_location("v_position"); @@ -923,6 +1015,15 @@ void GLModel::render(const std::pair& range) glsafe(::glEnableVertexAttribArray(tex_coord_id)); } } +#if ENABLE_OPENGL_ES + if (extra) { + extra_id = shader->get_attrib_location("v_extra"); + if (extra_id != -1) { + glsafe(::glVertexAttribPointer(extra_id, Geometry::extra_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::extra_offset_bytes(data.format))); + glsafe(::glEnableVertexAttribArray(extra_id)); + } + } +#endif // ENABLE_OPENGL_ES shader->set_uniform("uniform_color", data.color); @@ -935,6 +1036,10 @@ void GLModel::render(const std::pair& range) glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); #endif // !ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_ES + if (extra_id != -1) + glsafe(::glDisableVertexAttribArray(extra_id)); +#endif // ENABLE_OPENGL_ES if (tex_coord_id != -1) glsafe(::glDisableVertexAttribArray(tex_coord_id)); if (normal_id != -1) diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index 43398f450..3930c3a19 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -58,13 +58,16 @@ namespace GUI { enum class EVertexLayout : unsigned char { - P2, // position 2 floats - P2T2, // position 2 floats + texture coords 2 floats - P3, // position 3 floats - P3T2, // position 3 floats + texture coords 2 floats - P3N3, // position 3 floats + normal 3 floats + P2, // position 2 floats + P2T2, // position 2 floats + texture coords 2 floats + P3, // position 3 floats + P3T2, // position 3 floats + texture coords 2 floats + P3N3, // position 3 floats + normal 3 floats P3N3T2, // position 3 floats + normal 3 floats + texture coords 2 floats - P4, // position 4 floats +#if ENABLE_OPENGL_ES + P3N3E3, // position 3 floats + normal 3 floats + extra 3 floats +#endif // ENABLE_OPENGL_ES + P4, // position 4 floats }; enum class EIndexType : unsigned char @@ -95,6 +98,9 @@ namespace GUI { void add_vertex(const Vec3f& position, const Vec2f& tex_coord); // EVertexLayout::P3T2 void add_vertex(const Vec3f& position, const Vec3f& normal); // EVertexLayout::P3N3 void add_vertex(const Vec3f& position, const Vec3f& normal, const Vec2f& tex_coord); // EVertexLayout::P3N3T2 +#if ENABLE_OPENGL_ES + void add_vertex(const Vec3f& position, const Vec3f& normal, const Vec3f& extra); // EVertexLayout::P3N3E3 +#endif // ENABLE_OPENGL_ES void add_vertex(const Vec4f& position); // EVertexLayout::P4 void set_vertex(size_t id, const Vec3f& position, const Vec3f& normal); // EVertexLayout::P3N3 @@ -141,11 +147,21 @@ namespace GUI { static size_t tex_coord_offset_floats(const Format& format); static size_t tex_coord_offset_bytes(const Format& format) { return tex_coord_offset_floats(format) * sizeof(float); } +#if ENABLE_OPENGL_ES + static size_t extra_stride_floats(const Format& format); + static size_t extra_stride_bytes(const Format& format) { return extra_stride_floats(format) * sizeof(float); } + static size_t extra_offset_floats(const Format& format); + static size_t extra_offset_bytes(const Format& format) { return extra_offset_floats(format) * sizeof(float); } +#endif // ENABLE_OPENGL_ES + static size_t index_stride_bytes(const Geometry& data); static bool has_position(const Format& format); static bool has_normal(const Format& format); static bool has_tex_coord(const Format& format); +#if ENABLE_OPENGL_ES + static bool has_extra(const Format& format); +#endif // ENABLE_OPENGL_ES #else struct Entity { diff --git a/src/slic3r/GUI/GLSelectionRectangle.cpp b/src/slic3r/GUI/GLSelectionRectangle.cpp index 9249afc83..32dc9ad18 100644 --- a/src/slic3r/GUI/GLSelectionRectangle.cpp +++ b/src/slic3r/GUI/GLSelectionRectangle.cpp @@ -140,6 +140,7 @@ namespace GUI { glsafe(::glScaled(gui_scale, gui_scale, 1.0)); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL +#if !ENABLE_OPENGL_ES #if ENABLE_GL_CORE_PROFILE if (!core_profile) { #endif // ENABLE_GL_CORE_PROFILE @@ -149,13 +150,16 @@ namespace GUI { #if ENABLE_GL_CORE_PROFILE } #endif // ENABLE_GL_CORE_PROFILE +#endif // !ENABLE_OPENGL_ES #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_ES + GLShaderProgram* shader = wxGetApp().get_shader("dashed_lines"); +#elif ENABLE_GL_CORE_PROFILE GLShaderProgram* shader = core_profile ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat"); #else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_OPENGL_ES if (shader != nullptr) { shader->start_using(); @@ -165,7 +169,7 @@ namespace GUI { m_rectangle.reset(); GLModel::Geometry init_data; -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P4 }; init_data.reserve_vertices(8); init_data.reserve_indices(8); @@ -173,10 +177,10 @@ namespace GUI { init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2 }; init_data.reserve_vertices(4); init_data.reserve_indices(4); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES // vertices -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES const float width = right - left; const float height = top - bottom; float perimeter = 0.0f; @@ -213,14 +217,17 @@ namespace GUI { init_data.add_index(1); init_data.add_index(2); init_data.add_index(3); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES m_rectangle.init_from(std::move(init_data)); } shader->set_uniform("view_model_matrix", Transform3d::Identity()); shader->set_uniform("projection_matrix", Transform3d::Identity()); -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_ES + shader->set_uniform("dash_size", 0.01f); + shader->set_uniform("gap_size", 0.0075f); +#elif ENABLE_GL_CORE_PROFILE if (core_profile) { const std::array& viewport = wxGetApp().plater()->get_camera().get_viewport(); shader->set_uniform("viewport_size", Vec2d(double(viewport[2]), double(viewport[3]))); @@ -228,7 +235,7 @@ namespace GUI { shader->set_uniform("dash_size", 0.01f); shader->set_uniform("gap_size", 0.0075f); } -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_OPENGL_ES m_rectangle.set_color(ColorRGBA((m_state == EState::Select) ? 0.3f : 1.0f, (m_state == EState::Select) ? 1.0f : 0.3f, 0.3f, 1.0f)); m_rectangle.render(); @@ -243,10 +250,12 @@ namespace GUI { glsafe(::glEnd()); #endif // ENABLE_LEGACY_OPENGL_REMOVAL +#if !ENABLE_OPENGL_ES #if ENABLE_GL_CORE_PROFILE if (!core_profile) #endif // ENABLE_GL_CORE_PROFILE glsafe(::glPopAttrib()); +#endif // !ENABLE_OPENGL_ES #if !ENABLE_LEGACY_OPENGL_REMOVAL glsafe(::glPopMatrix()); diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index 0668ecec8..4171a57e3 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -37,7 +37,13 @@ std::pair GLShadersManager::init() bool valid = true; #if ENABLE_LEGACY_OPENGL_REMOVAL +#if ENABLE_OPENGL_ES + const std::string prefix = "ES/"; + // used to render wireframed triangles + valid &= append_shader("wireframe", { prefix + "wireframe.vs", prefix + "wireframe.fs" }); +#else const std::string prefix = GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 1) ? "140/" : "110/"; +#endif // ENABLE_OPENGL_ES // imgui shader valid &= append_shader("imgui", { prefix + "imgui.vs", prefix + "imgui.fs" }); // basic shader, used to render all what was previously rendered using the immediate mode @@ -48,11 +54,14 @@ std::pair GLShadersManager::init() valid &= append_shader("flat_texture", { prefix + "flat_texture.vs", prefix + "flat_texture.fs" }); // used to render 3D scene background valid &= append_shader("background", { prefix + "background.vs", prefix + "background.fs" }); -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_ES + // used to render dashed lines + valid &= append_shader("dashed_lines", { prefix + "dashed_lines.vs", prefix + "dashed_lines.fs" }); +#elif ENABLE_GL_CORE_PROFILE if (GUI::OpenGLManager::get_gl_info().is_core_profile()) // used to render thick and/or dashed lines valid &= append_shader("dashed_thick_lines", { prefix + "dashed_thick_lines.vs", prefix + "dashed_thick_lines.fs", prefix + "dashed_thick_lines.gs" }); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_OPENGL_ES #endif // ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_SHOW_TOOLPATHS_COG // used to render toolpaths center of gravity diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp index 17dfe9356..78c0e731d 100644 --- a/src/slic3r/GUI/GLTexture.cpp +++ b/src/slic3r/GUI/GLTexture.cpp @@ -335,10 +335,10 @@ void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right, glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); -#if !ENABLE_GL_CORE_PROFILE +#if !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES glsafe(::glEnable(GL_TEXTURE_2D)); glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)); -#endif // !ENABLE_GL_CORE_PROFILE +#endif // !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)tex_id)); @@ -382,9 +382,9 @@ void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right, glsafe(::glBindTexture(GL_TEXTURE_2D, 0)); -#if !ENABLE_GL_CORE_PROFILE +#if !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES glsafe(::glDisable(GL_TEXTURE_2D)); -#endif // !ENABLE_GL_CORE_PROFILE +#endif // !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES glsafe(::glDisable(GL_BLEND)); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index f326ab472..62611ac25 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -182,12 +182,12 @@ void GLGizmoPainterBase::render_cursor_circle() const float cnv_inv_height = 1.0f / cnv_height; const Vec2d center = m_parent.get_local_mouse_position(); -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES const float zoom = float(wxGetApp().plater()->get_camera().get_zoom()); const float radius = m_cursor_radius * zoom; #else const float radius = m_cursor_radius * float(wxGetApp().plater()->get_camera().get_zoom()); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES #else const float cnv_half_width = 0.5f * float(cnv_size.get_width()); const float cnv_half_height = 0.5f * float(cnv_size.get_height()); @@ -218,14 +218,14 @@ void GLGizmoPainterBase::render_cursor_circle() glsafe(::glScaled(gui_scale, gui_scale, 1.0)); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL -#if !ENABLE_GL_CORE_PROFILE +#if !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES glsafe(::glPushAttrib(GL_ENABLE_BIT)); glsafe(::glLineStipple(4, 0xAAAA)); glsafe(::glEnable(GL_LINE_STIPPLE)); -#endif // !ENABLE_GL_CORE_PROFILE +#endif // !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES if (!m_circle.is_initialized() || std::abs(m_old_cursor_radius - radius) > EPSILON) { m_old_cursor_radius = radius; m_circle.reset(); @@ -234,10 +234,10 @@ void GLGizmoPainterBase::render_cursor_circle() m_old_cursor_radius = radius; m_old_center = center; m_circle.reset(); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES GLModel::Geometry init_data; -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES const unsigned int StepsCount = (unsigned int)(2 * (4 + int(252 * (zoom - 1.0f) / (250.0f - 1.0f)))); const float StepSize = 2.0f * float(PI) / float(StepsCount); init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P2 }; @@ -245,14 +245,14 @@ void GLGizmoPainterBase::render_cursor_circle() static const unsigned int StepsCount = 32; static const float StepSize = 2.0f * float(PI) / float(StepsCount); init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2 }; -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES init_data.color = { 0.0f, 1.0f, 0.3f, 1.0f }; init_data.reserve_vertices(StepsCount); init_data.reserve_indices(StepsCount); // vertices + indices for (unsigned int i = 0; i < StepsCount; ++i) { -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES if (i % 2 != 0) continue; const float angle_i = float(i) * StepSize; @@ -269,7 +269,7 @@ void GLGizmoPainterBase::render_cursor_circle() init_data.add_vertex(Vec2f(2.0f * ((center.x() + ::cos(angle) * radius) * cnv_inv_width - 0.5f), -2.0f * ((center.y() + ::sin(angle) * radius) * cnv_inv_height - 0.5f))); init_data.add_index(i); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES } m_circle.init_from(std::move(init_data)); @@ -282,13 +282,13 @@ void GLGizmoPainterBase::render_cursor_circle() #endif // ENABLE_GL_CORE_PROFILE if (shader != nullptr) { shader->start_using(); -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES const Transform3d view_model_matrix = Geometry::translation_transform(Vec3d(2.0f * (center.x() * cnv_inv_width - 0.5f), -2.0f * (center.y() * cnv_inv_height - 0.5f), 0.0)) * Geometry::scale_transform(Vec3d(2.0f * radius * cnv_inv_width, 2.0f * radius * cnv_inv_height, 1.0f)); shader->set_uniform("view_model_matrix", view_model_matrix); #else shader->set_uniform("view_model_matrix", Transform3d::Identity()); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES shader->set_uniform("projection_matrix", Transform3d::Identity()); #if ENABLE_GL_CORE_PROFILE const std::array& viewport = wxGetApp().plater()->get_camera().get_viewport(); @@ -306,9 +306,9 @@ void GLGizmoPainterBase::render_cursor_circle() glsafe(::glEnd()); #endif // ENABLE_LEGACY_OPENGL_REMOVAL -#if !ENABLE_GL_CORE_PROFILE +#if !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES glsafe(::glPopAttrib()); -#endif // !ENABLE_GL_CORE_PROFILE +#endif // !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES #if !ENABLE_LEGACY_OPENGL_REMOVAL glsafe(::glPopMatrix()); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index 0134cf450..d501e6459 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -698,7 +698,30 @@ void GLGizmoSimplify::update_model(const State::Data &data) auto color = glmodel.get_color(); // when not reset it keeps old shape glmodel.reset(); +#if ENABLE_OPENGL_ES + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3E3 }; + init_data.reserve_vertices(3 * its.indices.size()); + init_data.reserve_indices(3 * its.indices.size()); + + // vertices + indices + std::array barycentric_coords = { Vec3f::UnitX(), Vec3f::UnitY(), Vec3f::UnitZ() }; + unsigned int vertices_counter = 0; + for (uint32_t i = 0; i < its.indices.size(); ++i) { + const stl_triangle_vertex_indices face = its.indices[i]; + const stl_vertex vertex[3] = { its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]] }; + const stl_vertex n = face_normal_normalized(vertex); + for (size_t j = 0; j < 3; ++j) { + init_data.add_vertex(vertex[j], n, barycentric_coords[j]); + } + vertices_counter += 3; + init_data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1); + } + + glmodel.init_from(std::move(init_data)); +#else glmodel.init_from(its); +#endif // ENABLE_OPENGL_ES #if ENABLE_LEGACY_OPENGL_REMOVAL glmodel.set_color(color); #else @@ -743,11 +766,11 @@ void GLGizmoSimplify::on_render() glsafe(::glMultMatrixd(trafo_matrix.data())); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL auto* gouraud_shader = wxGetApp().get_shader("gouraud_light"); -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES bool depth_test_enabled = ::glIsEnabled(GL_DEPTH_TEST); #else glsafe(::glPushAttrib(GL_DEPTH_TEST)); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES glsafe(::glEnable(GL_DEPTH_TEST)); gouraud_shader->start_using(); #if ENABLE_LEGACY_OPENGL_REMOVAL @@ -763,7 +786,11 @@ void GLGizmoSimplify::on_render() gouraud_shader->stop_using(); if (m_show_wireframe) { +#if ENABLE_OPENGL_ES + auto* contour_shader = wxGetApp().get_shader("wireframe"); +#else auto *contour_shader = wxGetApp().get_shader("mm_contour"); +#endif // ENABLE_OPENGL_ES contour_shader->start_using(); contour_shader->set_uniform("offset", OpenGLManager::get_gl_info().is_mesa() ? 0.0005 : 0.00001); #if ENABLE_LEGACY_OPENGL_REMOVAL @@ -776,20 +803,24 @@ void GLGizmoSimplify::on_render() if (!OpenGLManager::get_gl_info().is_core_profile()) #endif // ENABLE_GL_CORE_PROFILE glsafe(::glLineWidth(1.0f)); +#if !ENABLE_OPENGL_ES glsafe(::glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)); +#endif // !ENABLE_OPENGL_ES glmodel.render(); +#if !ENABLE_OPENGL_ES glsafe(::glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)); +#endif // !ENABLE_OPENGL_ES #if ENABLE_LEGACY_OPENGL_REMOVAL glmodel.set_color(color); #endif // ENABLE_LEGACY_OPENGL_REMOVAL contour_shader->stop_using(); } -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES if (depth_test_enabled) glsafe(::glEnable(GL_DEPTH_TEST)); #else glsafe(::glPopAttrib()); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES #if !ENABLE_LEGACY_OPENGL_REMOVAL glsafe(::glPopMatrix()); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index 19d073151..ce3ba1d4a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -222,23 +222,23 @@ void InstancesHider::render_cut() const glsafe(::glColor4fv(color.data())); } #endif // !ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES bool depth_test_enabled = ::glIsEnabled(GL_DEPTH_TEST); #else glsafe(::glPushAttrib(GL_DEPTH_TEST)); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES glsafe(::glDisable(GL_DEPTH_TEST)); #if ENABLE_LEGACY_OPENGL_REMOVAL clipper->render_cut(mv->is_model_part() ? ColorRGBA(0.8f, 0.3f, 0.0f, 1.0f) : color_from_model_volume(*mv)); #else clipper->render_cut(); #endif // ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES if (depth_test_enabled) glsafe(::glEnable(GL_DEPTH_TEST)); #else glsafe(::glPopAttrib()); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES #if !ENABLE_LEGACY_OPENGL_REMOVAL glsafe(::glPopMatrix()); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index b8220d609..a76f76e09 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -1480,7 +1480,7 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) draw_data->ScaleClipRects(io.DisplayFramebufferScale); #endif // ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES // Backup GL state GLenum last_active_texture; glsafe(::glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture)); GLuint last_program; glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program)); @@ -1537,7 +1537,7 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) glsafe(::glEnable(GL_TEXTURE_2D)); glsafe(::glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)); glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES #if ENABLE_LEGACY_OPENGL_REMOVAL // Setup viewport, orthographic projection matrix @@ -1679,7 +1679,7 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) #endif // ENABLE_LEGACY_OPENGL_REMOVAL } -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES // Restore modified GL state glsafe(::glBindTexture(GL_TEXTURE_2D, last_texture)); glsafe(::glActiveTexture(last_active_texture)); @@ -1713,7 +1713,7 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) glsafe(::glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]))); glsafe(::glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3])); glsafe(::glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3])); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES #if ENABLE_LEGACY_OPENGL_REMOVAL shader->stop_using(); diff --git a/src/slic3r/GUI/OpenGLManager.cpp b/src/slic3r/GUI/OpenGLManager.cpp index 9a296e172..5df41d59a 100644 --- a/src/slic3r/GUI/OpenGLManager.cpp +++ b/src/slic3r/GUI/OpenGLManager.cpp @@ -130,8 +130,16 @@ static bool version_greater_or_equal_to(const std::string& version, unsigned int if (tokens.empty()) return false; +#if ENABLE_OPENGL_ES + const std::string version_container = (tokens.size() > 1 && boost::istarts_with(tokens[1], "ES")) ? tokens[2] : tokens[0]; +#endif // ENABLE_OPENGL_ES + std::vector numbers; +#if ENABLE_OPENGL_ES + boost::split(numbers, version_container, boost::is_any_of("."), boost::token_compress_on); +#else boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on); +#endif // ENABLE_OPENGL_ES unsigned int gl_major = 0; unsigned int gl_minor = 0; @@ -320,9 +328,9 @@ static void CustomGLDebugOutput(GLenum source, GLenum type, unsigned int id, GLe bool OpenGLManager::init_gl() { if (!m_gl_initialized) { -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES glewExperimental = true; -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES GLenum err = glewInit(); if (err != GLEW_OK) { BOOST_LOG_TRIVIAL(error) << "Unable to init glew library: " << glewGetErrorString(err); @@ -356,22 +364,27 @@ bool OpenGLManager::init_gl() else s_framebuffers_type = EFramebufferType::Unknown; -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_ES + bool valid_version = s_gl_info.is_version_greater_or_equal_to(2, 0); +#elif ENABLE_GL_CORE_PROFILE bool valid_version = s_gl_info.is_core_profile() ? s_gl_info.is_version_greater_or_equal_to(3, 2) : s_gl_info.is_version_greater_or_equal_to(2, 0); #else bool valid_version = s_gl_info.is_version_greater_or_equal_to(2, 0); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_OPENGL_ES if (!valid_version) { // Complain about the OpenGL version. wxString message = from_u8((boost::format( -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_ES + _utf8(L("PrusaSlicer requires OpenGL ES 2.0 capable graphics driver to run correctly, \n" + "while OpenGL version %s, render %s, vendor %s was detected."))) % s_gl_info.get_version() % s_gl_info.get_renderer() % s_gl_info.get_vendor()).str()); +#elif ENABLE_GL_CORE_PROFILE _utf8(L("PrusaSlicer requires OpenGL %s capable graphics driver to run correctly, \n" "while OpenGL version %s, render %s, vendor %s was detected."))) % (s_gl_info.is_core_profile() ? "3.3" : "2.0") % s_gl_info.get_version() % s_gl_info.get_renderer() % s_gl_info.get_vendor()).str()); #else _utf8(L("PrusaSlicer requires OpenGL 2.0 capable graphics driver to run correctly, \n" "while OpenGL version %s, render %s, vendor %s was detected."))) % s_gl_info.get_version() % s_gl_info.get_renderer() % s_gl_info.get_vendor()).str()); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_OPENGL_ES message += "\n"; message += _L("You may need to update your graphics card driver."); #ifdef _WIN32 @@ -414,7 +427,11 @@ wxGLContext* OpenGLManager::init_glcontext(wxGLCanvas& canvas) #endif // ENABLE_GL_CORE_PROFILE { if (m_context == nullptr) { -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_ES + wxGLContextAttrs attrs; + attrs.PlatformDefaults().ES2().MajorVersion(2).EndList(); + m_context = new wxGLContext(&canvas, nullptr, &attrs); +#elif ENABLE_GL_CORE_PROFILE #if ENABLE_OPENGL_DEBUG_OPTION m_debug_enabled = enable_debug; #endif // ENABLE_OPENGL_DEBUG_OPTION @@ -491,7 +508,7 @@ wxGLContext* OpenGLManager::init_glcontext(wxGLCanvas& canvas) #endif // ENABLE_OPENGL_DEBUG_OPTION #else m_context = new wxGLContext(&canvas); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_OPENGL_ES #ifdef __APPLE__ // Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets @@ -505,7 +522,7 @@ wxGLContext* OpenGLManager::init_glcontext(wxGLCanvas& canvas) wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent) { -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES wxGLAttributes attribList; attribList.PlatformDefaults().RGBA().DoubleBuffer().MinRGBA(8, 8, 8, 8).Depth(24).SampleBuffers(1).Samplers(4).EndList(); #ifdef __APPLE__ @@ -528,7 +545,7 @@ wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent) WX_GL_SAMPLES, 4, 0 }; -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES if (s_multisample == EMultisampleState::Unknown) { detect_multisample(attribList); @@ -537,7 +554,7 @@ wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent) } if (!can_multisample()) -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES { attribList.Reset(); attribList.PlatformDefaults().RGBA().DoubleBuffer().MinRGBA(8, 8, 8, 8).Depth(24).EndList(); @@ -552,14 +569,14 @@ wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent) attribList[12] = 0; return new wxGLCanvas(&parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES } -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES void OpenGLManager::detect_multisample(const wxGLAttributes& attribList) #else void OpenGLManager::detect_multisample(int* attribList) -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES { int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER; bool enable_multisample = wxVersion >= 30003; diff --git a/src/slic3r/GUI/OpenGLManager.hpp b/src/slic3r/GUI/OpenGLManager.hpp index fb9d385a4..d8ca7eebb 100644 --- a/src/slic3r/GUI/OpenGLManager.hpp +++ b/src/slic3r/GUI/OpenGLManager.hpp @@ -6,9 +6,9 @@ class wxWindow; class wxGLCanvas; class wxGLContext; -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES class wxGLAttributes; -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES namespace Slic3r { namespace GUI { @@ -48,6 +48,14 @@ public: void set_core_profile(bool value) { m_core_profile = value; } bool is_mesa() const; + bool is_es() const { + return +#if ENABLE_OPENGL_ES + true; +#else + false; +#endif // ENABLE_OPENGL_ES + } int get_max_tex_size() const; float get_max_anisotropy() const; @@ -126,11 +134,11 @@ public: static const GLInfo& get_gl_info() { return s_gl_info; } private: -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES static void detect_multisample(const wxGLAttributes& attribList); #else static void detect_multisample(int* attribList); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES }; } // namespace GUI