Changeset View
Standalone View
source/blender/windowmanager/intern/wm_platform_support.c
- This file was added.
| #include "BLI_sys_types.h" | |||||
| #include "BLI_dynstr.h" | |||||
| #include "BKE_global.h" | |||||
| #include "MEM_guardedalloc.h" | |||||
| #include "GHOST_C-api.h" | |||||
| #include "GPU_glew.h" | |||||
| #include <string.h> | |||||
| #include <stdio.h> | |||||
| typedef struct WM_PlatformSupport { | |||||
| /* Have we already initialized this struct. Must be the first field */ | |||||
| bool initialized; | |||||
| } WM_PlatformSupport; | |||||
| typedef enum eWMSupportLevel { | |||||
| WM_SUPPORT_LEVEL_SUPPORTED, | |||||
| WM_SUPPORT_LEVEL_LIMITED, | |||||
| WM_SUPPORT_LEVEL_UNSUPPORTED, | |||||
| } eWMSupportLevel; | |||||
| static WM_PlatformSupport WM_PLATFORM_SUPPRORT = {false}; | |||||
| static char* wm_platform_support_load_state(void) | |||||
| { | |||||
| /* TODO: Not implemented Yet */ | |||||
| return NULL; | |||||
| } | |||||
| static void wm_platform_support_save_state(char* platform_key) | |||||
| { | |||||
| /* TODO: Not Implemented Yet */ | |||||
| } | |||||
| static char* wm_platform_create_platform_key(const char* vendor, const char* renderer,const char* version) | |||||
| { | |||||
| DynStr *ds = BLI_dynstr_new(); | |||||
| BLI_dynstr_append(ds, vendor); | |||||
| BLI_dynstr_append(ds, "/"); | |||||
| BLI_dynstr_append(ds, renderer); | |||||
| BLI_dynstr_append(ds, "/"); | |||||
| BLI_dynstr_append(ds, version); | |||||
| char *platform_key = BLI_dynstr_get_cstring(ds); | |||||
| BLI_dynstr_free(ds); | |||||
| return platform_key; | |||||
| } | |||||
| static bool wm_platform_support_is_intel_gpu(const char* vendor, const char renderer) { | |||||
| return false; | |||||
| } | |||||
| static bool wm_platform_support_is_nvidia_gpu(const char* vendor, const char renderer) { | |||||
| return false; | |||||
| } | |||||
| static bool wm_platform_support_is_amd_gpu(const char* vendor, const char renderer) { | |||||
| return false; | |||||
| } | |||||
| static void wm_platform_support_create_link(char *link, const char* vendor, const char renderer) | |||||
| { | |||||
| DynStr *ds = BLI_dynstr_new(); | |||||
| BLI_dynstr_append(ds, "https://docs.blender.org/manual/en/latest/troubleshooting/gpu/"); | |||||
| #if defined(_WIN32) | |||||
| BLI_dynstr_append(ds, "windows/"); | |||||
| #elif defined(__APPLE) | |||||
| BLI_dynstr_append(ds, "apple/"); | |||||
| #else /* UNIX */ | |||||
| BLI_dynstr_append(ds, "linux/"); | |||||
| #endif | |||||
| if (wm_platform_support_is_intel_gpu(vendor, renderer)) { | |||||
| BLI_dynstr_append(ds, "intel.html"); | |||||
| } | |||||
| else if (wm_platform_support_is_nvidia_gpu(vendor, renderer)) { | |||||
| BLI_dynstr_append(ds, "nvidia.html"); | |||||
| } | |||||
| else if (wm_platform_support_is_amd_gpu(vendor, renderer)) { | |||||
| BLI_dynstr_append(ds, "amd.html"); | |||||
brecht: Don't show a warning for unknown vendors, we should purely be blacklisting, not whitelisting. | |||||
Done Inline ActionsChange latest to dev since the 2.80 manual does not have this info. We could change it after the release, though maybe it is better regardless to always link to the very latest manual, in case the driver download links change or we want to add extra info. brecht: Change `latest` to `dev` since the 2.80 manual does not have this info.
We could change it… | |||||
| } | |||||
| else { | |||||
| BLI_dynstr_append(ds, "unknown.html"); | |||||
| } | |||||
| BLI_assert(BLI_dynstr_get_len(ds) < 1024); | |||||
| BLI_dynstr_get_cstring_ex(ds, link); | |||||
| BLI_dynstr_free(ds); | |||||
| } | |||||
| GHOST_PlatformSupportDialogOptions wm_platform_support_ghost_callback(char *title, char *message, char *link) | |||||
| { | |||||
| /* User has already seen the message or has already confirmed in a | |||||
Done Inline ActionsIf a computer has graphics switching and both cards are unsupported, we will show the warning many times. So I think this should store multiple keys. For the implementation, BLI_file_read_as_lines could be used. New lines would have to be stripped. It's may also be simplest if wm_platform_support_load_state and wm_platform_support_save_state get merged into a single function. It can check if the given key is in the file, and if not append it. brecht: If a computer has graphics switching and both cards are unsupported, we will show the warning… | |||||
| * previous run */ | |||||
| if (WM_PLATFORM_SUPPRORT.initialized) { | |||||
| return GHOST_DialogNoDialog; | |||||
| } | |||||
| eWMSupportLevel support_level = WM_SUPPORT_LEVEL_SUPPORTED; | |||||
| /* don't show the messagebox when running in background mode. Only | |||||
| * print it in the console */ | |||||
| if (G.background) { | |||||
| return GHOST_DialogNoDialog; | |||||
| } | |||||
| const char *vendor = (const char *)glGetString(GL_VENDOR); | |||||
| const char *renderer = (const char *)glGetString(GL_RENDERER); | |||||
| const char *version = (const char *)glGetString(GL_VERSION); | |||||
| char *platform_key = wm_platform_create_platform_key(vendor, renderer, version); | |||||
| /* load previous platform check */ | |||||
| char *last_confirmed_platform_key = wm_platform_support_load_state(); | |||||
| /* check if previous check matches the current check */ | |||||
| if (last_confirmed_platform_key && strcmp(last_confirmed_platform_key, platform_key) == 0) { | |||||
| /* if it matches the user has confirmed and whishes to use it only report */ | |||||
| return GHOST_DialogNoDialog; | |||||
| } | |||||
| /* if it doesn't match we should perform compatibility checking */ | |||||
| /* GLEW should at least report version 3.3 */ | |||||
| if (!GLEW_VERSION_3_3) { | |||||
| support_level = WM_SUPPORT_LEVEL_UNSUPPORTED; | |||||
| } | |||||
| else { | |||||
| if (strstr(vendor, "ATI") || strstr(vendor, "AMD")) { | |||||
| #if defined(_WIN32) | |||||
| if (strstr(version, "4.5.13517")) { | |||||
Done Inline Actionsthis writes a \n that later will be returned in wm_platform_support_load_state causing the strcmp later on to fail and give the popup every time the user starts blender. LazyDodo: this writes a `\n` that later will be returned in `wm_platform_support_load_state` causing the… | |||||
Done Inline ActionsGotcha! well we will be refactoring load_state and save_state so this will not be an issue anymore jbakker: Gotcha! well we will be refactoring load_state and save_state so this will not be an issue… | |||||
| support_level = WM_SUPPORT_LEVEL_UNSUPPORTED; | |||||
| } | |||||
| #elif defined (__APPLE__) | |||||
| if (strstr(renderer, "AMD Radeon Pro") || strstr(renderer, "AMD Radeon R9") || | |||||
| strstr(renderer, "AMD Radeon RX")) { | |||||
| support_level = WM_SUPPORT_LEVEL_LIMITED; | |||||
| } | |||||
| #else /* UNIX based systems */ | |||||
| #endif | |||||
| } | |||||
| } | |||||
| /* update the message and link based on the found support level */ | |||||
| GHOST_PlatformSupportDialogOptions result = GHOST_DialogNoDialog; | |||||
| switch (support_level) { | |||||
| default: | |||||
| case WM_SUPPORT_LEVEL_SUPPORTED: | |||||
| result = GHOST_DialogNoDialog; | |||||
| break; | |||||
| case WM_SUPPORT_LEVEL_LIMITED: | |||||
| strcpy(title, "Blender - Limitted Platform Support"); | |||||
| strcpy(message, "Limitted Supported Platform"); | |||||
| result = GHOST_DialogShow; | |||||
| break; | |||||
| case WM_SUPPORT_LEVEL_UNSUPPORTED: | |||||
| strcpy(title, "Blender - Platform Unsupport"); | |||||
| strcpy(message, "Unsupported Platform"); | |||||
| result = GHOST_DialogShow | GHOST_DialogExit; | |||||
| break; | |||||
| } | |||||
| wm_platform_support_create_link(link, vendor, renderer); | |||||
| /* We are running in the background print the message in the console. */ | |||||
Done Inline ActionsI think we should deduplicate this code with gpu_extensions_init. What I suggest is to add gpu_platform.c containing gpu_platform_init() to detect GG.device, GG.driver and GG.os. GPU_type_matches(), eWM_SupportLevel, WM_PlatformSupportTest would all in that file as well then. gpu_extensions_init() would use GPU_type_matches(). brecht: I think we should deduplicate this code with `gpu_extensions_init`.
What I suggest is to add… | |||||
| if (G.background && (result & GHOST_DialogShow)) { | |||||
| printf(title); | |||||
| printf("\n"); | |||||
| printf("\n"); | |||||
| printf(message); | |||||
| printf("\n"); | |||||
| printf(link); | |||||
| printf("\n"); | |||||
| } | |||||
| /* Mark that we bothered the user already */ | |||||
| WM_PLATFORM_SUPPRORT.initialized = true; | |||||
| wm_platform_support_save_state(platform_key); | |||||
| MEM_freeN(platform_key); | |||||
| return result; | |||||
| } | |||||
| No newline at end of file | |||||
Done Inline ActionsLimitted -> Limited brecht: Limitted -> Limited | |||||
Done Inline Actions__APPLE -> __APPLE__ brecht: `__APPLE` -> `__APPLE__` | |||||
Done Inline ActionsWhy not save in background mode? brecht: Why not save in background mode? | |||||
Done Inline ActionsWhen running in background mode the user might not notice that there is a support issue. By not doing this during background we know for sure that the message has been seen. jbakker: When running in background mode the user might not notice that there is a support issue.
There… | |||||
Done Inline Actionsand -> or brecht: and -> or | |||||
Done Inline ActionsThis seems to say a solution is definitely possible, might want to formulate it a bit different. brecht: This seems to say a solution is definitely possible, might want to formulate it a bit different. | |||||
Done Inline ActionsLazyDodo: {F7785798}
1) layout doesn't look great
2) `Your graphics card and driver has limited.`… | |||||
Done Inline Actionsis -> are LazyDodo: is -> are | |||||

Don't show a warning for unknown vendors, we should purely be blacklisting, not whitelisting.