diff --git a/include/Inventor/SoRenderManager.h b/include/Inventor/SoRenderManager.h index bf49be4728f..3bc9a6f5bbb 100644 --- a/include/Inventor/SoRenderManager.h +++ b/include/Inventor/SoRenderManager.h @@ -166,6 +166,8 @@ class COIN_DLL_API SoRenderManager { void scheduleRedraw(void); void setWindowSize(const SbVec2s & newsize); + void setDevicePixelRatio(float dpr); + float getDevicePixelRatio(void) const; const SbVec2s & getWindowSize(void) const; void setSize(const SbVec2s & newsize); const SbVec2s & getSize(void) const; diff --git a/include/Inventor/SoSceneManager.h b/include/Inventor/SoSceneManager.h index 9450ee56b86..bbabe9fa5ff 100644 --- a/include/Inventor/SoSceneManager.h +++ b/include/Inventor/SoSceneManager.h @@ -75,6 +75,8 @@ class COIN_DLL_API SoSceneManager { virtual SoNode * getSceneGraph(void) const; void setWindowSize(const SbVec2s & newsize); const SbVec2s & getWindowSize(void) const; + void setDevicePixelRatio(float dpr); + float getDevicePixelRatio(void) const; void setSize(const SbVec2s & newsize); const SbVec2s & getSize(void) const; void setOrigin(const SbVec2s & newOrigin); diff --git a/include/Inventor/elements/Makefile.am b/include/Inventor/elements/Makefile.am index 22c2c6430eb..48fbc73d348 100644 --- a/include/Inventor/elements/Makefile.am +++ b/include/Inventor/elements/Makefile.am @@ -20,6 +20,7 @@ PublicHeaders = \ SoCullElement.h \ SoDecimationPercentageElement.h \ SoDecimationTypeElement.h \ + SoDevicePixelRatioElement.h \ SoDiffuseColorElement.h \ SoDrawStyleElement.h \ SoElement.h \ diff --git a/include/Inventor/elements/SoDevicePixelRatioElement.h b/include/Inventor/elements/SoDevicePixelRatioElement.h new file mode 100644 index 00000000000..085ed8d4279 --- /dev/null +++ b/include/Inventor/elements/SoDevicePixelRatioElement.h @@ -0,0 +1,35 @@ +#ifndef COIN_SODEVICEPIXELRATIOELEMENT_H +#define COIN_SODEVICEPIXELRATIOELEMENT_H + +/**************************************************************************\ + * Copyright (c) 2026 The Coin3D contributors * + * * + * This file is part of Coin. * + * * + * Coin is free software; you can redistribute it and/or modify it under * + * the terms of the GNU General Public License as published by the Free * + * Software Foundation; either version 2 of the License, or (at your * + * option) any later version. * +\**************************************************************************/ + +#include + +class COIN_DLL_API SoDevicePixelRatioElement : public SoFloatElement { + typedef SoFloatElement inherited; + + SO_ELEMENT_HEADER(SoDevicePixelRatioElement); + +public: + static void initClass(void); + + void init(SoState * state) override; + + static void set(SoState * state, SoNode * node, float dpr); + static void set(SoState * state, float dpr); + static float get(SoState * state); + +protected: + ~SoDevicePixelRatioElement() override; +}; + +#endif // !COIN_SODEVICEPIXELRATIOELEMENT_H diff --git a/include/Inventor/elements/SoElements.h b/include/Inventor/elements/SoElements.h index 60402f6018d..3b10e6dc283 100644 --- a/include/Inventor/elements/SoElements.h +++ b/include/Inventor/elements/SoElements.h @@ -86,6 +86,7 @@ #include #include #include +#include #include #include #include diff --git a/src/actions/SoGLRenderAction.cpp b/src/actions/SoGLRenderAction.cpp index 0e4a274e08e..880a29432fb 100644 --- a/src/actions/SoGLRenderAction.cpp +++ b/src/actions/SoGLRenderAction.cpp @@ -80,6 +80,7 @@ #include #include #include +#include #include #include #include @@ -644,6 +645,7 @@ SoGLRenderAction::initClass(void) SO_ENABLE(SoGLRenderAction, SoDecimationPercentageElement); SO_ENABLE(SoGLRenderAction, SoDecimationTypeElement); + SO_ENABLE(SoGLRenderAction, SoDevicePixelRatioElement); SO_ENABLE_LEGACY_GL(SoGLRenderAction, SoGLLightIdElement); SO_ENABLE_LEGACY_GL(SoGLRenderAction, SoGLRenderPassElement); SO_ENABLE_LEGACY_GL(SoGLRenderAction, SoGLUpdateAreaElement); diff --git a/src/elements/CMakeLists.txt b/src/elements/CMakeLists.txt index addf8ef1122..4a5e62d14f2 100644 --- a/src/elements/CMakeLists.txt +++ b/src/elements/CMakeLists.txt @@ -22,6 +22,7 @@ set(COIN_ELEMENTS_FILES SoCullElement.cpp SoDecimationPercentageElement.cpp SoDecimationTypeElement.cpp + SoDevicePixelRatioElement.cpp SoDepthBufferElement.cpp SoDiffuseColorElement.cpp SoDrawStyleElement.cpp diff --git a/src/elements/Makefile.am b/src/elements/Makefile.am index 24c159c18d3..e57571d515b 100644 --- a/src/elements/Makefile.am +++ b/src/elements/Makefile.am @@ -24,6 +24,7 @@ RegularSources = \ SoCullElement.cpp \ SoDecimationPercentageElement.cpp \ SoDecimationTypeElement.cpp \ + SoDevicePixelRatioElement.cpp \ SoDepthBufferElement.cpp \ SoDiffuseColorElement.cpp \ SoDrawStyleElement.cpp \ diff --git a/src/elements/SoDevicePixelRatioElement.cpp b/src/elements/SoDevicePixelRatioElement.cpp new file mode 100644 index 00000000000..160077c67a2 --- /dev/null +++ b/src/elements/SoDevicePixelRatioElement.cpp @@ -0,0 +1,51 @@ +/**************************************************************************\ + * Copyright (c) 2026 The Coin3D contributors * + * * + * This file is part of Coin. * + * * + * Coin is free software; you can redistribute it and/or modify it under * + * the terms of the GNU General Public License as published by the Free * + * Software Foundation; either version 2 of the License, or (at your * + * option) any later version. * +\**************************************************************************/ + +#include + +#include + +SO_ELEMENT_SOURCE(SoDevicePixelRatioElement); + +void +SoDevicePixelRatioElement::initClass(void) +{ + SO_ELEMENT_INIT_CLASS(SoDevicePixelRatioElement, inherited); +} + +void +SoDevicePixelRatioElement::init(SoState * state) +{ + inherited::init(state); + this->data = 1.0f; +} + +void +SoDevicePixelRatioElement::set(SoState * state, SoNode * node, float dpr) +{ + inherited::set(classStackIndex, state, node, dpr); +} + +void +SoDevicePixelRatioElement::set(SoState * state, float dpr) +{ + SoDevicePixelRatioElement::set(state, NULL, dpr); +} + +float +SoDevicePixelRatioElement::get(SoState * state) +{ + return inherited::get(classStackIndex, state); +} + +SoDevicePixelRatioElement::~SoDevicePixelRatioElement(void) +{ +} diff --git a/src/elements/SoElement.cpp b/src/elements/SoElement.cpp index a0c5121a65a..9750a5ebb42 100644 --- a/src/elements/SoElement.cpp +++ b/src/elements/SoElement.cpp @@ -427,6 +427,7 @@ SoElement::initElements(void) SoComplexityElement::initClass(); SoCreaseAngleElement::initClass(); SoDecimationPercentageElement::initClass(); + SoDevicePixelRatioElement::initClass(); SoFocalDistanceElement::initClass(); SoFontSizeElement::initClass(); SoLineWidthElement::initClass(); diff --git a/src/elements/all-elements-cpp.cpp b/src/elements/all-elements-cpp.cpp index 4b2edd07adc..326dc5d6c1a 100644 --- a/src/elements/all-elements-cpp.cpp +++ b/src/elements/all-elements-cpp.cpp @@ -50,6 +50,7 @@ #include "SoCullElement.cpp" #include "SoDecimationPercentageElement.cpp" #include "SoDecimationTypeElement.cpp" +#include "SoDevicePixelRatioElement.cpp" #include "SoDepthBufferElement.cpp" #include "SoDiffuseColorElement.cpp" #include "SoDrawStyleElement.cpp" diff --git a/src/misc/SoSceneManager.cpp b/src/misc/SoSceneManager.cpp index 7578d55a744..49350052423 100644 --- a/src/misc/SoSceneManager.cpp +++ b/src/misc/SoSceneManager.cpp @@ -314,6 +314,18 @@ SoSceneManager::getWindowSize(void) const return PRIVATE(this)->rendermanager->getWindowSize(); } +void +SoSceneManager::setDevicePixelRatio(float dpr) +{ + PRIVATE(this)->rendermanager->setDevicePixelRatio(dpr); +} + +float +SoSceneManager::getDevicePixelRatio(void) const +{ + return PRIVATE(this)->rendermanager->getDevicePixelRatio(); +} + /*! Set size of rendering area for the viewport within the current window. diff --git a/src/rendering/SoRenderManager.cpp b/src/rendering/SoRenderManager.cpp index abb657268a3..3e36bf173a3 100644 --- a/src/rendering/SoRenderManager.cpp +++ b/src/rendering/SoRenderManager.cpp @@ -58,6 +58,7 @@ #include #include #include +#include #include #include @@ -264,6 +265,7 @@ SoRenderManager::SoRenderManager(void) PRIVATE(this)->stereostencilmask = NULL; PRIVATE(this)->superimpositions = NULL; PRIVATE(this)->viewport = SbViewportRegion(SbVec2s(400, 400)); + PRIVATE(this)->devicePixelRatio = 1.0f; PRIVATE(this)->doublebuffer = TRUE; PRIVATE(this)->deleteaudiorenderaction = TRUE; @@ -698,7 +700,13 @@ SoRenderManager::render(SoGLRenderAction * action, for (int i = 0; i < PRIVATE(this)->superimpositions->getLength(); i++) { Superimposition * s = (Superimposition *) (*PRIVATE(this)->superimpositions)[i]; if (s->getStateFlags() & Superimposition::BACKGROUND) { + SoState * state = action->getState(); + state->push(); + SoDevicePixelRatioElement::set(state, + PRIVATE(this)->dummynode, + PRIVATE(this)->devicePixelRatio); s->render(action, clearwindow_tmp); + state->pop(); clearwindow_tmp = FALSE; } } @@ -712,7 +720,13 @@ SoRenderManager::render(SoGLRenderAction * action, for (int i = 0; i < PRIVATE(this)->superimpositions->getLength(); i++) { Superimposition * s = (Superimposition *) (*PRIVATE(this)->superimpositions)[i]; if (!(s->getStateFlags() & Superimposition::BACKGROUND)) { + SoState * state = action->getState(); + state->push(); + SoDevicePixelRatioElement::set(state, + PRIVATE(this)->dummynode, + PRIVATE(this)->devicePixelRatio); s->render(action); + state->pop(); } } } @@ -845,6 +859,7 @@ SoRenderManager::renderSingle(SoGLRenderAction * action, state->push(); SoNode * node = PRIVATE(this)->dummynode; + SoDevicePixelRatioElement::set(state, node, PRIVATE(this)->devicePixelRatio); if (!this->isTexturesEnabled()) { SoTextureQualityElement::set(state, node, 0.0f); @@ -1266,6 +1281,20 @@ SoRenderManager::getWindowSize(void) const return PRIVATE(this)->viewport.getWindowSize(); } +void +SoRenderManager::setDevicePixelRatio(float dpr) +{ + if (PRIVATE(this)->devicePixelRatio == dpr) return; + PRIVATE(this)->devicePixelRatio = dpr; + this->scheduleRedraw(); +} + +float +SoRenderManager::getDevicePixelRatio(void) const +{ + return PRIVATE(this)->devicePixelRatio; +} + /*! Set size of rendering area for the viewport within the current window. diff --git a/src/rendering/SoRenderManagerP.h b/src/rendering/SoRenderManagerP.h index 6f8e7ee7aa1..c08ff50d656 100644 --- a/src/rendering/SoRenderManagerP.h +++ b/src/rendering/SoRenderManagerP.h @@ -114,6 +114,7 @@ class SoRenderManagerP { SbBool deleteglaction; #endif SbViewportRegion viewport; + float devicePixelRatio; SoRenderManager::StereoMode stereostenciltype; SoRenderManager::RenderMode rendermode; diff --git a/testsuite/SceneManagerCoreTest.cpp b/testsuite/SceneManagerCoreTest.cpp index 183b6dd5b62..52db7080bf3 100644 --- a/testsuite/SceneManagerCoreTest.cpp +++ b/testsuite/SceneManagerCoreTest.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -25,6 +26,10 @@ checkRenderManager(SoRenderManager & manager) manager.setWindowSize(SbVec2s(800, 600)); if (manager.getWindowSize() != SbVec2s(800, 600)) return 1; + if (manager.getDevicePixelRatio() != 1.0f) return 1; + manager.setDevicePixelRatio(2.0f); + if (manager.getDevicePixelRatio() != 2.0f) return 1; + manager.setSize(SbVec2s(640, 480)); if (manager.getSize() != SbVec2s(640, 480)) return 1; @@ -60,6 +65,10 @@ checkSceneManager(SoSceneManager & manager) manager.setWindowSize(SbVec2s(800, 600)); if (manager.getWindowSize() != SbVec2s(800, 600)) return 1; + if (manager.getDevicePixelRatio() != 1.0f) return 1; + manager.setDevicePixelRatio(2.0f); + if (manager.getDevicePixelRatio() != 2.0f) return 1; + manager.setSize(SbVec2s(640, 480)); if (manager.getSize() != SbVec2s(640, 480)) return 1;