GetConsoleMode() can be quite slow and in mpv the mode never changes, so we can just check it once. Fixes performance when writing lots of logs to terminal.
Unified · Split
| @@ -304,30 +304,6 @@ static int mp_vfprintf(FILE *stream, const char *format, va_list args) · 303 unmodified lines | |||
| 304 | return vfprintf(stream, format, args); | 304 | return vfprintf(stream, format, args); |
| 305 | } | 305 | } |
| 306 | #else | 306 | #else |
| 307 | static int mp_check_console(HANDLE wstream) | ||
| 308 | { | ||
| 309 | if (wstream != INVALID_HANDLE_VALUE) { | ||
| 310 | unsigned int filetype = GetFileType(wstream); | ||
| 311 | |||
| 312 | if (!((filetype == FILE_TYPE_UNKNOWN) && | ||
| 313 | (GetLastError() != ERROR_SUCCESS))) | ||
| 314 | { | ||
| 315 | filetype &= ~(FILE_TYPE_REMOTE); | ||
| 316 | |||
| 317 | if (filetype == FILE_TYPE_CHAR) { | ||
| 318 | DWORD ConsoleMode; | ||
| 319 | int ret = GetConsoleMode(wstream, &ConsoleMode); | ||
| 320 | |||
| 321 | if (!(!ret && (GetLastError() == ERROR_INVALID_HANDLE))) { | ||
| 322 | // This seems to be a console | ||
| 323 | return 1; | ||
| 324 | } | ||
| 325 | } | ||
| 326 | } | ||
| 327 | } | ||
| 328 | |||
| 329 | return 0; | ||
| 330 | } | ||
| 331 | 307 | ||
| 332 | static int mp_vfprintf(FILE *stream, const char *format, va_list args) | 308 | static int mp_vfprintf(FILE *stream, const char *format, va_list args) |
| 333 | { | 309 | { |
| @@ -53,20 +53,16 @@ static void attempt_native_out_vt(HANDLE hOut, DWORD basemode) · 52 unmodified lines | |||
| 53 | SetConsoleMode(hOut, basemode); | 53 | SetConsoleMode(hOut, basemode); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | static bool is_native_out_vt(HANDLE hOut) | ||
| 57 | { | ||
| 58 | DWORD cmode; | ||
| 59 | return GetConsoleMode(hOut, &cmode) && | ||
| 60 | (cmode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) && | ||
| 61 | !(cmode & DISABLE_NEWLINE_AUTO_RETURN); | ||
| 62 | } | ||
| 63 | 56 | ||
| 57 | #define hSTDIN GetStdHandle(STD_INPUT_HANDLE) | ||
| 64 | #define hSTDOUT GetStdHandle(STD_OUTPUT_HANDLE) | 58 | #define hSTDOUT GetStdHandle(STD_OUTPUT_HANDLE) |
| 65 | #define hSTDERR GetStdHandle(STD_ERROR_HANDLE) | 59 | #define hSTDERR GetStdHandle(STD_ERROR_HANDLE) |
| 66 | 60 | ||
| 67 | #define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) | 61 | #define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) |
| 68 | #define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE) | 62 | #define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE) |
| 69 | 63 | ||
| 64 | static bool is_console[STDERR_FILENO + 1]; | ||
| 65 | static bool is_vt[STDERR_FILENO + 1]; | ||
| 70 | static short stdoutAttrs = 0; // copied from the screen buffer on init | 66 | static short stdoutAttrs = 0; // copied from the screen buffer on init |
| 71 | static const unsigned char ansi2win32[8] = { | 67 | static const unsigned char ansi2win32[8] = { |
| 72 | 0, | 68 | 0, |
| @@ -94,6 +90,23 @@ static HANDLE death; · 21 unmodified lines | |||
| 94 | static mp_thread input_thread; | 90 | static mp_thread input_thread; |
| 95 | static struct input_ctx *input_ctx; | 91 | static struct input_ctx *input_ctx; |
| 96 | 92 | ||
| 93 | static bool is_native_out_vt_internal(HANDLE hOut) | ||
| 94 | { | ||
| 95 | DWORD cmode; | ||
| 96 | return GetConsoleMode(hOut, &cmode) && | ||
| 97 | (cmode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) && | ||
| 98 | !(cmode & DISABLE_NEWLINE_AUTO_RETURN); | ||
| 99 | } | ||
| 100 | |||
| 101 | static bool is_native_out_vt(HANDLE hOut) | ||
| 102 | { | ||
| 103 | if (hOut == hSTDOUT) | ||
| 104 | return is_vt[STDOUT_FILENO]; | ||
| 105 | if (hOut == hSTDERR) | ||
| 106 | return is_vt[STDERR_FILENO]; | ||
| 107 | return is_native_out_vt_internal(hOut); | ||
| 108 | } | ||
| 109 | |||
| 97 | void terminal_get_size(int *w, int *h) | 110 | void terminal_get_size(int *w, int *h) |
| 98 | { | 111 | { |
| 99 | CONSOLE_SCREEN_BUFFER_INFO cinfo; | 112 | CONSOLE_SCREEN_BUFFER_INFO cinfo; |
| @@ -360,6 +373,17 @@ static bool is_a_console(HANDLE h) · 260 unmodified lines | |||
| 360 | return GetConsoleMode(h, &(DWORD){0}); | 373 | return GetConsoleMode(h, &(DWORD){0}); |
| 361 | } | 374 | } |
| 362 | 375 | ||
| 376 | bool mp_check_console(void *handle) | ||
| 377 | { | ||
| 378 | if (handle == hSTDIN) | ||
| 379 | return is_console[STDIN_FILENO]; | ||
| 380 | if (handle == hSTDOUT) | ||
| 381 | return is_console[STDOUT_FILENO]; | ||
| 382 | if (handle == hSTDERR) | ||
| 383 | return is_console[STDERR_FILENO]; | ||
| 384 | return is_a_console(handle); | ||
| 385 | } | ||
| 386 | |||
| 363 | static void reopen_console_handle(DWORD std, int fd, FILE *stream) | 387 | static void reopen_console_handle(DWORD std, int fd, FILE *stream) |
| 364 | { | 388 | { |
| 365 | HANDLE handle = GetStdHandle(std); | 389 | HANDLE handle = GetStdHandle(std); |
| @@ -419,6 +443,16 @@ void terminal_init(void) · 53 unmodified lines | |||
| 419 | cmode |= (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT); | 443 | cmode |= (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT); |
| 420 | attempt_native_out_vt(hSTDOUT, cmode); | 444 | attempt_native_out_vt(hSTDOUT, cmode); |
| 421 | attempt_native_out_vt(hSTDERR, cmode); | 445 | attempt_native_out_vt(hSTDERR, cmode); |
| 446 | |||
| 447 | // Init for mp_check_console(), this never changes during runtime | ||
| 448 | is_console[STDIN_FILENO] = is_a_console(hSTDIN); | ||
| 449 | is_console[STDOUT_FILENO] = is_a_console(hSTDOUT); | ||
| 450 | is_console[STDERR_FILENO] = is_a_console(hSTDERR); | ||
| 451 | |||
| 452 | // Init for is_native_out_vt(), this is never disabled/changed during runtime | ||
| 453 | is_vt[STDOUT_FILENO] = is_native_out_vt_internal(hSTDOUT); | ||
| 454 | is_vt[STDERR_FILENO] = is_native_out_vt_internal(hSTDERR); | ||
| 455 | |||
| 422 | GetConsoleScreenBufferInfo(hSTDOUT, &cinfo); | 456 | GetConsoleScreenBufferInfo(hSTDOUT, &cinfo); |
| 423 | stdoutAttrs = cinfo.wAttributes; | 457 | stdoutAttrs = cinfo.wAttributes; |
| 424 | } | 458 | } |
| @@ -53,6 +53,7 @@ void terminal_get_size2(int *rows, int *cols, int *px_width, int *px_height); · 52 unmodified lines | |||
| 53 | 53 | ||
| 54 | // Windows only. | 54 | // Windows only. |
| 55 | void mp_write_console_ansi(void *wstream, char *buf); | 55 | void mp_write_console_ansi(void *wstream, char *buf); |
| 56 | bool mp_check_console(void *handle); | ||
| 56 | 57 | ||
| 57 | /* Windows-only function to attach to the parent process's console */ | 58 | /* Windows-only function to attach to the parent process's console */ |
| 58 | bool terminal_try_attach(void); | 59 | bool terminal_try_attach(void); |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | #include "options/m_option.h" | 4 | #include "options/m_option.h" |
| 5 | #include "options/path.h" | 5 | #include "options/path.h" |
| 6 | #include "osdep/subprocess.h" | 6 | #include "osdep/subprocess.h" |
| 7 | #include "osdep/terminal.h" | ||
| 7 | #include "test_utils.h" | 8 | #include "test_utils.h" |
| 8 | 9 | ||
| 9 | #ifdef NDEBUG | 10 | #ifdef NDEBUG |
| @@ -106,7 +107,8 @@ void mp_msg(struct mp_log *log, int lev, const char *format, ...) {}; · 96 unmodified lines | |||
| 106 | int mp_msg_find_level(const char *s) {return 0;}; | 107 | int mp_msg_find_level(const char *s) {return 0;}; |
| 107 | int mp_msg_level(struct mp_log *log) {return 0;}; | 108 | int mp_msg_level(struct mp_log *log) {return 0;}; |
| 108 | void mp_msg_set_max_level(struct mp_log *log, int lev) {}; | 109 | void mp_msg_set_max_level(struct mp_log *log, int lev) {}; |
| 109 | void mp_write_console_ansi(void) {}; | 110 | void mp_write_console_ansi(void *wstream, char *buf) {}; |
| 111 | bool mp_check_console(void *handle) { return false; }; | ||
| 110 | void mp_set_avdict(AVDictionary **dict, char **kv) {}; | 112 | void mp_set_avdict(AVDictionary **dict, char **kv) {}; |
| 111 | struct mp_log *mp_log_new(void *talloc_ctx, struct mp_log *parent, | 113 | struct mp_log *mp_log_new(void *talloc_ctx, struct mp_log *parent, |
| 112 | const char *name) { return NULL; }; | 114 | const char *name) { return NULL; }; |
| @@ -52,6 +52,5 @@ void mp_msg(struct mp_log *log, int lev, const char *format, ...) · 51 unmodified lines | |||
| 52 | int mp_msg_find_level(const char *s); | 52 | int mp_msg_find_level(const char *s); |
| 53 | int mp_msg_level(struct mp_log *log); | 53 | int mp_msg_level(struct mp_log *log); |
| 54 | void mp_msg_set_max_level(struct mp_log *log, int lev); | 54 | void mp_msg_set_max_level(struct mp_log *log, int lev); |
| 55 | void mp_write_console_ansi(void); | ||
| 56 | typedef struct AVDictionary AVDictionary; | 55 | typedef struct AVDictionary AVDictionary; |
| 57 | void mp_set_avdict(AVDictionary **dict, char **kv); | 56 | void mp_set_avdict(AVDictionary **dict, char **kv); |