diff --git a/src/framework/AbstractGraphicsEngine.cpp b/src/framework/AbstractGraphicsEngine.cpp
index 2f56439a19afd1415d3e080001ad50337692373e..f8f8cea4e546c88d8112d3d7afcaf666de88c2cc 100644
--- a/src/framework/AbstractGraphicsEngine.cpp
+++ b/src/framework/AbstractGraphicsEngine.cpp
@@ -29,6 +29,10 @@ AbstractGraphicsEngine::~AbstractGraphicsEngine()
 {
 }
 
+void AbstractGraphicsEngine::initialize(const int width, const int height, const float scale, const Resource *font, const bool recycle) {
+	m_Scale = scale;
+}
+
 void AbstractGraphicsEngine::refreshLocalBOINCInformation()
 {
 	m_BoincAdapter.refresh();
diff --git a/src/framework/AbstractGraphicsEngine.h b/src/framework/AbstractGraphicsEngine.h
index e36ee58e5fac4ddd2b62b9e007e04ba8b7dea891..f1a1ab8950fe0e47d48df837b6345cf879dde25a 100644
--- a/src/framework/AbstractGraphicsEngine.h
+++ b/src/framework/AbstractGraphicsEngine.h
@@ -26,6 +26,8 @@
 #include "BOINCClientAdapter.h"
 #include "Resource.h"
 
+#define DESIGN_DPI 129
+
 using namespace std;
 
 /**
@@ -56,10 +58,11 @@ public:
 	 *
 	 * \param width The current width of the display surface
 	 * \param height The current height of the display surface
+	 * \param scale The scaling factor on HDPI displays
 	 * \param font A pointer to a Resource object containing TTF font faces for text rendering
 	 * \param recycle This flag indicates whether we initialize (FALSE) or reinitialize (TRUE) the context
 	 */
-	virtual void initialize(const int width, const int height, const Resource *font, const bool recycle = false) = 0;
+	virtual void initialize(const int width, const int height, const float scale, const Resource *font, const bool recycle = false);
 
 	/**
 	 * \brief This method is called when the windowing system encounters a window resize event
@@ -196,6 +199,9 @@ protected:
 
 	/// BOINC client adapter instance for information retrieval
 	BOINCClientAdapter m_BoincAdapter;
+
+	/// Window scaling factor (relative to design DPI, see above)
+	float m_Scale;
 };
 
 /**
diff --git a/src/framework/WindowManager.cpp b/src/framework/WindowManager.cpp
index 0a7bfbd968319807995a03403be135e161efa632..a30be54589195d25227ce07758d4cfc450fc57bb 100644
--- a/src/framework/WindowManager.cpp
+++ b/src/framework/WindowManager.cpp
@@ -286,7 +286,7 @@ void WindowManager::eventLoop()
 			// notify our observers (currently exactly one, hence front())
 			// (windoze needs to be reinitialized instead of just resized, oh well)
 			/// \todo Can we determine the host OS? On X11 a resize() is sufficient!
-			eventObservers.front()->initialize(m_CurrentWidth, m_CurrentHeight, 0, true);
+			eventObservers.front()->initialize(m_CurrentWidth, m_CurrentHeight, getDisplayScalingFactor(), 0, true);
 		}
 		else if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
 			m_WindowedWidth = event.window.data1;
@@ -298,7 +298,7 @@ void WindowManager::eventLoop()
 			// notify our observers (currently exactly one, hence front())
 			// (windoze needs to be reinitialized instead of just resized, oh well)
 			/// \todo Can we determine the host OS? On X11 a resize() is sufficient!
-			eventObservers.front()->initialize(m_CurrentWidth, m_CurrentHeight, 0, true);
+			eventObservers.front()->initialize(m_CurrentWidth, m_CurrentHeight, getDisplayScalingFactor(), 0, true);
 		}
 		else if (event.type == SDL_QUIT ||
 				(event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)) {
@@ -474,10 +474,32 @@ void WindowManager::toggleFullscreen()
 	// notify our observers (currently exactly one, hence front())
 	// (windoze needs to be reinitialized instead of just resized, oh well)
 	/// \todo Can we determine the host OS? On X11 a resize() is sufficient!
-	eventObservers.front()->initialize(m_CurrentWidth, m_CurrentHeight, 0, true);
+	eventObservers.front()->initialize(m_CurrentWidth, m_CurrentHeight, getDisplayScalingFactor(), 0, true);
 }
 
 void WindowManager::setScreensaverMode(const bool enabled)
 {
 	m_ScreensaverMode = enabled;
 }
+
+float WindowManager::getDisplayScalingFactor() {
+	// DPI at which the reference layout was built
+	const float defaultDPI = DESIGN_DPI;
+
+	float vDPI;
+	float hDPI;
+	float dDPI;
+
+	int displayIndex = SDL_GetWindowDisplayIndex(m_Window);
+	if(displayIndex < 0 || SDL_GetDisplayDPI(displayIndex, &dDPI, &hDPI, &vDPI) != 0)
+	{
+		// Failed to get DPI, so return no scaling
+		cerr << "Could not determine display DPI: " << SDL_GetError() << endl;
+		return 1.0;
+	}
+
+	// cout << "Display DPI (v/h/d): " << vDPI <<" / " << hDPI << " / " << dDPI << endl;
+
+	// finally, return scaling factor;
+	return hDPI / defaultDPI;
+}
diff --git a/src/framework/WindowManager.h b/src/framework/WindowManager.h
index d598dafeed6186e22b2c60d4ee37bdfc7d6f9c32..70b8814d5b1468b32a6f06d664e3dff53b333ef0 100644
--- a/src/framework/WindowManager.h
+++ b/src/framework/WindowManager.h
@@ -222,6 +222,9 @@ private:
 	 */
     static Uint32 timerCallbackBOINCUpdateEvent(Uint32 interval, void *param);
 
+    /// Returns the HDPI scaling factor for the current window
+    float getDisplayScalingFactor();
+
     /// Local BOINC adapter instance to read project preferences
     BOINCClientAdapter *m_BoincAdapter;
 
diff --git a/src/starsphere/Starsphere.cpp b/src/starsphere/Starsphere.cpp
index a7ecf9a36a12de4f28b941135dc883e33ff0cd74..79c00ea8e7a5ee3e21bbceb4109da2d94c794323 100644
--- a/src/starsphere/Starsphere.cpp
+++ b/src/starsphere/Starsphere.cpp
@@ -588,7 +588,7 @@ void Starsphere::resize(const int width, const int height)
 	aspect = (float)width / (float)height;
 
 	// adjust HUD config
-	m_YStartPosTop = height - 25;
+	m_YStartPosTop = height - 65;
 
 	// make sure the search marker is updated (conditional rendering!)
 	m_RefreshSearchMarker = true;
@@ -604,8 +604,10 @@ void Starsphere::resize(const int width, const int height)
 /**
  *  What to do when graphics are "initialized".
  */
-void Starsphere::initialize(const int width, const int height, const Resource *font, const bool recycle)
+void Starsphere::initialize(const int width, const int height, const float scale, const Resource *font, const bool recycle)
 {
+	AbstractGraphicsEngine::initialize(width, height, scale, font, recycle);
+
 	// check whether we initialize the first time or have to recycle (required for windoze)
 	if(!recycle) {
 
@@ -616,8 +618,8 @@ void Starsphere::initialize(const int width, const int height, const Resource *f
 		m_BoincAdapter.initialize();
 
 		// inital HUD offset setup
-		m_XStartPosLeft = 5;
-		m_YOffsetLarge = 18;
+		m_XStartPosLeft = 20 * m_Scale;
+		m_YOffsetLarge = 35 * m_Scale;
 
 		setFeature(STARS, true);
 		setFeature(CONSTELLATIONS, true);
@@ -652,7 +654,7 @@ void Starsphere::initialize(const int width, const int height, const Resource *f
 		m_FontHeader = new OGLFT::TranslucentTexture(
 									&m_FontResource->data()->at(0),
 									m_FontResource->data()->size(),
-									13, 78 );
+									20, uint(DESIGN_DPI) );
 
 		if ( m_FontHeader == 0 || !m_FontHeader->isValid() ) {
 		     cerr << "Could not construct header font face from in memory resource!" << endl;
@@ -665,7 +667,7 @@ void Starsphere::initialize(const int width, const int height, const Resource *f
 		m_FontText = new OGLFT::TranslucentTexture(
 									&m_FontResource->data()->at(0),
 									m_FontResource->data()->size(),
-									11, 72 );
+									16, uint(DESIGN_DPI) );
 
 		if ( m_FontText == 0 || !m_FontText->isValid() ) {
 		     cerr << "Could not construct text font face from in memory resource!" << endl;
diff --git a/src/starsphere/Starsphere.h b/src/starsphere/Starsphere.h
index 7e736253ee1a31ef0a51cdd37c7987ad21940b96..ba8a2da72404f04501994cf22ed99a8f0945a2b9 100644
--- a/src/starsphere/Starsphere.h
+++ b/src/starsphere/Starsphere.h
@@ -96,10 +96,11 @@ public:
 	 *
 	 * \param width The current width of the display surface
 	 * \param height The current height of the display surface
+	 * \param scale The scaling factor on HDPI displays
 	 * \param font A pointer to a Resource object containing TTF font faces for text rendering
 	 * \param recycle This flag indicates whether we initialize (FALSE) or reinitialize (TRUE) the context
 	 */
-	virtual void initialize(const int width, const int height, const Resource *font, const bool recycle = false);
+	virtual void initialize(const int width, const int height, const float scale, const Resource *font, const bool recycle = false);
 
 	/**
 	 * \brief This method is called when the windowing system encounters a window resize event
diff --git a/src/starsphere/StarsphereRadio.cpp b/src/starsphere/StarsphereRadio.cpp
index 6afb58b41917fd7e1be2f7866a41d871bb4d5d01..17e265f548aedef6a774a04a5c32a56f6568a4be 100644
--- a/src/starsphere/StarsphereRadio.cpp
+++ b/src/starsphere/StarsphereRadio.cpp
@@ -34,9 +34,9 @@ StarsphereRadio::~StarsphereRadio()
 {
 }
 
-void StarsphereRadio::initialize(const int width, const int height, const Resource *font, const bool recycle)
+void StarsphereRadio::initialize(const int width, const int height, const float scale, const Resource *font, const bool recycle)
 {
-	Starsphere::initialize(width, height, font, recycle);
+	Starsphere::initialize(width, height, scale, font, recycle);
 
 	// store quality setting
 	m_QualitySetting = m_BoincAdapter.graphicsQualitySetting();
@@ -45,10 +45,10 @@ void StarsphereRadio::initialize(const int width, const int height, const Resour
 	if(!recycle) {
 
 		// adjust HUD config
-		m_YOffsetMedium = 15.0;
-		m_XStartPosRightWidthOffset = 125.0;
+		m_YOffsetMedium = 34.0 * m_Scale;
+		m_XStartPosRightWidthOffset = 325.0 * m_Scale;
 		m_XStartPosRight = width - m_XStartPosRightWidthOffset;
-		m_YStartPosBottom = 100.0;
+		m_YStartPosBottom = 225.0 * m_Scale;
 		m_Y1StartPosBottom = m_YStartPosBottom  - m_YOffsetMedium;
 		m_Y2StartPosBottom = m_Y1StartPosBottom - m_YOffsetMedium;
 		m_Y3StartPosBottom = m_Y2StartPosBottom - m_YOffsetMedium;
@@ -57,17 +57,17 @@ void StarsphereRadio::initialize(const int width, const int height, const Resour
 		m_Y6StartPosBottom = m_Y5StartPosBottom - m_YOffsetMedium;
 
 		// adjust Power Spectrum config
-		m_PowerSpectrumWidth = 200.0;
-		m_PowerSpectrumHeight = 50.0;
-		m_PowerSpectrumOriginWidthOffset = 210.0;
-		m_PowerSpectrumOriginHeightOffset = 60.0;
+		m_PowerSpectrumWidth = 410.0 * m_Scale;
+		m_PowerSpectrumHeight = 80.0 * m_Scale;
+		m_PowerSpectrumOriginWidthOffset = 430.0 * m_Scale;
+		m_PowerSpectrumOriginHeightOffset = 95.0 * m_Scale;
 		m_PowerSpectrumXPos = width - m_PowerSpectrumOriginWidthOffset;
 		m_PowerSpectrumYPos = height - m_PowerSpectrumOriginHeightOffset;
-		m_PowerSpectrumAxesWidth = 2.0;
-		m_PowerSpectrumBinWidth = 3.0;
-		m_PowerSpectrumBinDistance = 2.0;
-		m_PowerSpectrumLabelXOffset = (m_PowerSpectrumWidth - 150.0) / 2;
-		m_PowerSpectrumLabelYOffset = 15.0;
+		m_PowerSpectrumAxesWidth = 2.0 * m_Scale;
+		m_PowerSpectrumBinWidth = 6.2 * m_Scale;
+		m_PowerSpectrumBinDistance = 4.0 * m_Scale;
+		m_PowerSpectrumLabelXOffset = (m_PowerSpectrumWidth - 290.0 * m_Scale) / 2;
+		m_PowerSpectrumLabelYOffset = 30.0 * m_Scale;
 		m_PowerSpectrumLabelXPos = m_PowerSpectrumXPos + m_PowerSpectrumLabelXOffset;
 		m_PowerSpectrumLabelYPos = m_PowerSpectrumYPos - m_PowerSpectrumLabelYOffset;
 	}
@@ -76,7 +76,7 @@ void StarsphereRadio::initialize(const int width, const int height, const Resour
 	m_FontLogo1 = new OGLFT::TranslucentTexture(
 								&m_FontResource->data()->at(0),
 								m_FontResource->data()->size(),
-								26, 78 );
+								36, uint(DESIGN_DPI) );
 
 	if ( m_FontLogo1 == 0 || !m_FontLogo1->isValid() ) {
 	     cerr << "Could not construct logo1 font face from in memory resource!" << endl;
@@ -89,7 +89,7 @@ void StarsphereRadio::initialize(const int width, const int height, const Resour
 	m_FontLogo2 = new OGLFT::TranslucentTexture(
 								&m_FontResource->data()->at(0),
 								m_FontResource->data()->size(),
-								12, 72 );
+								15.5, uint(DESIGN_DPI) );
 
 	if ( m_FontLogo2 == 0 || !m_FontLogo2->isValid() ) {
 	     cerr << "Could not construct logo2 font face from in memory resource!" << endl;
@@ -227,7 +227,7 @@ void StarsphereRadio::renderSearchInformation()
 	m_FontText->draw(m_XStartPosRight, m_Y6StartPosBottom, m_WUTemplateOrbitalPhase.c_str());
 
 	// power spectrum label
-	m_FontText->draw(m_PowerSpectrumLabelXPos, m_PowerSpectrumLabelYPos, "Radio Signal Power Spectrum");
+	m_FontLogo2->draw(m_PowerSpectrumLabelXPos, m_PowerSpectrumLabelYPos, "Radio Power Spectrum");
 
 	// disable opt-in quality feature for power spectrum
 	if(m_QualitySetting == BOINCClientAdapter::HighGraphicsQualitySetting) {
@@ -288,7 +288,7 @@ void StarsphereRadio::generatePowerSpectrumBins(const int originX, const int ori
 {
 	GLfloat offsetX = (GLfloat)originX;
 	GLfloat offsetY = (GLfloat)originY;
-	GLfloat axesXOffset = m_PowerSpectrumAxesWidth + 2;
+	GLfloat axesXOffset = m_PowerSpectrumBinWidth + m_PowerSpectrumBinDistance / 2.0;
 	GLfloat axesYOffset = m_PowerSpectrumAxesWidth / 2.0 + 1;
 	GLfloat binXOffset = m_PowerSpectrumBinWidth + m_PowerSpectrumBinDistance;
 
diff --git a/src/starsphere/StarsphereRadio.h b/src/starsphere/StarsphereRadio.h
index 7a8b5d36c9ba154685ab19740b55d18713bb966c..b41397dc5155220da68e581e2984b80248f01819 100644
--- a/src/starsphere/StarsphereRadio.h
+++ b/src/starsphere/StarsphereRadio.h
@@ -71,10 +71,11 @@ public:
 	 *
 	 * \param width The current width of the display surface
 	 * \param height The current height of the display surface
+	 * \param scale The scaling factor on HDPI displays
 	 * \param font A pointer to a Resource object containing TTF font faces for text rendering
 	 * \param recycle This flag indicates whether we initialize (FALSE) or reinitialize (TRUE) the context
 	 */
-	virtual void initialize(const int width, const int height, const Resource *font, const bool recycle = false);
+	virtual void initialize(const int width, const int height, const float scale, const Resource *font, const bool recycle = false);
 
 	/**
 	 * \brief This method is called when the windowing system encounters a window resize event
diff --git a/src/starsphere/StarsphereS5R3.cpp b/src/starsphere/StarsphereS5R3.cpp
index e93e332be2df955d891c450a7726b5d4a0af6a43..cbee93ad1b2701769894d2000b1e656eaaa5ad54 100644
--- a/src/starsphere/StarsphereS5R3.cpp
+++ b/src/starsphere/StarsphereS5R3.cpp
@@ -33,29 +33,32 @@ StarsphereS5R3::~StarsphereS5R3()
 {
 }
 
-void StarsphereS5R3::initialize(const int width, const int height, const Resource *font, const bool recycle)
+void StarsphereS5R3::initialize(const int width, const int height, const float scale, const Resource *font, const bool recycle)
 {
-	Starsphere::initialize(width, height, font, recycle);
+	Starsphere::initialize(width, height, scale, font, recycle);
 
 	// check whether we initialize the first time or have to recycle (required for windoze)
 	if(!recycle) {
 
 		// adjust HUD config
-		m_YOffsetMedium = 15;
-		m_XStartPosRight = width - 125;
-		m_XStartPosClock = width - 98;
-		m_YStartPosBottom = 70;
+		m_YOffsetMedium = 34.0 * m_Scale;
+		m_XStartPosRightWidthOffset = 325 * m_Scale;
+		m_XStartPosRight = width - m_XStartPosRightWidthOffset;
+		m_XStartPosClockWidthOffset = 270 * m_Scale;
+		m_XStartPosClock = width - m_XStartPosClockWidthOffset;
+		m_YStartPosBottom = 160 * m_Scale;
 		m_Y1StartPosBottom = m_YStartPosBottom  - m_YOffsetMedium;
 		m_Y2StartPosBottom = m_Y1StartPosBottom - m_YOffsetMedium;
 		m_Y3StartPosBottom = m_Y2StartPosBottom - m_YOffsetMedium;
 		m_Y4StartPosBottom = m_Y3StartPosBottom - m_YOffsetMedium;
+		m_Logo2XOffset = 60;
 	}
 
 	// create large font instances using font resource (base address + size)
 	m_FontLogo1 = new OGLFT::TranslucentTexture(
 								&m_FontResource->data()->at(0),
 								m_FontResource->data()->size(),
-								24, 72 );
+								36, uint(DESIGN_DPI) );
 
 	if ( m_FontLogo1 == 0 || !m_FontLogo1->isValid() ) {
 	     cerr << "Could not construct logo1 font face from in memory resource!" << endl;
@@ -68,7 +71,7 @@ void StarsphereS5R3::initialize(const int width, const int height, const Resourc
 	m_FontLogo2 = new OGLFT::TranslucentTexture(
 								&m_FontResource->data()->at(0),
 								m_FontResource->data()->size(),
-								13, 78 );
+								16, uint(DESIGN_DPI) );
 
 	if ( m_FontLogo2 == 0 || !m_FontLogo2->isValid() ) {
 	     cerr << "Could not construct logo2 font face from in memory resource!" << endl;
@@ -86,8 +89,8 @@ void StarsphereS5R3::resize(const int width, const int height)
 	Starsphere::resize(width, height);
 
 	// adjust HUD config
-	m_XStartPosRight = width - 125;
-	m_XStartPosClock = width - 98;
+	m_XStartPosRight = width - m_XStartPosRightWidthOffset;
+	m_XStartPosClock = width - m_XStartPosClockWidthOffset;
 }
 
 void StarsphereS5R3::refreshBOINCInformation()
@@ -179,5 +182,5 @@ void StarsphereS5R3::generateObservatories(float dimFactor)
 void StarsphereS5R3::renderLogo()
 {
 	m_FontLogo1->draw(m_XStartPosLeft, m_YStartPosTop, "Einstein@Home");
-	m_FontLogo2->draw(m_XStartPosLeft, m_YStartPosTop - m_YOffsetLarge, "World Year of Physics 2005");
+	m_FontLogo2->draw(m_XStartPosLeft + m_Logo2XOffset, m_YStartPosTop - m_YOffsetLarge, "World Year of Physics 2005");
 }
diff --git a/src/starsphere/StarsphereS5R3.h b/src/starsphere/StarsphereS5R3.h
index 915dba5d6e998c326206b9b1660b2017bed281f2..7e59e2e901cd962e68d64b5eb25580dc00b1c780 100644
--- a/src/starsphere/StarsphereS5R3.h
+++ b/src/starsphere/StarsphereS5R3.h
@@ -64,10 +64,11 @@ public:
 	 *
 	 * \param width The current width of the display surface
 	 * \param height The current height of the display surface
+	 * \param scale The scaling factor on HDPI displays
 	 * \param font A pointer to a Resource object containing TTF font faces for text rendering
 	 * \param recycle This flag indicates whether we initialize (FALSE) or reinitialize (TRUE) the context
 	 */
-	virtual void initialize(const int width, const int height, const Resource *font, const bool recycle = false);
+	virtual void initialize(const int width, const int height, const float scale, const Resource *font, const bool recycle = false);
 
 	/**
 	 * \brief This method is called when the windowing system encounters a window resize event
@@ -139,9 +140,15 @@ private:
 	/// HUD configuration setting (line offset for medium sized font)
 	GLfloat m_YOffsetMedium;
 
+	/// HUD configuration setting (horizontal offset of the right part)
+	GLfloat m_XStartPosRightWidthOffset;
+
 	/// HUD configuration setting (horizontal start position for the right part)
 	GLfloat m_XStartPosRight;
 
+	/// HUD configuration setting (horizontal offset of the clock display)
+	GLfloat m_XStartPosClockWidthOffset;
+
 	/// HUD configuration setting (horizontal start position for the clock display)
 	GLfloat m_XStartPosClock;
 
@@ -159,6 +166,9 @@ private:
 
 	/// HUD configuration setting (vertical start postion for the bottom part, line 4)
 	GLfloat m_Y4StartPosBottom;
+
+	/// HUD configuration setting (horizontal offset of logo, line 2)
+	GLfloat m_Logo2XOffset;
 };
 
 /**
diff --git a/src/starsphere/main.cpp b/src/starsphere/main.cpp
index df55fcef6453193dd6f5af5ed402262452bdc98f..25441b893099f1ea83c293146dfe5625573b007b 100644
--- a/src/starsphere/main.cpp
+++ b/src/starsphere/main.cpp
@@ -123,7 +123,7 @@ int main(int argc, char **argv)
     window.registerEventObserver(graphics);
 
 	// pepare rendering
-	graphics->initialize(window.windowWidth(), window.windowHeight(), fontResource);
+	graphics->initialize(window.windowWidth(), window.windowHeight(), 1.0, fontResource);
 	graphics->refreshBOINCInformation();
 
 	// check optional command line parameters