diff --git a/src/eepp/ui/uilistbox.cpp b/src/eepp/ui/uilistbox.cpp index 785aadc5c..0d76e0e6f 100644 --- a/src/eepp/ui/uilistbox.cpp +++ b/src/eepp/ui/uilistbox.cpp @@ -271,7 +271,7 @@ void UIListBox::setRowHeight() { fontSize = fontStyleConfig.getFont()->getFontHeight( fontStyleConfig.getFontCharacterSize() ); - mRowHeight = PixelDensity::pxToDp( fontSize ) + PixelDensity::dpToPx( 4 ); + mRowHeight = PixelDensity::pxToDp( fontSize ) + 4; } if ( tOldRowHeight != mRowHeight ) { diff --git a/src/eepp/ui/uiloader.cpp b/src/eepp/ui/uiloader.cpp index 7a2bc875a..b2c86aa44 100644 --- a/src/eepp/ui/uiloader.cpp +++ b/src/eepp/ui/uiloader.cpp @@ -12,7 +12,7 @@ UILoader* UILoader::New() { UILoader::UILoader() : UIWidget( "loader" ), mRadius( 0 ), - mOutlineThickness( PixelDensity::dpToPx( 8 ) ), + mOutlineThickness( 8 ), mColor( Color::White ), mArcAngle( 0 ), mArcStartAngle( 0 ), diff --git a/src/eepp/ui/uiscenenode.cpp b/src/eepp/ui/uiscenenode.cpp index 3d3274f65..51308e7fb 100644 --- a/src/eepp/ui/uiscenenode.cpp +++ b/src/eepp/ui/uiscenenode.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -57,12 +58,13 @@ struct PendingAsyncResourceMainThread { enum class AsyncResourceMainThreadQueueState : Uint8 { Closed, Open, Closing }; std::mutex sAsyncResourceMainThreadMutex; -std::vector sAsyncResourceMainThreadQueue; +using AsyncResourceMainThreadQueue = SmallVector; +AsyncResourceMainThreadQueue sAsyncResourceMainThreadQueue; std::atomic sAsyncResourceMainThreadQueueState{ AsyncResourceMainThreadQueueState::Closed }; void drainAsyncResourceMainThreadQueue() { - std::vector pending; + AsyncResourceMainThreadQueue pending; { std::lock_guard lock( sAsyncResourceMainThreadMutex ); if ( sAsyncResourceMainThreadQueueState.load( std::memory_order_relaxed ) != @@ -71,7 +73,7 @@ void drainAsyncResourceMainThreadQueue() { pending.swap( sAsyncResourceMainThreadQueue ); } - std::vector delayed; + AsyncResourceMainThreadQueue delayed; for ( auto& item : pending ) { if ( !UISceneNode::isAsyncResourceLoadCurrent( item.resourceState, item.generation ) ) continue; @@ -82,8 +84,10 @@ void drainAsyncResourceMainThreadQueue() { } UISceneNode* owner = item.resourceState->owner.load( std::memory_order_acquire ); - if ( owner && item.func ) + if ( owner && item.func ) { + auto context = owner->makeCurrent(); item.func( owner ); + } } if ( !delayed.empty() ) { @@ -2323,8 +2327,10 @@ void UISceneNode::runAsyncResourceOnMainThread( if ( isAsyncResourceLoadCurrent( resourceState, generation ) && Engine::isMainThread() && delay <= Time::Zero ) { UISceneNode* owner = resourceState->owner.load( std::memory_order_acquire ); - if ( owner ) + if ( owner ) { + auto context = owner->makeCurrent(); func( owner ); + } return; } @@ -2342,7 +2348,7 @@ void UISceneNode::runAsyncResourceOnMainThread( } void UISceneNode::openAsyncResourceMainThreadQueue() { - std::vector stale; + AsyncResourceMainThreadQueue stale; { std::lock_guard lock( sAsyncResourceMainThreadMutex ); stale.swap( sAsyncResourceMainThreadQueue ); @@ -2358,7 +2364,7 @@ void UISceneNode::beginAsyncResourceMainThreadQueueShutdown() { } void UISceneNode::finishAsyncResourceMainThreadQueueShutdown() { - std::vector pending; + AsyncResourceMainThreadQueue pending; { std::lock_guard lock( sAsyncResourceMainThreadMutex ); sAsyncResourceMainThreadQueueState.store( AsyncResourceMainThreadQueueState::Closed, diff --git a/src/eepp/ui/uiviewpager.cpp b/src/eepp/ui/uiviewpager.cpp index 9911e25e0..7d69114be 100644 --- a/src/eepp/ui/uiviewpager.cpp +++ b/src/eepp/ui/uiviewpager.cpp @@ -20,7 +20,7 @@ UIViewPager::UIViewPager() : mOrientation( UIOrientation::Horizontal ), mDragging( false ), mLocked( false ), - mDragResistance( PixelDensity::dpToPx( 8 ) ), + mDragResistance( 8 ), mInitialDisplacement( 0 ), mDisplacement( 0 ), mChangePagePercent( 0.33f ), diff --git a/src/eepp/ui/uiwidget.cpp b/src/eepp/ui/uiwidget.cpp index eb795127d..c966096cd 100644 --- a/src/eepp/ui/uiwidget.cpp +++ b/src/eepp/ui/uiwidget.cpp @@ -1011,7 +1011,7 @@ UIWidget* UIWidget::setPaddingBottom( const Float& paddingBottom ) { UIWidget* UIWidget::setPaddingPixels( const Rectf& padding ) { if ( padding != mPadding ) { mPaddingPx = padding; - mPadding = PixelDensity::pxToDp( mPadding ).ceil(); + mPadding = PixelDensity::pxToDp( mPaddingPx ).ceil(); onAutoSize(); onPaddingChange(); notifyLayoutAttrChange( LayoutInvalidation::Self ); @@ -1023,7 +1023,7 @@ UIWidget* UIWidget::setPaddingPixels( const Rectf& padding ) { UIWidget* UIWidget::setPaddingPixelsLeft( const Float& paddingLeft ) { if ( paddingLeft != mPadding.Left ) { mPaddingPx.Left = paddingLeft; - mPadding.Left = eeceil( PixelDensity::pxToDp( mPadding.Left ) ); + mPadding.Left = eeceil( PixelDensity::pxToDp( mPaddingPx.Left ) ); onAutoSize(); onPaddingChange(); notifyLayoutAttrChange( LayoutInvalidation::Self ); @@ -1035,7 +1035,7 @@ UIWidget* UIWidget::setPaddingPixelsLeft( const Float& paddingLeft ) { UIWidget* UIWidget::setPaddingPixelsRight( const Float& paddingRight ) { if ( paddingRight != mPadding.Right ) { mPaddingPx.Right = paddingRight; - mPadding.Right = eeceil( PixelDensity::pxToDp( mPadding.Right ) ); + mPadding.Right = eeceil( PixelDensity::pxToDp( mPaddingPx.Right ) ); onAutoSize(); onPaddingChange(); notifyLayoutAttrChange( LayoutInvalidation::Self ); @@ -1047,7 +1047,7 @@ UIWidget* UIWidget::setPaddingPixelsRight( const Float& paddingRight ) { UIWidget* UIWidget::setPaddingPixelsTop( const Float& paddingTop ) { if ( paddingTop != mPadding.Top ) { mPaddingPx.Top = paddingTop; - mPadding.Top = eeceil( PixelDensity::pxToDp( mPadding.Top ) ); + mPadding.Top = eeceil( PixelDensity::pxToDp( mPaddingPx.Top ) ); onAutoSize(); onPaddingChange(); notifyLayoutAttrChange( LayoutInvalidation::Self ); @@ -1059,7 +1059,7 @@ UIWidget* UIWidget::setPaddingPixelsTop( const Float& paddingTop ) { UIWidget* UIWidget::setPaddingPixelsBottom( const Float& paddingBottom ) { if ( paddingBottom != mPadding.Bottom ) { mPaddingPx.Bottom = paddingBottom; - mPadding.Bottom = eeceil( PixelDensity::pxToDp( mPadding.Bottom ) ); + mPadding.Bottom = eeceil( PixelDensity::pxToDp( mPaddingPx.Bottom ) ); onAutoSize(); onPaddingChange(); notifyLayoutAttrChange( LayoutInvalidation::Self ); diff --git a/src/tests/unit_tests/uiscenenode_tests.cpp b/src/tests/unit_tests/uiscenenode_tests.cpp index e8651e2d9..d9310689b 100644 --- a/src/tests/unit_tests/uiscenenode_tests.cpp +++ b/src/tests/unit_tests/uiscenenode_tests.cpp @@ -21,6 +21,7 @@ #include #include #include +#include using namespace EE; using namespace EE::Graphics; @@ -134,6 +135,53 @@ UTEST( UISceneNode, ScopedContextBindsNodesAndRestoresNestedScene ) { eeDelete( sceneA ); } +UTEST( UISceneNode, AsyncResourceCallbacksBindOwnerSceneAndRestorePreviousScene ) { + auto* engine = Engine::instance(); + auto* window = engine->getCurrentWindow(); + if ( !window ) { + window = engine->createWindow( WindowSettings( 320, 240, "Async Resource Context Test", + WindowStyle::Default, WindowBackend::Default, + 32, {}, 1, false, true ), + ContextSettings( false, 0, 0, GLv_default, true, false ) ); + } + + auto* sceneA = UISceneNode::New( window ); + auto* sceneB = UISceneNode::New( window ); + auto* sceneManager = SceneManager::instance(); + sceneManager->add( sceneA ); + sceneManager->add( sceneB ); + sceneManager->setCurrentUISceneNode( sceneA ); + + auto state = sceneB->getAsyncResourceLoadState(); + const Uint64 generation = state->generation.load( std::memory_order_acquire ); + bool immediateBound = false; + bool queuedBound = false; + { + auto context = sceneA->makeCurrent(); + UISceneNode::runAsyncResourceOnMainThread( state, generation, [&]( UISceneNode* owner ) { + immediateBound = owner == sceneB && sceneManager->getUISceneNode() == sceneB; + } ); + EXPECT_EQ( sceneManager->getUISceneNode(), sceneA ); + + std::thread producer( [&] { + UISceneNode::runAsyncResourceOnMainThread( + state, generation, [&]( UISceneNode* owner ) { + queuedBound = owner == sceneB && sceneManager->getUISceneNode() == sceneB; + } ); + } ); + producer.join(); + sceneA->update( Time::Zero ); + EXPECT_EQ( sceneManager->getUISceneNode(), sceneA ); + } + + EXPECT_TRUE( immediateBound ); + EXPECT_TRUE( queuedBound ); + sceneManager->remove( sceneB ); + sceneManager->remove( sceneA ); + eeDelete( sceneB ); + eeDelete( sceneA ); +} + class TestUIApplication : public UIApplication { public: using UIApplication::UIApplication;