mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-25 01:31:14 -06:00 
			
		
		
		
	 8fd731f7a0
			
		
	
	
		8fd731f7a0
		
	
	
	
	
		
			
			Fixed some old support and infill issues. Fixes support problem #4295 Fixes Parts of interface layer extends beyond supports and cannot be printed Fixes support missing under horizontal overhang #6058 Fixes Slicer double-traces small sections of Rectilinear Supports, causes Fixes plastic buildup and nozzle crashes #4951 Fixes Add "Angle Interface layers" #2969
		
			
				
	
	
		
			313 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			313 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Why?
 | |
| #define _WIN32_WINNT 0x0502
 | |
| // The standard Windows includes.
 | |
| #define WIN32_LEAN_AND_MEAN
 | |
| #define NOMINMAX
 | |
| #include <Windows.h>
 | |
| #include <shellapi.h>
 | |
| #include <wchar.h>
 | |
| 
 | |
| 
 | |
| 
 | |
| #ifdef SLIC3R_GUI
 | |
| extern "C"
 | |
| {
 | |
|     // Let the NVIDIA and AMD know we want to use their graphics card
 | |
|     // on a dual graphics card system.
 | |
|     __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
 | |
|     __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
 | |
| }
 | |
| #endif /* SLIC3R_GUI */
 | |
| 
 | |
| #include <stdlib.h>
 | |
| #include <stdio.h>
 | |
| 
 | |
| #ifdef SLIC3R_GUI
 | |
|     #include <GL/GL.h>
 | |
| #endif /* SLIC3R_GUI */
 | |
| 
 | |
| #include <string>
 | |
| #include <vector>
 | |
| 
 | |
| #include <boost/algorithm/string/split.hpp>
 | |
| #include <boost/algorithm/string/classification.hpp>
 | |
| 
 | |
| #include <stdio.h>
 | |
| 
 | |
| #ifdef SLIC3R_GUI
 | |
| class OpenGLVersionCheck
 | |
| {
 | |
| public:
 | |
|     std::string version;
 | |
|     std::string glsl_version;
 | |
|     std::string vendor;
 | |
|     std::string renderer;
 | |
| 
 | |
|     HINSTANCE   hOpenGL = nullptr;
 | |
|     bool 		success = false;
 | |
| 
 | |
|     bool load_opengl_dll()
 | |
|     {
 | |
|         MSG      msg     = {0};
 | |
|         WNDCLASS wc      = {0};
 | |
|         wc.lpfnWndProc   = OpenGLVersionCheck::supports_opengl2_wndproc;
 | |
|         wc.hInstance     = (HINSTANCE)GetModuleHandle(nullptr);
 | |
|         wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
 | |
|         wc.lpszClassName = L"PrusaSlicer_opengl_version_check";
 | |
|         wc.style = CS_OWNDC;
 | |
|         if (RegisterClass(&wc)) {
 | |
|             HWND hwnd = CreateWindowW(wc.lpszClassName, L"PrusaSlicer_opengl_version_check", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, wc.hInstance, (LPVOID)this);
 | |
|             if (hwnd) {
 | |
|                 message_pump_exit = false;
 | |
|                 while (GetMessage(&msg, NULL, 0, 0 ) > 0 && ! message_pump_exit)
 | |
|                     DispatchMessage(&msg);
 | |
|             }
 | |
|         }
 | |
|         return this->success;
 | |
|     }
 | |
| 
 | |
|     void unload_opengl_dll()
 | |
|     {
 | |
|         if (this->hOpenGL) {
 | |
|             BOOL released = FreeLibrary(this->hOpenGL);
 | |
|             if (released)
 | |
|                 printf("System OpenGL library released\n");
 | |
|             else
 | |
|                 printf("System OpenGL library NOT released\n");
 | |
|             this->hOpenGL = nullptr;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     bool is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const
 | |
|     {
 | |
|         // printf("is_version_greater_or_equal_to, version: %s\n", version.c_str());
 | |
|         std::vector<std::string> tokens;
 | |
|         boost::split(tokens, version, boost::is_any_of(" "), boost::token_compress_on);
 | |
|         if (tokens.empty())
 | |
|             return false;
 | |
| 
 | |
|         std::vector<std::string> numbers;
 | |
|         boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on);
 | |
| 
 | |
|         unsigned int gl_major = 0;
 | |
|         unsigned int gl_minor = 0;
 | |
|         if (numbers.size() > 0)
 | |
|             gl_major = ::atoi(numbers[0].c_str());
 | |
|         if (numbers.size() > 1)
 | |
|             gl_minor = ::atoi(numbers[1].c_str());
 | |
|         // printf("Major: %d, minor: %d\n", gl_major, gl_minor);
 | |
|         if (gl_major < major)
 | |
|             return false;
 | |
|         else if (gl_major > major)
 | |
|             return true;
 | |
|         else
 | |
|             return gl_minor >= minor;
 | |
|     }
 | |
| 
 | |
| protected:
 | |
|     static bool message_pump_exit;
 | |
| 
 | |
|     void check(HWND hWnd)
 | |
|     {
 | |
|         hOpenGL = LoadLibraryExW(L"opengl32.dll", nullptr, 0);
 | |
|         if (hOpenGL == nullptr) {
 | |
|             printf("Failed loading the system opengl32.dll\n");
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         typedef HGLRC 		(WINAPI *Func_wglCreateContext)(HDC);
 | |
|         typedef BOOL 		(WINAPI *Func_wglMakeCurrent  )(HDC, HGLRC);
 | |
|         typedef BOOL     	(WINAPI *Func_wglDeleteContext)(HGLRC);
 | |
|         typedef GLubyte* 	(WINAPI *Func_glGetString     )(GLenum);
 | |
| 
 | |
|         Func_wglCreateContext 	wglCreateContext = (Func_wglCreateContext)GetProcAddress(hOpenGL, "wglCreateContext");
 | |
|         Func_wglMakeCurrent 	wglMakeCurrent 	 = (Func_wglMakeCurrent)  GetProcAddress(hOpenGL, "wglMakeCurrent");
 | |
|         Func_wglDeleteContext 	wglDeleteContext = (Func_wglDeleteContext)GetProcAddress(hOpenGL, "wglDeleteContext");
 | |
|         Func_glGetString 		glGetString 	 = (Func_glGetString)	  GetProcAddress(hOpenGL, "glGetString");
 | |
| 
 | |
|         if (wglCreateContext == nullptr || wglMakeCurrent == nullptr || wglDeleteContext == nullptr || glGetString == nullptr) {
 | |
|             printf("Failed loading the system opengl32.dll: The library is invalid.\n");
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         PIXELFORMATDESCRIPTOR pfd =
 | |
|         {
 | |
|             sizeof(PIXELFORMATDESCRIPTOR),
 | |
|             1,
 | |
|             PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
 | |
|             PFD_TYPE_RGBA,            	// The kind of framebuffer. RGBA or palette.
 | |
|             32,                        	// Color depth of the framebuffer.
 | |
|             0, 0, 0, 0, 0, 0,
 | |
|             0,
 | |
|             0,
 | |
|             0,
 | |
|             0, 0, 0, 0,
 | |
|             24,                        	// Number of bits for the depthbuffer
 | |
|             8,                        	// Number of bits for the stencilbuffer
 | |
|             0,                        	// Number of Aux buffers in the framebuffer.
 | |
|             PFD_MAIN_PLANE,
 | |
|             0,
 | |
|             0, 0, 0
 | |
|         };
 | |
| 
 | |
|         HDC ourWindowHandleToDeviceContext = ::GetDC(hWnd);
 | |
|         // Gdi32.dll
 | |
|         int letWindowsChooseThisPixelFormat = ::ChoosePixelFormat(ourWindowHandleToDeviceContext, &pfd);
 | |
|         // Gdi32.dll
 | |
|         SetPixelFormat(ourWindowHandleToDeviceContext, letWindowsChooseThisPixelFormat, &pfd);
 | |
|         // Opengl32.dll
 | |
|         HGLRC glcontext = wglCreateContext(ourWindowHandleToDeviceContext);
 | |
|         wglMakeCurrent(ourWindowHandleToDeviceContext, glcontext);
 | |
|         // Opengl32.dll
 | |
|         const char *data = (const char*)glGetString(GL_VERSION);
 | |
|         if (data != nullptr)
 | |
|             this->version = data;
 | |
|         // printf("check -version: %s\n", version.c_str());
 | |
|         data = (const char*)glGetString(0x8B8C); // GL_SHADING_LANGUAGE_VERSION
 | |
|         if (data != nullptr)
 | |
|             this->glsl_version = data;
 | |
|         data = (const char*)glGetString(GL_VENDOR);
 | |
|         if (data != nullptr)
 | |
|             this->vendor = data;
 | |
|         data = (const char*)glGetString(GL_RENDERER);
 | |
|         if (data != nullptr)
 | |
|             this->renderer = data;
 | |
|         // Opengl32.dll
 | |
|         wglDeleteContext(glcontext);
 | |
|         ::ReleaseDC(hWnd, ourWindowHandleToDeviceContext);
 | |
|         this->success = true;
 | |
|     }
 | |
| 
 | |
|     static LRESULT CALLBACK supports_opengl2_wndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 | |
|     {
 | |
|         switch(message)
 | |
|         {
 | |
|         case WM_CREATE:
 | |
|         {
 | |
|             CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);
 | |
|             OpenGLVersionCheck *ogl_data = reinterpret_cast<OpenGLVersionCheck*>(pCreate->lpCreateParams);
 | |
|             ogl_data->check(hWnd);
 | |
|             DestroyWindow(hWnd);
 | |
|             return 0;
 | |
|         }
 | |
|         case WM_NCDESTROY:
 | |
|             message_pump_exit = true;
 | |
|             return 0;
 | |
|         default:
 | |
|             return DefWindowProc(hWnd, message, wParam, lParam);
 | |
|         }
 | |
|     }
 | |
| };
 | |
| 
 | |
| bool OpenGLVersionCheck::message_pump_exit = false;
 | |
| #endif /* SLIC3R_GUI */
 | |
| 
 | |
| extern "C" {
 | |
|     typedef int (__stdcall *Slic3rMainFunc)(int argc, wchar_t **argv);
 | |
|     Slic3rMainFunc slic3r_main = nullptr;
 | |
| }
 | |
| 
 | |
| extern "C" {
 | |
| #ifdef SLIC3R_WRAPPER_NOCONSOLE
 | |
| int APIENTRY wWinMain(HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */, PWSTR /* lpCmdLine */, int /* nCmdShow */)
 | |
| {
 | |
|     int 	  argc;
 | |
|     wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
 | |
| #else
 | |
| int wmain(int argc, wchar_t **argv)
 | |
| {
 | |
| #endif
 | |
|     // Allow the asserts to open message box, such message box allows to ignore the assert and continue with the application.
 | |
|     // Without this call, the seemingly same message box is being opened by the abort() function, but that is too late and
 | |
|     // the application will be killed even if "Ignore" button is pressed.
 | |
|     _set_error_mode(_OUT_TO_MSGBOX);
 | |
| 
 | |
|     std::vector<wchar_t*> argv_extended;
 | |
|     argv_extended.emplace_back(argv[0]);
 | |
| 
 | |
| #ifdef SLIC3R_WRAPPER_GCODEVIEWER
 | |
|     wchar_t gcodeviewer_param[] = L"--gcodeviewer";
 | |
|     argv_extended.emplace_back(gcodeviewer_param);
 | |
| #endif /* SLIC3R_WRAPPER_GCODEVIEWER */
 | |
| 
 | |
| #ifdef SLIC3R_GUI
 | |
|     // Here one may push some additional parameters based on the wrapper type.
 | |
|     bool force_mesa = false;
 | |
| #endif /* SLIC3R_GUI */
 | |
|     for (int i = 1; i < argc; ++ i) {
 | |
| #ifdef SLIC3R_GUI
 | |
|         if (wcscmp(argv[i], L"--sw-renderer") == 0)
 | |
|             force_mesa = true;
 | |
|         else if (wcscmp(argv[i], L"--no-sw-renderer") == 0)
 | |
|             force_mesa = false;
 | |
| #endif /* SLIC3R_GUI */
 | |
|         argv_extended.emplace_back(argv[i]);
 | |
|     }
 | |
|     argv_extended.emplace_back(nullptr);
 | |
| 
 | |
| #ifdef SLIC3R_GUI
 | |
|     OpenGLVersionCheck opengl_version_check;
 | |
|     bool load_mesa =
 | |
|         // Forced from the command line.
 | |
|         force_mesa ||
 | |
|         // Running over a rempote desktop, and the RemoteFX is not enabled, therefore Windows will only provide SW OpenGL 1.1 context.
 | |
|         // In that case, use Mesa.
 | |
|         ::GetSystemMetrics(SM_REMOTESESSION) ||
 | |
|         // Try to load the default OpenGL driver and test its context version.
 | |
|         ! opengl_version_check.load_opengl_dll() || ! opengl_version_check.is_version_greater_or_equal_to(2, 0);
 | |
| #endif /* SLIC3R_GUI */
 | |
| 
 | |
|     wchar_t path_to_exe[MAX_PATH + 1] = { 0 };
 | |
|     ::GetModuleFileNameW(nullptr, path_to_exe, MAX_PATH);
 | |
|     wchar_t drive[_MAX_DRIVE];
 | |
|     wchar_t dir[_MAX_DIR];
 | |
|     wchar_t fname[_MAX_FNAME];
 | |
|     wchar_t ext[_MAX_EXT];
 | |
|     _wsplitpath(path_to_exe, drive, dir, fname, ext);
 | |
|     _wmakepath(path_to_exe, drive, dir, nullptr, nullptr);
 | |
| 
 | |
| #ifdef SLIC3R_GUI
 | |
| // https://wiki.qt.io/Cross_compiling_Mesa_for_Windows
 | |
| // http://download.qt.io/development_releases/prebuilt/llvmpipe/windows/
 | |
|     if (load_mesa) {
 | |
|         opengl_version_check.unload_opengl_dll();
 | |
|         wchar_t path_to_mesa[MAX_PATH + 1] = { 0 };
 | |
|         wcscpy(path_to_mesa, path_to_exe);
 | |
|         wcscat(path_to_mesa, L"mesa\\opengl32.dll");
 | |
|         printf("Loading MESA OpenGL library: %S\n", path_to_mesa);
 | |
|         HINSTANCE hInstance_OpenGL = LoadLibraryExW(path_to_mesa, nullptr, 0);
 | |
|         if (hInstance_OpenGL == nullptr) {
 | |
|             printf("MESA OpenGL library was not loaded\n");
 | |
|         } else
 | |
|             printf("MESA OpenGL library was loaded sucessfully\n");
 | |
|     }
 | |
| #endif /* SLIC3R_GUI */
 | |
| 
 | |
| 
 | |
|     wchar_t path_to_slic3r[MAX_PATH + 1] = { 0 };
 | |
|     wcscpy(path_to_slic3r, path_to_exe);
 | |
|     wcscat(path_to_slic3r, L"PrusaSlicer.dll");
 | |
| //	printf("Loading Slic3r library: %S\n", path_to_slic3r);
 | |
|     HINSTANCE hInstance_Slic3r = LoadLibraryExW(path_to_slic3r, nullptr, 0);
 | |
|     if (hInstance_Slic3r == nullptr) {
 | |
|         printf("PrusaSlicer.dll was not loaded\n");
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     // resolve function address here
 | |
|     slic3r_main = (Slic3rMainFunc)GetProcAddress(hInstance_Slic3r,
 | |
| #ifdef _WIN64
 | |
|         // there is just a single calling conversion, therefore no mangling of the function name.
 | |
|         "slic3r_main"
 | |
| #else	// stdcall calling convention declaration
 | |
|         "_slic3r_main@8"
 | |
| #endif
 | |
|         );
 | |
|     if (slic3r_main == nullptr) {
 | |
|         printf("could not locate the function slic3r_main in PrusaSlicer.dll\n");
 | |
|         return -1;
 | |
|     }
 | |
|     // argc minus the trailing nullptr of the argv
 | |
|     return slic3r_main((int)argv_extended.size() - 1, argv_extended.data());
 | |
| }
 | |
| }
 |