From 8a5f07f9c321e0abac131b0ca0124ada20c88cca Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 5 Jan 2015 18:10:45 +0100 Subject: [PATCH 1/3] Forgot two HAVE_FMODEX lines --- panda/src/audiotraits/config_fmodAudio.cxx | 3 --- panda/src/audiotraits/config_fmodAudio.h | 3 --- 2 files changed, 6 deletions(-) diff --git a/panda/src/audiotraits/config_fmodAudio.cxx b/panda/src/audiotraits/config_fmodAudio.cxx index 31297c0347..0f0c1cf700 100644 --- a/panda/src/audiotraits/config_fmodAudio.cxx +++ b/panda/src/audiotraits/config_fmodAudio.cxx @@ -13,7 +13,6 @@ //////////////////////////////////////////////////////////////////// #include "pandabase.h" -#ifdef HAVE_FMODEX //[ #include "config_fmodAudio.h" #include "audioManager.h" @@ -73,5 +72,3 @@ get_audio_manager_func_fmod_audio() { init_libFmodAudio(); return &Create_FmodAudioManager; } - -#endif //] diff --git a/panda/src/audiotraits/config_fmodAudio.h b/panda/src/audiotraits/config_fmodAudio.h index be695d21fe..cea24744c9 100644 --- a/panda/src/audiotraits/config_fmodAudio.h +++ b/panda/src/audiotraits/config_fmodAudio.h @@ -17,7 +17,6 @@ #include "pandabase.h" -#ifdef HAVE_FMODEX //[ #include "notifyCategoryProxy.h" #include "dconfig.h" #include "audioManager.h" @@ -30,6 +29,4 @@ extern ConfigVariableInt fmod_audio_preload_threshold; extern EXPCL_FMOD_AUDIO void init_libFmodAudio(); extern "C" EXPCL_FMOD_AUDIO Create_AudioManager_proc *get_audio_manager_func_fmod_audio(); -#endif //] - #endif // CONFIG_FMODAUDIO_H From b19ff5b10e5ebcdef13c7279efe26d204a9087bc Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 5 Jan 2015 22:38:09 +0100 Subject: [PATCH 2/3] Fix crash that may occur when handle_reshape in called before the window is fully created. Not sure if this affects any renderer but the tinydisplay renderer. --- .../src/tinydisplay/tinyWinGraphicsWindow.cxx | 16 +- panda/src/tinydisplay/zbuffer.cxx | 2 + panda/src/windisplay/winGraphicsWindow.cxx | 273 +++++++++--------- 3 files changed, 148 insertions(+), 143 deletions(-) diff --git a/panda/src/tinydisplay/tinyWinGraphicsWindow.cxx b/panda/src/tinydisplay/tinyWinGraphicsWindow.cxx index b7a508c4ab..3f45a741c5 100755 --- a/panda/src/tinydisplay/tinyWinGraphicsWindow.cxx +++ b/panda/src/tinydisplay/tinyWinGraphicsWindow.cxx @@ -33,7 +33,7 @@ TypeHandle TinyWinGraphicsWindow::_type_handle; // Description: //////////////////////////////////////////////////////////////////// TinyWinGraphicsWindow:: -TinyWinGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, +TinyWinGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, const string &name, const FrameBufferProperties &fb_prop, const WindowProperties &win_prop, @@ -85,7 +85,7 @@ begin_frame(FrameMode mode, Thread *current_thread) { tinygsg->_current_frame_buffer = _frame_buffer; tinygsg->reset_if_new(); - + _gsg->set_current_properties(&get_fb_properties()); return _gsg->begin_frame(current_thread); } @@ -152,7 +152,7 @@ end_flip() { bmdc, 0, 0,fb_xsize, fb_ysize, SRCCOPY); } - + DeleteDC(bmdc); DeleteObject(bm); GdiFlush(); @@ -220,7 +220,7 @@ open_window() { } else { DCAST_INTO_R(tinygsg, _gsg, false); } - + _hdc = GetDC(_hWnd); create_frame_buffer(); @@ -231,7 +231,7 @@ open_window() { } tinygsg->_current_frame_buffer = _frame_buffer; - + tinygsg->reset_if_new(); if (!tinygsg->is_valid()) { close_window(); @@ -251,8 +251,10 @@ open_window() { void TinyWinGraphicsWindow:: handle_reshape() { WinGraphicsWindow::handle_reshape(); - ZB_resize(_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size()); - setup_bitmap_info(); + if (_frame_buffer != NULL) { + ZB_resize(_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size()); + setup_bitmap_info(); + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/tinydisplay/zbuffer.cxx b/panda/src/tinydisplay/zbuffer.cxx index a3b5c67343..fa5677398d 100644 --- a/panda/src/tinydisplay/zbuffer.cxx +++ b/panda/src/tinydisplay/zbuffer.cxx @@ -107,6 +107,8 @@ void ZB_resize(ZBuffer * zb, void *frame_buffer, int xsize, int ysize) { int size; + nassertv(zb != NULL); + /* xsize must be a multiple of 4 */ xsize = (xsize + 3) & ~3; diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index 1e65e6ce69..cc498a9772 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -26,8 +26,6 @@ #include - - TypeHandle WinGraphicsWindow::_type_handle; TypeHandle WinGraphicsWindow::WinWindowHandle::_type_handle; @@ -86,7 +84,7 @@ WinGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, const WindowProperties &win_prop, int flags, GraphicsStateGuardian *gsg, - GraphicsOutput *host) : + GraphicsOutput *host) : GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host) { initialize_input_devices(); @@ -124,7 +122,7 @@ WinGraphicsWindow:: // Function: WinGraphicsWindow::move_pointer // Access: Published, Virtual // Description: Forces the pointer to the indicated position within -// the window, if possible. +// the window, if possible. // // Returns true if successful, false on failure. This // may fail if the mouse is not currently within the @@ -142,7 +140,7 @@ move_pointer(int device, int x, int y) { if (device == 0) { // Move the system mouse pointer. if (!_properties.get_foreground() ) - // !_input_devices[0].get_pointer().get_in_window()) + // !_input_devices[0].get_pointer().get_in_window()) { // If the window doesn't have input focus, or the mouse isn't // currently within the window, forget it. @@ -151,7 +149,7 @@ move_pointer(int device, int x, int y) { RECT view_rect; get_client_rect_screen(_hWnd, &view_rect); - + SetCursorPos(view_rect.left + x, view_rect.top + y); _input_devices[0].set_pointer_in_window(x, y); return true; @@ -235,11 +233,11 @@ process_events() { } _return_control_to_app = false; - } else + } else */ MSG msg; - + // Handle all the messages on the queue in a row. Some of these // might be for another window, but they will get dispatched // appropriately. @@ -314,18 +312,18 @@ set_properties_now(WindowProperties &properties) { WindowProperties::ZOrder last_z_order = _properties.get_z_order(); _properties.set_z_order(properties.get_z_order()); adjust_z_order(last_z_order, properties.get_z_order()); - + properties.clear_z_order(); } if (properties.has_foreground() && properties.get_foreground()) { if (!SetActiveWindow(_hWnd)) { - windisplay_cat.warning() + windisplay_cat.warning() << "SetForegroundWindow() failed!\n"; } else { _properties.set_foreground(true); } - + properties.clear_foreground(); } @@ -446,11 +444,11 @@ open_window() { // Now that we have a window handle, store it in our global map, so // future messages for this window can be routed properly. _window_handles.insert(WindowHandles::value_type(_hWnd, this)); - + // move window to top of zorder. - SetWindowPos(_hWnd, HWND_TOP, 0,0,0,0, + SetWindowPos(_hWnd, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE); - + // need to do twice to override any minimized flags in StartProcessInfo if (want_minimized) { ShowWindow(_hWnd, SW_MINIMIZE); @@ -492,8 +490,8 @@ open_window() { // Registers to receive the WM_INPUT messages if ((pRegisterRawInputDevices)&&(_input_devices.size() > 1)) { RAWINPUTDEVICE Rid; - Rid.usUsagePage = 0x01; - Rid.usUsage = 0x02; + Rid.usUsagePage = 0x01; + Rid.usUsage = 0x02; Rid.dwFlags = 0;// RIDEV_NOLEGACY; // adds HID mouse and also ignores legacy mouse messages Rid.hwndTarget = _hWnd; pRegisterRawInputDevices(&Rid, 1, sizeof (Rid)); @@ -517,7 +515,7 @@ open_window() { #ifdef HAVE_WIN_TOUCHINPUT RegisterTouchWindow(_hWnd, 0); #endif - + return true; } @@ -537,13 +535,13 @@ initialize_input_devices() { PRAWINPUTDEVICELIST pRawInputDeviceList; nassertv(_input_devices.size() == 0); - + // Clear the handle array, and set up the system keyboard/mouse memset(_input_device_handle, 0, sizeof(_input_device_handle)); GraphicsWindowInputDevice device = GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse"); add_input_device(device); - + // Try initializing the Raw Input function pointers. if (pRegisterRawInputDevices==0) { HMODULE user32 = LoadLibrary("user32.dll"); @@ -554,7 +552,7 @@ initialize_input_devices() { pGetRawInputData = (tGetRawInputData) GetProcAddress(user32,"GetRawInputData"); } } - + if (pRegisterRawInputDevices==0) return; if (pGetRawInputDeviceList==0) return; if (pGetRawInputDeviceInfoA==0) return; @@ -563,7 +561,7 @@ initialize_input_devices() { // Get the number of devices. if (pGetRawInputDeviceList(NULL, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) != 0) return; - + // Allocate the array to hold the DeviceList pRawInputDeviceList = (PRAWINPUTDEVICELIST)alloca(sizeof(RAWINPUTDEVICELIST) * nInputDevices); if (pRawInputDeviceList==0) return; @@ -571,7 +569,7 @@ initialize_input_devices() { // Fill the Array if (pGetRawInputDeviceList(pRawInputDeviceList, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) == -1) return; - + // Loop through all raw devices and find the raw mice for (int i = 0; i < (int)nInputDevices; i++) { if (pRawInputDeviceList[i].dwType == RIM_TYPEMOUSE) { @@ -668,7 +666,7 @@ do_reshape_request(int x_origin, int y_origin, bool has_origin, has_origin = false; } } - + // Compute the appropriate size and placement for the window, // including decorations. RECT view_rect; @@ -725,7 +723,7 @@ handle_reshape() { // But in practice, GetClientRect() doesn't really fail, but just // returns all zeroes. Ignore this too. - if (view_rect.left == 0 && view_rect.right == 0 && + if (view_rect.left == 0 && view_rect.right == 0 && view_rect.bottom == 0 && view_rect.top == 0) { if (windisplay_cat.is_debug()) { windisplay_cat.debug() @@ -746,17 +744,17 @@ handle_reshape() { } return; } - + WindowProperties properties; - properties.set_size((view_rect.right - view_rect.left), + properties.set_size((view_rect.right - view_rect.left), (view_rect.bottom - view_rect.top)); // _props origin should reflect upper left of view rectangle properties.set_origin(view_rect.left, view_rect.top); - + if (windisplay_cat.is_spam()) { windisplay_cat.spam() - << "reshape to origin: (" << properties.get_x_origin() << "," + << "reshape to origin: (" << properties.get_x_origin() << "," << properties.get_y_origin() << "), size: (" << properties.get_x_size() << "," << properties.get_y_size() << ")\n"; } @@ -788,22 +786,22 @@ do_fullscreen_resize(int x_size, int y_size) { if (!find_acceptable_display_mode(x_size, y_size, dwFullScreenBitDepth, dm)) { windisplay_cat.error() - << "window resize(" << x_size << ", " << y_size + << "window resize(" << x_size << ", " << y_size << ") failed, no compatible fullscreen display mode found!\n"; return false; } // this causes WM_SIZE msg to be produced - SetWindowPos(_hWnd, NULL, 0,0, x_size, y_size, + SetWindowPos(_hWnd, NULL, 0,0, x_size, y_size, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSENDCHANGING); int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN); if (chg_result != DISP_CHANGE_SUCCESSFUL) { windisplay_cat.error() - << "resize ChangeDisplaySettings failed (error code: " + << "resize ChangeDisplaySettings failed (error code: " << chg_result << ") for specified res: " << dm.dmPelsWidth << " x " << dm.dmPelsHeight - << " x " << dm.dmBitsPerPel << ", " + << " x " << dm.dmBitsPerPel << ", " << dm.dmDisplayFrequency << " Hz\n"; return false; } @@ -811,7 +809,7 @@ do_fullscreen_resize(int x_size, int y_size) { _fullscreen_display_mode = dm; windisplay_cat.info() - << "Resized fullscreen window to " << x_size << ", " << y_size + << "Resized fullscreen window to " << x_size << ", " << y_size << " bitdepth " << dwFullScreenBitDepth << ", " << dm.dmDisplayFrequency << "Hz\n"; @@ -866,7 +864,7 @@ do_windowed_switch() { if (!calculate_metrics(false, window_style, metrics, has_origin)){ return false; } - + // We send SWP_FRAMECHANGED so that the new styles are taken into account. // Also, we place the Windows at 0,0 to play safe until we decide how to // get Panda to remember the windowed origin. @@ -950,7 +948,7 @@ calculate_metrics(bool fullscreen, DWORD window_style, WINDOW_METRICS &metrics, if (!fullscreen && has_origin) { metrics.x = _properties.get_x_origin(); metrics.y = _properties.get_y_origin(); - + // A coordinate of -2 means to center the window in its client area. if (metrics.x == -2) { metrics.x = 0.5 * (_pipe->get_display_width() - _properties.get_x_size()); @@ -974,7 +972,7 @@ calculate_metrics(bool fullscreen, DWORD window_style, WINDOW_METRICS &metrics, RECT win_rect; SetRect(&win_rect, metrics.x, metrics.y, metrics.x + metrics.width, metrics.y + metrics.height); - + // Compute window size based on desired client area size if (!AdjustWindowRect(&win_rect, window_style, FALSE)) { windisplay_cat.error() @@ -1004,7 +1002,7 @@ calculate_metrics(bool fullscreen, DWORD window_style, WINDOW_METRICS &metrics, bool WinGraphicsWindow:: open_graphic_window(bool fullscreen) { DWORD window_style = make_style(fullscreen); - + wstring title; if (_properties.has_title()) { TextEncoder encoder; @@ -1026,7 +1024,7 @@ open_graphic_window(bool fullscreen) { HINSTANCE hinstance = GetModuleHandle(NULL); _hparent = NULL; - + if (!fullscreen){ WindowHandle *window_handle = _properties.get_parent_window(); if (window_handle != NULL) { @@ -1036,7 +1034,7 @@ open_graphic_window(bool fullscreen) { if (os_handle != NULL) { windisplay_cat.info() << "os_handle type " << os_handle->get_type() << "\n"; - + if (os_handle->is_of_type(NativeWindowHandle::WinHandle::get_class_type())) { NativeWindowHandle::WinHandle *win_handle = DCAST(NativeWindowHandle::WinHandle, os_handle); _hparent = win_handle->get_handle(); @@ -1052,7 +1050,7 @@ open_graphic_window(bool fullscreen) { } if (!_hparent) { // This can be a regular window or a fullscreen window - _hWnd = CreateWindowW(wclass._name.c_str(), title.c_str(), window_style, + _hWnd = CreateWindowW(wclass._name.c_str(), title.c_str(), window_style, metrics.x, metrics.y, metrics.width, metrics.height, @@ -1060,18 +1058,18 @@ open_graphic_window(bool fullscreen) { } else { // This is a regular window with a parent int x_origin = 0; int y_origin = 0; - + if (!fullscreen && has_origin) { x_origin = _properties.get_x_origin(); y_origin = _properties.get_y_origin(); } - _hWnd = CreateWindowW(wclass._name.c_str(), title.c_str(), + _hWnd = CreateWindowW(wclass._name.c_str(), title.c_str(), WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS , x_origin, y_origin, _properties.get_x_size(), _properties.get_y_size(), _hparent, NULL, hinstance, 0); - + if (_hWnd) { // join our keyboard state with the parents @@ -1079,13 +1077,13 @@ open_graphic_window(bool fullscreen) { // It causes problems with the browser plugin--it deadlocks when // the parent process is waiting on the child process. //AttachThreadInput(GetWindowThreadProcessId(_hparent,NULL), GetCurrentThreadId(),TRUE); - + WindowProperties properties; properties.set_foreground(true); system_changed_properties(properties); } } - + if (!_hWnd) { windisplay_cat.error() << "CreateWindow() failed!" << endl; @@ -1123,7 +1121,7 @@ do_fullscreen_enable() { // DWORD cur_scrnwidth = GetDeviceCaps(scrnDC, HORZRES); // DWORD cur_scrnheight = GetDeviceCaps(scrnDC, VERTRES); ReleaseDC(hDesktopWindow, scrnDC); - + DWORD dwWidth = _properties.get_x_size(); DWORD dwHeight = _properties.get_y_size(); DWORD dwFullScreenBitDepth = cur_bitdepth; @@ -1131,7 +1129,7 @@ do_fullscreen_enable() { DEVMODE dm; reconsider_fullscreen_size(dwWidth, dwHeight, dwFullScreenBitDepth); if (!find_acceptable_display_mode(dwWidth, dwHeight, dwFullScreenBitDepth, dm)) { - windisplay_cat.error() + windisplay_cat.error() << "Videocard has no supported display resolutions at specified res (" << dwWidth << " x " << dwHeight << " x " << dwFullScreenBitDepth <<")\n"; return false; @@ -1147,7 +1145,7 @@ do_fullscreen_enable() { << "ChangeDisplaySettings failed (error code: " << chg_result << ") for specified res: " << dm.dmPelsWidth << " x " << dm.dmPelsHeight - << " x " << dm.dmBitsPerPel << ", " + << " x " << dm.dmBitsPerPel << ", " << dm.dmDisplayFrequency << " Hz\n"; return false; } @@ -1202,13 +1200,13 @@ adjust_z_order(WindowProperties::ZOrder last_z_order, WindowProperties::ZOrder this_z_order) { HWND order; bool do_change = false; - + switch (this_z_order) { case WindowProperties::Z_bottom: order = HWND_BOTTOM; do_change = true; break; - + case WindowProperties::Z_normal: if ((last_z_order != WindowProperties::Z_normal) && // If we aren't changing the window order, don't move it to @@ -1223,14 +1221,14 @@ adjust_z_order(WindowProperties::ZOrder last_z_order, do_change = true; } break; - + case WindowProperties::Z_top: order = HWND_TOPMOST; do_change = true; break; } if (do_change) { - BOOL result = SetWindowPos(_hWnd, order, 0,0,0,0, + BOOL result = SetWindowPos(_hWnd, order, 0,0,0,0, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE); if (!result) { windisplay_cat.warning() @@ -1265,13 +1263,13 @@ track_mouse_leaving(HWND hwnd) { }; // tell win32 to post WM_MOUSELEAVE msgs - BOOL bSucceeded = winpipe->_pfnTrackMouseEvent(&tme); - + BOOL bSucceeded = winpipe->_pfnTrackMouseEvent(&tme); + if ((!bSucceeded) && windisplay_cat.is_debug()) { windisplay_cat.debug() << "TrackMouseEvent failed!, LastError=" << GetLastError() << endl; } - + _tracking_mouse_leaving = true; } } @@ -1331,7 +1329,7 @@ LONG WinGraphicsWindow:: window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { if (windisplay_cat.is_spam()) { windisplay_cat.spam() - << ClockObject::get_global_clock()->get_real_time() + << ClockObject::get_global_clock()->get_real_time() << " window_proc(" << (void *)this << ", " << hwnd << ", " << msg << ", " << wparam << ", " << lparam << ")\n"; } @@ -1339,7 +1337,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { int button = -1; switch (msg) { - case WM_MOUSEMOVE: + case WM_MOUSEMOVE: if (!_tracking_mouse_leaving) { // need to re-call TrackMouseEvent every time mouse re-enters window track_mouse_leaving(hwnd); @@ -1348,22 +1346,22 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { if(handle_mouse_motion(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)))) return 0; break; - + case WM_INPUT: handle_raw_input((HRAWINPUT)lparam); break; - + case WM_MOUSELEAVE: _tracking_mouse_leaving = false; handle_mouse_exit(); set_cursor_out_of_window(); break; - - case WM_CREATE: + + case WM_CREATE: { track_mouse_leaving(hwnd); ClearToBlack(hwnd, _properties); - + POINT cpos; GetCursorPos(&cpos); ScreenToClient(hwnd, &cpos); @@ -1399,7 +1397,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } break; */ - + case WM_CLOSE: // This is a message from the system indicating that the user // has requested to close the window (e.g. alt-f4). @@ -1410,14 +1408,14 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { // the request and process it directly. throw_event(close_request_event); return 0; - + } else { // In this case, the default case, the app does not intend // to service the request, so we do by closing the window. close_window(); properties.set_open(false); system_changed_properties(properties); - + // TODO: make sure we release the GSG properly. } } @@ -1429,17 +1427,17 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { << "WM_CHILDACTIVATE: " << hwnd << "\n"; } break; - + case WM_ACTIVATE: if (windisplay_cat.is_debug()) { windisplay_cat.debug() << "WM_ACTIVATE: " << hwnd << ", " << wparam << ", " << lparam << "\n"; } properties.set_minimized((wparam & 0xffff0000) != 0); - if ((wparam & 0xffff) != WA_INACTIVE) + if ((wparam & 0xffff) != WA_INACTIVE) { properties.set_foreground(true); - if (is_fullscreen()) + if (is_fullscreen()) { // When a fullscreen window goes active, it automatically gets // un-minimized. @@ -1448,10 +1446,10 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { if (chg_result != DISP_CHANGE_SUCCESSFUL) { const DEVMODE &dm = _fullscreen_display_mode; windisplay_cat.error() - << "restore ChangeDisplaySettings failed (error code: " + << "restore ChangeDisplaySettings failed (error code: " << chg_result << ") for specified res: " << dm.dmPelsWidth << " x " << dm.dmPelsHeight - << " x " << dm.dmBitsPerPel << ", " + << " x " << dm.dmBitsPerPel << ", " << dm.dmDisplayFrequency << " Hz\n"; } @@ -1460,10 +1458,10 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { fullscreen_restored(properties); } } - else + else { properties.set_foreground(false); - if (is_fullscreen()) + if (is_fullscreen()) { // When a fullscreen window goes inactive, it automatically // gets minimized. @@ -1489,7 +1487,10 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { << "WM_SIZE: " << hwnd << ", " << wparam << "\n"; } - handle_reshape(); + // Resist calling handle_reshape before the window has opened. + if (_hWnd == NULL) { + handle_reshape(); + } break; case WM_EXITSIZEMOVE: @@ -1524,7 +1525,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { // A button-click in the window means to grab the keyboard focus. set_focus(); return 0; - + case WM_MBUTTONDOWN: if (_lost_keypresses) { resend_lost_keypresses(); @@ -1562,7 +1563,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } } return 0; - + case WM_LBUTTONUP: if (_lost_keypresses) { resend_lost_keypresses(); @@ -1628,7 +1629,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } break; - + case WM_IME_SETCONTEXT: if (!ime_hide) break; @@ -1640,15 +1641,15 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { windisplay_cat.debug() << "SendMessage failed for " << _ime_hWnd << endl; else windisplay_cat.debug() << "SendMessage Succeeded for " << _ime_hWnd << endl; - + windisplay_cat.debug() << "wparam is " << wparam << ", lparam is " << lparam << endl; lparam &= ~ISC_SHOWUIALL; if (ImmIsUIMessage(_ime_hWnd, msg, wparam, lparam)) windisplay_cat.debug() << "wparam is " << wparam << ", lparam is " << lparam << endl; - + break; - + case WM_IME_NOTIFY: if (wparam == IMN_SETOPENSTATUS) { HIMC hIMC = ImmGetContext(hwnd); @@ -1663,20 +1664,20 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { CANDIDATEFORM canf; ImmGetCompositionWindow(hIMC, &comf); ImmGetCandidateWindow(hIMC, 0, &canf); - windisplay_cat.debug() << - "comf style " << comf.dwStyle << + windisplay_cat.debug() << + "comf style " << comf.dwStyle << " comf point: x" << comf.ptCurrentPos.x << ",y " << comf.ptCurrentPos.y << " comf rect: l " << comf.rcArea.left << ",t " << comf.rcArea.top << ",r " << comf.rcArea.right << ",b " << comf.rcArea.bottom << endl; - windisplay_cat.debug() << - "canf style " << canf.dwStyle << + windisplay_cat.debug() << + "canf style " << canf.dwStyle << " canf point: x" << canf.ptCurrentPos.x << ",y " << canf.ptCurrentPos.y << " canf rect: l " << canf.rcArea.left << ",t " << canf.rcArea.top << ",r " << canf.rcArea.right << ",b " << canf.rcArea.bottom << endl; comf.dwStyle = CFS_POINT; comf.ptCurrentPos.x = 2000; comf.ptCurrentPos.y = 2000; - + canf.dwStyle = CFS_EXCLUDE; canf.dwIndex = 0; canf.ptCurrentPos.x = 0; @@ -1685,14 +1686,14 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { canf.rcArea.top = 0; canf.rcArea.right = 640; canf.rcArea.bottom = 480; - + #if 0 comf.rcArea.left = 200; comf.rcArea.top = 200; comf.rcArea.right = 0; comf.rcArea.bottom = 0; #endif - + if (ImmSetCompositionWindow(hIMC, &comf)) windisplay_cat.debug() << "set composition form: success\n"; for (int i=0; i<3; ++i) { @@ -1705,12 +1706,12 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { ImmReleaseContext(hwnd, hIMC); } break; - + case WM_IME_STARTCOMPOSITION: support_overlay_window(true); _ime_active = true; break; - + case WM_IME_ENDCOMPOSITION: support_overlay_window(false); _ime_active = false; @@ -1719,9 +1720,9 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { wstring ws; _input_devices[0].candidate(ws, 0, 0, 0); } - + break; - + case WM_IME_COMPOSITION: if (ime_aware) { @@ -1736,13 +1737,13 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { HIMC hIMC = ImmGetContext(hwnd); nassertr(hIMC != 0, 0); - + DWORD result_size = 0; static const int ime_buffer_size = 256; static const int ime_buffer_size_bytes = ime_buffer_size / sizeof(wchar_t); wchar_t ime_buffer[ime_buffer_size]; size_t cursor_pos, delta_start; - + if (lparam & GCS_RESULTSTR) { result_size = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, ime_buffer, ime_buffer_size_bytes); @@ -1755,21 +1756,21 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { if (lparam & GCS_COMPSTR) { result_size = ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, NULL, 0); cursor_pos = result_size & 0xffff; - + result_size = ImmGetCompositionStringW(hIMC, GCS_DELTASTART, NULL, 0); delta_start = result_size & 0xffff; result_size = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, ime_buffer, ime_buffer_size); size_t num_chars = result_size / sizeof(wchar_t); - - _input_devices[0].candidate(wstring(ime_buffer, num_chars), - min(cursor_pos, delta_start), - max(cursor_pos, delta_start), + + _input_devices[0].candidate(wstring(ime_buffer, num_chars), + min(cursor_pos, delta_start), + max(cursor_pos, delta_start), cursor_pos); } ImmReleaseContext(hwnd, hIMC); } break; - + case WM_CHAR: // Ignore WM_CHAR messages if we have the IME open, since // everything will come in through WM_IME_COMPOSITION. (It's @@ -1786,8 +1787,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { _input_devices[0].keystroke(wparam); } break; - - case WM_SYSKEYDOWN: + + case WM_SYSKEYDOWN: if (_lost_keypresses) { resend_lost_keypresses(); } @@ -1802,7 +1803,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { POINT point; GetCursorPos(&point); ScreenToClient(hwnd, &point); - handle_keypress(lookup_key(wparam), point.x, point.y, + handle_keypress(lookup_key(wparam), point.x, point.y, get_message_time()); if ((lparam & 0x40000000) == 0) { @@ -1836,7 +1837,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } } break; - + case WM_SYSCOMMAND: if (wparam == SC_KEYMENU) { // if Alt is released (alone w/o other keys), defwindproc will @@ -1850,8 +1851,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { return 0; } break; - - case WM_KEYDOWN: + + case WM_KEYDOWN: if (_lost_keypresses) { resend_lost_keypresses(); } @@ -1905,7 +1906,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { !_input_devices.empty()) { HGLOBAL hglb; char *lptstr; - + if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL)) { // Maybe we should support CF_UNICODETEXT if it is available // too? @@ -1985,7 +1986,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } } break; - + case WM_SYSKEYUP: case WM_KEYUP: if (_lost_keypresses) { @@ -2031,8 +2032,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } } break; - - case WM_KILLFOCUS: + + case WM_KILLFOCUS: if (windisplay_cat.is_debug()) { windisplay_cat.debug() << "killfocus\n"; @@ -2042,8 +2043,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { properties.set_foreground(false); system_changed_properties(properties); break; - - case WM_SETFOCUS: + + case WM_SETFOCUS: // You would think that this would be a good time to call // resend_lost_keypresses(), but it turns out that we get // WM_SETFOCUS slightly before Windows starts resending key @@ -2196,9 +2197,9 @@ update_cursor_window(WinGraphicsWindow *to_window) { // We are leaving a graphics window; we should restore the Win2000 // effects. if (_got_saved_params) { - SystemParametersInfo(SPI_SETMOUSETRAILS, NULL, + SystemParametersInfo(SPI_SETMOUSETRAILS, NULL, (PVOID)_saved_mouse_trails, NULL); - SystemParametersInfo(SPI_SETCURSORSHADOW, NULL, + SystemParametersInfo(SPI_SETCURSORSHADOW, NULL, (PVOID)_saved_cursor_shadow, NULL); SystemParametersInfo(SPI_SETMOUSEVANISH, NULL, (PVOID)_saved_mouse_vanish, NULL); @@ -2216,11 +2217,11 @@ update_cursor_window(WinGraphicsWindow *to_window) { // These parameters are only defined for Win2000/XP, but they // should just cause a silent error on earlier OS's, which is OK. if (!_got_saved_params) { - SystemParametersInfo(SPI_GETMOUSETRAILS, NULL, + SystemParametersInfo(SPI_GETMOUSETRAILS, NULL, &_saved_mouse_trails, NULL); - SystemParametersInfo(SPI_GETCURSORSHADOW, NULL, + SystemParametersInfo(SPI_GETCURSORSHADOW, NULL, &_saved_cursor_shadow, NULL); - SystemParametersInfo(SPI_GETMOUSEVANISH, NULL, + SystemParametersInfo(SPI_GETMOUSEVANISH, NULL, &_saved_mouse_vanish, NULL); _got_saved_params = true; @@ -2231,7 +2232,7 @@ update_cursor_window(WinGraphicsWindow *to_window) { SetCursor(to_window->_cursor); } - + hide_or_show_cursor(hide_cursor); _cursor_window = to_window; @@ -2280,18 +2281,18 @@ find_acceptable_display_mode(DWORD dwWidth, DWORD dwHeight, DWORD bpp, while (1) { ZeroMemory(&dm, sizeof(dm)); dm.dmSize = sizeof(dm); - + if (!EnumDisplaySettings(NULL, modenum, &dm)) { break; } - + if ((dm.dmPelsWidth == dwWidth) && (dm.dmPelsHeight == dwHeight) && (dm.dmBitsPerPel == bpp)) { return true; } modenum++; } - + return false; } @@ -2309,7 +2310,7 @@ show_error_message(DWORD message_id) { if (message_id == 0) { message_id = GetLastError(); } - + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, message_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language @@ -2681,26 +2682,26 @@ handle_raw_input(HRAWINPUT hraw) { if (pGetRawInputData(hraw, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)) == -1) { return; } - + lpb = (LPBYTE)alloca(sizeof(LPBYTE) * dwSize); if (lpb == NULL) { return; } - + if (pGetRawInputData(hraw, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) { return; } - + RAWINPUT *raw = (RAWINPUT *)lpb; if (raw->header.hDevice == 0) { return; } - + for (int i = 1; i < (int)(_input_devices.size()); ++i) { if (_input_device_handle[i] == raw->header.hDevice) { int adjx = raw->data.mouse.lLastX; int adjy = raw->data.mouse.lLastY; - + if (raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) { _input_devices[i].set_pointer_in_window(adjx, adjy); } else { @@ -2708,7 +2709,7 @@ handle_raw_input(HRAWINPUT hraw) { int oldy = _input_devices[i].get_raw_pointer().get_y(); _input_devices[i].set_pointer_in_window(oldx + adjx, oldy + adjy); } - + if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) { _input_devices[i].button_down(MouseButton::button(0), get_message_time()); } @@ -2871,7 +2872,7 @@ get_cursor(const Filename &filename) { } static HCURSOR get_cursor(const Filename &filename); - + //////////////////////////////////////////////////////////////////// // Function: WinGraphicsWindow::register_window_class // Access: Private, Static @@ -2912,7 +2913,7 @@ register_window_class(const WindowProperties &props) { wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = wclass._name.c_str(); - + if (!RegisterClassW(&wc)) { windisplay_cat.error() << "could not register window class " << wclass._name << "!" << endl; @@ -2925,7 +2926,7 @@ register_window_class(const WindowProperties &props) { //////////////////////////////////////////////////////////////////// // Function: WinGraphicsWindow::WinWindowHandle::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// WinGraphicsWindow::WinWindowHandle:: WinWindowHandle(WinGraphicsWindow *window, const WindowHandle ©) : @@ -3033,7 +3034,7 @@ void get_client_rect_screen(HWND hwnd, RECT *view_rect) { // Access: Public, Virtual // Description: Adds the specified Windows proc event handler to be called // whenever a Windows event occurs. -// +// //////////////////////////////////////////////////////////////////// void WinGraphicsWindow::add_window_proc( const GraphicsWindowProc* wnd_proc ){ nassertv(wnd_proc != NULL); @@ -3044,7 +3045,7 @@ void WinGraphicsWindow::add_window_proc( const GraphicsWindowProc* wnd_proc ){ // Function: WinGraphicsWindow::remove_window_proc // Access: Public, Virtual // Description: Removes the specified Windows proc event handler. -// +// //////////////////////////////////////////////////////////////////// void WinGraphicsWindow::remove_window_proc( const GraphicsWindowProc* wnd_proc ){ nassertv(wnd_proc != NULL); @@ -3055,7 +3056,7 @@ void WinGraphicsWindow::remove_window_proc( const GraphicsWindowProc* wnd_proc ) // Function: WinGraphicsWindow::clear_window_procs // Access: Public, Virtual // Description: Removes all Windows proc event handlers. -// +// //////////////////////////////////////////////////////////////////// void WinGraphicsWindow::clear_window_procs(){ _window_proc_classes.clear(); @@ -3065,7 +3066,7 @@ void WinGraphicsWindow::clear_window_procs(){ // Function: WinGraphicsWindow::supports_window_procs // Access: Public, Virtual // Description: Returns whether this window supports adding of windows proc handlers. -// +// //////////////////////////////////////////////////////////////////// bool WinGraphicsWindow::supports_window_procs() const{ return true; @@ -3075,7 +3076,7 @@ bool WinGraphicsWindow::supports_window_procs() const{ // Function: WinGraphicsWindow::is_touch_event // Access: Public, Virtual // Description: Returns whether the specified event msg is a touch message. -// +// //////////////////////////////////////////////////////////////////// bool WinGraphicsWindow:: is_touch_event(GraphicsWindowProcCallbackData* callbackData){ @@ -3090,7 +3091,7 @@ is_touch_event(GraphicsWindowProcCallbackData* callbackData){ // Function: WinGraphicsWindow::get_num_touches // Access: Public, Virtual // Description: Returns the current number of touches on this window. -// +// //////////////////////////////////////////////////////////////////// int WinGraphicsWindow:: get_num_touches(){ @@ -3105,7 +3106,7 @@ get_num_touches(){ // Function: WinGraphicsWindow::get_touch_info // Access: Public, Virtual // Description: Returns the TouchInfo object describing the specified touch. -// +// //////////////////////////////////////////////////////////////////// TouchInfo WinGraphicsWindow:: get_touch_info(int index){ From af15797a25df903ba5a428e4d7408b87946be551 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 7 Jan 2015 19:30:01 +0100 Subject: [PATCH 3/3] Many, many performance optimizations and enhancements --- dtool/src/dtoolbase/dtoolbase_cc.h | 7 +- dtool/src/dtoolbase/stl_compares.I | 22 ++ dtool/src/dtoolbase/stl_compares.h | 20 +- dtool/src/dtoolbase/typeHandle.h | 3 +- dtool/src/dtoolbase/typeRegistry.I | 27 +++ dtool/src/dtoolbase/typeRegistry.cxx | 19 +- dtool/src/dtoolbase/typeRegistry.h | 5 +- dtool/src/dtoolbase/typeRegistryNode.cxx | 5 - makepanda/makepanda.py | 2 +- panda/src/cull/drawCullHandler.cxx | 2 +- panda/src/cull/drawCullHandler.h | 4 +- panda/src/display/graphicsStateGuardian.cxx | 48 ++-- panda/src/express/memoryUsage.I | 17 ++ panda/src/express/memoryUsage.cxx | 18 -- panda/src/express/memoryUsage.h | 2 +- panda/src/express/nodePointerTo.I | 88 ++++++++ panda/src/express/nodePointerTo.h | 22 ++ panda/src/express/nodePointerToBase.I | 37 +++ panda/src/express/nodePointerToBase.h | 5 + panda/src/express/pointerTo.I | 60 ++--- panda/src/express/pointerTo.h | 14 +- panda/src/express/pointerToBase.I | 51 +++-- panda/src/express/pointerToBase.h | 3 +- panda/src/express/pointerToVoid.I | 9 +- panda/src/express/pointerToVoid.h | 2 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 81 +++++-- panda/src/gobj/geom.I | 93 ++++++-- panda/src/gobj/geom.h | 38 ++-- panda/src/gobj/geomMunger.cxx | 42 ++-- panda/src/gobj/geomVertexData.I | 104 ++++++--- panda/src/gobj/geomVertexData.cxx | 212 +++++++++--------- panda/src/gobj/geomVertexData.h | 57 +++-- panda/src/linmath/lmatrix3_src.I | 13 +- panda/src/linmath/lmatrix3_src.cxx | 15 +- panda/src/linmath/lmatrix3_src.h | 13 +- panda/src/linmath/lmatrix4_src.I | 14 +- panda/src/linmath/lmatrix4_src.cxx | 13 +- panda/src/linmath/lmatrix4_src.h | 15 +- panda/src/pgraph/config_pgraph.cxx | 12 +- panda/src/pgraph/config_pgraph.h | 1 - panda/src/pgraph/cullBin.I | 25 --- panda/src/pgraph/cullBin.cxx | 34 --- panda/src/pgraph/cullBin.h | 3 - panda/src/pgraph/cullBinManager.I | 73 ++++++ panda/src/pgraph/cullBinManager.cxx | 59 ++--- panda/src/pgraph/cullBinManager.h | 15 +- panda/src/pgraph/cullPlanes.cxx | 2 +- panda/src/pgraph/cullResult.cxx | 62 +++-- panda/src/pgraph/cullResult.h | 2 +- panda/src/pgraph/cullTraverser.I | 60 +++++ panda/src/pgraph/cullTraverser.cxx | 88 ++------ panda/src/pgraph/cullTraverser.h | 4 + panda/src/pgraph/cullTraverserData.I | 4 +- panda/src/pgraph/cullTraverserData.cxx | 21 +- panda/src/pgraph/cullTraverserData.h | 4 +- panda/src/pgraph/cullableObject.cxx | 9 +- panda/src/pgraph/geomNode.I | 23 ++ panda/src/pgraph/geomNode.h | 5 + panda/src/pgraph/pandaNode.I | 69 ++++++ panda/src/pgraph/pandaNode.h | 53 +++-- panda/src/pgraph/renderAttrib.I | 19 +- panda/src/pgraph/renderAttrib.cxx | 20 +- panda/src/pgraph/renderAttrib.h | 7 +- panda/src/pgraph/renderState.I | 36 +++ panda/src/pgraph/renderState.cxx | 36 --- panda/src/pgraph/renderState.h | 4 +- panda/src/pgraph/texMatrixAttrib.cxx | 2 +- panda/src/pgraph/transformState.I | 42 ++-- panda/src/pgraph/transformState.cxx | 189 +++++++++++----- panda/src/pgraph/transformState.h | 23 +- panda/src/pgui/pgItem.cxx | 2 +- panda/src/pgui/pgSliderBar.cxx | 4 +- panda/src/pstatclient/pStatClient.cxx | 24 +- panda/src/putil/copyOnWritePointer.I | 60 +++++ panda/src/putil/copyOnWritePointer.h | 10 + panda/src/putil/simpleHashMap.I | 41 +++- panda/src/putil/simpleHashMap.h | 9 +- panda/src/windisplay/config_windisplay.cxx | 11 +- 78 files changed, 1613 insertions(+), 756 deletions(-) diff --git a/dtool/src/dtoolbase/dtoolbase_cc.h b/dtool/src/dtoolbase/dtoolbase_cc.h index 93d90efe48..ad5caaa327 100644 --- a/dtool/src/dtoolbase/dtoolbase_cc.h +++ b/dtool/src/dtoolbase/dtoolbase_cc.h @@ -132,7 +132,7 @@ typedef ios::seekdir ios_seekdir; # else # define NOEXCEPT # endif -# if __has_extension(cxx_rvalue_references) +# if __has_extension(cxx_rvalue_references) && (__cplusplus >= 201103L) # define USE_MOVE_SEMANTICS # endif #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && (__cplusplus >= 201103L) @@ -141,6 +141,11 @@ typedef ios::seekdir ios_seekdir; # define CONSTEXPR constexpr # define NOEXCEPT noexcept # define USE_MOVE_SEMANTICS +#elif defined(_MSC_VER) && _MSC_VER >= 1600 +// MSVC 2010 has move semantics. +# define CONSTEXPR INLINE +# define NOEXCEPT throw() +# define USE_MOVE_SEMANTICS #else # define CONSTEXPR INLINE # define NOEXCEPT diff --git a/dtool/src/dtoolbase/stl_compares.I b/dtool/src/dtoolbase/stl_compares.I index 002db30aca..31ac164cad 100644 --- a/dtool/src/dtoolbase/stl_compares.I +++ b/dtool/src/dtoolbase/stl_compares.I @@ -234,3 +234,25 @@ INLINE size_t indirect_method_hash:: operator () (const Key &key) const { return (*key).get_hash(); } + +//////////////////////////////////////////////////////////////////// +// Function: indirect_equals_hash::operator () +// Access: Public +// Description: Calls the Key's get_hash() method. +//////////////////////////////////////////////////////////////////// +template +INLINE size_t indirect_equals_hash:: +operator () (const Key &key) const { + return (*key).get_hash(); +} + +//////////////////////////////////////////////////////////////////// +// Function: indirect_equals_hash::is_equal +// Access: Public +// Description: Returns true if a is equal to b, false otherwise. +//////////////////////////////////////////////////////////////////// +template +INLINE bool indirect_equals_hash:: +is_equal(const Key &a, const Key &b) const { + return (a == b || (*a) == (*b)); +} diff --git a/dtool/src/dtoolbase/stl_compares.h b/dtool/src/dtoolbase/stl_compares.h index ff298db9d1..806f3722ff 100644 --- a/dtool/src/dtoolbase/stl_compares.h +++ b/dtool/src/dtoolbase/stl_compares.h @@ -33,7 +33,6 @@ public: } }; - #else #include // for less @@ -212,6 +211,23 @@ public: } }; +//////////////////////////////////////////////////////////////////// +// Class : indirect_equals_hash +// Description : An STL function object class, this is intended to be +// used on any ordered collection of pointers to classes +// that contain an operator ==() method. It defines +// the equality of the pointers via operator ==(). +// +// Since it doesn't define the ordering of the pointers, +// it can only be used with hash containers. +//////////////////////////////////////////////////////////////////// +template +class indirect_equals_hash { +public: + INLINE size_t operator () (const Key &key) const; + INLINE bool is_equal(const Key &a, const Key &b) const; +}; + #include "stl_compares.I" typedef floating_point_hash float_hash; @@ -234,5 +250,3 @@ class indirect_compare_names_hash : public indirect_method_hash @@ -152,7 +151,7 @@ private: int _index; static TypeHandle _none; -friend class TypeRegistry; + friend class TypeRegistry; }; diff --git a/dtool/src/dtoolbase/typeRegistry.I b/dtool/src/dtoolbase/typeRegistry.I index 45e535aa84..21f15f1f1d 100644 --- a/dtool/src/dtoolbase/typeRegistry.I +++ b/dtool/src/dtoolbase/typeRegistry.I @@ -39,3 +39,30 @@ init_lock() { _lock = new MutexImpl; } } + +//////////////////////////////////////////////////////////////////// +// Function: TypeRegistry::look_up +// Access: Private +// Description: Returns the TypeRegistryNode associated with the +// indicated TypeHandle. If there is no associated +// TypeRegistryNode, reports an error condition and +// returns NULL. +// +// The associated TypedObject pointer is the pointer to +// the object that owns the handle, if available. It is +// only used in an error condition, if for some reason +// the handle was uninitialized. +// +// Assumes the lock is already held. +//////////////////////////////////////////////////////////////////// +INLINE TypeRegistryNode *TypeRegistry:: +look_up(TypeHandle handle, TypedObject *object) const { +#ifndef NDEBUG + if (handle._index >= (int)_handle_registry.size() || + handle._index <= 0) { + // Invalid or uninitialized type handle. + return look_up_invalid(handle, object); + } +#endif + return _handle_registry[handle._index]; +} diff --git a/dtool/src/dtoolbase/typeRegistry.cxx b/dtool/src/dtoolbase/typeRegistry.cxx index 4b61ec56a2..f88f923f04 100644 --- a/dtool/src/dtoolbase/typeRegistry.cxx +++ b/dtool/src/dtoolbase/typeRegistry.cxx @@ -498,7 +498,7 @@ get_parent_towards(TypeHandle child, TypeHandle base, TypeHandle handle; const TypeRegistryNode *child_node = look_up(child, child_object); const TypeRegistryNode *base_node = look_up(base, NULL); - assert(child_node != (TypeRegistryNode *)NULL && + assert(child_node != (TypeRegistryNode *)NULL && base_node != (TypeRegistryNode *)NULL); freshen_derivations(); handle = TypeRegistryNode::get_parent_towards(child_node, base_node); @@ -688,22 +688,17 @@ write_node(ostream &out, int indent_level, const TypeRegistryNode *node) const { } //////////////////////////////////////////////////////////////////// -// Function: TypeRegistry::look_up +// Function: TypeRegistry::look_up_invalid // Access: Private -// Description: Returns the TypeRegistryNode associated with the -// indicated TypeHandle. If there is no associated -// TypeRegistryNode, reports an error condition and -// returns NULL. -// -// The associated TypedObject pointer is the pointer to -// the object that owns the handle, if available. It is -// only used in an error condition, if for some reason -// the handle was uninitialized. +// Description: Called by look_up when it detects an invalid +// TypeHandle pointer. In non-release builds, this +// method will do what it can to recover from this +// and initialize the type anyway. // // Assumes the lock is already held. //////////////////////////////////////////////////////////////////// TypeRegistryNode *TypeRegistry:: -look_up(TypeHandle handle, TypedObject *object) const { +look_up_invalid(TypeHandle handle, TypedObject *object) const { #ifndef NDEBUG if (handle._index == 0) { // The TypeHandle is unregistered. This is an error condition. diff --git a/dtool/src/dtoolbase/typeRegistry.h b/dtool/src/dtoolbase/typeRegistry.h index 10efa40cad..85e071bf0d 100644 --- a/dtool/src/dtoolbase/typeRegistry.h +++ b/dtool/src/dtoolbase/typeRegistry.h @@ -88,7 +88,8 @@ private: TypeRegistry(); static void init_global_pointer(); - TypeRegistryNode *look_up(TypeHandle type, TypedObject *object) const; + INLINE TypeRegistryNode *look_up(TypeHandle type, TypedObject *object) const; + TypeRegistryNode *look_up_invalid(TypeHandle type, TypedObject *object) const; INLINE void freshen_derivations(); void rebuild_derivations(); @@ -120,6 +121,8 @@ private: // Helper function to allow for "C" interaction into the type system extern "C" EXPCL_DTOOL int get_best_parent_from_Set(int id, const std::set &this_set); +#include "typeHandle.h" + #include "typeRegistry.I" #endif diff --git a/dtool/src/dtoolbase/typeRegistryNode.cxx b/dtool/src/dtoolbase/typeRegistryNode.cxx index 2a5860e834..09e36a7ceb 100644 --- a/dtool/src/dtoolbase/typeRegistryNode.cxx +++ b/dtool/src/dtoolbase/typeRegistryNode.cxx @@ -48,11 +48,6 @@ is_derived_from(const TypeRegistryNode *child, const TypeRegistryNode *base) { // code. Therefore, we go through some pains to make this function // as efficient as possible. - // (Actually, it appears that the function is not called as often as - // I'd first thought, and it wasn't really all that expensive to - // begin with. So much of this complexity is of limited usefulness. - // Oh well.) - // First, compare the subtree tops. If they are the same, then this // node and the base node are within the same single-inheritance // subtree, and we can use our bitmask trick to determine the diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index c6645baa6a..3e04ee31ca 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -1953,7 +1953,7 @@ DTOOL_CONFIG=[ ("DO_PSTATS", 'UNDEF', 'UNDEF'), ("DO_DCAST", 'UNDEF', 'UNDEF'), ("DO_COLLISION_RECORDING", 'UNDEF', 'UNDEF'), - ("SUPPORT_IMMEDIATE_MODE", '1', '1'), + ("SUPPORT_IMMEDIATE_MODE", 'UNDEF', 'UNDEF'), ("TRACK_IN_INTERPRETER", 'UNDEF', 'UNDEF'), ("DO_MEMORY_USAGE", 'UNDEF', 'UNDEF'), ("DO_PIPELINING", '1', '1'), diff --git a/panda/src/cull/drawCullHandler.cxx b/panda/src/cull/drawCullHandler.cxx index 02d6a660bb..bbaa2fe1b3 100644 --- a/panda/src/cull/drawCullHandler.cxx +++ b/panda/src/cull/drawCullHandler.cxx @@ -19,7 +19,7 @@ #include "renderState.h" #include "graphicsStateGuardianBase.h" #include "config_pgraph.h" - +#include "cullTraverser.h" //////////////////////////////////////////////////////////////////// // Function: DrawCullHandler::record_object diff --git a/panda/src/cull/drawCullHandler.h b/panda/src/cull/drawCullHandler.h index 91038bd597..7fea30c8b3 100644 --- a/panda/src/cull/drawCullHandler.h +++ b/panda/src/cull/drawCullHandler.h @@ -35,7 +35,7 @@ class EXPCL_PANDA_CULL DrawCullHandler : public CullHandler { public: INLINE DrawCullHandler(GraphicsStateGuardianBase *gsg); - virtual void record_object(CullableObject *object, + virtual void record_object(CullableObject *object, const CullTraverser *traverser); private: @@ -46,5 +46,3 @@ private: #endif - - diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 3ac9bfd84c..3dc4cf7e50 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -365,6 +365,9 @@ set_coordinate_system(CoordinateSystem cs) { if (cs == CS_default) { cs = get_default_coordinate_system(); } + if (_coordinate_system == cs) { + return; + } _coordinate_system = cs; // Changing the external coordinate system changes the cs_transform. @@ -1041,7 +1044,8 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 & return &t; } case Shader::SMO_attr_material: { - const MaterialAttrib *target_material = DCAST(MaterialAttrib, _target_rs->get_attrib_def(MaterialAttrib::get_class_slot())); + const MaterialAttrib *target_material = (const MaterialAttrib *) + _target_rs->get_attrib_def(MaterialAttrib::get_class_slot()); // Material matrix contains AMBIENT, DIFFUSE, EMISSION, SPECULAR+SHININESS if (target_material->is_off()) { t = LMatrix4(1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0); @@ -1060,7 +1064,8 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 & return &t; } case Shader::SMO_attr_color: { - const ColorAttrib *target_color = DCAST(ColorAttrib, _target_rs->get_attrib_def(ColorAttrib::get_class_slot())); + const ColorAttrib *target_color = (const ColorAttrib *) + _target_rs->get_attrib_def(ColorAttrib::get_class_slot()); if (target_color->get_color_type() != ColorAttrib::T_flat) { return &LMatrix4::ones_mat(); } @@ -1069,7 +1074,8 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 & return &t; } case Shader::SMO_attr_colorscale: { - const ColorScaleAttrib *target_color = DCAST(ColorScaleAttrib, _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot())); + const ColorScaleAttrib *target_color = (const ColorScaleAttrib *) + _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot()); if (target_color->is_identity()) { return &LMatrix4::ones_mat(); } @@ -1078,7 +1084,8 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 & return &t; } case Shader::SMO_attr_fog: { - const FogAttrib *target_fog = DCAST(FogAttrib, _target_rs->get_attrib_def(FogAttrib::get_class_slot())); + const FogAttrib *target_fog = (const FogAttrib *) + _target_rs->get_attrib_def(FogAttrib::get_class_slot()); Fog *fog = target_fog->get_fog(); if (fog == (Fog*) NULL) { return &LMatrix4::ones_mat(); @@ -1089,7 +1096,8 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 & return &t; } case Shader::SMO_attr_fogcolor: { - const FogAttrib *target_fog = DCAST(FogAttrib, _target_rs->get_attrib_def(FogAttrib::get_class_slot())); + const FogAttrib *target_fog = (const FogAttrib *) + _target_rs->get_attrib_def(FogAttrib::get_class_slot()); Fog *fog = target_fog->get_fog(); if (fog == (Fog*) NULL) { return &LMatrix4::ones_mat(); @@ -2074,8 +2082,12 @@ get_render_buffer(int buffer_type, const FrameBufferProperties &prop) { //////////////////////////////////////////////////////////////////// CPT(TransformState) GraphicsStateGuardian:: get_cs_transform_for(CoordinateSystem cs) const { - if (_internal_coordinate_system == CS_default || - _internal_coordinate_system == cs) { + if (_coordinate_system == cs) { + // We've already calculated this. + return _cs_transform; + + } else if (_internal_coordinate_system == CS_default || + _internal_coordinate_system == cs) { return TransformState::make_identity(); } else { @@ -2111,7 +2123,9 @@ do_issue_clip_plane() { int num_enabled = 0; int num_on_planes = 0; - const ClipPlaneAttrib *target_clip_plane = DCAST(ClipPlaneAttrib, _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot())); + const ClipPlaneAttrib *target_clip_plane = (const ClipPlaneAttrib *) + _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot()); + if (target_clip_plane != (ClipPlaneAttrib *)NULL) { CPT(ClipPlaneAttrib) new_plane = target_clip_plane->filter_to_max(_max_clip_planes); @@ -2171,7 +2185,9 @@ do_issue_clip_plane() { //////////////////////////////////////////////////////////////////// void GraphicsStateGuardian:: do_issue_color() { - const ColorAttrib *target_color = DCAST(ColorAttrib, _target_rs->get_attrib_def(ColorAttrib::get_class_slot())); + const ColorAttrib *target_color = (const ColorAttrib *) + _target_rs->get_attrib_def(ColorAttrib::get_class_slot()); + switch (target_color->get_color_type()) { case ColorAttrib::T_flat: // Color attribute flat: it specifies a scene graph color that @@ -2219,7 +2235,9 @@ do_issue_color_scale() { _state_mask.clear_bit(TextureAttrib::get_class_slot()); } - const ColorScaleAttrib *target_color_scale = DCAST(ColorScaleAttrib, _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot())); + const ColorScaleAttrib *target_color_scale = (const ColorScaleAttrib *) + _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot()); + _color_scale_enabled = target_color_scale->has_scale(); _current_color_scale = target_color_scale->get_scale(); _has_texture_alpha_scale = false; @@ -2278,7 +2296,9 @@ do_issue_light() { int num_enabled = 0; int num_on_lights = 0; - const LightAttrib *target_light = DCAST(LightAttrib, _target_rs->get_attrib_def(LightAttrib::get_class_slot())); + const LightAttrib *target_light = (const LightAttrib *) + _target_rs->get_attrib_def(LightAttrib::get_class_slot()); + if (display_cat.is_spam()) { display_cat.spam() << "do_issue_light: " << target_light << "\n"; @@ -2639,8 +2659,10 @@ end_bind_clip_planes() { //////////////////////////////////////////////////////////////////// void GraphicsStateGuardian:: determine_target_texture() { - const TextureAttrib *target_texture = DCAST(TextureAttrib, _target_rs->get_attrib_def(TextureAttrib::get_class_slot())); - const TexGenAttrib *target_tex_gen = DCAST(TexGenAttrib, _target_rs->get_attrib_def(TexGenAttrib::get_class_slot())); + const TextureAttrib *target_texture = (const TextureAttrib *) + _target_rs->get_attrib_def(TextureAttrib::get_class_slot()); + const TexGenAttrib *target_tex_gen = (const TexGenAttrib *) + _target_rs->get_attrib_def(TexGenAttrib::get_class_slot()); nassertv(target_texture != (TextureAttrib *)NULL && target_tex_gen != (TexGenAttrib *)NULL); diff --git a/panda/src/express/memoryUsage.I b/panda/src/express/memoryUsage.I index 03939f09d1..8f52d9172d 100644 --- a/panda/src/express/memoryUsage.I +++ b/panda/src/express/memoryUsage.I @@ -366,3 +366,20 @@ INLINE void MemoryUsage:: show_trend_ages() { get_global_ptr()->ns_show_trend_ages(); } + +//////////////////////////////////////////////////////////////////// +// Function: MemoryUsage::get_global_ptr +// Access: Private, Static +// Description: Returns the pointer to the only MemoryUsage object in +// the world. +//////////////////////////////////////////////////////////////////// +INLINE MemoryUsage *MemoryUsage:: +get_global_ptr() { + if (_global_ptr == (MemoryUsage *)NULL) { + init_memory_hook(); + _global_ptr = new MemoryUsage(*memory_hook); + memory_hook = _global_ptr; + } + + return _global_ptr; +} diff --git a/panda/src/express/memoryUsage.cxx b/panda/src/express/memoryUsage.cxx index 9061aab12d..93315ac428 100644 --- a/panda/src/express/memoryUsage.cxx +++ b/panda/src/express/memoryUsage.cxx @@ -564,24 +564,6 @@ overflow_heap_size() { _report_memory_usage = true; } -//////////////////////////////////////////////////////////////////// -// Function: MemoryUsage::get_global_ptr -// Access: Private, Static -// Description: Returns the pointer to the only MemoryUsage object in -// the world. -//////////////////////////////////////////////////////////////////// -MemoryUsage *MemoryUsage:: -get_global_ptr() { - if (_global_ptr == (MemoryUsage *)NULL) { - init_memory_hook(); - _global_ptr = new MemoryUsage(*memory_hook); - memory_hook = _global_ptr; - } - - return _global_ptr; -} - - //////////////////////////////////////////////////////////////////// // Function: MemoryUsage::ns_record_pointer // Access: Private diff --git a/panda/src/express/memoryUsage.h b/panda/src/express/memoryUsage.h index 893b0c8351..0a2f653e7e 100644 --- a/panda/src/express/memoryUsage.h +++ b/panda/src/express/memoryUsage.h @@ -96,7 +96,7 @@ protected: private: MemoryUsage(const MemoryHook ©); - static MemoryUsage *get_global_ptr(); + INLINE static MemoryUsage *get_global_ptr(); void ns_record_pointer(ReferenceCount *ptr); void ns_update_type(ReferenceCount *ptr, TypeHandle type); diff --git a/panda/src/express/nodePointerTo.I b/panda/src/express/nodePointerTo.I index 8897c160b3..cdc2d6cbdd 100644 --- a/panda/src/express/nodePointerTo.I +++ b/panda/src/express/nodePointerTo.I @@ -51,6 +51,36 @@ INLINE NodePointerTo:: } #endif // CPPPARSER +#ifdef USE_MOVE_SEMANTICS +#ifndef CPPPARSER +//////////////////////////////////////////////////////////////////// +// Function: NodePointerTo::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodePointerTo:: +NodePointerTo(NodePointerTo &&from) NOEXCEPT : + NodePointerToBase((NodePointerToBase &&)from) +{ +} +#endif // CPPPARSER + +#ifndef CPPPARSER +//////////////////////////////////////////////////////////////////// +// Function: NodePointerTo::Move Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodePointerTo &NodePointerTo:: +operator = (NodePointerTo &&from) NOEXCEPT { + this->reassign(move(from)); + return *this; +} +#endif // CPPPARSER +#endif // USE_MOVE_SEMANTICS + #ifndef CPPPARSER //////////////////////////////////////////////////////////////////// // Function: NodePointerTo::Dereference operator @@ -192,6 +222,64 @@ INLINE NodeConstPointerTo:: } #endif // CPPPARSER +#ifdef USE_MOVE_SEMANTICS +#ifndef CPPPARSER +//////////////////////////////////////////////////////////////////// +// Function: NodeConstPointerTo::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodeConstPointerTo:: +NodeConstPointerTo(NodePointerTo &&from) NOEXCEPT : + NodePointerToBase((NodePointerToBase &&)from) +{ +} +#endif // CPPPARSER + +#ifndef CPPPARSER +//////////////////////////////////////////////////////////////////// +// Function: NodeConstPointerTo::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodeConstPointerTo:: +NodeConstPointerTo(NodeConstPointerTo &&from) NOEXCEPT : + NodePointerToBase((NodePointerToBase &&)from) +{ +} +#endif // CPPPARSER + +#ifndef CPPPARSER +//////////////////////////////////////////////////////////////////// +// Function: NodeConstPointerTo::Move Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodeConstPointerTo &NodeConstPointerTo:: +operator = (NodePointerTo &&from) NOEXCEPT { + this->reassign(move(from)); + return *this; +} +#endif // CPPPARSER + +#ifndef CPPPARSER +//////////////////////////////////////////////////////////////////// +// Function: NodeConstPointerTo::Move Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodeConstPointerTo &NodeConstPointerTo:: +operator = (NodeConstPointerTo &&from) NOEXCEPT { + this->reassign(move(from)); + return *this; +} +#endif // CPPPARSER +#endif // USE_MOVE_SEMANTICS + #ifndef CPPPARSER //////////////////////////////////////////////////////////////////// // Function: NodeConstPointerTo::Dereference operator diff --git a/panda/src/express/nodePointerTo.h b/panda/src/express/nodePointerTo.h index 5de988ddfc..dfd87923ab 100644 --- a/panda/src/express/nodePointerTo.h +++ b/panda/src/express/nodePointerTo.h @@ -36,6 +36,11 @@ public: INLINE NodePointerTo(const NodePointerTo ©); INLINE ~NodePointerTo(); +#ifdef USE_MOVE_SEMANTICS + INLINE NodePointerTo(NodePointerTo &&from) NOEXCEPT; + INLINE NodePointerTo &operator = (NodePointerTo &&from) NOEXCEPT; +#endif + INLINE To &operator *() const; INLINE To *operator -> () const; @@ -67,6 +72,13 @@ public: INLINE NodeConstPointerTo(const NodeConstPointerTo ©); INLINE ~NodeConstPointerTo(); +#ifdef USE_MOVE_SEMANTICS + INLINE NodeConstPointerTo(NodePointerTo &&from) NOEXCEPT; + INLINE NodeConstPointerTo(NodeConstPointerTo &&from) NOEXCEPT; + INLINE NodeConstPointerTo &operator = (NodePointerTo &&from) NOEXCEPT; + INLINE NodeConstPointerTo &operator = (NodeConstPointerTo &&from) NOEXCEPT; +#endif + INLINE const To &operator *() const; INLINE const To *operator -> () const; INLINE operator const T *() const; @@ -79,6 +91,16 @@ public: #endif // CPPPARSER }; +template +void swap(NodePointerTo &one, NodePointerTo &two) NOEXCEPT { + one.swap(two); +} + +template +void swap(NodeConstPointerTo &one, NodeConstPointerTo &two) NOEXCEPT { + one.swap(two); +} + #define NPT(type) NodePointerTo< type > #define NCPT(type) NodeConstPointerTo< type > diff --git a/panda/src/express/nodePointerToBase.I b/panda/src/express/nodePointerToBase.I index d76afccc94..4729f6184d 100644 --- a/panda/src/express/nodePointerToBase.I +++ b/panda/src/express/nodePointerToBase.I @@ -46,6 +46,43 @@ INLINE NodePointerToBase:: reassign((To *)NULL); } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: NodePointerToBase::Move Constructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodePointerToBase:: +NodePointerToBase(NodePointerToBase &&from) NOEXCEPT { + _void_ptr = from._void_ptr; + from._void_ptr = (void *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerToBase::reassign +// Access: Protected +// Description: This version of reassign is called when a +// NodePointerTo is assigned to this Node PointerTo +// as an rvalue. In this case, we can steal the +// reference count from the other PointerTo, without +// needing to call ref() and unref() unnecessarily. +//////////////////////////////////////////////////////////////////// +template +INLINE void NodePointerToBase:: +reassign(NodePointerToBase &&from) NOEXCEPT { + To *old_ptr = (To *)this->_void_ptr; + + this->_void_ptr = from._void_ptr; + from._void_ptr = NULL; + + // Now delete the old pointer. + if (old_ptr != (To *)NULL) { + node_unref_delete(old_ptr); + } +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: NodePointerToBase::reassign // Access: Protected diff --git a/panda/src/express/nodePointerToBase.h b/panda/src/express/nodePointerToBase.h index 44377d6569..870824c2b6 100644 --- a/panda/src/express/nodePointerToBase.h +++ b/panda/src/express/nodePointerToBase.h @@ -42,6 +42,11 @@ protected: INLINE NodePointerToBase(const NodePointerToBase ©); INLINE ~NodePointerToBase(); +#ifdef USE_MOVE_SEMANTICS + INLINE NodePointerToBase(NodePointerToBase &&from) NOEXCEPT; + INLINE void reassign(NodePointerToBase &&from) NOEXCEPT; +#endif + void reassign(To *ptr); INLINE void reassign(const NodePointerToBase ©); diff --git a/panda/src/express/pointerTo.I b/panda/src/express/pointerTo.I index 5b021f8e86..caaccbcd42 100644 --- a/panda/src/express/pointerTo.I +++ b/panda/src/express/pointerTo.I @@ -43,8 +43,8 @@ PointerTo(const PointerTo ©) : //////////////////////////////////////////////////////////////////// template INLINE PointerTo:: -PointerTo(PointerTo &&move) NOEXCEPT : - PointerToBase((PointerToBase &&)move) +PointerTo(PointerTo &&from) NOEXCEPT : + PointerToBase(move(from)) { } @@ -55,19 +55,11 @@ PointerTo(PointerTo &&move) NOEXCEPT : //////////////////////////////////////////////////////////////////// template INLINE PointerTo &PointerTo:: -operator = (PointerTo &&move) NOEXCEPT { - To *old_ptr = (To *)this->_void_ptr; - - this->_void_ptr = move._void_ptr; - move._void_ptr = NULL; - - if (old_ptr != (To *)NULL) { - unref_delete(old_ptr); - } - +operator = (PointerTo &&from) NOEXCEPT { + this->reassign(move(from)); return *this; } -#endif +#endif // USE_MOVE_SEMANTICS //////////////////////////////////////////////////////////////////// // Function: PointerTo::Destructor @@ -208,8 +200,20 @@ ConstPointerTo(const ConstPointerTo ©) : //////////////////////////////////////////////////////////////////// template INLINE ConstPointerTo:: -ConstPointerTo(ConstPointerTo &&move) NOEXCEPT : - PointerToBase((PointerToBase &&)move) +ConstPointerTo(PointerTo &&from) NOEXCEPT : + PointerToBase(move(from)) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ConstPointerTo::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE ConstPointerTo:: +ConstPointerTo(ConstPointerTo &&from) NOEXCEPT : + PointerToBase(move(from)) { } @@ -220,19 +224,23 @@ ConstPointerTo(ConstPointerTo &&move) NOEXCEPT : //////////////////////////////////////////////////////////////////// template INLINE ConstPointerTo &ConstPointerTo:: -operator = (ConstPointerTo &&move) NOEXCEPT { - To *old_ptr = (To *)this->_void_ptr; - - this->_void_ptr = move._void_ptr; - move._void_ptr = NULL; - - if (old_ptr != (To *)NULL) { - unref_delete(old_ptr); - } - +operator = (PointerTo &&from) NOEXCEPT { + this->reassign(move(from)); return *this; } -#endif + +//////////////////////////////////////////////////////////////////// +// Function: ConstPointerTo::Move Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE ConstPointerTo &ConstPointerTo:: +operator = (ConstPointerTo &&from) NOEXCEPT { + this->reassign(move(from)); + return *this; +} +#endif // USE_MOVE_SEMANTICS //////////////////////////////////////////////////////////////////// // Function: ConstPointerTo::Dereference operator diff --git a/panda/src/express/pointerTo.h b/panda/src/express/pointerTo.h index e93ef68f80..1597b94d41 100644 --- a/panda/src/express/pointerTo.h +++ b/panda/src/express/pointerTo.h @@ -86,8 +86,8 @@ PUBLISHED: public: #ifdef USE_MOVE_SEMANTICS - INLINE PointerTo(PointerTo &&move) NOEXCEPT; - INLINE PointerTo &operator = (PointerTo &&move) NOEXCEPT; + INLINE PointerTo(PointerTo &&from) NOEXCEPT; + INLINE PointerTo &operator = (PointerTo &&from) NOEXCEPT; #endif INLINE To &operator *() const; @@ -150,8 +150,10 @@ PUBLISHED: public: #ifdef USE_MOVE_SEMANTICS - INLINE ConstPointerTo(ConstPointerTo &&move) NOEXCEPT; - INLINE ConstPointerTo &operator = (ConstPointerTo &&move) NOEXCEPT; + INLINE ConstPointerTo(PointerTo &&from) NOEXCEPT; + INLINE ConstPointerTo(ConstPointerTo &&from) NOEXCEPT; + INLINE ConstPointerTo &operator = (PointerTo &&from) NOEXCEPT; + INLINE ConstPointerTo &operator = (ConstPointerTo &&from) NOEXCEPT; #endif INLINE const To &operator *() const; @@ -177,12 +179,12 @@ PUBLISHED: // of PointerTo objects without incurring the cost of unnecessary // reference count changes. The performance difference is dramatic! template -void swap(PointerTo &one, PointerTo &two) { +void swap(PointerTo &one, PointerTo &two) NOEXCEPT { one.swap(two); } template -void swap(ConstPointerTo &one, ConstPointerTo &two) { +void swap(ConstPointerTo &one, ConstPointerTo &two) NOEXCEPT { one.swap(two); } diff --git a/panda/src/express/pointerToBase.I b/panda/src/express/pointerToBase.I index f6c5e192fd..783d59353e 100644 --- a/panda/src/express/pointerToBase.I +++ b/panda/src/express/pointerToBase.I @@ -35,20 +35,6 @@ PointerToBase(const PointerToBase ©) { reassign(copy); } -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Move Constructor -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -#ifdef USE_MOVE_SEMANTICS -template -INLINE PointerToBase:: -PointerToBase(PointerToBase &&move) NOEXCEPT { - _void_ptr = move._void_ptr; - move._void_ptr = (void *)NULL; -} -#endif - //////////////////////////////////////////////////////////////////// // Function: PointerToBase::Destructor // Access: Protected @@ -60,6 +46,43 @@ INLINE PointerToBase:: reassign((To *)NULL); } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: PointerToBase::Move Constructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE PointerToBase:: +PointerToBase(PointerToBase &&from) NOEXCEPT { + _void_ptr = from._void_ptr; + from._void_ptr = (void *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToBase::reassign +// Access: Protected +// Description: This version of reassign is called when a PointerTo +// is assigned to this PointerTo as an rvalue. In +// this case, we can steal the reference count from +// the other PointerTo, without needing to call ref() +// and unref() unnecessarily. +//////////////////////////////////////////////////////////////////// +template +INLINE void PointerToBase:: +reassign(PointerToBase &&from) NOEXCEPT { + To *old_ptr = (To *)this->_void_ptr; + + this->_void_ptr = from._void_ptr; + from._void_ptr = NULL; + + // Now delete the old pointer. + if (old_ptr != (To *)NULL) { + unref_delete(old_ptr); + } +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: PointerToBase::reassign // Access: Protected diff --git a/panda/src/express/pointerToBase.h b/panda/src/express/pointerToBase.h index 495033ff71..0828e300f8 100644 --- a/panda/src/express/pointerToBase.h +++ b/panda/src/express/pointerToBase.h @@ -39,7 +39,8 @@ protected: INLINE ~PointerToBase(); #ifdef USE_MOVE_SEMANTICS - INLINE PointerToBase(PointerToBase &&move) NOEXCEPT; + INLINE PointerToBase(PointerToBase &&from) NOEXCEPT; + INLINE void reassign(PointerToBase &&from) NOEXCEPT; #endif INLINE void reassign(To *ptr); diff --git a/panda/src/express/pointerToVoid.I b/panda/src/express/pointerToVoid.I index 108e959323..8080801837 100644 --- a/panda/src/express/pointerToVoid.I +++ b/panda/src/express/pointerToVoid.I @@ -110,8 +110,13 @@ operator != (const PointerToVoid &other) const { // Access: Public // Description: Swaps the contents of this PointerTo with the other, // without touching the reference counts. +// +// For internal use only. Use the global swap() +// function instead. //////////////////////////////////////////////////////////////////// INLINE void PointerToVoid:: -swap(PointerToVoid &other) { - std::swap(_void_ptr, other._void_ptr); +swap(PointerToVoid &other) NOEXCEPT { + AtomicAdjust::Pointer temp = _void_ptr; + _void_ptr = other._void_ptr; + other._void_ptr = temp; } diff --git a/panda/src/express/pointerToVoid.h b/panda/src/express/pointerToVoid.h index 2556b1eb8c..d3a71d7c8b 100644 --- a/panda/src/express/pointerToVoid.h +++ b/panda/src/express/pointerToVoid.h @@ -54,7 +54,7 @@ public: INLINE bool operator == (const PointerToVoid &other) const; INLINE bool operator != (const PointerToVoid &other) const; - INLINE void swap(PointerToVoid &other); + INLINE void swap(PointerToVoid &other) NOEXCEPT; protected: // Within the PointerToVoid class, we only store a void pointer. diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 222ae9d977..4fc36abbfc 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -2288,6 +2288,7 @@ clear(DrawableRegion *clearable) { return; } + //XXX rdb: Is this line really necessary? set_state_and_transform(RenderState::make_empty(), _internal_transform); int mask = 0; @@ -2842,7 +2843,7 @@ end_frame(Thread *current_thread) { // Now is a good time to delete any pending display lists. #ifndef OPENGLES - { + if (display_lists) { LightMutexHolder holder(_lock); if (!_deleted_display_lists.empty()) { DeletedNames::iterator ddli; @@ -2857,10 +2858,13 @@ end_frame(Thread *current_thread) { } _deleted_display_lists.clear(); } + } - // And deleted queries, too, unless we're using query timers - // in which case we'll need to reuse lots of them. - if (!get_timer_queries_active() && !_deleted_queries.empty()) { + // And deleted queries, too, unless we're using query timers + // in which case we'll need to reuse lots of them. + if (_supports_occlusion_query && !get_timer_queries_active()) { + LightMutexHolder holder(_lock); + if (!_deleted_queries.empty()) { if (GLCAT.is_spam()) { DeletedNames::iterator dqi; for (dqi = _deleted_queries.begin(); @@ -5122,9 +5126,9 @@ issue_timer_query(int pstats_index) { // Issue the timestamp query. _glQueryCounter(query->_index, GL_TIMESTAMP); - _pending_timer_queries.push_back(DCAST(TimerQueryContext, query)); + _pending_timer_queries.push_back((TimerQueryContext *)query); - return DCAST(TimerQueryContext, query); + return (TimerQueryContext *)query; #else return NULL; @@ -5637,7 +5641,9 @@ do_issue_transform() { void CLP(GraphicsStateGuardian):: do_issue_shade_model() { #ifndef OPENGLES_2 - const ShadeModelAttrib *target_shade_model = DCAST(ShadeModelAttrib, _target_rs->get_attrib_def(ShadeModelAttrib::get_class_slot())); + const ShadeModelAttrib *target_shade_model = (const ShadeModelAttrib *) + _target_rs->get_attrib_def(ShadeModelAttrib::get_class_slot()); + switch (target_shade_model->get_mode()) { case ShadeModelAttrib::M_smooth: glShadeModel(GL_SMOOTH); @@ -5720,7 +5726,9 @@ do_issue_shader(bool state_has_changed) { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: do_issue_render_mode() { - const RenderModeAttrib *target_render_mode = DCAST(RenderModeAttrib, _target_rs->get_attrib_def(RenderModeAttrib::get_class_slot())); + const RenderModeAttrib *target_render_mode = (const RenderModeAttrib *) + _target_rs->get_attrib_def(RenderModeAttrib::get_class_slot()); + _render_mode = target_render_mode->get_mode(); _point_size = target_render_mode->get_thickness(); _point_perspective = target_render_mode->get_perspective(); @@ -5764,7 +5772,9 @@ do_issue_render_mode() { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: do_issue_antialias() { - const AntialiasAttrib *target_antialias = DCAST(AntialiasAttrib, _target_rs->get_attrib_def(AntialiasAttrib::get_class_slot())); + const AntialiasAttrib *target_antialias = (const AntialiasAttrib *) + _target_rs->get_attrib_def(AntialiasAttrib::get_class_slot()); + if (target_antialias->get_mode_type() == AntialiasAttrib::M_auto) { // In this special mode, we must enable antialiasing on a // case-by-case basis, because we enable it differently for @@ -5830,7 +5840,9 @@ do_issue_antialias() { void CLP(GraphicsStateGuardian):: do_issue_rescale_normal() { #ifndef OPENGLES_2 // OpenGL ES 2.0 doesn't support rescaling normals. - const RescaleNormalAttrib *target_rescale_normal = DCAST(RescaleNormalAttrib, _target_rs->get_attrib_def(RescaleNormalAttrib::get_class_slot())); + const RescaleNormalAttrib *target_rescale_normal = (const RescaleNormalAttrib *) + _target_rs->get_attrib_def(RescaleNormalAttrib::get_class_slot()); + RescaleNormalAttrib::Mode mode = target_rescale_normal->get_mode(); _auto_rescale_normal = false; @@ -5882,7 +5894,9 @@ do_issue_rescale_normal() { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: do_issue_depth_test() { - const DepthTestAttrib *target_depth_test = DCAST(DepthTestAttrib, _target_rs->get_attrib_def(DepthTestAttrib::get_class_slot())); + const DepthTestAttrib *target_depth_test = (const DepthTestAttrib *) + _target_rs->get_attrib_def(DepthTestAttrib::get_class_slot()); + DepthTestAttrib::PandaCompareFunc mode = target_depth_test->get_mode(); if (mode == DepthTestAttrib::M_none) { enable_depth_test(false); @@ -5903,7 +5917,9 @@ do_issue_alpha_test() { if (_target_shader->get_flag(ShaderAttrib::F_subsume_alpha_test)) { enable_alpha_test(false); } else { - const AlphaTestAttrib *target_alpha_test = DCAST(AlphaTestAttrib, _target_rs->get_attrib_def(AlphaTestAttrib::get_class_slot())); + const AlphaTestAttrib *target_alpha_test = (const AlphaTestAttrib *) + _target_rs->get_attrib_def(AlphaTestAttrib::get_class_slot()); + AlphaTestAttrib::PandaCompareFunc mode = target_alpha_test->get_mode(); if (mode == AlphaTestAttrib::M_none) { enable_alpha_test(false); @@ -5924,7 +5940,9 @@ do_issue_alpha_test() { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: do_issue_depth_write() { - const DepthWriteAttrib *target_depth_write = DCAST(DepthWriteAttrib, _target_rs->get_attrib_def(DepthWriteAttrib::get_class_slot())); + const DepthWriteAttrib *target_depth_write = (const DepthWriteAttrib *) + _target_rs->get_attrib_def(DepthWriteAttrib::get_class_slot()); + DepthWriteAttrib::Mode mode = target_depth_write->get_mode(); if (mode == DepthWriteAttrib::M_off) { #ifdef GSG_VERBOSE @@ -5949,7 +5967,9 @@ do_issue_depth_write() { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: do_issue_cull_face() { - const CullFaceAttrib *target_cull_face = DCAST(CullFaceAttrib, _target_rs->get_attrib_def(CullFaceAttrib::get_class_slot())); + const CullFaceAttrib *target_cull_face = (const CullFaceAttrib *) + _target_rs->get_attrib_def(CullFaceAttrib::get_class_slot()); + CullFaceAttrib::Mode mode = target_cull_face->get_effective_mode(); switch (mode) { @@ -5979,7 +5999,9 @@ do_issue_cull_face() { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: do_issue_fog() { - const FogAttrib *target_fog = DCAST(FogAttrib, _target_rs->get_attrib_def(FogAttrib::get_class_slot())); + const FogAttrib *target_fog = (const FogAttrib *) + _target_rs->get_attrib_def(FogAttrib::get_class_slot()); + if (!target_fog->is_off()) { enable_fog(true); Fog *fog = target_fog->get_fog(); @@ -5998,7 +6020,9 @@ do_issue_fog() { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: do_issue_depth_offset() { - const DepthOffsetAttrib *target_depth_offset = DCAST(DepthOffsetAttrib, _target_rs->get_attrib_def(DepthOffsetAttrib::get_class_slot())); + const DepthOffsetAttrib *target_depth_offset = (const DepthOffsetAttrib *) + _target_rs->get_attrib_def(DepthOffsetAttrib::get_class_slot()); + int offset = target_depth_offset->get_offset(); if (offset != 0) { @@ -6039,7 +6063,8 @@ do_issue_material() { static Material empty; const Material *material; - const MaterialAttrib *target_material = DCAST(MaterialAttrib, _target_rs->get_attrib_def(MaterialAttrib::get_class_slot())); + const MaterialAttrib *target_material = (const MaterialAttrib *) + _target_rs->get_attrib_def(MaterialAttrib::get_class_slot()); if (target_material == (MaterialAttrib *)NULL || target_material->is_off()) { @@ -6146,7 +6171,8 @@ do_issue_blending() { // all the other blending-related stuff doesn't matter. If the // device doesn't support color-write, we use blending tricks // to effectively disable color write. - const ColorWriteAttrib *target_color_write = DCAST(ColorWriteAttrib, _target_rs->get_attrib_def(ColorWriteAttrib::get_class_slot())); + const ColorWriteAttrib *target_color_write = (const ColorWriteAttrib *) + _target_rs->get_attrib_def(ColorWriteAttrib::get_class_slot()); unsigned int color_channels = target_color_write->get_channels() & _color_write_mask; @@ -6176,11 +6202,13 @@ do_issue_blending() { } - const ColorBlendAttrib *target_color_blend = DCAST(ColorBlendAttrib, _target_rs->get_attrib_def(ColorBlendAttrib::get_class_slot())); + const ColorBlendAttrib *target_color_blend = (const ColorBlendAttrib *) + _target_rs->get_attrib_def(ColorBlendAttrib::get_class_slot()); CPT(ColorBlendAttrib) color_blend = target_color_blend; ColorBlendAttrib::Mode color_blend_mode = target_color_blend->get_mode(); - const TransparencyAttrib *target_transparency = DCAST(TransparencyAttrib, _target_rs->get_attrib_def(TransparencyAttrib::get_class_slot())); + const TransparencyAttrib *target_transparency = (const TransparencyAttrib *) + _target_rs->get_attrib_def(TransparencyAttrib::get_class_slot()); TransparencyAttrib::Mode transparency_mode = target_transparency->get_mode(); _color_blend_involves_color_scale = color_blend->involves_color_scale(); @@ -8731,7 +8759,8 @@ set_state_and_transform(const RenderState *target, } _target_rs = target; - _target_shader = DCAST(ShaderAttrib, _target_rs->get_attrib_def(ShaderAttrib::get_class_slot())); + _target_shader = (const ShaderAttrib *) + _target_rs->get_attrib_def(ShaderAttrib::get_class_slot()); #ifndef OPENGLES _instance_count = _target_shader->get_instance_count(); #endif @@ -9558,7 +9587,9 @@ do_issue_tex_matrix() { glMatrixMode(GL_TEXTURE); - const TexMatrixAttrib *target_tex_matrix = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot())); + const TexMatrixAttrib *target_tex_matrix = (const TexMatrixAttrib *) + _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()); + if (target_tex_matrix->has_stage(stage)) { GLPf(LoadMatrix)(target_tex_matrix->get_mat(stage).get_data()); } else { @@ -11886,7 +11917,8 @@ do_issue_stencil() { return; } - const StencilAttrib *stencil = DCAST(StencilAttrib, _target_rs->get_attrib(StencilAttrib::get_class_slot())); + const StencilAttrib *stencil = (const StencilAttrib *) + _target_rs->get_attrib(StencilAttrib::get_class_slot()); if (stencil != (const StencilAttrib *)NULL) { // DEBUG @@ -11974,7 +12006,8 @@ do_issue_stencil() { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: do_issue_scissor() { - const ScissorAttrib *target_scissor = DCAST(ScissorAttrib, _target_rs->get_attrib_def(ScissorAttrib::get_class_slot())); + const ScissorAttrib *target_scissor = (const ScissorAttrib *) + _target_rs->get_attrib_def(ScissorAttrib::get_class_slot()); if (!target_scissor->is_off()) { // A non-off ScissorAttrib means to override the scissor setting diff --git a/panda/src/gobj/geom.I b/panda/src/gobj/geom.I index acf7b61745..4af24f95b2 100644 --- a/panda/src/gobj/geom.I +++ b/panda/src/gobj/geom.I @@ -380,14 +380,14 @@ clear_bounds() { //////////////////////////////////////////////////////////////////// INLINE void Geom:: calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, - bool &found_any, + bool &found_any, const GeomVertexData *vertex_data, bool got_mat, const LMatrix4 &mat, Thread *current_thread) const { CDReader cdata(_cycler, current_thread); - - do_calc_tight_bounds(min_point, max_point, found_any, - vertex_data, got_mat, mat, + + do_calc_tight_bounds(min_point, max_point, found_any, + vertex_data, got_mat, mat, InternalName::get_vertex(), cdata, current_thread); } @@ -409,7 +409,7 @@ INLINE void Geom:: calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any, Thread *current_thread) const { calc_tight_bounds(min_point, max_point, found_any, - get_vertex_data(current_thread), false, + get_vertex_data(current_thread), false, LMatrix4::ident_mat(), current_thread); } @@ -422,15 +422,15 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, //////////////////////////////////////////////////////////////////// INLINE void Geom:: calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, - bool &found_any, + bool &found_any, const GeomVertexData *vertex_data, bool got_mat, const LMatrix4 &mat, const InternalName *column_name, Thread *current_thread) const { CDReader cdata(_cycler, current_thread); - - do_calc_tight_bounds(min_point, max_point, found_any, - vertex_data, got_mat, mat, + + do_calc_tight_bounds(min_point, max_point, found_any, + vertex_data, got_mat, mat, column_name, cdata, current_thread); } @@ -450,7 +450,7 @@ mark_internal_bounds_stale(CData *cdata) { //////////////////////////////////////////////////////////////////// // Function: Geom::CDataCache::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE Geom::CDataCache:: CDataCache() : @@ -463,7 +463,7 @@ CDataCache() : //////////////////////////////////////////////////////////////////// // Function: Geom::CDataCache::Copy Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE Geom::CDataCache:: CDataCache(const Geom::CDataCache ©) : @@ -500,7 +500,7 @@ set_result(const Geom *geom_result, const GeomVertexData *data_result) { //////////////////////////////////////////////////////////////////// // Function: Geom::CacheKey::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE Geom::CacheKey:: CacheKey(const GeomVertexData *source_data, const GeomMunger *modifier) : @@ -509,6 +509,32 @@ CacheKey(const GeomVertexData *source_data, const GeomMunger *modifier) : { } +//////////////////////////////////////////////////////////////////// +// Function: Geom::CacheKey::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Geom::CacheKey:: +CacheKey(const CacheKey ©) : + _source_data(copy._source_data), + _modifier(copy._modifier) +{ +} + +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: Geom::CacheKey::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Geom::CacheKey:: +CacheKey(CacheKey &&from) NOEXCEPT : + _source_data(move(from._source_data)), + _modifier(move(from._modifier)) +{ +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: Geom::CacheKey::operator < // Access: Public @@ -531,7 +557,7 @@ operator < (const CacheKey &other) const { //////////////////////////////////////////////////////////////////// // Function: Geom::CacheEntry::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE Geom::CacheEntry:: CacheEntry(Geom *source, const GeomVertexData *source_data, @@ -541,6 +567,31 @@ CacheEntry(Geom *source, const GeomVertexData *source_data, { } +//////////////////////////////////////////////////////////////////// +// Function: Geom::CacheEntry::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Geom::CacheEntry:: +CacheEntry(Geom *source, const Geom::CacheKey &key) : + _source(source), + _key(key) +{ +} + +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: Geom::CacheEntry::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Geom::CacheEntry:: +CacheEntry(Geom *source, Geom::CacheKey &&key) NOEXCEPT : + _source(source), + _key(move(key)) +{ +} +#endif // USE_MOVE_SEMANTICS //////////////////////////////////////////////////////////////////// // Function: Geom::CData::Constructor @@ -667,7 +718,7 @@ get_current_thread() const { //////////////////////////////////////////////////////////////////// // Function: GeomPipelineReader::get_primitive_type // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE GeomPipelineReader::PrimitiveType GeomPipelineReader:: get_primitive_type() const { @@ -677,7 +728,7 @@ get_primitive_type() const { //////////////////////////////////////////////////////////////////// // Function: GeomPipelineReader::get_shade_model // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE GeomPipelineReader::ShadeModel GeomPipelineReader:: get_shade_model() const { @@ -687,7 +738,7 @@ get_shade_model() const { //////////////////////////////////////////////////////////////////// // Function: GeomPipelineReader::get_geom_rendering // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE int GeomPipelineReader:: get_geom_rendering() const { @@ -697,7 +748,7 @@ get_geom_rendering() const { //////////////////////////////////////////////////////////////////// // Function: GeomPipelineReader::get_usage_hint // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE GeomPipelineReader::UsageHint GeomPipelineReader:: get_usage_hint() const { @@ -708,7 +759,7 @@ get_usage_hint() const { //////////////////////////////////////////////////////////////////// // Function: GeomPipelineReader::get_vertex_data // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE CPT(GeomVertexData) GeomPipelineReader:: get_vertex_data() const { @@ -718,7 +769,7 @@ get_vertex_data() const { //////////////////////////////////////////////////////////////////// // Function: GeomPipelineReader::get_num_primitives // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE int GeomPipelineReader:: get_num_primitives() const { @@ -728,7 +779,7 @@ get_num_primitives() const { //////////////////////////////////////////////////////////////////// // Function: GeomPipelineReader::get_primitive // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE CPT(GeomPrimitive) GeomPipelineReader:: get_primitive(int i) const { @@ -739,7 +790,7 @@ get_primitive(int i) const { //////////////////////////////////////////////////////////////////// // Function: GeomPipelineReader::get_modified // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE UpdateSeq GeomPipelineReader:: get_modified() const { diff --git a/panda/src/gobj/geom.h b/panda/src/gobj/geom.h index af0eca41a0..773188ee8f 100644 --- a/panda/src/gobj/geom.h +++ b/panda/src/gobj/geom.h @@ -142,24 +142,24 @@ PUBLISHED: bool release(PreparedGraphicsObjects *prepared_objects); int release_all(); - GeomContext *prepare_now(PreparedGraphicsObjects *prepared_objects, + GeomContext *prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg); public: - bool draw(GraphicsStateGuardianBase *gsg, + bool draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger, const GeomVertexData *vertex_data, bool force, Thread *current_thread) const; - + INLINE void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, - bool &found_any, + bool &found_any, const GeomVertexData *vertex_data, bool got_mat, const LMatrix4 &mat, Thread *current_thread) const; INLINE void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any, Thread *current_thread) const; INLINE void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, - bool &found_any, + bool &found_any, const GeomVertexData *vertex_data, bool got_mat, const LMatrix4 &mat, const InternalName *column_name, @@ -174,7 +174,7 @@ private: void compute_internal_bounds(CData *cdata, Thread *current_thread) const; void do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, - bool &found_any, + bool &found_any, const GeomVertexData *vertex_data, bool got_mat, const LMatrix4 &mat, const InternalName *column_name, @@ -220,7 +220,7 @@ private: Geom *_source; // A back pointer to the containing Geom const Geom *_geom_result; // ref-counted if not NULL and not same as _source CPT(GeomVertexData) _data_result; - + public: static TypeHandle get_class_type() { return _type_handle; @@ -228,7 +228,7 @@ private: static void init_type() { register_type(_type_handle, "Geom::CDataCache"); } - + private: static TypeHandle _type_handle; }; @@ -245,6 +245,10 @@ public: public: INLINE CacheKey(const GeomVertexData *source_data, const GeomMunger *modifier); + INLINE CacheKey(const CacheKey ©); +#ifdef USE_MOVE_SEMANTICS + INLINE CacheKey(CacheKey &&from) NOEXCEPT; +#endif INLINE bool operator < (const CacheKey &other) const; CPT(GeomVertexData) _source_data; @@ -253,9 +257,13 @@ public: // It is not clear why MSVC7 needs this class to be public. class CacheEntry : public GeomCacheEntry { public: - INLINE CacheEntry(Geom *source, + INLINE CacheEntry(Geom *source, const GeomVertexData *source_data, const GeomMunger *modifier); + INLINE CacheEntry(Geom *source, const CacheKey &key); +#ifdef USE_MOVE_SEMANTICS + INLINE CacheEntry(Geom *source, CacheKey &&key) NOEXCEPT; +#endif ALLOC_DELETED_CHAIN(CacheEntry); virtual void evict_callback(); @@ -265,7 +273,7 @@ public: CacheKey _key; PipelineCycler _cycler; - + public: static TypeHandle get_class_type() { return _type_handle; @@ -275,7 +283,7 @@ public: register_type(_type_handle, "Geom::CacheEntry", GeomCacheEntry::get_class_type()); } - + private: static TypeHandle _type_handle; }; @@ -304,13 +312,13 @@ private: UsageHint _usage_hint; bool _got_usage_hint; UpdateSeq _modified; - + CPT(BoundingVolume) _internal_bounds; int _nested_vertices; bool _internal_bounds_stale; BoundingVolume::BoundsType _bounds_type; CPT(BoundingVolume) _user_bounds; - + public: static TypeHandle get_class_type() { return _type_handle; @@ -318,11 +326,11 @@ private: static void init_type() { register_type(_type_handle, "Geom::CData"); } - + private: static TypeHandle _type_handle; }; - + PipelineCycler _cycler; typedef CycleDataLockedReader CDLockedReader; typedef CycleDataReader CDReader; diff --git a/panda/src/gobj/geomMunger.cxx b/panda/src/gobj/geomMunger.cxx index 4848f48c72..8ce1175c5d 100644 --- a/panda/src/gobj/geomMunger.cxx +++ b/panda/src/gobj/geomMunger.cxx @@ -27,7 +27,7 @@ PStatCollector GeomMunger::_munge_pcollector("*:Munge"); //////////////////////////////////////////////////////////////////// // Function: GeomMunger::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomMunger:: GeomMunger(GraphicsStateGuardianBase *gsg) : @@ -44,7 +44,7 @@ GeomMunger(GraphicsStateGuardianBase *gsg) : //////////////////////////////////////////////////////////////////// // Function: GeomMunger::Copy Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomMunger:: GeomMunger(const GeomMunger ©) : @@ -60,7 +60,7 @@ GeomMunger(const GeomMunger ©) : //////////////////////////////////////////////////////////////////// // Function: GeomMunger::Copy Assignment Operator // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// void GeomMunger:: operator = (const GeomMunger ©) { @@ -70,7 +70,7 @@ operator = (const GeomMunger ©) { //////////////////////////////////////////////////////////////////// // Function: GeomMunger::Destructor // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomMunger:: ~GeomMunger() { @@ -96,7 +96,7 @@ remove_data(const GeomVertexData *data) { // Access: Public // Description: Applies the indicated munger to the geom and its // data, and returns a (possibly different) geom and -// data, according to the munger's whim. +// data, according to the munger's whim. // // The assumption is that for a particular geom and a // particular munger, the result will always be the @@ -110,13 +110,12 @@ remove_data(const GeomVertexData *data) { bool GeomMunger:: munge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data, bool force, Thread *current_thread) { - CPT(GeomVertexData) source_data = data; // Look up the munger in the geom's cache--maybe we've recently // applied it. PT(Geom::CacheEntry) entry; - Geom::CacheKey key(source_data, this); + Geom::CacheKey key(data, this); geom->_cache_lock.acquire(); Geom::Cache::const_iterator ci = geom->_cache.find(&key); @@ -126,12 +125,12 @@ munge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data, entry = (*ci).second; geom->_cache_lock.release(); nassertr(entry->_source == geom, false); - + // Here's an element in the cache for this computation. Record a // cache hit, so this element will stay in the cache a while // longer. entry->refresh(current_thread); - + // Now check that it's fresh. Geom::CDCacheReader cdata(entry->_cycler, current_thread); if (cdata->_source == geom && @@ -139,12 +138,12 @@ munge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data, geom->get_modified(current_thread) <= cdata->_geom_result->get_modified(current_thread) && data->get_modified(current_thread) <= cdata->_data_result->get_modified(current_thread)) { // The cache entry is still good; use it. - + geom = cdata->_geom_result; data = cdata->_data_result; return true; } - + // The cache entry is stale, but we'll recompute it below. Note // that there's a small race condition here; another thread might // recompute the cache at the same time. No big deal, since it'll @@ -166,7 +165,12 @@ munge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data, // Record the new result in the cache. if (entry == (Geom::CacheEntry *)NULL) { // Create a new entry for the result. - entry = new Geom::CacheEntry(orig_geom, source_data, this); +#ifdef USE_MOVE_SEMANTICS + // We don't need the key anymore, move the pointers into the CacheEntry. + entry = new Geom::CacheEntry(orig_geom, move(key)); +#else + entry = new Geom::CacheEntry(orig_geom, key); +#endif { LightMutexHolder holder(orig_geom->_cache_lock); bool inserted = orig_geom->_cache.insert(Geom::Cache::value_type(&entry->_key, entry)).second; @@ -176,7 +180,7 @@ munge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data, return true; } } - + // And tell the cache manager about the new entry. (It might // immediately request a delete from the cache of the thing we // just added.) @@ -198,7 +202,7 @@ munge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data, // exists just to cast away the const pointer. //////////////////////////////////////////////////////////////////// CPT(GeomVertexFormat) GeomMunger:: -do_munge_format(const GeomVertexFormat *format, +do_munge_format(const GeomVertexFormat *format, const GeomVertexAnimationSpec &animation) { nassertr(_is_registered, NULL); nassertr(format->is_registered(), NULL); @@ -248,7 +252,7 @@ munge_data_impl(const GeomVertexData *data) { nassertr(_is_registered, NULL); CPT(GeomVertexFormat) orig_format = data->get_format(); - CPT(GeomVertexFormat) new_format = + CPT(GeomVertexFormat) new_format = munge_format(orig_format, orig_format->get_animation()); if (new_format == orig_format) { @@ -384,7 +388,7 @@ make_registry() { _registry = new Registry; } } - + //////////////////////////////////////////////////////////////////// // Function: GeomMunger::do_register // Access: Private @@ -408,7 +412,7 @@ do_register(Thread *current_thread) { _is_registered = true; } - + //////////////////////////////////////////////////////////////////// // Function: GeomMunger::do_unregister // Access: Private @@ -430,7 +434,7 @@ do_unregister() { //////////////////////////////////////////////////////////////////// // Function: GeomMunger::CacheEntry::output // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// void GeomMunger::CacheEntry:: output(ostream &out) const { @@ -440,7 +444,7 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// // Function: GeomMunger::Registry::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomMunger::Registry:: Registry() { diff --git a/panda/src/gobj/geomVertexData.I b/panda/src/gobj/geomVertexData.I index e489566fe6..3341b20e4a 100644 --- a/panda/src/gobj/geomVertexData.I +++ b/panda/src/gobj/geomVertexData.I @@ -414,7 +414,7 @@ INLINE int GeomVertexData:: add_transform(TransformTable *table, const VertexTransform *transform, TransformMap &already_added) { pair result = already_added.insert(TransformMap::value_type(transform, table->get_num_transforms())); - + if (result.second) { table->add_transform(transform); } @@ -425,7 +425,7 @@ add_transform(TransformTable *table, const VertexTransform *transform, //////////////////////////////////////////////////////////////////// // Function: GeomVertexData::CDataCache::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexData::CDataCache:: CDataCache() { @@ -434,7 +434,7 @@ CDataCache() { //////////////////////////////////////////////////////////////////// // Function: GeomVertexData::CDataCache::Copy Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexData::CDataCache:: CDataCache(const GeomVertexData::CDataCache ©) : @@ -445,7 +445,7 @@ CDataCache(const GeomVertexData::CDataCache ©) : //////////////////////////////////////////////////////////////////// // Function: GeomVertexData::CacheKey::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexData::CacheKey:: CacheKey(const GeomVertexFormat *modifier) : @@ -453,6 +453,30 @@ CacheKey(const GeomVertexFormat *modifier) : { } +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexData::CacheKey::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE GeomVertexData::CacheKey:: +CacheKey(const CacheKey ©) : + _modifier(copy._modifier) +{ +} + +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexData::CacheKey::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE GeomVertexData::CacheKey:: +CacheKey(CacheKey &&from) NOEXCEPT : + _modifier(move(from._modifier)) +{ +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: GeomVertexData::CacheKey::operator < // Access: Public @@ -466,7 +490,7 @@ operator < (const CacheKey &other) const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexData::CacheEntry::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexData::CacheEntry:: CacheEntry(GeomVertexData *source, const GeomVertexFormat *modifier) : @@ -475,6 +499,32 @@ CacheEntry(GeomVertexData *source, const GeomVertexFormat *modifier) : { } +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexData::CacheEntry::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE GeomVertexData::CacheEntry:: +CacheEntry(GeomVertexData *source, const CacheKey &key) : + _source(source), + _key(key) +{ +} + +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexData::CacheEntry::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE GeomVertexData::CacheEntry:: +CacheEntry(GeomVertexData *source, CacheKey &&key) NOEXCEPT : + _source(source), + _key(move(key)) +{ +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: GeomVertexData::CData::Constructor // Access: Public @@ -511,7 +561,7 @@ CData(const GeomVertexData::CData ©) : // Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexDataPipelineBase:: -GeomVertexDataPipelineBase(GeomVertexData *object, +GeomVertexDataPipelineBase(GeomVertexData *object, Thread *current_thread, GeomVertexData::CData *cdata) : _object(object), @@ -560,7 +610,7 @@ get_current_thread() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineBase::get_usage_hint // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexDataPipelineBase::UsageHint GeomVertexDataPipelineBase:: get_usage_hint() const { @@ -570,7 +620,7 @@ get_usage_hint() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineBase::get_format // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE const GeomVertexFormat *GeomVertexDataPipelineBase:: get_format() const { @@ -580,7 +630,7 @@ get_format() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineBase::has_column // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE bool GeomVertexDataPipelineBase:: has_column(const InternalName *name) const { @@ -590,7 +640,7 @@ has_column(const InternalName *name) const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineBase::get_num_arrays // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE int GeomVertexDataPipelineBase:: get_num_arrays() const { @@ -600,7 +650,7 @@ get_num_arrays() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineBase::get_array // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE CPT(GeomVertexArrayData) GeomVertexDataPipelineBase:: get_array(int i) const { @@ -611,7 +661,7 @@ get_array(int i) const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineBase::get_transform_table // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE const TransformTable *GeomVertexDataPipelineBase:: get_transform_table() const { @@ -621,7 +671,7 @@ get_transform_table() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineBase::get_transform_blend_table // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE CPT(TransformBlendTable) GeomVertexDataPipelineBase:: get_transform_blend_table() const { @@ -631,7 +681,7 @@ get_transform_blend_table() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineBase::get_slider_table // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE const SliderTable *GeomVertexDataPipelineBase:: get_slider_table() const { @@ -641,7 +691,7 @@ get_slider_table() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineBase::get_modified // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE UpdateSeq GeomVertexDataPipelineBase:: get_modified() const { @@ -654,7 +704,7 @@ get_modified() const { // Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexDataPipelineReader:: -GeomVertexDataPipelineReader(const GeomVertexData *object, +GeomVertexDataPipelineReader(const GeomVertexData *object, Thread *current_thread) : GeomVertexDataPipelineBase((GeomVertexData *)object, current_thread, (GeomVertexData::CData *)object->_cycler.read_unlocked(current_thread)), @@ -668,7 +718,7 @@ GeomVertexDataPipelineReader(const GeomVertexData *object, // Description: Don't attempt to copy these objects. //////////////////////////////////////////////////////////////////// INLINE GeomVertexDataPipelineReader:: -GeomVertexDataPipelineReader(const GeomVertexDataPipelineReader ©) : +GeomVertexDataPipelineReader(const GeomVertexDataPipelineReader ©) : GeomVertexDataPipelineBase(copy) { nassertv(false); @@ -710,7 +760,7 @@ get_object() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineReader::check_array_readers // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE void GeomVertexDataPipelineReader:: check_array_readers() const { @@ -722,7 +772,7 @@ check_array_readers() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineReader::get_array_reader // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE const GeomVertexArrayDataHandle *GeomVertexDataPipelineReader:: get_array_reader(int i) const { @@ -734,7 +784,7 @@ get_array_reader(int i) const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineReader::has_vertex // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE bool GeomVertexDataPipelineReader:: has_vertex() const { @@ -744,7 +794,7 @@ has_vertex() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineReader::is_vertex_transformed // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE bool GeomVertexDataPipelineReader:: is_vertex_transformed() const { @@ -759,7 +809,7 @@ is_vertex_transformed() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineReader::has_normal // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE bool GeomVertexDataPipelineReader:: has_normal() const { @@ -769,7 +819,7 @@ has_normal() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineReader::has_color // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE bool GeomVertexDataPipelineReader:: has_color() const { @@ -782,7 +832,7 @@ has_color() const { // Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexDataPipelineWriter:: -GeomVertexDataPipelineWriter(GeomVertexData *object, bool force_to_0, +GeomVertexDataPipelineWriter(GeomVertexData *object, bool force_to_0, Thread *current_thread) : GeomVertexDataPipelineBase(object, current_thread, object->_cycler.write_upstream(force_to_0, current_thread)), @@ -803,7 +853,7 @@ GeomVertexDataPipelineWriter(GeomVertexData *object, bool force_to_0, // Description: Don't attempt to copy these objects. //////////////////////////////////////////////////////////////////// INLINE GeomVertexDataPipelineWriter:: -GeomVertexDataPipelineWriter(const GeomVertexDataPipelineWriter ©) : +GeomVertexDataPipelineWriter(const GeomVertexDataPipelineWriter ©) : GeomVertexDataPipelineBase(copy) { nassertv(false); @@ -845,7 +895,7 @@ get_object() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineWriter::check_array_writers // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE void GeomVertexDataPipelineWriter:: check_array_writers() const { @@ -857,7 +907,7 @@ check_array_writers() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineWriter::get_array_writer // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexArrayDataHandle *GeomVertexDataPipelineWriter:: get_array_writer(int i) const { diff --git a/panda/src/gobj/geomVertexData.cxx b/panda/src/gobj/geomVertexData.cxx index 08e6fdc200..32b067facf 100644 --- a/panda/src/gobj/geomVertexData.cxx +++ b/panda/src/gobj/geomVertexData.cxx @@ -64,7 +64,7 @@ make_cow_copy() { //////////////////////////////////////////////////////////////////// // Function: GeomVertexData::Constructor // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomVertexData:: GeomVertexData(const string &name, @@ -97,7 +97,7 @@ GeomVertexData(const string &name, //////////////////////////////////////////////////////////////////// // Function: GeomVertexData::Copy Constructor // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomVertexData:: GeomVertexData(const GeomVertexData ©) : @@ -127,7 +127,7 @@ GeomVertexData(const GeomVertexData ©) : // and it allows you to specify a different format. //////////////////////////////////////////////////////////////////// GeomVertexData:: -GeomVertexData(const GeomVertexData ©, +GeomVertexData(const GeomVertexData ©, const GeomVertexFormat *format) : CopyOnWriteObject(copy), _name(copy._name), @@ -159,7 +159,7 @@ GeomVertexData(const GeomVertexData ©, } CLOSE_ITERATE_ALL_STAGES(_cycler); } - + //////////////////////////////////////////////////////////////////// // Function: GeomVertexData::Copy Assignment Operator // Access: Published @@ -186,14 +186,14 @@ operator = (const GeomVertexData ©) { cdata->_modified = Geom::get_next_modified(); cdata->_animated_vertices = NULL; cdata->_animated_vertices_modified = UpdateSeq(); - } + } CLOSE_ITERATE_ALL_STAGES(_cycler); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexData::Destructor // Access: Published, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// GeomVertexData:: ~GeomVertexData() { @@ -564,22 +564,22 @@ copy_from(const GeomVertexData *source, bool keep_data_objects, pset done_arrays; for (source_i = 0; source_i < num_arrays; ++source_i) { - const GeomVertexArrayFormat *source_array_format = + const GeomVertexArrayFormat *source_array_format = source_format->get_array(source_i); bool array_done = false; int dest_num_arrays = dest_format->get_num_arrays(); - for (int dest_i = 0; - dest_i < dest_num_arrays && !array_done; + for (int dest_i = 0; + dest_i < dest_num_arrays && !array_done; ++dest_i) { - const GeomVertexArrayFormat *dest_array_format = + const GeomVertexArrayFormat *dest_array_format = dest_format->get_array(dest_i); if (dest_array_format->is_data_subset_of(*source_array_format)) { // Great! Just use the same data for this one. if (keep_data_objects) { - // Copy the data, but keep the same GeomVertexArrayData object. - + // Copy the data, but keep the same GeomVertexArrayData object. + PT(GeomVertexArrayData) dest_data = modify_array(dest_i); CPT(GeomVertexArrayData) source_data = source->get_array(source_i); dest_data->modify_handle()->copy_data_from(source_data->get_handle()); @@ -613,9 +613,9 @@ copy_from(const GeomVertexData *source, bool keep_data_objects, int dest_i = dest_format->get_array_with(source_column->get_name()); if (dest_i >= 0 && done_arrays.count(dest_i) == 0) { // The data type exists in the new format; we have to copy it. - const GeomVertexArrayFormat *dest_array_format = + const GeomVertexArrayFormat *dest_array_format = dest_format->get_array(dest_i); - const GeomVertexColumn *dest_column = + const GeomVertexColumn *dest_column = dest_array_format->get_column(source_column->get_name()); nassertv(dest_column != (const GeomVertexColumn *)NULL); @@ -625,12 +625,12 @@ copy_from(const GeomVertexData *source, bool keep_data_objects, PT(GeomVertexArrayDataHandle) dest_handle = dest_array_obj->modify_handle(); unsigned char *dest_array_data = dest_handle->get_write_pointer(); - bytewise_copy(dest_array_data + dest_column->get_start(), + bytewise_copy(dest_array_data + dest_column->get_start(), dest_array_format->get_stride(), array_data + source_column->get_start(), source_array_format->get_stride(), source_column, num_rows); - } else if (dest_column->is_packed_argb() && + } else if (dest_column->is_packed_argb() && source_column->is_uint8_rgba()) { // A common special case: OpenGL color to DirectX color. PT(GeomVertexArrayData) dest_array_obj = modify_array(dest_i); @@ -638,12 +638,12 @@ copy_from(const GeomVertexData *source, bool keep_data_objects, unsigned char *dest_array_data = dest_handle->get_write_pointer(); uint8_rgba_to_packed_argb - (dest_array_data + dest_column->get_start(), + (dest_array_data + dest_column->get_start(), dest_array_format->get_stride(), array_data + source_column->get_start(), source_array_format->get_stride(), num_rows); - } else if (dest_column->is_uint8_rgba() && + } else if (dest_column->is_uint8_rgba() && source_column->is_packed_argb()) { // Another common special case: DirectX color to OpenGL // color. @@ -652,7 +652,7 @@ copy_from(const GeomVertexData *source, bool keep_data_objects, unsigned char *dest_array_data = dest_handle->get_write_pointer(); packed_argb_to_uint8_rgba - (dest_array_data + dest_column->get_start(), + (dest_array_data + dest_column->get_start(), dest_array_format->get_stride(), array_data + source_column->get_start(), source_array_format->get_stride(), num_rows); @@ -661,7 +661,7 @@ copy_from(const GeomVertexData *source, bool keep_data_objects, // A generic copy. if (gobj_cat.is_debug()) { gobj_cat.debug() - << "generic copy " << *dest_column << " from " + << "generic copy " << *dest_column << " from " << *source_column << "\n"; } GeomVertexWriter to(this); @@ -695,13 +695,13 @@ copy_from(const GeomVertexData *source, bool keep_data_objects, GeomVertexWriter weight(this, InternalName::get_transform_weight()); GeomVertexWriter index(this, InternalName::get_transform_index()); GeomVertexReader from(source, InternalName::get_transform_blend()); - + while (!from.is_at_end()) { const TransformBlend &blend = blend_table->get_blend(from.get_data1i()); LVecBase4 weights = LVecBase4::zero(); LVecBase4i indices(0, 0, 0, 0); nassertv(blend.get_num_transforms() <= 4); - + for (int i = 0; i < blend.get_num_transforms(); i++) { weights[i] = blend.get_weight(i); indices[i] = add_transform(transform_table, blend.get_transform(i), @@ -717,11 +717,11 @@ copy_from(const GeomVertexData *source, bool keep_data_objects, // use the same n transforms, in the same order, for each vertex. GeomVertexWriter weight(this, InternalName::get_transform_weight()); GeomVertexReader from(source, InternalName::get_transform_blend()); - + while (!from.is_at_end()) { const TransformBlend &blend = blend_table->get_blend(from.get_data1i()); LVecBase4 weights = LVecBase4::zero(); - + for (int i = 0; i < blend.get_num_transforms(); i++) { int index = add_transform(transform_table, blend.get_transform(i), already_added); @@ -733,7 +733,7 @@ copy_from(const GeomVertexData *source, bool keep_data_objects, } } } - + clear_transform_blend_table(); set_transform_table(TransformTable::register_table(transform_table)); } @@ -754,7 +754,7 @@ copy_from(const GeomVertexData *source, bool keep_data_objects, // have recently made in an upstream thread. //////////////////////////////////////////////////////////////////// void GeomVertexData:: -copy_row_from(int dest_row, const GeomVertexData *source, +copy_row_from(int dest_row, const GeomVertexData *source, int source_row, Thread *current_thread) { const GeomVertexFormat *source_format = source->get_format(); const GeomVertexFormat *dest_format = get_format(); @@ -842,7 +842,7 @@ convert_to(const GeomVertexFormat *new_format) const { } PStatTimer timer(_convert_pcollector); - PT(GeomVertexData) new_data = + PT(GeomVertexData) new_data = new GeomVertexData(get_name(), new_format, get_usage_hint()); new_data->set_transform_blend_table(get_transform_blend_table()); new_data->set_slider_table(get_slider_table()); @@ -852,7 +852,12 @@ convert_to(const GeomVertexFormat *new_format) const { // Record the new result in the cache. if (entry == (CacheEntry *)NULL) { // Create a new entry for the result. - entry = new CacheEntry((GeomVertexData *)this, new_format); +#ifdef USE_MOVE_SEMANTICS + // We don't need the key anymore, move the pointers into the CacheEntry. + entry = new CacheEntry((GeomVertexData *)this, move(key)); +#else + entry = new CacheEntry((GeomVertexData *)this, key); +#endif { LightMutexHolder holder(_cache_lock); bool inserted = ((GeomVertexData *)this)->_cache.insert(Cache::value_type(&entry->_key, entry)).second; @@ -862,7 +867,7 @@ convert_to(const GeomVertexFormat *new_format) const { return new_data; } } - + // And tell the cache manager about the new entry. (It might // immediately request a delete from the cache of the thing we // just added.) @@ -876,7 +881,6 @@ convert_to(const GeomVertexFormat *new_format) const { return new_data; } - //////////////////////////////////////////////////////////////////// // Function: GeomVertexData::scale_color // Access: Published @@ -888,7 +892,7 @@ convert_to(const GeomVertexFormat *new_format) const { //////////////////////////////////////////////////////////////////// CPT(GeomVertexData) GeomVertexData:: scale_color(const LVecBase4 &color_scale) const { - const GeomVertexColumn *old_column = + const GeomVertexColumn *old_column = get_format()->get_column(InternalName::get_color()); if (old_column == (GeomVertexColumn *)NULL) { return this; @@ -965,7 +969,7 @@ scale_color(const LVecBase4 &color_scale, int num_components, //////////////////////////////////////////////////////////////////// CPT(GeomVertexData) GeomVertexData:: set_color(const LColor &color) const { - const GeomVertexColumn *old_column = + const GeomVertexColumn *old_column = get_format()->get_column(InternalName::get_color()); if (old_column == (GeomVertexColumn *)NULL) { return this; @@ -1026,7 +1030,7 @@ set_color(const LColor &color, int num_components, //////////////////////////////////////////////////////////////////// CPT(GeomVertexData) GeomVertexData:: reverse_normals() const { - const GeomVertexColumn *old_column = + const GeomVertexColumn *old_column = get_format()->get_column(InternalName::get_normal()); if (old_column == (GeomVertexColumn *)NULL) { return this; @@ -1094,16 +1098,16 @@ animate_vertices(bool force, Thread *current_thread) const { PStatTimer timer2(((GeomVertexData *)this)->_blends_pcollector, current_thread); if (!cdata->_transform_blend_table.is_null()) { if (cdata->_slider_table != (SliderTable *)NULL) { - modified = + modified = max(cdata->_transform_blend_table.get_read_pointer()->get_modified(current_thread), cdata->_slider_table->get_modified(current_thread)); } else { modified = cdata->_transform_blend_table.get_read_pointer()->get_modified(current_thread); } - + } else if (cdata->_slider_table != (SliderTable *)NULL) { modified = cdata->_slider_table->get_modified(current_thread); - + } else { // No transform blend table or slider table--ergo, no vertex // animation. @@ -1185,7 +1189,7 @@ transform_vertices(const LMatrix4 &mat, int begin_row, int end_row) { GeomVertexRewriter data(this, format->get_point(ci)); do_transform_point_column(format, data, mat, begin_row, end_row); } - + for (ci = 0; ci < format->get_num_vectors(); ci++) { GeomVertexRewriter data(this, format->get_vector(ci)); do_transform_vector_column(format, data, mat, begin_row, end_row); @@ -1208,7 +1212,7 @@ bytewise_copy(unsigned char *to, int to_stride, << ", " << (const void *)from << ", " << from_stride << ", " << *from_type << ", " << num_records << ")\n"; } - if (to_stride == from_type->get_total_bytes() && + if (to_stride == from_type->get_total_bytes() && from_stride == from_type->get_total_bytes()) { // Fantastic! It's just a linear array of this one data type. // Copy the whole thing all at once. @@ -1257,32 +1261,32 @@ replace_column(InternalName *name, int num_components, // just drop the whole array. new_format->remove_array(old_type_array); removed_type_array = true; - + } else { // Remove the description for the type, but don't bother to // repack the array. array_format->remove_column(name); } } - + // Now define a new array to contain just the type. int new_type_array = -1; if (num_components != 0) { - PT(GeomVertexArrayFormat) type_array_format = + PT(GeomVertexArrayFormat) type_array_format = new GeomVertexArrayFormat(name, num_components, numeric_type, contents); new_type_array = new_format->add_array(type_array_format); } - CPT(GeomVertexFormat) format = + CPT(GeomVertexFormat) format = GeomVertexFormat::register_format(new_format); if (gobj_cat.is_debug()) { gobj_cat.debug() << "Replacing data type " << *name << "; converting " - << get_num_rows() << " rows from " + << get_num_rows() << " rows from " << *cdata->_format << " to " << *format << "\n"; } - + PT(GeomVertexData) new_data = new GeomVertexData(*this, format); int j = 0; @@ -1320,7 +1324,7 @@ replace_column(InternalName *name, int num_components, //////////////////////////////////////////////////////////////////// // Function: GeomVertexData::output // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// void GeomVertexData:: output(ostream &out) const { @@ -1333,7 +1337,7 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexData::write // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// void GeomVertexData:: write(ostream &out, int indent_level) const { @@ -1369,16 +1373,16 @@ describe_vertex(ostream &out, int row) const { if (format->get_animation().get_animation_type() == AT_panda) { tb_table = get_transform_blend_table(); } - + int num_columns = format->get_num_columns(); for (int ci = 0; ci < num_columns; ++ci) { int ai = format->get_array_with(ci); const GeomVertexColumn *column = format->get_column(ci); reader.set_column(ai, column); - + int num_values = min(column->get_num_values(), 4); const LVecBase4 &d = reader.get_data4(); - + out << " " << *column->get_name(); for (int v = 0; v < num_values; v++) { out << " " << d[v]; @@ -1545,7 +1549,7 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) { if (cdata->_animated_vertices == (GeomVertexData *)NULL) { new_format = orig_format->get_post_animated_format(); - cdata->_animated_vertices = + cdata->_animated_vertices = new GeomVertexData(get_name(), new_format, min(get_usage_hint(), UH_dynamic)); } @@ -1670,7 +1674,7 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) { CPT(GeomVertexArrayFormat) blend_array_format = orig_format->get_array(blend_array_index); - if (blend_array_format->get_stride() == 2 && + if (blend_array_format->get_stride() == 2 && blend_array_format->get_column(0)->get_component_bytes() == 2) { // The blend indices are a table of ushorts. Optimize this // common case. @@ -1688,11 +1692,11 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) { int first_vertex = begin; int first_bi = blendt[first_vertex]; - + while (first_vertex < end) { // At this point, first_vertex is the first of a series of // vertices that shares the blend index first_bi. - + // Scan for the end of this series of vertices--we're // looking for the next vertex with a different blend index. int next_vertex = first_vertex; @@ -1705,13 +1709,13 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) { } ++next_vertex; } - + // We've just reached the end of the vertices with a matching // blend index. Transform all those vertices as a block. LMatrix4 mat; tb_table->get_blend(first_bi).get_blend(mat, current_thread); new_data->do_transform_point_column(new_format, data, mat, first_vertex, next_vertex); - + first_vertex = next_vertex; first_bi = next_bi; } @@ -1728,11 +1732,11 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) { int first_vertex = begin; int first_bi = blendt[first_vertex]; - + while (first_vertex < end) { // At this point, first_vertex is the first of a series of // vertices that shares the blend index first_bi. - + // Scan for the end of this series of vertices--we're // looking for the next vertex with a different blend index. int next_vertex = first_vertex; @@ -1745,13 +1749,13 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) { } ++next_vertex; } - + // We've just reached the end of the vertices with a matching // blend index. Transform all those vertices as a block. LMatrix4 mat; tb_table->get_blend(first_bi).get_blend(mat, current_thread); new_data->do_transform_vector_column(new_format, data, mat, first_vertex, next_vertex); - + first_vertex = next_vertex; first_bi = next_bi; } @@ -1773,14 +1777,14 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) { int end = rows.get_subrange_end(i); nassertv(begin < end); blendi.set_row_unsafe(begin); - + int first_vertex = begin; int first_bi = blendi.get_data1i(); - + while (first_vertex < end) { // At this point, first_vertex is the first of a series of // vertices that shares the blend index first_bi. - + // Scan for the end of this series of vertices--we're // looking for the next vertex with a different blend index. int next_vertex = first_vertex; @@ -1793,13 +1797,13 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) { } ++next_vertex; } - + // We've just reached the end of the vertices with a matching // blend index. Transform all those vertices as a block. LMatrix4 mat; tb_table->get_blend(first_bi).get_blend(mat, current_thread); new_data->do_transform_point_column(new_format, data, mat, first_vertex, next_vertex); - + first_vertex = next_vertex; first_bi = next_bi; } @@ -1814,14 +1818,14 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) { int end = rows.get_subrange_end(i); nassertv(begin != end); blendi.set_row_unsafe(begin); - + int first_vertex = begin; int first_bi = blendi.get_data1i(); - + while (first_vertex < end) { // At this point, first_vertex is the first of a series of // vertices that shares the blend index first_bi. - + // Scan for the end of this series of vertices--we're // looking for the next vertex with a different blend index. int next_vertex = first_vertex; @@ -1834,13 +1838,13 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) { } ++next_vertex; } - + // We've just reached the end of the vertices with a matching // blend index. Transform all those vertices as a block. LMatrix4 mat; tb_table->get_blend(first_bi).get_blend(mat, current_thread); new_data->do_transform_vector_column(new_format, data, mat, first_vertex, next_vertex); - + first_vertex = next_vertex; first_bi = next_bi; } @@ -1880,11 +1884,11 @@ do_transform_point_column(const GeomVertexFormat *format, GeomVertexRewriter &da } else { table_xform_vecbase4f(datat, num_rows, stride, matf); } - + } else if (num_values == 4) { // Use the GeomVertexRewriter to adjust the 4-component // points. - + data.set_row_unsafe(begin_row); for (int j = begin_row; j < end_row; ++j) { LPoint4 vertex = data.get_data4(); @@ -2110,7 +2114,7 @@ finalize(BamReader *manager) { CDWriter cdata(_cycler, true); for (size_t i = 0; i < cdata->_arrays.size(); ++i) { - CPT(GeomVertexFormat) new_format = + CPT(GeomVertexFormat) new_format = GeomVertexFormat::register_format(cdata->_format); manager->change_pointer(cdata->_format, new_format); cdata->_format = new_format; @@ -2124,14 +2128,14 @@ finalize(BamReader *manager) { } if (cdata->_transform_table != (TransformTable *)NULL) { - CPT(TransformTable) new_transform_table = + CPT(TransformTable) new_transform_table = TransformTable::register_table(cdata->_transform_table); manager->change_pointer(cdata->_transform_table, new_transform_table); cdata->_transform_table = new_transform_table; } if (cdata->_slider_table != (SliderTable *)NULL) { - CPT(SliderTable) new_slider_table = + CPT(SliderTable) new_slider_table = SliderTable::register_table(cdata->_slider_table); manager->change_pointer(cdata->_slider_table, new_slider_table); cdata->_slider_table = new_slider_table; @@ -2181,11 +2185,11 @@ evict_callback() { //////////////////////////////////////////////////////////////////// // Function: GeomVertexData::CacheEntry::output // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// void GeomVertexData::CacheEntry:: output(ostream &out) const { - out << "vertex data " << (void *)_source << " to " + out << "vertex data " << (void *)_source << " to " << *_key._modifier; } @@ -2236,7 +2240,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { Arrays::iterator ai; for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) { - (*ai) = DCAST(GeomVertexArrayData, p_list[pi++]); + (*ai) = DCAST(GeomVertexArrayData, p_list[pi++]); } _transform_table = DCAST(TransformTable, p_list[pi++]); @@ -2295,7 +2299,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineBase::get_num_bytes // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// int GeomVertexDataPipelineBase:: get_num_bytes() const { @@ -2312,7 +2316,7 @@ get_num_bytes() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineReader::get_num_rows // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// int GeomVertexDataPipelineReader:: get_num_rows() const { @@ -2332,13 +2336,13 @@ get_num_rows() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineReader::get_array_info // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// bool GeomVertexDataPipelineReader:: -get_array_info(const InternalName *name, +get_array_info(const InternalName *name, const GeomVertexArrayDataHandle *&array_reader, - int &num_values, - GeomVertexDataPipelineReader::NumericType &numeric_type, + int &num_values, + GeomVertexDataPipelineReader::NumericType &numeric_type, int &start, int &stride) const { nassertr(_got_array_readers, false); int array_index; @@ -2357,12 +2361,12 @@ get_array_info(const InternalName *name, //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineReader::get_vertex_info // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// bool GeomVertexDataPipelineReader:: get_vertex_info(const GeomVertexArrayDataHandle *&array_reader, - int &num_values, - GeomVertexDataPipelineReader::NumericType &numeric_type, + int &num_values, + GeomVertexDataPipelineReader::NumericType &numeric_type, int &start, int &stride) const { nassertr(_got_array_readers, false); int array_index = _cdata->_format->get_vertex_array_index(); @@ -2382,11 +2386,11 @@ get_vertex_info(const GeomVertexArrayDataHandle *&array_reader, //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineReader::get_normal_info // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// bool GeomVertexDataPipelineReader:: get_normal_info(const GeomVertexArrayDataHandle *&array_reader, - GeomVertexDataPipelineReader::NumericType &numeric_type, + GeomVertexDataPipelineReader::NumericType &numeric_type, int &start, int &stride) const { nassertr(_got_array_readers, false); int array_index = _cdata->_format->get_normal_array_index(); @@ -2405,12 +2409,12 @@ get_normal_info(const GeomVertexArrayDataHandle *&array_reader, //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineReader::get_color_info // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// bool GeomVertexDataPipelineReader:: get_color_info(const GeomVertexArrayDataHandle *&array_reader, - int &num_values, - GeomVertexDataPipelineReader::NumericType &numeric_type, + int &num_values, + GeomVertexDataPipelineReader::NumericType &numeric_type, int &start, int &stride) const { nassertr(_got_array_readers, false); int array_index = _cdata->_format->get_color_array_index(); @@ -2430,7 +2434,7 @@ get_color_info(const GeomVertexArrayDataHandle *&array_reader, //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineReader::make_array_readers // Access: Private -// Description: +// Description: //////////////////////////////////////////////////////////////////// void GeomVertexDataPipelineReader:: make_array_readers() { @@ -2449,7 +2453,7 @@ make_array_readers() { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineReader::delete_array_readers // Access: Private -// Description: +// Description: //////////////////////////////////////////////////////////////////// void GeomVertexDataPipelineReader:: delete_array_readers() { @@ -2462,7 +2466,7 @@ delete_array_readers() { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineWriter::get_num_rows // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// int GeomVertexDataPipelineWriter:: get_num_rows() const { @@ -2482,7 +2486,7 @@ get_num_rows() const { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineWriter::set_num_rows // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// bool GeomVertexDataPipelineWriter:: set_num_rows(int n) { @@ -2510,10 +2514,10 @@ set_num_rows(int n) { // (1, 1, 1, 1), for the programmer's convenience. GeomVertexArrayDataHandle *array_writer = _array_writers[color_array]; const GeomVertexArrayFormat *array_format = array_writer->get_array_format(); - const GeomVertexColumn *column = + const GeomVertexColumn *column = array_format->get_column(InternalName::get_color()); int stride = array_format->get_stride(); - unsigned char *start = + unsigned char *start = array_writer->get_write_pointer() + column->get_start(); unsigned char *stop = start + array_writer->get_data_size_bytes(); unsigned char *pointer = start + stride * orig_color_rows; @@ -2554,7 +2558,7 @@ set_num_rows(int n) { case NT_stdfloat: // Shouldn't have this type in the format. nassertr(false, false); - } + } } if (any_changed) { @@ -2569,7 +2573,7 @@ set_num_rows(int n) { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineWriter::unclean_set_num_rows // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// bool GeomVertexDataPipelineWriter:: unclean_set_num_rows(int n) { @@ -2598,7 +2602,7 @@ unclean_set_num_rows(int n) { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineWriter::reserve_num_rows // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// bool GeomVertexDataPipelineWriter:: reserve_num_rows(int n) { @@ -2619,7 +2623,7 @@ reserve_num_rows(int n) { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineWriter::modify_array // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// PT(GeomVertexArrayData) GeomVertexDataPipelineWriter:: modify_array(int i) { @@ -2642,7 +2646,7 @@ modify_array(int i) { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineWriter::set_array // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// void GeomVertexDataPipelineWriter:: set_array(int i, const GeomVertexArrayData *array) { @@ -2660,7 +2664,7 @@ set_array(int i, const GeomVertexArrayData *array) { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineWriter::make_array_writers // Access: Private -// Description: +// Description: //////////////////////////////////////////////////////////////////// void GeomVertexDataPipelineWriter:: make_array_writers() { @@ -2683,7 +2687,7 @@ make_array_writers() { //////////////////////////////////////////////////////////////////// // Function: GeomVertexDataPipelineWriter::delete_array_writers // Access: Private -// Description: +// Description: //////////////////////////////////////////////////////////////////// void GeomVertexDataPipelineWriter:: delete_array_writers() { diff --git a/panda/src/gobj/geomVertexData.h b/panda/src/gobj/geomVertexData.h index 152446878d..ec3ff8ae3e 100644 --- a/panda/src/gobj/geomVertexData.h +++ b/panda/src/gobj/geomVertexData.h @@ -78,10 +78,10 @@ private: GeomVertexData(); protected: virtual PT(CopyOnWriteObject) make_cow_copy(); - + PUBLISHED: GeomVertexData(const string &name, - const GeomVertexFormat *format, + const GeomVertexFormat *format, UsageHint usage_hint); GeomVertexData(const GeomVertexData ©); GeomVertexData(const GeomVertexData ©, @@ -136,17 +136,17 @@ PUBLISHED: void copy_from(const GeomVertexData *source, bool keep_data_objects, Thread *current_thread = Thread::get_current_thread()); - void copy_row_from(int dest_row, const GeomVertexData *source, + void copy_row_from(int dest_row, const GeomVertexData *source, int source_row, Thread *current_thread); CPT(GeomVertexData) convert_to(const GeomVertexFormat *new_format) const; - CPT(GeomVertexData) + CPT(GeomVertexData) scale_color(const LVecBase4 &color_scale) const; - CPT(GeomVertexData) + CPT(GeomVertexData) scale_color(const LVecBase4 &color_scale, int num_components, NumericType numeric_type, Contents contents) const; - CPT(GeomVertexData) + CPT(GeomVertexData) set_color(const LColor &color) const; - CPT(GeomVertexData) + CPT(GeomVertexData) set_color(const LColor &color, int num_components, NumericType numeric_type, Contents contents) const; @@ -157,7 +157,7 @@ PUBLISHED: void transform_vertices(const LMatrix4 &mat); void transform_vertices(const LMatrix4 &mat, int begin_row, int end_row); - PT(GeomVertexData) + PT(GeomVertexData) replace_column(InternalName *name, int num_components, NumericType numeric_type, Contents contents) const; @@ -191,7 +191,7 @@ private: int num_records); typedef pmap TransformMap; - INLINE static int + INLINE static int add_transform(TransformTable *table, const VertexTransform *transform, TransformMap &already_added); @@ -212,7 +212,7 @@ private: } CPT(GeomVertexData) _result; - + public: static TypeHandle get_class_type() { return _type_handle; @@ -220,7 +220,7 @@ private: static void init_type() { register_type(_type_handle, "GeomVertexData::CDataCache"); } - + private: static TypeHandle _type_handle; }; @@ -236,15 +236,24 @@ public: class EXPCL_PANDA_GOBJ CacheKey { public: INLINE CacheKey(const GeomVertexFormat *modifier); + INLINE CacheKey(const CacheKey ©); +#ifdef USE_MOVE_SEMANTICS + INLINE CacheKey(CacheKey &&from) NOEXCEPT; +#endif + INLINE bool operator < (const CacheKey &other) const; CPT(GeomVertexFormat) _modifier; }; - // It is not clear why MSVC7 needs this class to be public. + // It is not clear why MSVC7 needs this class to be public. class EXPCL_PANDA_GOBJ CacheEntry : public GeomCacheEntry { public: INLINE CacheEntry(GeomVertexData *source, const GeomVertexFormat *modifier); + INLINE CacheEntry(GeomVertexData *source, const CacheKey &key); +#ifdef USE_MOVE_SEMANTICS + INLINE CacheEntry(GeomVertexData *source, CacheKey &&key) NOEXCEPT; +#endif ALLOC_DELETED_CHAIN(CacheEntry); virtual void evict_callback(); @@ -254,7 +263,7 @@ public: CacheKey _key; PipelineCycler _cycler; - + public: static TypeHandle get_class_type() { return _type_handle; @@ -264,7 +273,7 @@ public: register_type(_type_handle, "GeomVertexData::CacheEntry", GeomCacheEntry::get_class_type()); } - + private: static TypeHandle _type_handle; }; @@ -294,7 +303,7 @@ private: PT(GeomVertexData) _animated_vertices; UpdateSeq _animated_vertices_modified; UpdateSeq _modified; - + public: static TypeHandle get_class_type() { return _type_handle; @@ -302,7 +311,7 @@ private: static void init_type() { register_type(_type_handle, "GeomVertexData::CData"); } - + private: static TypeHandle _type_handle; }; @@ -323,11 +332,11 @@ private: const LMatrix4 &mat, int begin_row, int end_row); void do_transform_vector_column(const GeomVertexFormat *format, GeomVertexRewriter &data, const LMatrix4 &mat, int begin_row, int end_row); - static void table_xform_point3f(unsigned char *datat, size_t num_rows, + static void table_xform_point3f(unsigned char *datat, size_t num_rows, size_t stride, const LMatrix4f &matf); - static void table_xform_vector3f(unsigned char *datat, size_t num_rows, + static void table_xform_vector3f(unsigned char *datat, size_t num_rows, size_t stride, const LMatrix4f &matf); - static void table_xform_vecbase4f(unsigned char *datat, size_t num_rows, + static void table_xform_vecbase4f(unsigned char *datat, size_t num_rows, size_t stride, const LMatrix4f &matf); static PStatCollector _convert_pcollector; @@ -386,7 +395,7 @@ private: //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_GOBJ GeomVertexDataPipelineBase : public GeomEnums { protected: - INLINE GeomVertexDataPipelineBase(GeomVertexData *object, + INLINE GeomVertexDataPipelineBase(GeomVertexData *object, Thread *current_thread, GeomVertexData::CData *cdata); @@ -436,15 +445,15 @@ public: INLINE const GeomVertexArrayDataHandle *get_array_reader(int i) const; int get_num_rows() const; - bool get_array_info(const InternalName *name, + bool get_array_info(const InternalName *name, const GeomVertexArrayDataHandle *&array_reader, - int &num_values, NumericType &numeric_type, + int &num_values, NumericType &numeric_type, int &start, int &stride) const; INLINE bool has_vertex() const; INLINE bool is_vertex_transformed() const; bool get_vertex_info(const GeomVertexArrayDataHandle *&array_reader, - int &num_values, NumericType &numeric_type, + int &num_values, NumericType &numeric_type, int &start, int &stride) const; INLINE bool has_normal() const; @@ -454,7 +463,7 @@ public: INLINE bool has_color() const; bool get_color_info(const GeomVertexArrayDataHandle *&array_reader, - int &num_values, NumericType &numeric_type, + int &num_values, NumericType &numeric_type, int &start, int &stride) const; private: diff --git a/panda/src/linmath/lmatrix3_src.I b/panda/src/linmath/lmatrix3_src.I index 6b12ee6642..402dbbaba4 100644 --- a/panda/src/linmath/lmatrix3_src.I +++ b/panda/src/linmath/lmatrix3_src.I @@ -385,6 +385,17 @@ is_nan() const { cnan(_m(2, 0)) || cnan(_m(2, 1)) || cnan(_m(2, 2)); } +//////////////////////////////////////////////////////////////////// +// Function: LMatrix3::is_identity +// Access: Public +// Description: Returns true if this is (close enough to) the +// identity matrix, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH bool FLOATNAME(LMatrix3):: +is_identity() const { + return almost_equal(ident_mat(), NEARLY_ZERO(FLOATTYPE)); +} + //////////////////////////////////////////////////////////////////// // Function: LMatrix3::get_cell // Access: Published @@ -504,7 +515,7 @@ operator == (const FLOATNAME(LMatrix3) &other) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH bool FLOATNAME(LMatrix3):: operator != (const FLOATNAME(LMatrix3) &other) const { - return !operator == (other); + return compare_to(other) != 0; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lmatrix3_src.cxx b/panda/src/linmath/lmatrix3_src.cxx index b5352a11cb..6906aa503f 100644 --- a/panda/src/linmath/lmatrix3_src.cxx +++ b/panda/src/linmath/lmatrix3_src.cxx @@ -77,7 +77,7 @@ set_scale_shear_mat(const FLOATNAME(LVecBase3) &scale, shear._v(1) * scale._v(2), shear._v(2) * scale._v(2), scale._v(2)); } break; - + case CS_zup_left: if (temp_hpr_fix) { set(scale._v(0), shear._v(0) * scale._v(0), 0.0f, @@ -89,7 +89,7 @@ set_scale_shear_mat(const FLOATNAME(LVecBase3) &scale, -shear._v(1) * scale._v(2), -shear._v(2) * scale._v(2), scale._v(2)); } break; - + case CS_yup_right: if (temp_hpr_fix) { set(scale._v(0), 0.0f, shear._v(1) * scale._v(0), @@ -101,7 +101,7 @@ set_scale_shear_mat(const FLOATNAME(LVecBase3) &scale, shear._v(1) * scale._v(2), 0.0f, scale._v(2)); } break; - + case CS_yup_left: if (temp_hpr_fix) { set(scale._v(0), 0.0f, -shear._v(1) * scale._v(0), @@ -113,7 +113,7 @@ set_scale_shear_mat(const FLOATNAME(LVecBase3) &scale, -shear._v(1) * scale._v(2), 0.0f, scale._v(2)); } break; - + case CS_default: case CS_invalid: default: @@ -352,6 +352,9 @@ set_rotate_mat_normaxis(FLOATTYPE angle, const FLOATNAME(LVecBase3) &axis, bool FLOATNAME(LMatrix3):: almost_equal(const FLOATNAME(LMatrix3) &other, FLOATTYPE threshold) const { TAU_PROFILE("bool LMatrix3::almost_equal(const LMatrix3 &, FLOATTYPE)", " ", TAU_USER); +#ifdef HAVE_EIGEN + return ((_m - other._m).cwiseAbs().maxCoeff() < NEARLY_ZERO(FLOATTYPE)); +#else return (IS_THRESHOLD_EQUAL((*this)(0, 0), other(0, 0), threshold) && IS_THRESHOLD_EQUAL((*this)(0, 1), other(0, 1), threshold) && IS_THRESHOLD_EQUAL((*this)(0, 2), other(0, 2), threshold) && @@ -361,9 +364,9 @@ almost_equal(const FLOATNAME(LMatrix3) &other, FLOATTYPE threshold) const { IS_THRESHOLD_EQUAL((*this)(2, 0), other(2, 0), threshold) && IS_THRESHOLD_EQUAL((*this)(2, 1), other(2, 1), threshold) && IS_THRESHOLD_EQUAL((*this)(2, 2), other(2, 2), threshold)); +#endif } - //////////////////////////////////////////////////////////////////// // Function: LMatrix3::output // Access: Published @@ -440,7 +443,7 @@ void FLOATNAME(LMatrix3):: write_datagram_fixed(Datagram &destination) const { for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { -#if FLOATTOKEN == 'f' +#if FLOATTOKEN == 'f' destination.add_float32(get_cell(i,j)); #else destination.add_float64(get_cell(i,j)); diff --git a/panda/src/linmath/lmatrix3_src.h b/panda/src/linmath/lmatrix3_src.h index 4ce9a5c148..c132a58e1e 100644 --- a/panda/src/linmath/lmatrix3_src.h +++ b/panda/src/linmath/lmatrix3_src.h @@ -99,6 +99,7 @@ PUBLISHED: INLINE_LINMATH static int size(); INLINE_LINMATH bool is_nan() const; + INLINE_LINMATH bool is_identity() const; INLINE_LINMATH FLOATTYPE get_cell(int row, int col) const; INLINE_LINMATH void set_cell(int row, int col, FLOATTYPE value); @@ -247,28 +248,28 @@ PUBLISHED: scale_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz); INLINE_LINMATH void - set_shear_mat(const FLOATNAME(LVecBase3) &shear, + set_shear_mat(const FLOATNAME(LVecBase3) &shear, CoordinateSystem cs = CS_default); static INLINE_LINMATH FLOATNAME(LMatrix3) - shear_mat(const FLOATNAME(LVecBase3) &shear, + shear_mat(const FLOATNAME(LVecBase3) &shear, CoordinateSystem cs = CS_default); static INLINE_LINMATH FLOATNAME(LMatrix3) - shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, + shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, CoordinateSystem cs = CS_default); void set_scale_shear_mat(const FLOATNAME(LVecBase3) &scale, - const FLOATNAME(LVecBase3) &shear, + const FLOATNAME(LVecBase3) &shear, CoordinateSystem cs = CS_default); static INLINE_LINMATH FLOATNAME(LMatrix3) scale_shear_mat(const FLOATNAME(LVecBase3) &scale, - const FLOATNAME(LVecBase3) &shear, + const FLOATNAME(LVecBase3) &shear, CoordinateSystem cs = CS_default); static INLINE_LINMATH FLOATNAME(LMatrix3) scale_shear_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz, - FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, + FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, CoordinateSystem cs = CS_default); static const FLOATNAME(LMatrix3) &convert_mat(CoordinateSystem from, diff --git a/panda/src/linmath/lmatrix4_src.I b/panda/src/linmath/lmatrix4_src.I index 38fe84b0ad..9dc886c22b 100644 --- a/panda/src/linmath/lmatrix4_src.I +++ b/panda/src/linmath/lmatrix4_src.I @@ -616,6 +616,18 @@ is_nan() const { cnan(_m(3, 0)) || cnan(_m(3, 1)) || cnan(_m(3, 2)) || cnan(_m(3, 3)); } +//////////////////////////////////////////////////////////////////// +// Function: LMatrix4::is_identity +// Access: Public +// Description: Returns true if this is (close enough to) the +// identity matrix, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH bool FLOATNAME(LMatrix4):: +is_identity() const { + // Eigen has isIdentity, but it seems to be twice as slow as this. + return almost_equal(ident_mat(), NEARLY_ZERO(FLOATTYPE)); +} + //////////////////////////////////////////////////////////////////// // Function: LMatrix4::get_cell // Access: Public @@ -735,7 +747,7 @@ operator == (const FLOATNAME(LMatrix4) &other) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH bool FLOATNAME(LMatrix4):: operator != (const FLOATNAME(LMatrix4) &other) const { - return !operator == (other); + return compare_to(other) != 0; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lmatrix4_src.cxx b/panda/src/linmath/lmatrix4_src.cxx index cf8fabcc58..4123fd17aa 100644 --- a/panda/src/linmath/lmatrix4_src.cxx +++ b/panda/src/linmath/lmatrix4_src.cxx @@ -182,7 +182,7 @@ set_rotate_mat(FLOATTYPE angle, const FLOATNAME(LVecBase3) &axis, FLOATTYPE length_sq = axis_0 * axis_0 + axis_1 * axis_1 + axis_2 * axis_2; nassertv(length_sq != 0.0f); FLOATTYPE recip_length = 1.0f/csqrt(length_sq); - + axis_0 *= recip_length; axis_1 *= recip_length; axis_2 *= recip_length; @@ -288,11 +288,16 @@ set_rotate_mat_normaxis(FLOATTYPE angle, const FLOATNAME(LVecBase3) &axis, // Function: LMatrix4::almost_equal // Access: Public // Description: Returns true if two matrices are memberwise equal -// within a specified tolerance. +// within a specified tolerance. This is faster than +// the equivalence operator as this doesn't have to +// guarantee that it is transitive. //////////////////////////////////////////////////////////////////// bool FLOATNAME(LMatrix4):: almost_equal(const FLOATNAME(LMatrix4) &other, FLOATTYPE threshold) const { TAU_PROFILE("bool LMatrix4::almost_equal(const LMatrix4 &, FLOATTYPE)", " ", TAU_USER); +#ifdef HAVE_EIGEN + return ((_m - other._m).cwiseAbs().maxCoeff() < NEARLY_ZERO(FLOATTYPE)); +#else return (IS_THRESHOLD_EQUAL((*this)(0, 0), other(0, 0), threshold) && IS_THRESHOLD_EQUAL((*this)(0, 1), other(0, 1), threshold) && IS_THRESHOLD_EQUAL((*this)(0, 2), other(0, 2), threshold) && @@ -309,9 +314,9 @@ almost_equal(const FLOATNAME(LMatrix4) &other, FLOATTYPE threshold) const { IS_THRESHOLD_EQUAL((*this)(3, 1), other(3, 1), threshold) && IS_THRESHOLD_EQUAL((*this)(3, 2), other(3, 2), threshold) && IS_THRESHOLD_EQUAL((*this)(3, 3), other(3, 3), threshold)); +#endif } - //////////////////////////////////////////////////////////////////// // Function: LMatrix4::output // Access: Public @@ -520,7 +525,7 @@ void FLOATNAME(LMatrix4):: write_datagram_fixed(Datagram &destination) const { for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { -#if FLOATTOKEN == 'f' +#if FLOATTOKEN == 'f' destination.add_float32(get_cell(i,j)); #else destination.add_float64(get_cell(i,j)); diff --git a/panda/src/linmath/lmatrix4_src.h b/panda/src/linmath/lmatrix4_src.h index ccb770cb4d..370b82d6c0 100644 --- a/panda/src/linmath/lmatrix4_src.h +++ b/panda/src/linmath/lmatrix4_src.h @@ -107,6 +107,7 @@ PUBLISHED: INLINE_LINMATH static int size(); INLINE_LINMATH bool is_nan() const; + INLINE_LINMATH bool is_identity() const; INLINE_LINMATH FLOATTYPE get_cell(int row, int col) const; INLINE_LINMATH void set_cell(int row, int col, FLOATTYPE value); @@ -205,13 +206,13 @@ PUBLISHED: INLINE_LINMATH void set_scale_mat(const FLOATNAME(LVecBase3) &scale); INLINE_LINMATH void - set_shear_mat(const FLOATNAME(LVecBase3) &shear, + set_shear_mat(const FLOATNAME(LVecBase3) &shear, CoordinateSystem cs = CS_default); INLINE_LINMATH void set_scale_shear_mat(const FLOATNAME(LVecBase3) &scale, - const FLOATNAME(LVecBase3) &shear, + const FLOATNAME(LVecBase3) &shear, CoordinateSystem cs = CS_default); - + INLINE_LINMATH static FLOATNAME(LMatrix4) translate_mat(const FLOATNAME(LVecBase3) &trans); INLINE_LINMATH static FLOATNAME(LMatrix4) @@ -232,19 +233,19 @@ PUBLISHED: scale_mat(FLOATTYPE scale); static INLINE_LINMATH FLOATNAME(LMatrix4) - shear_mat(const FLOATNAME(LVecBase3) &shear, + shear_mat(const FLOATNAME(LVecBase3) &shear, CoordinateSystem cs = CS_default); static INLINE_LINMATH FLOATNAME(LMatrix4) - shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, + shear_mat(FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, CoordinateSystem cs = CS_default); static INLINE_LINMATH FLOATNAME(LMatrix4) scale_shear_mat(const FLOATNAME(LVecBase3) &scale, - const FLOATNAME(LVecBase3) &shear, + const FLOATNAME(LVecBase3) &shear, CoordinateSystem cs = CS_default); static INLINE_LINMATH FLOATNAME(LMatrix4) scale_shear_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz, - FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, + FLOATTYPE shxy, FLOATTYPE shxz, FLOATTYPE shyz, CoordinateSystem cs = CS_default); INLINE_LINMATH static const FLOATNAME(LMatrix4) &y_to_z_up_mat(); diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index 639f7f4a5a..dbb1b7a6d5 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -106,7 +106,8 @@ ConfigVariableBool fake_view_frustum_cull ("fake-view-frustum-cull", false, PRC_DESC("Set this true to cause culling to be performed by rendering the " "object in red wireframe, rather than actually culling it. This " - "helps make culling errors obvious.")); + "helps make culling errors obvious. This variable only has an " + "effect when Panda is not compiled for a release build.")); ConfigVariableBool clip_plane_cull ("clip-plane-cull", true, @@ -168,15 +169,6 @@ ConfigVariableBool compose_componentwise "operations when possible. If this is false, the compositions " "are always computed by matrix.")); -ConfigVariableBool uniquify_matrix -("uniquify-matrix", true, - PRC_DESC("Set this true to look up arbitarary 4x4 transform matrices in the " - "cache, to ensure that two differently-computed transforms that " - "happen to encode the same matrix will be " - "collapsed into a single pointer. Nowadays, " - "with the transforms stored in a hashtable, we're generally better " - "off with this set true.")); - ConfigVariableBool paranoid_const ("paranoid-const", false, PRC_DESC("Set this true to double-check that nothing is inappropriately " diff --git a/panda/src/pgraph/config_pgraph.h b/panda/src/pgraph/config_pgraph.h index 3595917bae..a7158b5a86 100644 --- a/panda/src/pgraph/config_pgraph.h +++ b/panda/src/pgraph/config_pgraph.h @@ -41,7 +41,6 @@ extern ConfigVariableBool no_unsupported_copy; extern ConfigVariableBool allow_unrelated_wrt; extern ConfigVariableBool paranoid_compose; extern ConfigVariableBool compose_componentwise; -extern ConfigVariableBool uniquify_matrix; extern ConfigVariableBool paranoid_const; extern ConfigVariableBool auto_break_cycles; extern EXPCL_PANDA_PGRAPH ConfigVariableBool garbage_collect_states; diff --git a/panda/src/pgraph/cullBin.I b/panda/src/pgraph/cullBin.I index 9017049980..3e78aca5ed 100644 --- a/panda/src/pgraph/cullBin.I +++ b/panda/src/pgraph/cullBin.I @@ -26,7 +26,6 @@ CullBin(const CullBin ©) : _cull_this_pcollector(copy._cull_this_pcollector), _draw_this_pcollector(copy._draw_this_pcollector) { - check_flash_color(); } //////////////////////////////////////////////////////////////////// @@ -44,7 +43,6 @@ CullBin(const string &name, CullBin::BinType bin_type, _cull_this_pcollector(_cull_bin_pcollector, name), _draw_this_pcollector(draw_region_pcollector, name) { - check_flash_color(); } //////////////////////////////////////////////////////////////////// @@ -66,26 +64,3 @@ INLINE CullBin::BinType CullBin:: get_bin_type() const { return _bin_type; } - -//////////////////////////////////////////////////////////////////// -// Function: CullBin::has_flash_color -// Access: Public -// Description: Returns true if this bin has a flash color configured -// via the flash-bin-binname config directive, or false -// otherwise. -//////////////////////////////////////////////////////////////////// -INLINE bool CullBin:: -has_flash_color() const { - return _has_flash_color; -} - -//////////////////////////////////////////////////////////////////// -// Function: CullBin::get_flash_color -// Access: Public -// Description: If has_flash_color returns true, this returns the -// color specified. -//////////////////////////////////////////////////////////////////// -INLINE const LColor &CullBin:: -get_flash_color() const { - return _flash_color; -} diff --git a/panda/src/pgraph/cullBin.cxx b/panda/src/pgraph/cullBin.cxx index ce1a97c402..c0f4b2a472 100644 --- a/panda/src/pgraph/cullBin.cxx +++ b/panda/src/pgraph/cullBin.cxx @@ -87,40 +87,6 @@ make_result_graph() { return root_node; } -//////////////////////////////////////////////////////////////////// -// Function: CullBin::check_flash_color -// Access: Private -// Description: Checks the config variables for a user variable of -// the name flash-bin-binname. If found, it defines the -// r g b color to flash geometry in this bin. -//////////////////////////////////////////////////////////////////// -void CullBin:: -check_flash_color() { -#ifdef NDEBUG - _has_flash_color = false; -#else - ConfigVariableDouble flash_bin - ("flash-bin-" + _name, "", "", ConfigVariable::F_dynamic); - if (flash_bin.get_num_words() == 0) { - _has_flash_color = false; - - } else if (flash_bin.get_num_words() == 3) { - _has_flash_color = true; - _flash_color.set(flash_bin[0], flash_bin[1], flash_bin[2], 1.0f); - - } else if (flash_bin.get_num_words() == 4) { - _has_flash_color = true; - _flash_color.set(flash_bin[0], flash_bin[1], flash_bin[2], flash_bin[3]); - - } else { - _has_flash_color = false; - pgraph_cat.warning() - << "Invalid value for flash-bin-" << _name << ": " - << flash_bin.get_string_value() << "\n"; - } -#endif // NDEBUG -} - //////////////////////////////////////////////////////////////////// // Function: CullBin::ResultGraphBuilder::Constructor // Access: Public diff --git a/panda/src/pgraph/cullBin.h b/panda/src/pgraph/cullBin.h index 0f813df7b1..e93f7bed9b 100644 --- a/panda/src/pgraph/cullBin.h +++ b/panda/src/pgraph/cullBin.h @@ -77,9 +77,6 @@ protected: BinType _bin_type; GraphicsStateGuardianBase *_gsg; - bool _has_flash_color; - LColor _flash_color; - // Used in make_result_graph() and fill_result_graph(). class ResultGraphBuilder { public: diff --git a/panda/src/pgraph/cullBinManager.I b/panda/src/pgraph/cullBinManager.I index 50e43c66d5..94aa3fc0da 100644 --- a/panda/src/pgraph/cullBinManager.I +++ b/panda/src/pgraph/cullBinManager.I @@ -284,3 +284,76 @@ set_bin_active(const string &name, bool active) { nassertv(bin_index != -1); set_bin_active(bin_index, active); } + +#ifndef NDEBUG +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::get_bin_flash_active +// Access: Published +// Description: Returns true if the bin with the given bin_index is +// configured to flash at a predetermined color (where +// bin_index was retrieved by get_bin() or find_bin()). +// +// This method is not available in release builds. +//////////////////////////////////////////////////////////////////// +INLINE bool CullBinManager:: +get_bin_flash_active(int bin_index) const { + nassertr(bin_index >= 0 && bin_index < (int)_bin_definitions.size(), false); + return _bin_definitions[bin_index]._flash_active; +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::get_bin_flash_color +// Access: Published +// Description: Returns the color that this bin has been configured +// to flash to, if configured. +// +// This method is not available in release builds. +//////////////////////////////////////////////////////////////////// +INLINE const LColor &CullBinManager:: +get_bin_flash_color(int bin_index) const { + nassertr(bin_index >= 0 && bin_index < (int)_bin_definitions.size(), LColor::zero()); + return _bin_definitions[bin_index]._flash_color; +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::set_bin_flash_active +// Access: Published +// Description: When set to true, the given bin_index is configured +// to flash at a predetermined color (where +// bin_index was retrieved by get_bin() or find_bin()). +// +// This method is not available in release builds. +//////////////////////////////////////////////////////////////////// +INLINE void CullBinManager:: +set_bin_flash_active(int bin_index, bool active) { + nassertv(bin_index >= 0 && bin_index < (int)_bin_definitions.size()); + _bin_definitions[bin_index]._flash_active = active; +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::set_bin_flash_color +// Access: Published +// Description: Changes the flash color for the given bin index. + +// This method is not available in release builds. +//////////////////////////////////////////////////////////////////// +INLINE void CullBinManager:: +set_bin_flash_color(int bin_index, const LColor &color) { + nassertv(bin_index >= 0 && bin_index < (int)_bin_definitions.size()); + _bin_definitions[bin_index]._flash_color = color; +} +#endif // NDEBUG + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::get_global_ptr +// Access: Published, Static +// Description: Returns the pointer to the global CullBinManager +// object. +//////////////////////////////////////////////////////////////////// +INLINE CullBinManager *CullBinManager:: +get_global_ptr() { + if (_global_ptr == (CullBinManager *)NULL) { + _global_ptr = new CullBinManager; + } + return _global_ptr; +} diff --git a/panda/src/pgraph/cullBinManager.cxx b/panda/src/pgraph/cullBinManager.cxx index f87a7d6094..6201042873 100644 --- a/panda/src/pgraph/cullBinManager.cxx +++ b/panda/src/pgraph/cullBinManager.cxx @@ -109,6 +109,29 @@ add_bin(const string &name, BinType type, int sort) { def._sort = sort; def._active = true; +#ifndef NDEBUG + // Check if there was a flash color configured for this bin name. + ConfigVariableDouble flash_bin + ("flash-bin-" + name, "", "", ConfigVariable::F_dynamic); + if (flash_bin.get_num_words() == 0) { + def._flash_active = false; + + } else if (flash_bin.get_num_words() == 3) { + def._flash_active = true; + def._flash_color.set(flash_bin[0], flash_bin[1], flash_bin[2], 1.0f); + + } else if (flash_bin.get_num_words() == 4) { + def._flash_active = true; + def._flash_color.set(flash_bin[0], flash_bin[1], flash_bin[2], flash_bin[3]); + + } else { + def._flash_active = false; + pgraph_cat.warning() + << "Invalid value for flash-bin-" << name << ": " + << flash_bin.get_string_value() << "\n"; + } +#endif + _bins_by_name.insert(BinsByName::value_type(name, new_bin_index)); _sorted_bins.push_back(new_bin_index); _bins_are_sorted = false; @@ -133,7 +156,7 @@ remove_bin(int bin_index) { nassertv(_bin_definitions[bin_index]._in_use); _bin_definitions[bin_index]._in_use = false; - SortedBins::iterator si = + SortedBins::iterator si = find(_sorted_bins.begin(), _sorted_bins.end(), bin_index); nassertv(si != _sorted_bins.end()); _sorted_bins.erase(si); @@ -142,7 +165,7 @@ remove_bin(int bin_index) { // Now we have to make sure all of the data objects in the world // that had cached this bin index or have a bin object are correctly // updated. - + // First, tell all the RenderStates in the world to reset their bin // index cache. RenderState::bin_removed(bin_index); @@ -170,7 +193,7 @@ find_bin(const string &name) const { //////////////////////////////////////////////////////////////////// // Function: CullBinManager::write // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// void CullBinManager:: write(ostream &out) const { @@ -185,20 +208,6 @@ write(ostream &out) const { } } -//////////////////////////////////////////////////////////////////// -// Function: CullBinManager::get_global_ptr -// Access: Published, Static -// Description: Returns the pointer to the global CullBinManager -// object. -//////////////////////////////////////////////////////////////////// -CullBinManager *CullBinManager:: -get_global_ptr() { - if (_global_ptr == (CullBinManager *)NULL) { - _global_ptr = new CullBinManager; - } - return _global_ptr; -} - //////////////////////////////////////////////////////////////////// // Function: CullBinManager::make_new_bin // Access: Public @@ -260,11 +269,11 @@ do_sort_bins() { void CullBinManager:: setup_initial_bins() { ConfigVariableList cull_bin - ("cull-bin", + ("cull-bin", PRC_DESC("Creates a new cull bin by name, with the specified properties. " "This is a string in three tokens, separated by whitespace: " "'bin_name sort type'.")); - + // First, add all of the bins specified in the Configrc file. int num_bins = cull_bin.get_num_unique_values(); @@ -351,26 +360,26 @@ parse_bin_type(const string &bin_type) { //////////////////////////////////////////////////////////////////// // Function: CullBinManager::BinType output operator -// Description: +// Description: //////////////////////////////////////////////////////////////////// ostream & operator << (ostream &out, CullBinManager::BinType bin_type) { switch (bin_type) { case CullBinManager::BT_invalid: return out << "invalid"; - + case CullBinManager::BT_unsorted: return out << "unsorted"; - + case CullBinManager::BT_state_sorted: return out << "state_sorted"; - + case CullBinManager::BT_back_to_front: return out << "back_to_front"; - + case CullBinManager::BT_front_to_back: return out << "front_to_back"; - + case CullBinManager::BT_fixed: return out << "fixed"; } diff --git a/panda/src/pgraph/cullBinManager.h b/panda/src/pgraph/cullBinManager.h index 75007b8025..9502667182 100644 --- a/panda/src/pgraph/cullBinManager.h +++ b/panda/src/pgraph/cullBinManager.h @@ -65,9 +65,16 @@ PUBLISHED: INLINE void set_bin_active(int bin_index, bool active); INLINE void set_bin_active(const string &name, bool active); +#ifndef NDEBUG + INLINE bool get_bin_flash_active(int bin_index) const; + INLINE const LColor &get_bin_flash_color(int bin_index) const; + INLINE void set_bin_flash_active(int bin_index, bool active); + INLINE void set_bin_flash_color(int bin_index, const LColor &color); +#endif + void write(ostream &out) const; - static CullBinManager *get_global_ptr(); + INLINE static CullBinManager *get_global_ptr(); public: // This interface is only intended to be used by CullResult. @@ -77,7 +84,7 @@ public: // This defines the factory interface for defining constructors to // bin types (the implementations are in the cull directory, not // here in pgraph, so we can't call the constructors directly). - typedef CullBin *BinConstructor(const string &name, + typedef CullBin *BinConstructor(const string &name, GraphicsStateGuardianBase *gsg, const PStatCollector &draw_region_pcollector); @@ -95,6 +102,10 @@ private: BinType _type; int _sort; bool _active; +#ifndef NDEBUG + bool _flash_active; + LColorf _flash_color; +#endif }; typedef pvector BinDefinitions; BinDefinitions _bin_definitions; diff --git a/panda/src/pgraph/cullPlanes.cxx b/panda/src/pgraph/cullPlanes.cxx index cc02bab922..d4b6ce7ed6 100644 --- a/panda/src/pgraph/cullPlanes.cxx +++ b/panda/src/pgraph/cullPlanes.cxx @@ -13,12 +13,12 @@ //////////////////////////////////////////////////////////////////// #include "cullPlanes.h" +#include "cullTraverser.h" #include "cullTraverserData.h" #include "clipPlaneAttrib.h" #include "occluderEffect.h" #include "boundingBox.h" - //////////////////////////////////////////////////////////////////// // Function: CullPlanes::make_empty // Access: Public, Static diff --git a/panda/src/pgraph/cullResult.cxx b/panda/src/pgraph/cullResult.cxx index cd795c489f..65b05fd3fd 100644 --- a/panda/src/pgraph/cullResult.cxx +++ b/panda/src/pgraph/cullResult.cxx @@ -26,6 +26,7 @@ #include "renderState.h" #include "clockObject.h" #include "config_pgraph.h" +#include "depthOffsetAttrib.h" TypeHandle CullResult::_type_handle; @@ -114,12 +115,15 @@ add_object(CullableObject *object, const CullTraverser *traverser) { bool force = !traverser->get_effective_incomplete_render(); Thread *current_thread = traverser->get_current_thread(); + CullBinManager *bin_manager = CullBinManager::get_global_ptr(); // Check to see if there's a special transparency setting. const RenderState *state = object->_state; nassertv(state != (const RenderState *)NULL); - const TransparencyAttrib *trans = DCAST(TransparencyAttrib, state->get_attrib(TransparencyAttrib::get_class_slot())); + const TransparencyAttrib *trans = (const TransparencyAttrib *) + state->get_attrib(TransparencyAttrib::get_class_slot()); + if (trans != (const TransparencyAttrib *)NULL) { switch (trans->get_mode()) { case TransparencyAttrib::M_alpha: @@ -168,7 +172,9 @@ add_object(CullableObject *object, const CullTraverser *traverser) { // explicit bin already applied; otherwise, M_dual falls back // to M_alpha. { - const CullBinAttrib *bin_attrib = DCAST(CullBinAttrib, state->get_attrib(CullBinAttrib::get_class_slot())); + const CullBinAttrib *bin_attrib = (const CullBinAttrib *) + state->get_attrib(CullBinAttrib::get_class_slot()); + if (bin_attrib == (CullBinAttrib *)NULL || bin_attrib->get_bin_name().empty()) { // We make a copy of the object to draw the transparent part; @@ -183,10 +189,14 @@ add_object(CullableObject *object, const CullTraverser *traverser) { if (transparent_part->munge_geom (_gsg, _gsg->get_geom_munger(transparent_part->_state, current_thread), traverser, force)) { - CullBin *bin = get_bin(transparent_part->_state->get_bin_index()); + int transparent_bin_index = transparent_part->_state->get_bin_index(); + CullBin *bin = get_bin(transparent_bin_index); nassertv(bin != (CullBin *)NULL); #ifndef NDEBUG - check_flash_bin(transparent_part->_state, bin); + if (bin_manager->get_bin_flash_active(transparent_bin_index)) { + do_flash_bin(transparent_part->_state, + bin_manager->get_bin_flash_color(transparent_bin_index)); + } #endif bin->add_object(transparent_part, current_thread); } else { @@ -215,11 +225,15 @@ add_object(CullableObject *object, const CullTraverser *traverser) { } } - CullBin *bin = get_bin(object->_state->get_bin_index()); + int bin_index = object->_state->get_bin_index(); + CullBin *bin = get_bin(bin_index); nassertv(bin != (CullBin *)NULL); #ifndef NDEBUG - check_flash_bin(object->_state, bin); + if (bin_manager->get_bin_flash_active(bin_index)) { + do_flash_bin(object->_state, + bin_manager->get_bin_flash_color(bin_index)); + } #endif // Munge vertices as needed for the GSG's requirements, and the @@ -346,16 +360,20 @@ make_new_bin(int bin_index) { CullBinManager *bin_manager = CullBinManager::get_global_ptr(); PT(CullBin) bin = bin_manager->make_new_bin(bin_index, _gsg, _draw_region_pcollector); - if (bin != (CullBin *)NULL) { + CullBin *bin_ptr = bin.p(); + + if (bin_ptr != (CullBin *)NULL) { // Now store it in the vector. while (bin_index >= (int)_bins.size()) { _bins.push_back((CullBin *)NULL); } nassertr(bin_index >= 0 && bin_index < (int)_bins.size(), NULL); - _bins[bin_index] = bin; + + // Prevent unnecessary ref/unref by swapping the PointerTos. + swap(_bins[bin_index], bin); } - return bin; + return bin_ptr; } //////////////////////////////////////////////////////////////////// @@ -393,25 +411,25 @@ get_binary_state() { } //////////////////////////////////////////////////////////////////// -// Function: CullResult::check_flash_bin +// Function: CullResult::do-flash_bin // Access: Private // Description: If the user configured flash-bin-binname, then update // the object's state to flash all the geometry in the // bin. //////////////////////////////////////////////////////////////////// void CullResult:: -check_flash_bin(CPT(RenderState) &state, CullBin *bin) { - if (bin->has_flash_color()) { - int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate); - if ((cycle & 1) == 0) { - state = state->remove_attrib(TextureAttrib::get_class_slot()); - state = state->remove_attrib(LightAttrib::get_class_slot()); - state = state->remove_attrib(ColorScaleAttrib::get_class_slot()); - state = state->remove_attrib(FogAttrib::get_class_slot()); - state = state->add_attrib(ColorAttrib::make_flat(bin->get_flash_color()), - RenderState::get_max_priority()); - } +do_flash_bin(CPT(RenderState) &state, const LColor &flash_color) { +#ifndef NDEBUG + int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate); + if ((cycle & 1) == 0) { + state = state->remove_attrib(TextureAttrib::get_class_slot()); + state = state->remove_attrib(LightAttrib::get_class_slot()); + state = state->remove_attrib(ColorScaleAttrib::get_class_slot()); + state = state->remove_attrib(FogAttrib::get_class_slot()); + state = state->add_attrib(ColorAttrib::make_flat(flash_color), + RenderState::get_max_priority()); } +#endif // NDEBUG } //////////////////////////////////////////////////////////////////// @@ -423,6 +441,7 @@ check_flash_bin(CPT(RenderState) &state, CullBin *bin) { //////////////////////////////////////////////////////////////////// void CullResult:: check_flash_transparency(CPT(RenderState) &state, const LColor &transparency) { +#ifndef NDEBUG if (show_transparency) { int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate); if ((cycle & 1) == 0) { @@ -434,6 +453,7 @@ check_flash_transparency(CPT(RenderState) &state, const LColor &transparency) { RenderState::get_max_priority()); } } +#endif } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/cullResult.h b/panda/src/pgraph/cullResult.h index 93604fc558..c6814dd3af 100644 --- a/panda/src/pgraph/cullResult.h +++ b/panda/src/pgraph/cullResult.h @@ -66,7 +66,7 @@ public: private: CullBin *make_new_bin(int bin_index); - void check_flash_bin(CPT(RenderState) &state, CullBin *bin); + void do_flash_bin(CPT(RenderState) &state, const LColor &flash_color); void check_flash_transparency(CPT(RenderState) &state, const LColor &color); static CPT(RenderState) get_alpha_state(); diff --git a/panda/src/pgraph/cullTraverser.I b/panda/src/pgraph/cullTraverser.I index 291221b2de..76df04145a 100644 --- a/panda/src/pgraph/cullTraverser.I +++ b/panda/src/pgraph/cullTraverser.I @@ -245,3 +245,63 @@ flush_level() { _geoms_pcollector.flush_level(); _geoms_occluded_pcollector.flush_level(); } + +//////////////////////////////////////////////////////////////////// +// Function: CullTraverser::do_traverse +// Access: Protected +// Description: This is implemented inline to reduce recursion. +//////////////////////////////////////////////////////////////////// +INLINE void CullTraverser:: +do_traverse(CullTraverserData &data) { + if (is_in_view(data)) { + if (pgraph_cat.is_spam()) { + pgraph_cat.spam() + << "\n" << data._node_path + << " " << data._draw_mask << "\n"; + } + + PandaNodePipelineReader *node_reader = data.node_reader(); + int fancy_bits = node_reader->get_fancy_bits(); + + if ((fancy_bits & (PandaNode::FB_transform | + PandaNode::FB_state | + PandaNode::FB_effects | + PandaNode::FB_tag | + PandaNode::FB_draw_mask | + PandaNode::FB_cull_callback)) == 0 && + data._cull_planes->is_empty()) { + // Nothing interesting in this node; just move on. + + } else { + // Something in this node is worth taking a closer look. + const RenderEffects *node_effects = node_reader->get_effects(); + if (node_effects->has_show_bounds()) { + // If we should show the bounding volume for this node, make it + // up now. + show_bounds(data, node_effects->has_show_tight_bounds()); + } + + data.apply_transform_and_state(this); + + const FogAttrib *fog = (const FogAttrib *) + node_reader->get_state()->get_attrib(FogAttrib::get_class_slot()); + + if (fog != (const FogAttrib *)NULL && fog->get_fog() != (Fog *)NULL) { + // If we just introduced a FogAttrib here, call adjust_to_camera() + // now. This maybe isn't the perfect time to call it, but it's + // good enough; and at this time we have all the information we + // need for it. + fog->get_fog()->adjust_to_camera(get_camera_transform()); + } + + if (fancy_bits & PandaNode::FB_cull_callback) { + PandaNode *node = data.node(); + if (!node->cull_callback(this, data)) { + return; + } + } + } + + traverse_below(data); + } +} diff --git a/panda/src/pgraph/cullTraverser.cxx b/panda/src/pgraph/cullTraverser.cxx index 292e81565e..70c953499a 100644 --- a/panda/src/pgraph/cullTraverser.cxx +++ b/panda/src/pgraph/cullTraverser.cxx @@ -17,7 +17,6 @@ #include "cullTraverserData.h" #include "transformState.h" #include "renderState.h" -#include "fogAttrib.h" #include "colorAttrib.h" #include "renderModeAttrib.h" #include "cullFaceAttrib.h" @@ -164,7 +163,7 @@ traverse(const NodePath &root) { _initial_state, _view_frustum, _current_thread); - traverse(data); + do_traverse(data); } } @@ -177,55 +176,7 @@ traverse(const NodePath &root) { //////////////////////////////////////////////////////////////////// void CullTraverser:: traverse(CullTraverserData &data) { - if (is_in_view(data)) { - if (pgraph_cat.is_spam()) { - pgraph_cat.spam() - << "\n" << data._node_path - << " " << data._draw_mask << "\n"; - } - - PandaNodePipelineReader *node_reader = data.node_reader(); - int fancy_bits = node_reader->get_fancy_bits(); - - if ((fancy_bits & (PandaNode::FB_transform | - PandaNode::FB_state | - PandaNode::FB_effects | - PandaNode::FB_tag | - PandaNode::FB_draw_mask | - PandaNode::FB_cull_callback)) == 0 && - data._cull_planes->is_empty()) { - // Nothing interesting in this node; just move on. - traverse_below(data); - - } else { - // Something in this node is worth taking a closer look. - const RenderEffects *node_effects = node_reader->get_effects(); - if (node_effects->has_show_bounds()) { - // If we should show the bounding volume for this node, make it - // up now. - show_bounds(data, node_effects->has_show_tight_bounds()); - } - - data.apply_transform_and_state(this); - - const FogAttrib *fog = DCAST(FogAttrib, node_reader->get_state()->get_attrib(FogAttrib::get_class_slot())); - if (fog != (const FogAttrib *)NULL && fog->get_fog() != (Fog *)NULL) { - // If we just introduced a FogAttrib here, call adjust_to_camera() - // now. This maybe isn't the perfect time to call it, but it's - // good enough; and at this time we have all the information we - // need for it. - fog->get_fog()->adjust_to_camera(get_camera_transform()); - } - - if (fancy_bits & PandaNode::FB_cull_callback) { - PandaNode *node = data.node(); - if (!node->cull_callback(this, data)) { - return; - } - } - traverse_below(data); - } - } + do_traverse(data); } //////////////////////////////////////////////////////////////////// @@ -241,27 +192,24 @@ traverse_below(CullTraverserData &data) { PandaNodePipelineReader *node_reader = data.node_reader(); PandaNode *node = data.node(); - bool this_node_hidden = data.is_this_node_hidden(this); - - const RenderEffects *node_effects = node_reader->get_effects(); - bool has_decal = !this_node_hidden && node_effects->has_decal(); - - if (!this_node_hidden) { + if (!data.is_this_node_hidden(_camera_mask)) { node->add_for_draw(this, data); - } - if (has_decal) { - // If we *are* implementing decals with DepthOffsetAttribs, - // apply it now, so that each child of this node gets offset by - // a tiny amount. - data._state = data._state->compose(get_depth_offset_state()); + // Check for a decal effect. + const RenderEffects *node_effects = node_reader->get_effects(); + if (node_effects->has_decal()) { + // If we *are* implementing decals with DepthOffsetAttribs, + // apply it now, so that each child of this node gets offset by + // a tiny amount. + data._state = data._state->compose(get_depth_offset_state()); #ifndef NDEBUG - // This is just a sanity check message. - if (!node->is_geom_node()) { - pgraph_cat.error() - << "DecalEffect applied to " << *node << ", not a GeomNode.\n"; - } + // This is just a sanity check message. + if (!node->is_geom_node()) { + pgraph_cat.error() + << "DecalEffect applied to " << *node << ", not a GeomNode.\n"; + } #endif + } } // Now visit all the node's children. @@ -272,14 +220,14 @@ traverse_below(CullTraverserData &data) { int i = node->get_first_visible_child(); while (i < num_children) { CullTraverserData next_data(data, children.get_child(i)); - traverse(next_data); + do_traverse(next_data); i = node->get_next_visible_child(i); } } else { for (int i = 0; i < num_children; i++) { CullTraverserData next_data(data, children.get_child(i)); - traverse(next_data); + do_traverse(next_data); } } } diff --git a/panda/src/pgraph/cullTraverser.h b/panda/src/pgraph/cullTraverser.h index 4ec772076f..9c22bec368 100644 --- a/panda/src/pgraph/cullTraverser.h +++ b/panda/src/pgraph/cullTraverser.h @@ -27,6 +27,8 @@ #include "drawMask.h" #include "typedReferenceCount.h" #include "pStatCollector.h" +#include "cullTraverserData.h" +#include "fogAttrib.h" class GraphicsStateGuardian; class PandaNode; @@ -92,6 +94,8 @@ PUBLISHED: const TransformState *modelview_transform) const; protected: + INLINE void do_traverse(CullTraverserData &data); + virtual bool is_in_view(CullTraverserData &data); public: diff --git a/panda/src/pgraph/cullTraverserData.I b/panda/src/pgraph/cullTraverserData.I index acd2ababfb..0bb5a3a316 100644 --- a/panda/src/pgraph/cullTraverserData.I +++ b/panda/src/pgraph/cullTraverserData.I @@ -185,7 +185,7 @@ is_in_view(const DrawMask &camera_mask) { // rendered. //////////////////////////////////////////////////////////////////// INLINE bool CullTraverserData:: -is_this_node_hidden(const CullTraverser *trav) const { +is_this_node_hidden(const DrawMask &camera_mask) const { return (_draw_mask & PandaNode::get_overall_bit()).is_zero() || - (_draw_mask & trav->get_camera_mask()).is_zero(); + (_draw_mask & camera_mask).is_zero(); } diff --git a/panda/src/pgraph/cullTraverserData.cxx b/panda/src/pgraph/cullTraverserData.cxx index a103cb2903..b79ffcaba3 100644 --- a/panda/src/pgraph/cullTraverserData.cxx +++ b/panda/src/pgraph/cullTraverserData.cxx @@ -145,6 +145,9 @@ is_in_view_impl() { if (result == BoundingVolume::IF_no_intersection) { // No intersection at all. Cull. +#ifdef NDEBUG + return false; +#else if (!fake_view_frustum_cull) { return false; } @@ -155,12 +158,13 @@ is_in_view_impl() { _view_frustum = (GeometricBoundingVolume *)NULL; CPT(RenderState) fake_state = get_fake_view_frustum_cull_state(); _state = _state->compose(fake_state); - +#endif + } else if ((result & BoundingVolume::IF_all) != 0) { // The node and its descendents are completely enclosed within // the frustum. No need to cull further. _view_frustum = (GeometricBoundingVolume *)NULL; - + } else { // The node is partially, but not completely, within the viewing // frustum. @@ -197,16 +201,20 @@ is_in_view_impl() { _state->write(pgraph_cat.spam(false), 2); } } - + if (result == BoundingVolume::IF_no_intersection) { // No intersection at all. Cull. +#ifdef NDEBUG + return false; +#else if (!fake_view_frustum_cull) { return false; } _cull_planes = CullPlanes::make_empty(); CPT(RenderState) fake_state = get_fake_view_frustum_cull_state(); _state = _state->compose(fake_state); - +#endif + } else if ((result & BoundingVolume::IF_all) != 0) { // The node and its descendents are completely in front of all // of the clip planes and occluders. The do_cull() call should @@ -227,6 +235,9 @@ is_in_view_impl() { //////////////////////////////////////////////////////////////////// CPT(RenderState) CullTraverserData:: get_fake_view_frustum_cull_state() { +#ifdef NDEBUG + return NULL; +#else // Once someone asks for this pointer, we hold its reference count // and never free it. static CPT(RenderState) state = (const RenderState *)NULL; @@ -238,5 +249,5 @@ get_fake_view_frustum_cull_state() { RenderState::get_max_priority()); } return state; +#endif } - diff --git a/panda/src/pgraph/cullTraverserData.h b/panda/src/pgraph/cullTraverserData.h index 1cca501caa..bae251a307 100644 --- a/panda/src/pgraph/cullTraverserData.h +++ b/panda/src/pgraph/cullTraverserData.h @@ -23,10 +23,10 @@ #include "geometricBoundingVolume.h" #include "pointerTo.h" #include "drawMask.h" -#include "cullTraverser.h" #include "pvector.h" class PandaNode; +class CullTraverser; //////////////////////////////////////////////////////////////////// // Class : CullTraverserData @@ -67,7 +67,7 @@ PUBLISHED: INLINE const TransformState *get_net_transform(const CullTraverser *trav) const; INLINE bool is_in_view(const DrawMask &camera_mask); - INLINE bool is_this_node_hidden(const CullTraverser *trav) const; + INLINE bool is_this_node_hidden(const DrawMask &camera_mask) const; void apply_transform_and_state(CullTraverser *trav); void apply_transform_and_state(CullTraverser *trav, diff --git a/panda/src/pgraph/cullableObject.cxx b/panda/src/pgraph/cullableObject.cxx index 6d5e2d2e27..a43a193168 100644 --- a/panda/src/pgraph/cullableObject.cxx +++ b/panda/src/pgraph/cullableObject.cxx @@ -133,7 +133,7 @@ munge_geom(GraphicsStateGuardianBase *gsg, _munged_data->animate_vertices(force, current_thread); if (animated_vertices != _munged_data) { cpu_animated = true; - _munged_data = animated_vertices; + swap(_munged_data, animated_vertices); } if (!munge_texcoord_light_vector(traverser, force)) { return false; @@ -159,7 +159,7 @@ munge_geom(GraphicsStateGuardianBase *gsg, _munged_data->animate_vertices(force, current_thread); if (animated_vertices != _munged_data) { cpu_animated = true; - _munged_data = animated_vertices; + swap(_munged_data, animated_vertices); } } @@ -589,7 +589,12 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { } _geom = new_geom.p(); + +#ifdef USE_MOVE_SEMANTICS + _munged_data = move(new_data); +#else _munged_data = new_data; +#endif return true; } diff --git a/panda/src/pgraph/geomNode.I b/panda/src/pgraph/geomNode.I index 8173ce50ef..cd9a72084b 100644 --- a/panda/src/pgraph/geomNode.I +++ b/panda/src/pgraph/geomNode.I @@ -320,6 +320,29 @@ operator = (const GeomNode::Geoms ©) { _geoms = copy._geoms; } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: GeomNode::Geoms::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE GeomNode::Geoms:: +Geoms(GeomNode::Geoms &&from) NOEXCEPT : + _geoms(move(from._geoms)) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomNode::Geoms::Move Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void GeomNode::Geoms:: +operator = (GeomNode::Geoms &&from) NOEXCEPT { + _geoms = move(from._geoms); +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: GeomNode::Geoms::get_num_geoms // Access: Public diff --git a/panda/src/pgraph/geomNode.h b/panda/src/pgraph/geomNode.h index ffedec99c2..e839ef8344 100644 --- a/panda/src/pgraph/geomNode.h +++ b/panda/src/pgraph/geomNode.h @@ -168,6 +168,11 @@ public: INLINE Geoms(const Geoms ©); INLINE void operator = (const Geoms ©); +#ifdef USE_MOVE_SEMANTICS + INLINE Geoms(Geoms &&from) NOEXCEPT; + INLINE void operator = (Geoms &&from) NOEXCEPT; +#endif + INLINE int get_num_geoms() const; INLINE CPT(Geom) get_geom(int n) const; INLINE const RenderState *get_geom_state(int n) const; diff --git a/panda/src/pgraph/pandaNode.I b/panda/src/pgraph/pandaNode.I index 6b3e27275c..2f35d6a3be 100644 --- a/panda/src/pgraph/pandaNode.I +++ b/panda/src/pgraph/pandaNode.I @@ -1130,6 +1130,29 @@ operator = (const PandaNode::Children ©) { _down = copy._down; } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::Children::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE PandaNode::Children:: +Children(PandaNode::Children &&from) NOEXCEPT : + _down(move(from._down)) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::Children::Move Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void PandaNode::Children:: +operator = (PandaNode::Children &&from) NOEXCEPT { + _down = move(from._down); +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: PandaNode::Children::get_num_children // Access: Public @@ -1208,6 +1231,29 @@ operator = (const PandaNode::Stashed ©) { _stashed = copy._stashed; } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::Stashed::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE PandaNode::Stashed:: +Stashed(PandaNode::Stashed &&from) NOEXCEPT : + _stashed(move(from._stashed)) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::Stashed::Move Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void PandaNode::Stashed:: +operator = (PandaNode::Stashed &&from) NOEXCEPT { + _stashed = move(from._stashed); +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: PandaNode::Stashed::get_num_stashed // Access: Public @@ -1286,6 +1332,29 @@ operator = (const PandaNode::Parents ©) { _up = copy._up; } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::Parents::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE PandaNode::Parents:: +Parents(PandaNode::Parents &&from) NOEXCEPT : + _up(move(from._up)) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::Parents::Move Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void PandaNode::Parents:: +operator = (PandaNode::Parents &&from) NOEXCEPT { + _up = move(from._up); +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: PandaNode::Parents::get_num_parents // Access: Public diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index d7d19efba4..2b15517a9b 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/panda/src/pgraph/pandaNode.h @@ -69,14 +69,14 @@ class GraphicsStateGuardianBase; // is the base class of all specialized nodes, and also // serves as a generic node with no special properties. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA_PGRAPH PandaNode : public TypedWritable, public Namable, +class EXPCL_PANDA_PGRAPH PandaNode : public TypedWritable, public Namable, public LinkedListNode, virtual public ReferenceCount { PUBLISHED: PandaNode(const string &name); virtual ~PandaNode(); - //published so that characters can be combined. - virtual PandaNode *combine_with(PandaNode *other); + //published so that characters can be combined. + virtual PandaNode *combine_with(PandaNode *other); protected: PandaNode(const PandaNode ©); @@ -105,7 +105,7 @@ public: bool &found_any, const TransformState *transform, Thread *current_thread = Thread::get_current_thread()) const; - + virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data); virtual bool has_selective_visibility() const; virtual int get_first_visible_child() const; @@ -195,9 +195,9 @@ PUBLISHED: INLINE bool has_dirty_prev_transform() const; static void reset_all_prev_transform(Thread *current_thread = Thread::get_current_thread()); - void set_tag(const string &key, const string &value, + void set_tag(const string &key, const string &value, Thread *current_thread = Thread::get_current_thread()); - INLINE string get_tag(const string &key, + INLINE string get_tag(const string &key, Thread *current_thread = Thread::get_current_thread()) const; INLINE bool has_tag(const string &key, Thread *current_thread = Thread::get_current_thread()) const; @@ -393,7 +393,7 @@ private: // parent-child manipulation for NodePath support. Don't try to // call these directly. - static PT(NodePathComponent) attach(NodePathComponent *parent, + static PT(NodePathComponent) attach(NodePathComponent *parent, PandaNode *child, int sort, int pipeline_stage, Thread *current_thread); static void detach(NodePathComponent *child, int pipeline_stage, Thread *current_thread); @@ -402,7 +402,7 @@ private: NodePathComponent *child, int sort, bool as_stashed, int pipeline_stage, Thread *current_thread); static bool reparent_one_stage(NodePathComponent *new_parent, - NodePathComponent *child, int sort, + NodePathComponent *child, int sort, bool as_stashed, int pipeline_stage, Thread *current_thread); static PT(NodePathComponent) get_component(NodePathComponent *parent, PandaNode *child, @@ -411,7 +411,7 @@ private: int pipeline_stage, Thread *current_thread); PT(NodePathComponent) get_generic_component(bool accept_ambiguity, int pipeline_stage, Thread *current_thread); - PT(NodePathComponent) r_get_generic_component(bool accept_ambiguity, + PT(NodePathComponent) r_get_generic_component(bool accept_ambiguity, bool &ambiguity_detected, int pipeline_stage, Thread *current_thread); void delete_component(NodePathComponent *component); @@ -421,7 +421,7 @@ private: int pipeline_stage, Thread *current_thread); void fix_path_lengths(int pipeline_stage, Thread *current_thread); void r_list_descendants(ostream &out, int indent_level) const; - + INLINE void do_set_dirty_prev_transform(); INLINE void do_clear_dirty_prev_transform(); @@ -461,14 +461,14 @@ private: static TypeHandle get_class_type() { return _type_handle; } - + public: static void init_type() { BamReaderAuxData::init_type(); register_type(_type_handle, "BamReaderAuxDataDown", BamReaderAuxData::get_class_type()); } - + private: static TypeHandle _type_handle; }; @@ -513,8 +513,8 @@ private: #ifndef NDEBUG unsigned int _unexpected_change_flags; #endif // !NDEBUG - - // This is the data that must be cycled between pipeline stages. + + // This is the data that must be cycled between pipeline stages. class EXPCL_PANDA_PGRAPH CData : public BoundsData { public: @@ -524,7 +524,7 @@ private: ALLOC_DELETED_CHAIN(CData); virtual CycleData *make_copy() const; - virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; void update_bam_nested(BamWriter *manager) const; virtual int complete_pointers(TypedWritable **plist, BamReader *manager); virtual void fillin(DatagramIterator &scan, BamReader *manager); @@ -545,7 +545,7 @@ private: // are less likely to change as often: tags, collide mask. INLINE void set_fancy_bit(int bits, bool value); - + #ifdef HAVE_PYTHON void inc_py_refs(); void dec_py_refs(); @@ -648,7 +648,7 @@ private: COWPT(Down) _down; COWPT(Down) _stashed; COWPT(Up) _up; - + public: static TypeHandle get_class_type() { return _type_handle; @@ -656,7 +656,7 @@ private: static void init_type() { register_type(_type_handle, "PandaNode::CData"); } - + private: static TypeHandle _type_handle; }; @@ -691,6 +691,11 @@ public: INLINE Children(const Children ©); INLINE void operator = (const Children ©); +#ifdef USE_MOVE_SEMANTICS + INLINE Children(Children &&from) NOEXCEPT; + INLINE void operator = (Children &&from) NOEXCEPT; +#endif + INLINE int get_num_children() const; INLINE PandaNode *get_child(int n) const; INLINE int get_child_sort(int n) const; @@ -707,6 +712,11 @@ public: INLINE Stashed(const Stashed ©); INLINE void operator = (const Stashed ©); +#ifdef USE_MOVE_SEMANTICS + INLINE Stashed(Stashed &&from) NOEXCEPT; + INLINE void operator = (Stashed &&from) NOEXCEPT; +#endif + INLINE int get_num_stashed() const; INLINE PandaNode *get_stashed(int n) const; INLINE int get_stashed_sort(int n) const; @@ -723,6 +733,11 @@ public: INLINE Parents(const Parents ©); INLINE void operator = (const Parents ©); +#ifdef USE_MOVE_SEMANTICS + INLINE Parents(Parents &&from) NOEXCEPT; + INLINE void operator = (Parents &&from) NOEXCEPT; +#endif + INLINE int get_num_parents() const; INLINE PandaNode *get_parent(int n) const; @@ -750,7 +765,7 @@ protected: static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); void fillin_recorder(DatagramIterator &scan, BamReader *manager); - + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/pgraph/renderAttrib.I b/panda/src/pgraph/renderAttrib.I index bb12b66e62..a32e666c3c 100644 --- a/panda/src/pgraph/renderAttrib.I +++ b/panda/src/pgraph/renderAttrib.I @@ -96,11 +96,7 @@ compare_to(const RenderAttrib &other) const { //////////////////////////////////////////////////////////////////// INLINE size_t RenderAttrib:: get_hash() const { - size_t hash = get_hash_impl(); - - // The type is also added to the hash. - hash = int_hash::add_hash(hash, get_type().get_index()); - return hash; + return _hash; } //////////////////////////////////////////////////////////////////// @@ -143,6 +139,19 @@ get_auto_shader_attrib(const RenderState *state) const { return get_auto_shader_attrib_impl(state); } +//////////////////////////////////////////////////////////////////// +// Function: RenderAttrib::calc_hash +// Access: Published +// Description: Calculates a suitable hash value for phash_map. +//////////////////////////////////////////////////////////////////// +INLINE void RenderAttrib:: +calc_hash() { + size_t hash = get_hash_impl(); + + // The type is also added to the hash. + _hash = int_hash::add_hash(hash, get_type().get_index()); +} + //////////////////////////////////////////////////////////////////// // Function: RenderAttrib::register_slot // Access: Public, Static diff --git a/panda/src/pgraph/renderAttrib.cxx b/panda/src/pgraph/renderAttrib.cxx index fcb5ee7b52..255405402c 100644 --- a/panda/src/pgraph/renderAttrib.cxx +++ b/panda/src/pgraph/renderAttrib.cxx @@ -143,7 +143,7 @@ cull_callback(CullTraverser *, const CullTraverserData &) const { //////////////////////////////////////////////////////////////////// // Function: RenderAttrib::get_auto_shader_attrib_impl // Access: Protected, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) RenderAttrib:: get_auto_shader_attrib_impl(const RenderState *state) const { @@ -191,7 +191,7 @@ unref() const { //////////////////////////////////////////////////////////////////// // Function: RenderAttrib::output // Access: Published, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// void RenderAttrib:: output(ostream &out) const { @@ -201,7 +201,7 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// // Function: RenderAttrib::write // Access: Published, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// void RenderAttrib:: write(ostream &out, int indent_level) const { @@ -274,7 +274,7 @@ garbage_collect() { } num_this_pass = min(num_this_pass, size); int stop_at_element = (_garbage_index + num_this_pass) % size; - + int num_elements = 0; int si = _garbage_index; do { @@ -291,7 +291,7 @@ garbage_collect() { attrib->release_new(); unref_delete(attrib); } - } + } si = (si + 1) % size; } while (si != stop_at_element); @@ -328,12 +328,11 @@ validate_attribs() { } const RenderAttrib *attrib = _attribs->get_key(si); cerr << si << ": " << attrib << "\n"; - attrib->get_hash(); attrib->write(cerr, 2); } return false; - } + } int size = _attribs->get_size(); int si = 0; @@ -391,6 +390,7 @@ CPT(RenderAttrib) RenderAttrib:: return_new(RenderAttrib *attrib) { nassertr(attrib != (RenderAttrib *)NULL, attrib); if (!uniquify_attribs) { + attrib->calc_hash(); return attrib; } @@ -415,6 +415,8 @@ CPT(RenderAttrib) RenderAttrib:: return_unique(RenderAttrib *attrib) { nassertr(attrib != (RenderAttrib *)NULL, attrib); + attrib->calc_hash(); + if (!state_cache) { return attrib; } @@ -442,7 +444,7 @@ return_unique(RenderAttrib *attrib) { // There's an equivalent attrib already in the set. Return it. return _attribs->get_key(si); } - + // Not already in the set; add it. if (garbage_collect_states) { // If we'll be garbage collecting attribs explicitly, we'll @@ -656,7 +658,7 @@ change_this(TypedWritable *old_ptr, BamReader *manager) { pointer->ref(); manager->register_finalize(attrib); } - + // We have to cast the pointer back to non-const, because the bam // reader expects that. return (RenderAttrib *)pointer.p(); diff --git a/panda/src/pgraph/renderAttrib.h b/panda/src/pgraph/renderAttrib.h index 0783080a0b..49a7e78ebe 100644 --- a/panda/src/pgraph/renderAttrib.h +++ b/panda/src/pgraph/renderAttrib.h @@ -105,7 +105,7 @@ PUBLISHED: M_greater, // incoming > reference_alpha M_not_equal, // incoming != reference_alpha M_greater_equal, // incoming >= reference_alpha - M_always // Always draw. + M_always // Always draw. }; // This is the enumerated type for TexGenAttrib. It is inherited @@ -181,6 +181,8 @@ PUBLISHED: }; protected: + INLINE void calc_hash(); + static CPT(RenderAttrib) return_new(RenderAttrib *attrib); static CPT(RenderAttrib) return_unique(RenderAttrib *attrib); virtual int compare_to_impl(const RenderAttrib *other) const; @@ -212,6 +214,7 @@ private: static Attribs *_attribs; int _saved_entry; + size_t _hash; // This keeps track of our current position through the garbage // collection cycle. @@ -227,7 +230,7 @@ public: protected: static TypedWritable *new_from_bam(RenderAttrib *attrib, BamReader *manager); void fillin(DatagramIterator &scan, BamReader *manager); - + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/pgraph/renderState.I b/panda/src/pgraph/renderState.I index 8cce7408af..da6679bd7a 100644 --- a/panda/src/pgraph/renderState.I +++ b/panda/src/pgraph/renderState.I @@ -51,6 +51,42 @@ has_cull_callback() const { return (_flags & F_has_cull_callback) != 0; } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::make_empty +// Access: Published, Static +// Description: Returns a RenderState with no attributes set. +//////////////////////////////////////////////////////////////////// +INLINE CPT(RenderState) RenderState:: +make_empty() { + // The empty state is asked for so often, we make it a special case + // and store a pointer forever once we find it the first time. + if (_empty_state == (RenderState *)NULL) { + RenderState *state = new RenderState; + _empty_state = return_unique(state); + } + + return _empty_state; +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderState::make_full_default +// Access: Published, Static +// Description: Returns a RenderState with all possible attributes +// set to their default value. +//////////////////////////////////////////////////////////////////// +INLINE CPT(RenderState) RenderState:: +make_full_default() { + // The empty state is asked for so often, we make it a special case + // and store a pointer forever once we find it the first time. + if (_full_default_state == (RenderState *)NULL) { + RenderState *state = new RenderState; + state->fill_default(); + _full_default_state = return_unique(state); + } + + return _full_default_state; +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::remove_attrib // Access: Published diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index 03262e26c7..a7cf3ecddc 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -281,42 +281,6 @@ cull_callback(CullTraverser *trav, const CullTraverserData &data) const { return true; } -//////////////////////////////////////////////////////////////////// -// Function: RenderState::make_empty -// Access: Published, Static -// Description: Returns a RenderState with no attributes set. -//////////////////////////////////////////////////////////////////// -CPT(RenderState) RenderState:: -make_empty() { - // The empty state is asked for so often, we make it a special case - // and store a pointer forever once we find it the first time. - if (_empty_state == (RenderState *)NULL) { - RenderState *state = new RenderState; - _empty_state = return_unique(state); - } - - return _empty_state; -} - -//////////////////////////////////////////////////////////////////// -// Function: RenderState::make_full_default -// Access: Published, Static -// Description: Returns a RenderState with all possible attributes -// set to their default value. -//////////////////////////////////////////////////////////////////// -CPT(RenderState) RenderState:: -make_full_default() { - // The empty state is asked for so often, we make it a special case - // and store a pointer forever once we find it the first time. - if (_full_default_state == (RenderState *)NULL) { - RenderState *state = new RenderState; - state->fill_default(); - _full_default_state = return_unique(state); - } - - return _full_default_state; -} - //////////////////////////////////////////////////////////////////// // Function: RenderState::make // Access: Published, Static diff --git a/panda/src/pgraph/renderState.h b/panda/src/pgraph/renderState.h index 9b87926045..7ed8a05729 100644 --- a/panda/src/pgraph/renderState.h +++ b/panda/src/pgraph/renderState.h @@ -75,8 +75,8 @@ PUBLISHED: INLINE bool has_cull_callback() const; bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const; - static CPT(RenderState) make_empty(); - static CPT(RenderState) make_full_default(); + INLINE static CPT(RenderState) make_empty(); + INLINE static CPT(RenderState) make_full_default(); static CPT(RenderState) make(const RenderAttrib *attrib, int override = 0); static CPT(RenderState) make(const RenderAttrib *attrib1, const RenderAttrib *attrib2, int override = 0); diff --git a/panda/src/pgraph/texMatrixAttrib.cxx b/panda/src/pgraph/texMatrixAttrib.cxx index 308ff574f2..7afe6f9014 100644 --- a/panda/src/pgraph/texMatrixAttrib.cxx +++ b/panda/src/pgraph/texMatrixAttrib.cxx @@ -62,7 +62,7 @@ CPT(RenderAttrib) TexMatrixAttrib:: make(const LMatrix4 &mat) { pgraph_cat.warning() << "Using deprecated TexMatrixAttrib interface.\n"; - if (mat == LMatrix4::ident_mat()) { + if (mat.is_identity()) { return make(); } CPT(TransformState) transform = TransformState::make_mat(mat); diff --git a/panda/src/pgraph/transformState.I b/panda/src/pgraph/transformState.I index 58fe5d1bb3..9f4ff96c90 100644 --- a/panda/src/pgraph/transformState.I +++ b/panda/src/pgraph/transformState.I @@ -14,15 +14,13 @@ //////////////////////////////////////////////////////////////////// -// Function: TransformState::operator < +// Function: TransformState::operator != // Access: Published -// Description: Provides an arbitrary ordering among all unique -// TransformStates, so we can store the essentially -// different ones in a big set and throw away the rest. +// Description: Opposite of operator ==. //////////////////////////////////////////////////////////////////// INLINE bool TransformState:: -operator < (const TransformState &other) const { - return compare_to(other) < 0; +operator != (const TransformState &other) const { + return !(operator == (other)); } //////////////////////////////////////////////////////////////////// @@ -31,10 +29,14 @@ operator < (const TransformState &other) const { // Description: Provides an arbitrary ordering among all unique // TransformStates, so we can store the essentially // different ones in a big set and throw away the rest. +// +// Note that if this returns 0, it doesn't necessarily +// imply that operator == returns true; it uses a very +// slightly different comparison threshold. //////////////////////////////////////////////////////////////////// INLINE int TransformState:: compare_to(const TransformState &other) const { - return compare_to(other, uniquify_matrix); + return compare_to(other, _uniquify_matrix); } //////////////////////////////////////////////////////////////////// @@ -56,7 +58,7 @@ get_hash() const { //////////////////////////////////////////////////////////////////// INLINE CPT(TransformState) TransformState:: make_pos(const LVecBase3 &pos) { - return make_pos_hpr_scale(pos, + return make_pos_hpr_scale(pos, LVecBase3(0.0f, 0.0f, 0.0f), LVecBase3(1.0f, 1.0f, 1.0f)); } @@ -70,7 +72,7 @@ make_pos(const LVecBase3 &pos) { INLINE CPT(TransformState) TransformState:: make_hpr(const LVecBase3 &hpr) { return make_pos_hpr_scale(LVecBase3(0.0f, 0.0f, 0.0f), - hpr, + hpr, LVecBase3(1.0f, 1.0f, 1.0f)); } @@ -83,7 +85,7 @@ make_hpr(const LVecBase3 &hpr) { INLINE CPT(TransformState) TransformState:: make_quat(const LQuaternion &quat) { return make_pos_quat_scale(LVecBase3(0.0f, 0.0f, 0.0f), - quat, + quat, LVecBase3(1.0f, 1.0f, 1.0f)); } @@ -146,7 +148,7 @@ make_shear(const LVecBase3 &shear) { // components. //////////////////////////////////////////////////////////////////// INLINE CPT(TransformState) TransformState:: -make_pos_hpr_scale(const LVecBase3 &pos, const LVecBase3 &hpr, +make_pos_hpr_scale(const LVecBase3 &pos, const LVecBase3 &hpr, const LVecBase3 &scale) { return make_pos_hpr_scale_shear(pos, hpr, scale, LVecBase3::zero()); } @@ -158,7 +160,7 @@ make_pos_hpr_scale(const LVecBase3 &pos, const LVecBase3 &hpr, // components. //////////////////////////////////////////////////////////////////// INLINE CPT(TransformState) TransformState:: -make_pos_quat_scale(const LVecBase3 &pos, const LQuaternion &quat, +make_pos_quat_scale(const LVecBase3 &pos, const LQuaternion &quat, const LVecBase3 &scale) { return make_pos_quat_scale_shear(pos, quat, scale, LVecBase3::zero()); } @@ -182,7 +184,7 @@ make_pos2d(const LVecBase2 &pos) { //////////////////////////////////////////////////////////////////// INLINE CPT(TransformState) TransformState:: make_rotate2d(PN_stdfloat rotate) { - return make_pos_rotate_scale2d(LVecBase2(0.0f, 0.0f), rotate, + return make_pos_rotate_scale2d(LVecBase2(0.0f, 0.0f), rotate, LVecBase2(1.0f, 1.0f)); } @@ -229,7 +231,7 @@ make_scale2d(const LVecBase2 &scale) { //////////////////////////////////////////////////////////////////// INLINE CPT(TransformState) TransformState:: make_shear2d(PN_stdfloat shear) { - return make_pos_rotate_scale_shear2d(LVecBase2(0.0f, 0.0f), 0.0f, + return make_pos_rotate_scale_shear2d(LVecBase2(0.0f, 0.0f), 0.0f, LVecBase2(1.0f, 1.0f), shear); } @@ -240,7 +242,7 @@ make_shear2d(PN_stdfloat shear) { // components. //////////////////////////////////////////////////////////////////// INLINE CPT(TransformState) TransformState:: -make_pos_rotate_scale2d(const LVecBase2 &pos, PN_stdfloat rotate, +make_pos_rotate_scale2d(const LVecBase2 &pos, PN_stdfloat rotate, const LVecBase2 &scale) { return make_pos_rotate_scale_shear2d(pos, rotate, scale, 0.0f); } @@ -353,7 +355,7 @@ hpr_given() const { //////////////////////////////////////////////////////////////////// // Function: TransformState::quat_given // Access: Published -// Description: Returns true if the rotation was specified via a +// Description: Returns true if the rotation was specified via a // quaternion, false otherwise. If this is true, // get_quat() will be exactly as set; otherwise, it will // return a computed value. @@ -1142,7 +1144,7 @@ calc_mat() { //////////////////////////////////////////////////////////////////// INLINE void TransformState:: check_uniform_scale() { - if (IS_NEARLY_EQUAL(_scale[0], _scale[1]) && + if (IS_NEARLY_EQUAL(_scale[0], _scale[1]) && IS_NEARLY_EQUAL(_scale[0], _scale[2])) { _flags |= F_uniform_scale; if (IS_NEARLY_EQUAL(_scale[0], 1.0f)) { @@ -1234,7 +1236,7 @@ consider_update_pstats(int old_referenced_bits) const { //////////////////////////////////////////////////////////////////// // Function: TransformState::Composition::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE TransformState::Composition:: Composition() { @@ -1243,7 +1245,7 @@ Composition() { //////////////////////////////////////////////////////////////////// // Function: TransformState::Composition::Copy Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE TransformState::Composition:: Composition(const TransformState::Composition ©) : @@ -1254,7 +1256,7 @@ Composition(const TransformState::Composition ©) : //////////////////////////////////////////////////////////////////// // Function: TransformState::CompositionCycleDescEntry::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE TransformState::CompositionCycleDescEntry:: CompositionCycleDescEntry(const TransformState *obj, diff --git a/panda/src/pgraph/transformState.cxx b/panda/src/pgraph/transformState.cxx index a9ec305914..bffa840479 100644 --- a/panda/src/pgraph/transformState.cxx +++ b/panda/src/pgraph/transformState.cxx @@ -32,6 +32,7 @@ CPT(TransformState) TransformState::_identity_state; CPT(TransformState) TransformState::_invalid_state; UpdateSeq TransformState::_last_cycle_detect; int TransformState::_garbage_index = 0; +bool TransformState::_uniquify_matrix = true; PStatCollector TransformState::_cache_update_pcollector("*:State Cache:Update"); PStatCollector TransformState::_garbage_collect_pcollector("*:State Cache:Garbage Collect"); @@ -98,7 +99,7 @@ TransformState:: // We'd better not call the destructor twice on a particular object. nassertv(!is_destructing()); set_destructing(); - + // Free the inverse matrix computation, if it has been stored. if (_inv_mat != (LMatrix4 *)NULL) { delete _inv_mat; @@ -124,6 +125,10 @@ TransformState:: // TransformStates, so we can store the essentially // different ones in a big set and throw away the rest. // +// Note that if this returns 0, it doesn't necessarily +// imply that operator == returns true; it uses a very +// slightly different comparison threshold. +// // If uniquify_matrix is true, then matrix-defined // TransformStates are also uniqified. If // uniquify_matrix is false, then only component-defined @@ -132,7 +137,7 @@ TransformState:: //////////////////////////////////////////////////////////////////// int TransformState:: compare_to(const TransformState &other, bool uniquify_matrix) const { - static const int significant_flags = + static const int significant_flags = (F_is_invalid | F_is_identity | F_components_given | F_hpr_given | F_quat_given | F_is_2d); int flags = (_flags & significant_flags); @@ -191,6 +196,73 @@ compare_to(const TransformState &other, bool uniquify_matrix) const { } } +//////////////////////////////////////////////////////////////////// +// Function: TransformState::operator == +// Access: Published +// Description: Tests equivalence between two transform states. +// We use this instead of compare_to since this is +// faster, and we don't need an ordering between +// TransformStates because we use a hash map. +// +// If uniquify_matrix is true, then matrix-defined +// TransformStates are also uniqified. If +// uniquify_matrix is false, then only component-defined +// TransformStates are uniquified, which is less +// expensive. +//////////////////////////////////////////////////////////////////// +bool TransformState:: +operator == (const TransformState &other) const { + static const int significant_flags = + (F_is_invalid | F_is_identity | F_components_given | F_hpr_given | F_quat_given | F_is_2d); + + int flags = (_flags & significant_flags); + int other_flags = (other._flags & significant_flags); + if (flags != other_flags) { + return false; + } + + if ((_flags & (F_is_invalid | F_is_identity)) != 0) { + // All invalid transforms are equivalent to each other, and all + // identity transforms are equivalent to each other. + return true; + } + + if ((_flags & F_components_given) != 0) { + // If the transform was specified componentwise, compare them + // componentwise. + if (_pos != other._pos) { + return false; + } + + if ((_flags & F_hpr_given) != 0) { + if (_hpr != other._hpr) { + return false; + } + } else if ((_flags & F_quat_given) != 0) { + if (_quat != other._quat) { + return false; + } + } + + if (_scale != other._scale) { + return false; + } + + return (_shear == other._shear); + } + + // Otherwise, compare the matrices . . . + if (_uniquify_matrix) { + // . . . but only if the user thinks that's a worthwhile + // comparison. + return get_mat().almost_equal(other.get_mat()); + + } else { + // If not, we just compare the pointers. + return (this == &other); + } +} + //////////////////////////////////////////////////////////////////// // Function: TransformState::make_identity // Access: Published, Static @@ -232,7 +304,7 @@ make_invalid() { // components. //////////////////////////////////////////////////////////////////// CPT(TransformState) TransformState:: -make_pos_hpr_scale_shear(const LVecBase3 &pos, const LVecBase3 &hpr, +make_pos_hpr_scale_shear(const LVecBase3 &pos, const LVecBase3 &hpr, const LVecBase3 &scale, const LVecBase3 &shear) { nassertr(!(pos.is_nan() || hpr.is_nan() || scale.is_nan() || shear.is_nan()) , make_invalid()); // Make a special-case check for the identity transform. @@ -260,7 +332,7 @@ make_pos_hpr_scale_shear(const LVecBase3 &pos, const LVecBase3 &hpr, // components. //////////////////////////////////////////////////////////////////// CPT(TransformState) TransformState:: -make_pos_quat_scale_shear(const LVecBase3 &pos, const LQuaternion &quat, +make_pos_quat_scale_shear(const LVecBase3 &pos, const LQuaternion &quat, const LVecBase3 &scale, const LVecBase3 &shear) { nassertr(!(pos.is_nan() || quat.is_nan() || scale.is_nan() || shear.is_nan()) , make_invalid()); // Make a special-case check for the identity transform. @@ -291,7 +363,7 @@ CPT(TransformState) TransformState:: make_mat(const LMatrix4 &mat) { nassertr(!mat.is_nan(), make_invalid()); // Make a special-case check for the identity matrix. - if (mat == LMatrix4::ident_mat()) { + if (mat.is_identity()) { return make_identity(); } @@ -301,7 +373,6 @@ make_mat(const LMatrix4 &mat) { return return_new(state); } - //////////////////////////////////////////////////////////////////// // Function: TransformState::make_pos_rotate_scale_shear2d // Access: Published, Static @@ -356,7 +427,7 @@ CPT(TransformState) TransformState:: make_mat3(const LMatrix3 &mat) { nassertr(!mat.is_nan(), make_invalid()); // Make a special-case check for the identity matrix. - if (mat == LMatrix3::ident_mat()) { + if (mat.is_identity()) { return make_identity(); } @@ -529,7 +600,7 @@ set_rotate2d(PN_stdfloat rotate) const { } } - return make_pos_rotate_scale_shear2d(get_pos2d(), rotate, get_scale2d(), + return make_pos_rotate_scale_shear2d(get_pos2d(), rotate, get_scale2d(), get_shear2d()); } @@ -592,7 +663,7 @@ compose(const TransformState *other) const { if (other->is_identity()) { return this; } - + // If either transform is invalid, the result is invalid. if (is_invalid()) { return this; @@ -754,7 +825,7 @@ unref() const { // it and tries to ref it. ((TransformState *)this)->release_new(); ((TransformState *)this)->remove_cache_pointers(); - + return false; } @@ -821,7 +892,7 @@ validate_composition_cache() const { //////////////////////////////////////////////////////////////////// // Function: TransformState::output // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// void TransformState:: output(ostream &out) const { @@ -913,7 +984,7 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// // Function: TransformState::write // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// void TransformState:: write(ostream &out, int indent_level) const { @@ -1037,7 +1108,7 @@ get_num_unused_states() { if (pgraph_cat.is_debug()) { pgraph_cat.debug() - << "Unused state: " << (void *)state << ":" + << "Unused state: " << (void *)state << ":" << state->get_ref_count() << " =\n"; state->write(pgraph_cat.debug(false), 2); } @@ -1167,7 +1238,7 @@ garbage_collect() { } num_this_pass = min(num_this_pass, size); int stop_at_element = (_garbage_index + num_this_pass) % size; - + int num_elements = 0; int si = _garbage_index; do { @@ -1197,8 +1268,8 @@ garbage_collect() { state->cache_unref(); delete state; } - } - + } + si = (si + 1) % size; } while (si != stop_at_element); _garbage_index = si; @@ -1276,7 +1347,7 @@ list_cycles(ostream &out) { if (r_detect_reverse_cycles(state, state, 1, _last_cycle_detect, &cycle_desc)) { // This state begins a cycle. CompositionCycleDesc::iterator csi; - + out << "\nReverse cycle detected of length " << cycle_desc.size() + 1 << ":\n" << "state "; for (csi = cycle_desc.begin(); csi != cycle_desc.end(); ++csi) { @@ -1292,7 +1363,7 @@ list_cycles(ostream &out) { out << (void *)state << ":" << state->get_ref_count() << " =\n"; state->write(out, 2); - + cycle_desc.clear(); } } @@ -1355,7 +1426,7 @@ validate_states() { pgraph_cat.error() << "TransformState::_states cache is invalid!\n"; return false; - } + } int size = _states->get_size(); int si = 0; @@ -1376,13 +1447,11 @@ validate_states() { return false; } const TransformState *ssnext = _states->get_key(snext); - int c = ssi->compare_to(*ssnext); - int ci = ssnext->compare_to(*ssi); - if ((ci < 0) != (c > 0) || - (ci > 0) != (c < 0) || - (ci == 0) != (c == 0)) { + bool c = (*ssi) == (*ssnext); + bool ci = (*ssnext) == (*ssi); + if (c != ci) { pgraph_cat.error() - << "TransformState::compare_to() not defined properly!\n"; + << "TransformState::operator == () not defined properly!\n"; pgraph_cat.error(false) << "(a, b): " << c << "\n"; pgraph_cat.error(false) @@ -1415,6 +1484,18 @@ void TransformState:: init_states() { _states = new States; + ConfigVariableBool uniquify_matrix + ("uniquify-matrix", true, + PRC_DESC("Set this true to look up arbitrary 4x4 transform matrices in " + "the cache, to ensure that two differently-computed transforms " + "that happen to encode the same matrix will be collapsed into " + "a single pointer. Nowadays, with the transforms stored in a " + "hashtable, we're generally better off with this set true.")); + + // Store this at the beginning, so that we don't have to query this + // every time that the comparison operator is invoked. + _uniquify_matrix = uniquify_matrix; + // TODO: we should have a global Panda mutex to allow us to safely // create _states_lock without a startup race condition. For the // meantime, this is OK because we guarantee that this method is @@ -1424,7 +1505,7 @@ init_states() { _cache_stats.init(); nassertv(Thread::get_current_thread() == Thread::get_main_thread()); } - + //////////////////////////////////////////////////////////////////// // Function: TransformState::return_new // Access: Private, Static @@ -1519,8 +1600,8 @@ do_compose(const TransformState *other) const { nassertr((_flags & F_is_invalid) == 0, this); nassertr((other->_flags & F_is_invalid) == 0, other); - if (compose_componentwise && - has_uniform_scale() && + if (compose_componentwise && + has_uniform_scale() && !has_nonzero_shear() && !other->has_nonzero_shear() && ((components_given() && other->has_components()) || (other->components_given() && has_components()))) { @@ -1541,7 +1622,7 @@ do_compose(const TransformState *other) const { rotate += other->get_rotate2d(); LVecBase2 new_scale = other->get_scale2d() * scale; - + result = make_pos_rotate_scale2d(pos, rotate, new_scale); } else { @@ -1549,14 +1630,14 @@ do_compose(const TransformState *other) const { LVecBase3 pos = get_pos(); LQuaternion quat = get_norm_quat(); PN_stdfloat scale = get_uniform_scale(); - + pos += quat.xform(other->get_pos()) * scale; quat = other->get_norm_quat() * quat; LVecBase3 new_scale = other->get_scale() * scale; - + result = make_pos_quat_scale(pos, quat, new_scale); } - + #ifndef NDEBUG if (paranoid_compose) { // Now verify against the matrix. @@ -1653,7 +1734,7 @@ store_compose(const TransformState *other, const TransformState *result) { // to decrement it again later, when the composition entry is // removed from the cache. result->cache_ref(); - + // (If the result was just this again, we still store the // result, but we don't increment the reference count, since // that would be a self-referential leak.) @@ -1730,7 +1811,7 @@ store_invert_compose(const TransformState *other, const TransformState *result) // to decrement it again later, when the composition entry is // removed from the cache. result->cache_ref(); - + // (If the result was just this again, we still store the // result, but we don't increment the reference count, since // that would be a self-referential leak.) @@ -1751,8 +1832,8 @@ do_invert_compose(const TransformState *other) const { nassertr((_flags & F_is_invalid) == 0, this); nassertr((other->_flags & F_is_invalid) == 0, other); - if (compose_componentwise && - has_uniform_scale() && + if (compose_componentwise && + has_uniform_scale() && !has_nonzero_shear() && !other->has_nonzero_shear() && ((components_given() && other->has_components()) || (other->components_given() && has_components()))) { @@ -1767,7 +1848,7 @@ do_invert_compose(const TransformState *other) const { PN_stdfloat rotate = get_rotate2d(); LQuaternion quat = get_norm_quat(); PN_stdfloat scale = get_uniform_scale(); - + // First, invert our own transform. if (scale == 0.0f) { ((TransformState *)this)->_flags |= F_is_singular | F_singular_known; @@ -1779,7 +1860,7 @@ do_invert_compose(const TransformState *other) const { LVecBase3 mp = quat.xform(-LVecBase3(pos[0], pos[1], 0.0f)); pos = LVecBase2(mp[0], mp[1]) * scale; LVecBase2 new_scale(scale, scale); - + // Now compose the inverted transform with the other transform. if (!other->is_identity()) { LPoint3 op = quat.xform(other->get_pos()); @@ -1796,7 +1877,7 @@ do_invert_compose(const TransformState *other) const { LVecBase3 pos = get_pos(); LQuaternion quat = get_norm_quat(); PN_stdfloat scale = get_uniform_scale(); - + // First, invert our own transform. if (scale == 0.0f) { ((TransformState *)this)->_flags |= F_is_singular | F_singular_known; @@ -1806,7 +1887,7 @@ do_invert_compose(const TransformState *other) const { quat.invert_in_place(); pos = quat.xform(-pos) * scale; LVecBase3 new_scale(scale, scale, scale); - + // Now compose the inverted transform with the other transform. if (!other->is_identity()) { pos += quat.xform(other->get_pos()) * scale; @@ -1879,7 +1960,7 @@ do_invert_compose(const TransformState *other) const { void TransformState:: detect_and_break_cycles() { PStatTimer timer(_transform_break_cycles_pcollector); - + ++_last_cycle_detect; if (r_detect_cycles(this, this, 1, _last_cycle_detect, NULL)) { // Ok, we have a cycle. This will be a leak unless we break the @@ -1888,7 +1969,7 @@ detect_and_break_cycles() { pgraph_cat.debug() << "Breaking cycle involving " << (*this) << "\n"; } - + remove_cache_pointers(); } else { ++_last_cycle_detect; @@ -1897,7 +1978,7 @@ detect_and_break_cycles() { pgraph_cat.debug() << "Breaking cycle involving " << (*this) << "\n"; } - + remove_cache_pointers(); } } @@ -1936,7 +2017,7 @@ r_detect_cycles(const TransformState *start_state, if (current_state->_composition_cache.has_element(i)) { const TransformState *result = current_state->_composition_cache.get_data(i)._result; if (result != (const TransformState *)NULL) { - if (r_detect_cycles(start_state, result, length + 1, + if (r_detect_cycles(start_state, result, length + 1, this_seq, cycle_desc)) { // Cycle detected. if (cycle_desc != (CompositionCycleDesc *)NULL) { @@ -2008,7 +2089,7 @@ r_detect_reverse_cycles(const TransformState *start_state, const TransformState *result = other->_composition_cache.get_data(oi)._result; if (result != (const TransformState *)NULL) { - if (r_detect_reverse_cycles(start_state, result, length + 1, + if (r_detect_reverse_cycles(start_state, result, length + 1, this_seq, cycle_desc)) { // Cycle detected. if (cycle_desc != (CompositionCycleDesc *)NULL) { @@ -2033,7 +2114,7 @@ r_detect_reverse_cycles(const TransformState *start_state, const TransformState *result = other->_invert_composition_cache.get_data(oi)._result; if (result != (const TransformState *)NULL) { - if (r_detect_reverse_cycles(start_state, result, length + 1, + if (r_detect_reverse_cycles(start_state, result, length + 1, this_seq, cycle_desc)) { // Cycle detected. if (cycle_desc != (CompositionCycleDesc *)NULL) { @@ -2065,7 +2146,7 @@ r_detect_reverse_cycles(const TransformState *start_state, void TransformState:: release_new() { nassertv(_states_lock->debug_is_locked()); - + if (_saved_entry != -1) { //nassertv(_states->find(this) == _saved_entry); _saved_entry = _states->find(this); @@ -2088,7 +2169,7 @@ release_new() { void TransformState:: remove_cache_pointers() { nassertv(_states_lock->debug_is_locked()); - + // Fortunately, since we added CompositionCache records in pairs, we // know exactly the set of TransformState objects that have us in their // cache: it's the same set of TransformState objects that we have in @@ -2150,11 +2231,11 @@ remove_cache_pointers() { if (oi != -1) { // Hold a copy of the other composition result, too. Composition ocomp = other->_composition_cache.get_data(oi); - + other->_composition_cache.remove_element(oi); _cache_stats.add_total_size(-1); _cache_stats.inc_dels(); - + // It's finally safe to let our held pointers go away. This may // have cascading effects as other TransformState objects are // destructed, but there will be no harm done if they destruct @@ -2213,7 +2294,7 @@ do_calc_hash() { PStatTimer timer(_transform_hash_pcollector); _hash = 0; - static const int significant_flags = + static const int significant_flags = (F_is_invalid | F_is_identity | F_components_given | F_hpr_given | F_is_2d); int flags = (_flags & significant_flags); @@ -2222,7 +2303,7 @@ do_calc_hash() { if ((_flags & (F_is_invalid | F_is_identity)) == 0) { // Only bother to put the rest of the stuff in the hash if the // transform is not invalid or empty. - + if ((_flags & F_components_given) != 0) { // If the transform was specified componentwise, hash it // componentwise. @@ -2239,7 +2320,7 @@ do_calc_hash() { } else { // Otherwise, hash the matrix . . . - if (uniquify_matrix) { + if (_uniquify_matrix) { // . . . but only if the user thinks that's worthwhile. if ((_flags & F_mat_known) == 0) { // Calculate the matrix without doubly-locking. @@ -2556,7 +2637,7 @@ change_this(TypedWritableReferenceCount *old_ptr, BamReader *manager) { // First, uniquify the pointer. TransformState *state = DCAST(TransformState, old_ptr); CPT(TransformState) pointer = return_unique(state); - + // We have to cast the pointer back to non-const, because the bam // reader expects that. return (TransformState *)pointer.p(); diff --git a/panda/src/pgraph/transformState.h b/panda/src/pgraph/transformState.h index e6e3223cb9..69b1a9f326 100644 --- a/panda/src/pgraph/transformState.h +++ b/panda/src/pgraph/transformState.h @@ -72,9 +72,10 @@ public: ALLOC_DELETED_CHAIN(TransformState); PUBLISHED: - INLINE bool operator < (const TransformState &other) const; + INLINE bool operator != (const TransformState &other) const; INLINE int compare_to(const TransformState &other) const; int compare_to(const TransformState &other, bool uniquify_matrix) const; + bool operator == (const TransformState &other) const; INLINE size_t get_hash() const; static CPT(TransformState) make_identity(); @@ -88,17 +89,17 @@ PUBLISHED: INLINE static CPT(TransformState) make_scale(const LVecBase3 &scale); INLINE static CPT(TransformState) make_shear(const LVecBase3 &shear); INLINE static CPT(TransformState) make_pos_hpr_scale(const LVecBase3 &pos, - const LVecBase3 &hpr, + const LVecBase3 &hpr, const LVecBase3 &scale); INLINE static CPT(TransformState) make_pos_quat_scale(const LVecBase3 &pos, - const LQuaternion &quat, + const LQuaternion &quat, const LVecBase3 &scale); static CPT(TransformState) make_pos_hpr_scale_shear(const LVecBase3 &pos, - const LVecBase3 &hpr, + const LVecBase3 &hpr, const LVecBase3 &scale, const LVecBase3 &shear); static CPT(TransformState) make_pos_quat_scale_shear(const LVecBase3 &pos, - const LQuaternion &quat, + const LQuaternion &quat, const LVecBase3 &scale, const LVecBase3 &shear); static CPT(TransformState) make_mat(const LMatrix4 &mat); @@ -112,7 +113,7 @@ PUBLISHED: INLINE static CPT(TransformState) make_scale2d(const LVecBase2 &scale); INLINE static CPT(TransformState) make_shear2d(PN_stdfloat shear); INLINE static CPT(TransformState) make_pos_rotate_scale2d(const LVecBase2 &pos, - PN_stdfloat rotate, + PN_stdfloat rotate, const LVecBase2 &scale); static CPT(TransformState) make_pos_rotate_scale_shear2d(const LVecBase2 &pos, PN_stdfloat rotate, @@ -257,7 +258,7 @@ private: static LightReMutex *_states_lock; class Empty { }; - typedef SimpleHashMap > States; + typedef SimpleHashMap > States; static States *_states; static CPT(TransformState) _identity_state; static CPT(TransformState) _invalid_state; @@ -272,7 +273,7 @@ private: // remove the entry if *either* of the input TransformStates destructs. // To implement this, we always record Composition entries in pairs, // one in each of the two involved TransformState objects. - + // The first element of the map is the object we compose with. This // is not reference counted within this map; instead we store a // companion pointer in the other object, and remove the references @@ -299,6 +300,8 @@ private: // collection cycle. static int _garbage_index; + static bool _uniquify_matrix; + static PStatCollector _cache_update_pcollector; static PStatCollector _garbage_collect_pcollector; static PStatCollector _transform_compose_pcollector; @@ -369,7 +372,7 @@ private: LMatrix4 _mat; LMatrix4 *_inv_mat; size_t _hash; - + unsigned int _flags; // This mutex protects _flags, and all of the above computed values. @@ -385,7 +388,7 @@ public: protected: static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); - + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/pgui/pgItem.cxx b/panda/src/pgui/pgItem.cxx index 8c356618c1..e8832e72fa 100644 --- a/panda/src/pgui/pgItem.cxx +++ b/panda/src/pgui/pgItem.cxx @@ -209,7 +209,7 @@ draw_mask_changed() { bool PGItem:: cull_callback(CullTraverser *trav, CullTraverserData &data) { LightReMutexHolder holder(_lock); - bool this_node_hidden = data.is_this_node_hidden(trav); + bool this_node_hidden = data.is_this_node_hidden(trav->get_camera_mask()); if (!this_node_hidden && has_frame() && get_active()) { // The item has a frame, so we want to generate a region for it // and update the MouseWatcher. diff --git a/panda/src/pgui/pgSliderBar.cxx b/panda/src/pgui/pgSliderBar.cxx index a6ef1e9963..53fed5253b 100755 --- a/panda/src/pgui/pgSliderBar.cxx +++ b/panda/src/pgui/pgSliderBar.cxx @@ -717,7 +717,7 @@ reposition() { _needs_reposition = false; PN_stdfloat t = get_ratio(); - + if (_thumb_button != (PGButton *)NULL) { LPoint3 pos = (t * _range_x) * _axis + _thumb_start; CPT(TransformState) transform = TransformState::make_pos(pos); @@ -727,7 +727,7 @@ reposition() { // we'll get caught in an update loop. if (transform == orig_transform) { // No change. - } else if (*transform < *orig_transform || *orig_transform < *transform) { + } else if (*transform != *orig_transform) { _thumb_button->set_transform(transform); } } diff --git a/panda/src/pstatclient/pStatClient.cxx b/panda/src/pstatclient/pStatClient.cxx index fa526afd69..0cd70c5d96 100644 --- a/panda/src/pstatclient/pStatClient.cxx +++ b/panda/src/pstatclient/pStatClient.cxx @@ -720,6 +720,10 @@ is_started(int collector_index, int thread_index) const { //////////////////////////////////////////////////////////////////// void PStatClient:: start(int collector_index, int thread_index) { + if (!client_is_connected()) { + return; + } + #ifdef _DEBUG nassertv(collector_index >= 0 && collector_index < AtomicAdjust::get(_num_collectors)); nassertv(thread_index >= 0 && thread_index < AtomicAdjust::get(_num_threads)); @@ -728,7 +732,7 @@ start(int collector_index, int thread_index) { Collector *collector = get_collector_ptr(collector_index); InternalThread *thread = get_thread_ptr(thread_index); - if (client_is_connected() && collector->is_active() && thread->_is_active) { + if (collector->is_active() && thread->_is_active) { LightMutexHolder holder(thread->_thread_lock); if (collector->_per_thread[thread_index]._nested_count == 0) { // This collector wasn't already started in this thread; record @@ -750,6 +754,10 @@ start(int collector_index, int thread_index) { //////////////////////////////////////////////////////////////////// void PStatClient:: start(int collector_index, int thread_index, double as_of) { + if (!client_is_connected()) { + return; + } + #ifdef _DEBUG nassertv(collector_index >= 0 && collector_index < AtomicAdjust::get(_num_collectors)); nassertv(thread_index >= 0 && thread_index < AtomicAdjust::get(_num_threads)); @@ -758,7 +766,7 @@ start(int collector_index, int thread_index, double as_of) { Collector *collector = get_collector_ptr(collector_index); InternalThread *thread = get_thread_ptr(thread_index); - if (client_is_connected() && collector->is_active() && thread->_is_active) { + if (collector->is_active() && thread->_is_active) { LightMutexHolder holder(thread->_thread_lock); if (collector->_per_thread[thread_index]._nested_count == 0) { // This collector wasn't already started in this thread; record @@ -780,6 +788,10 @@ start(int collector_index, int thread_index, double as_of) { //////////////////////////////////////////////////////////////////// void PStatClient:: stop(int collector_index, int thread_index) { + if (!client_is_connected()) { + return; + } + #ifdef _DEBUG nassertv(collector_index >= 0 && collector_index < AtomicAdjust::get(_num_collectors)); nassertv(thread_index >= 0 && thread_index < AtomicAdjust::get(_num_threads)); @@ -788,7 +800,7 @@ stop(int collector_index, int thread_index) { Collector *collector = get_collector_ptr(collector_index); InternalThread *thread = get_thread_ptr(thread_index); - if (client_is_connected() && collector->is_active() && thread->_is_active) { + if (collector->is_active() && thread->_is_active) { LightMutexHolder holder(thread->_thread_lock); if (collector->_per_thread[thread_index]._nested_count == 0) { if (pstats_cat.is_debug()) { @@ -821,6 +833,10 @@ stop(int collector_index, int thread_index) { //////////////////////////////////////////////////////////////////// void PStatClient:: stop(int collector_index, int thread_index, double as_of) { + if (!client_is_connected()) { + return; + } + #ifdef _DEBUG nassertv(collector_index >= 0 && collector_index < AtomicAdjust::get(_num_collectors)); nassertv(thread_index >= 0 && thread_index < AtomicAdjust::get(_num_threads)); @@ -829,7 +845,7 @@ stop(int collector_index, int thread_index, double as_of) { Collector *collector = get_collector_ptr(collector_index); InternalThread *thread = get_thread_ptr(thread_index); - if (client_is_connected() && collector->is_active() && thread->_is_active) { + if (collector->is_active() && thread->_is_active) { LightMutexHolder holder(thread->_thread_lock); if (collector->_per_thread[thread_index]._nested_count == 0) { if (pstats_cat.is_debug()) { diff --git a/panda/src/putil/copyOnWritePointer.I b/panda/src/putil/copyOnWritePointer.I index d36558fbbd..d9c81d9de5 100644 --- a/panda/src/putil/copyOnWritePointer.I +++ b/panda/src/putil/copyOnWritePointer.I @@ -81,6 +81,37 @@ INLINE CopyOnWritePointer:: } } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: CopyOnWritePointer::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE CopyOnWritePointer:: +CopyOnWritePointer(CopyOnWritePointer &&move) NOEXCEPT : + _cow_object(move._cow_object) +{ + // Steal the other's reference count. + move._cow_object = (CopyOnWriteObject *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: CopyOnWritePointer::Move Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void CopyOnWritePointer:: +operator = (CopyOnWritePointer &&move) NOEXCEPT { + CopyOnWriteObject *old_object = _cow_object; + _cow_object = move._cow_object; + move._cow_object = NULL; + + if (old_object != (CopyOnWriteObject *)NULL) { + cache_unref_delete(old_object); + } +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: CopyOnWritePointer::operator == // Access: Public @@ -272,6 +303,35 @@ operator = (To *object) { } #endif // CPPPARSER +#ifdef USE_MOVE_SEMANTICS +#ifndef CPPPARSER +//////////////////////////////////////////////////////////////////// +// Function: CopyOnWritePointerTo::Move Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE CopyOnWritePointerTo:: +CopyOnWritePointerTo(CopyOnWritePointerTo &&move) NOEXCEPT : + CopyOnWritePointer((CopyOnWritePointer &&)move) +{ +} +#endif // CPPPARSER + +#ifndef CPPPARSER +//////////////////////////////////////////////////////////////////// +// Function: CopyOnWritePointerTo::Move Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE void CopyOnWritePointerTo:: +operator = (CopyOnWritePointerTo &&move) NOEXCEPT { + CopyOnWritePointer::operator = ((CopyOnWritePointer &&)move); +} +#endif // CPPPARSER +#endif // USE_MOVE_SEMANTICS + #ifndef CPPPARSER #ifdef COW_THREADED //////////////////////////////////////////////////////////////////// diff --git a/panda/src/putil/copyOnWritePointer.h b/panda/src/putil/copyOnWritePointer.h index eb985250a3..20e2f42f50 100644 --- a/panda/src/putil/copyOnWritePointer.h +++ b/panda/src/putil/copyOnWritePointer.h @@ -40,6 +40,11 @@ public: INLINE void operator = (CopyOnWriteObject *object); INLINE ~CopyOnWritePointer(); +#ifdef USE_MOVE_SEMANTICS + INLINE CopyOnWritePointer(CopyOnWritePointer &&move) NOEXCEPT; + INLINE void operator = (CopyOnWritePointer &&move) NOEXCEPT; +#endif + INLINE bool operator == (const CopyOnWritePointer &other) const; INLINE bool operator != (const CopyOnWritePointer &other) const; INLINE bool operator < (const CopyOnWritePointer &other) const; @@ -83,6 +88,11 @@ public: INLINE void operator = (const CopyOnWritePointerTo ©); INLINE void operator = (To *object); +#ifdef USE_MOVE_SEMANTICS + INLINE CopyOnWritePointerTo(CopyOnWritePointerTo &&move) NOEXCEPT; + INLINE void operator = (CopyOnWritePointerTo &&move) NOEXCEPT; +#endif + #ifdef COW_THREADED INLINE CPT(To) get_read_pointer() const; INLINE PT(To) get_write_pointer(); diff --git a/panda/src/putil/simpleHashMap.I b/panda/src/putil/simpleHashMap.I index 8670600a7b..d605d22235 100644 --- a/panda/src/putil/simpleHashMap.I +++ b/panda/src/putil/simpleHashMap.I @@ -16,7 +16,7 @@ //////////////////////////////////////////////////////////////////// // Function: SimpleHashMap::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// template INLINE SimpleHashMap:: @@ -32,7 +32,7 @@ SimpleHashMap(const Compare &comp) : //////////////////////////////////////////////////////////////////// // Function: SimpleHashMap::Destructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// template INLINE SimpleHashMap:: @@ -417,7 +417,7 @@ is_empty() const { //////////////////////////////////////////////////////////////////// // Function: SimpleHashMap::output // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// template void SimpleHashMap:: @@ -443,7 +443,7 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// // Function: SimpleHashMap::write // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// template void SimpleHashMap:: @@ -575,9 +575,9 @@ void SimpleHashMap:: new_table() { nassertv(_table_size == 0 && _num_entries == 0); - // Pick a good initial table size. For now, we make it as small as - // possible. Maybe that's the right answer. - _table_size = 2; + // Pick a good initial table size. For now, we make it really + // small. Maybe that's the right answer. + _table_size = 4; // We allocate enough bytes for _table_size elements of TableEntry, // plus _table_size more bytes at the end (for the exists array). @@ -618,7 +618,9 @@ expand_table() { SimpleHashMap old_map(_comp); swap(old_map); - _table_size = (old_map._table_size << 1); + // Double the table size. + size_t old_table_size = old_map._table_size; + _table_size = (old_table_size << 1); nassertv(_table == NULL); // We allocate enough bytes for _table_size elements of TableEntry, @@ -626,15 +628,30 @@ expand_table() { size_t alloc_size = _table_size * sizeof(TableEntry) + _table_size; _deleted_chain = memory_hook->get_deleted_chain(alloc_size); _table = (TableEntry *)_deleted_chain->allocate(alloc_size, TypeHandle::none()); - memset(get_exists_array(), 0, _table_size); + unsigned char *exists_array = get_exists_array(); + memset(exists_array, 0, _table_size); nassertv(_num_entries == 0); // Now copy the entries from the old table into the new table. int num_added = 0; - for (size_t i = 0; i < old_map._table_size; ++i) { + for (size_t i = 0; i < old_table_size; ++i) { if (old_map.has_element(i)) { - store(old_map._table[i]._key, old_map._table[i]._data); - ++num_added; + size_t new_index = get_hash(old_map._table[i]._key); + + while (exists_array[new_index] != 0) { + // Hash conflict; look for a better spot. This has to succeed. + new_index = (new_index + 1) & (_table_size - 1); + } + +#ifdef USE_MOVE_SEMANTICS + // Use C++11 rvalue references to invoke the move constructor, + // which may be more efficient. + new(&_table[new_index]) TableEntry(move(old_map._table[i])); +#else + new(&_table[new_index]) TableEntry(old_map._table[i]); +#endif + exists_array[new_index] = true; + ++_num_entries; } } diff --git a/panda/src/putil/simpleHashMap.h b/panda/src/putil/simpleHashMap.h index 9f72450ee5..b9b690ffc7 100644 --- a/panda/src/putil/simpleHashMap.h +++ b/panda/src/putil/simpleHashMap.h @@ -79,6 +79,14 @@ private: INLINE TableEntry(const Key &key, const Value &data) : _key(key), _data(data) {} + INLINE TableEntry(const TableEntry ©) : + _key(copy._key), + _data(copy._data) {} +#ifdef USE_MOVE_SEMANTICS + INLINE TableEntry(TableEntry &&from) NOEXCEPT : + _key(move(from._key)), + _data(move(from._data)) {} +#endif Key _key; Value _data; }; @@ -103,4 +111,3 @@ inline ostream &operator << (ostream &out, const SimpleHashMap