diff --git a/panda/src/device/winInputDeviceManager.cxx b/panda/src/device/winInputDeviceManager.cxx index 232c612186..2ca4540ae6 100644 --- a/panda/src/device/winInputDeviceManager.cxx +++ b/panda/src/device/winInputDeviceManager.cxx @@ -62,7 +62,9 @@ WinInputDeviceManager() : } // If we have threading enabled, start a thread with a message-only window - // loop to listen for input events. + // loop to listen for input events. We can't actually just let this be + // handled by the main window loop, because the main window might actually + // have been created in a different thread. #ifdef HAVE_THREADS if (Thread::is_threading_supported()) { PT(Thread) thread = new InputThread(this); @@ -462,6 +464,23 @@ destroy_message_loop() { } } +/** + * Sends a signal to the thread input thread, asking it to shut itself down. + */ +void WinInputDeviceManager:: +stop_thread() { +#ifdef HAVE_THREADS + WinInputDeviceManager *mgr = (WinInputDeviceManager *)_global_ptr; + if (mgr != nullptr) { + LightMutexHolder holder(mgr->_lock); + HWND hwnd = mgr->_message_hwnd; + if (hwnd) { + PostMessage(hwnd, WM_QUIT, 0, 0); + } + } +#endif +} + /** * Implementation of the message loop. */ @@ -518,10 +537,26 @@ thread_main() { } MSG msg; +#ifdef SIMPLE_THREADS + // In the simple threading case, we can't block the thread waiting for a + // message; we yield control back if there are no more messages. + while (true) { + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + if (msg.message == WM_QUIT) { + break; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } else { + Thread::force_yield(); + } + } +#else while (GetMessage(&msg, nullptr, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } +#endif if (device_cat.is_debug()) { device_cat.debug() diff --git a/panda/src/device/winInputDeviceManager.h b/panda/src/device/winInputDeviceManager.h index 44eaa053dc..13cab3d7c0 100644 --- a/panda/src/device/winInputDeviceManager.h +++ b/panda/src/device/winInputDeviceManager.h @@ -44,6 +44,8 @@ public: HWND setup_message_loop(); void destroy_message_loop(); + static void stop_thread(); + private: // There are always exactly four of these in existence. XInputDevice _xinput_device0; diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index 671f12c6aa..39a1e73aa2 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -50,6 +50,10 @@ #include "depthTestAttrib.h" #include "unionBoundingVolume.h" +#if defined(_WIN32) && defined(HAVE_THREADS) && defined(SIMPLE_THREADS) +#include "winInputDeviceManager.h" +#endif + #if defined(WIN32) #define WINDOWS_LEAN_AND_MEAN #include @@ -638,6 +642,12 @@ remove_all_windows() { PStatClient::get_global_pstats()->disconnect(); #endif +#if defined(_WIN32) && defined(HAVE_THREADS) && defined(SIMPLE_THREADS) + // Send a message to the input message pump asking it to shut itself down. + // If we don't do that, the next call will deadlock. + WinInputDeviceManager::stop_thread(); +#endif + // Well, and why not clean up all threads here? Thread::prepare_for_exit(); } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index c913d1ff34..42b29f5944 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -275,6 +275,22 @@ uchar_bgr_to_rgb(unsigned char *dest, const unsigned char *source, } } +/** + * Recopies the given array of pixels, converting from luminance to RGB + * arrangement. + */ +static void +uchar_l_to_rgb(unsigned char *dest, const unsigned char *source, + int num_pixels) { + for (int i = 0; i < num_pixels; i++) { + dest[0] = source[0]; + dest[1] = source[0]; + dest[2] = source[0]; + dest += 3; + source += 1; + } +} + /** * Recopies the given array of pixels, converting from BGRA to RGBA * arrangement. @@ -292,6 +308,23 @@ uchar_bgra_to_rgba(unsigned char *dest, const unsigned char *source, } } +/** + * Recopies the given array of pixels, converting from luminance-alpha to RGBA + * arrangement. + */ +static void +uchar_la_to_rgba(unsigned char *dest, const unsigned char *source, + int num_pixels) { + for (int i = 0; i < num_pixels; i++) { + dest[0] = source[0]; + dest[1] = source[0]; + dest[2] = source[0]; + dest[3] = source[1]; + dest += 4; + source += 2; + } +} + /** * Recopies the given array of pixels, converting from BGR to RGB arrangement. */ @@ -307,6 +340,22 @@ ushort_bgr_to_rgb(unsigned short *dest, const unsigned short *source, } } +/** + * Recopies the given array of pixels, converting from luminance to RGB + * arrangement. + */ +static void +ushort_l_to_rgb(unsigned short *dest, const unsigned short *source, + int num_pixels) { + for (int i = 0; i < num_pixels; i++) { + dest[0] = source[0]; + dest[1] = source[0]; + dest[2] = source[0]; + dest += 3; + source += 1; + } +} + /** * Recopies the given array of pixels, converting from BGRA to RGBA * arrangement. @@ -324,6 +373,23 @@ ushort_bgra_to_rgba(unsigned short *dest, const unsigned short *source, } } +/** + * Recopies the given array of pixels, converting from luminance-alpha to RGBA + * arrangement. + */ +static void +ushort_la_to_rgba(unsigned short *dest, const unsigned short *source, + int num_pixels) { + for (int i = 0; i < num_pixels; i++) { + dest[0] = source[0]; + dest[1] = source[0]; + dest[2] = source[0]; + dest[3] = source[1]; + dest += 4; + source += 2; + } +} + /** * Reverses the order of the components within the image, to convert (for * instance) GL_BGR to GL_RGB. Returns the byte pointer representing the @@ -343,6 +409,12 @@ fix_component_ordering(PTA_uchar &new_image, switch (external_format) { case GL_RGB: + if (tex->get_num_components() == 1) { + new_image = PTA_uchar::empty_array(orig_image_size * 3); + uchar_l_to_rgb(new_image, orig_image, orig_image_size); + result = new_image; + break; + } switch (tex->get_component_type()) { case Texture::T_unsigned_byte: case Texture::T_byte: @@ -366,6 +438,12 @@ fix_component_ordering(PTA_uchar &new_image, break; case GL_RGBA: + if (tex->get_num_components() == 2) { + new_image = PTA_uchar::empty_array(orig_image_size * 2); + uchar_la_to_rgba(new_image, orig_image, orig_image_size / 2); + result = new_image; + break; + } switch (tex->get_component_type()) { case Texture::T_unsigned_byte: case Texture::T_byte: @@ -9450,7 +9528,6 @@ get_external_image_format(Texture *tex) const { return _supports_bgr ? GL_BGRA : GL_RGBA; case Texture::F_luminance: - case Texture::F_sluminance: #ifdef OPENGLES return GL_LUMINANCE; #else @@ -9458,13 +9535,25 @@ get_external_image_format(Texture *tex) const { #endif case Texture::F_luminance_alphamask: case Texture::F_luminance_alpha: - case Texture::F_sluminance_alpha: #ifdef OPENGLES return GL_LUMINANCE_ALPHA; #else return _supports_luminance_texture ? GL_LUMINANCE_ALPHA : GL_RG; #endif + case Texture::F_sluminance: +#ifdef OPENGLES + return GL_LUMINANCE; +#else + return _supports_luminance_texture ? GL_LUMINANCE : GL_RGB; +#endif + case Texture::F_sluminance_alpha: +#ifdef OPENGLES + return GL_LUMINANCE_ALPHA; +#else + return _supports_luminance_texture ? GL_LUMINANCE_ALPHA : GL_RGBA; +#endif + #ifndef OPENGLES_1 case Texture::F_r8i: case Texture::F_r16i: @@ -10200,9 +10289,9 @@ get_internal_image_format(Texture *tex, bool force_sized) const { #endif #ifndef OPENGLES case Texture::F_sluminance: - return GL_SLUMINANCE8; + return _core_profile ? GL_SRGB8 : GL_SLUMINANCE8; case Texture::F_sluminance_alpha: - return GL_SLUMINANCE8_ALPHA8; + return _core_profile ? GL_SRGB8_ALPHA8 : GL_SLUMINANCE8_ALPHA8; #endif #ifndef OPENGLES