diff --git a/CMakeLists.txt b/CMakeLists.txt
index 99e8c3ab9..29ac80778 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -158,7 +158,7 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR
 endif()
 
 if (ENABLE_VR_DEFAULT)
-    find_package(osgXR 0.3.3 QUIET)
+    find_package(osgXR 0.3.9 QUIET)
     if (osgXR_FOUND)
         set(SYSTEM_OSGXR_DEFAULT 1)
     endif()
diff --git a/src/Viewer/splash.cxx b/src/Viewer/splash.cxx
index 6a874559d..8fec18368 100644
--- a/src/Viewer/splash.cxx
+++ b/src/Viewer/splash.cxx
@@ -57,6 +57,7 @@
 #include <Main/util.hxx>
 #include "splash.hxx"
 #include "renderer.hxx"
+#include "VRManager.hxx"
 
 #include <sstream>
 
@@ -79,6 +80,19 @@ public:
 SplashScreen::SplashScreen() :
     _splashAlphaNode(fgGetNode("/sim/startup/splash-alpha", true))
 {
+#ifdef ENABLE_OSGXR
+    uint32_t splashW = 1920, splashH = 1080;
+    float aspect = (float)splashW / splashH;
+    _splashSwapchain = new osgXR::Swapchain(splashW, splashH);
+    _splashSwapchain->setAlphaBits(8);
+    _splashSwapchain->allowRGBEncoding(osgXR::Swapchain::Encoding::ENCODING_SRGB);
+    _splashLayer = new osgXR::CompositionLayerQuad(flightgear::VRManager::instance());
+    _splashLayer->setSubImage(_splashSwapchain);
+    _splashLayer->setSize(osg::Vec2f(aspect, 1.0f));
+    _splashLayer->setPosition(osg::Vec3f(0, 0, -2.0f));
+    _splashLayer->setAlphaMode(osgXR::CompositionLayer::BLEND_ALPHA_UNPREMULT);
+#endif
+
     setName("splashGroup");
     setUpdateCallback(new SplashScreenUpdateCallback);
 }
@@ -91,7 +105,7 @@ void SplashScreen::createNodes()
 {
     // setup the base geometry 
     _splashFBOTexture = new osg::Texture2D;
-    _splashFBOTexture->setInternalFormat(GL_RGB);
+    _splashFBOTexture->setInternalFormat(GL_SRGB8);
     _splashFBOTexture->setResizeNonPowerOfTwoHint(false);
     _splashFBOTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
     _splashFBOTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
@@ -226,6 +240,7 @@ void SplashScreen::createNodes()
     stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
     stateSet->setRenderBinDetails(1000, "RenderBin");
     stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
+    stateSet->setMode(GL_FRAMEBUFFER_SRGB, osg::StateAttribute::ON);
     
     geometry = osg::createTexturedQuadGeometry(osg::Vec3(0.0, 0.0, 0.0),
                                                osg::Vec3(1.0, 0.0, 0.0),
@@ -244,6 +259,9 @@ void SplashScreen::createNodes()
     geode = new osg::Geode;
     geode->addDrawable(geometry);
 
+#ifdef ENABLE_OSGXR
+    _splashSwapchain->attachToMirror(stateSet);
+#endif
     _splashQuadCamera->addChild(geode);
     addChild(_splashQuadCamera);
 }
@@ -325,6 +343,9 @@ osg::ref_ptr<osg::Camera> SplashScreen::createFBOCamera()
     c->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
     c->setRenderOrder(osg::Camera::PRE_RENDER);
     c->attach(osg::Camera::COLOR_BUFFER, _splashFBOTexture);
+#ifdef ENABLE_OSGXR
+    _splashSwapchain->attachToCamera(c);
+#endif
 
     osg::StateSet* stateSet = c->getOrCreateStateSet();
     stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF);
@@ -570,11 +591,18 @@ void SplashScreen::doUpdate()
         removeChild(0, getNumChildren());
         _splashFBOCamera = nullptr;
         _splashQuadCamera = nullptr;
+#ifdef ENABLE_OSGXR
+        _splashLayer->setVisible(false);
+#endif
     } else if (getNumChildren() == 0) {
         createNodes();
         _splashStartTime.stamp();
         resize(fgGetInt("/sim/startup/xsize"),
                fgGetInt("/sim/startup/ysize"));
+#ifdef ENABLE_OSGXR
+        _splashLayer->setVisible(true);
+        _splashSwapchain->setForcedAlpha(alpha);
+#endif
     } else {
         (*_splashFSQuadColor)[0] = osg::Vec4(1.0, 1.0, 1.0, _splashAlphaNode->getFloatValue());
         _splashFSQuadColor->dirty();
@@ -603,6 +631,9 @@ void SplashScreen::doUpdate()
         }
         updateSplashSpinner();
         updateTipText();
+#ifdef ENABLE_OSGXR
+        _splashSwapchain->setForcedAlpha(alpha);
+#endif
     }
 }
 
@@ -686,6 +717,11 @@ void SplashScreen::resize( int width, int height )
     _splashFBOCamera->setViewport(0, 0, width, height);
     _splashFBOCamera->setProjectionMatrixAsOrtho2D(-width * 0.5, width * 0.5,
                                                    -height * 0.5, height * 0.5);
+#ifdef ENABLE_OSGXR
+    float aspect = (float)width / height;
+    _splashSwapchain->setSize(width, height);
+    _splashLayer->setSize(osg::Vec2f(aspect, 1.0f));
+#endif
 
     const double screenAspectRatio = static_cast<double>(width) / height;
  
diff --git a/src/Viewer/splash.hxx b/src/Viewer/splash.hxx
index 9350c8225..5b50059a4 100644
--- a/src/Viewer/splash.hxx
+++ b/src/Viewer/splash.hxx
@@ -25,9 +25,16 @@
 #ifndef _SPLASH_HXX
 #define _SPLASH_HXX
 
+#include <config.h>
+
 #include <osg/Group>
 #include <osgText/Text>
 
+#ifdef ENABLE_OSGXR
+#include <osgXR/CompositionLayerQuad>
+#include <osgXR/Swapchain>
+#endif
+
 #include <simgear/props/props.hxx>
 #include <simgear/timing/timestamp.hxx>
 
@@ -117,6 +124,13 @@ private:
     osg::ref_ptr<osg::Camera> _splashQuadCamera;
 
      std::vector<ImageItem> _imageItems;
+
+#ifdef ENABLE_OSGXR
+    // Splash as OpenXR composition layer
+    osg::ref_ptr<osgXR::Swapchain> _splashSwapchain;
+    osg::ref_ptr<osgXR::CompositionLayerQuad> _splashLayer;
+#endif
+
     std::vector<TextItem> _items;
     
     SGTimeStamp _splashStartTime;