Fix pick() picking from weird places on the screen with high DPI scaling

Wed, 25 May 2022 20:36:34 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Wed, 25 May 2022 20:36:34 +0300
changeset 199
6988973515d2
parent 198
eb9d900dc79a
child 200
ca23936b455b

Fix pick() picking from weird places on the screen with high DPI scaling

glReadPixels reads data from the frame buffer, which contains data after
high DPI scaling, so any reads to that need to take this scaling into account

src/gl/partrenderer.cpp file | annotate | diff | comparison | revisions
src/gl/partrenderer.h file | annotate | diff | comparison | revisions
--- a/src/gl/partrenderer.cpp	Wed May 25 18:33:38 2022 +0300
+++ b/src/gl/partrenderer.cpp	Wed May 25 20:36:34 2022 +0300
@@ -352,15 +352,21 @@
 		viewportVector);
 }
 
-ldraw::id_t PartRenderer::pick(const QPoint& where)
+ldraw::id_t PartRenderer::pick(QPoint where)
 {
+	// y is flipped, take that into account
+	where.setY(this->height() - where.y());
+	// Since we are dealing with pixel data right from the framebuffer, its size
+	// will be affected by High DPI scaling. We need to take this into account
+	// and multiply the pixel positions by the screen pixel scaling factor.
+	where *= this->devicePixelRatioF();
 	const gl::RenderStyle oldRenderStyle = this->renderPreferences.style;
 	this->renderPreferences.style = gl::RenderStyle::PickScene;
 	this->makeCurrent();
 	this->renderScene();
 	std::array<GLubyte, 3> data;
 	this->checkForGLErrors();
-	glReadPixels(where.x(), this->height() - where.y(), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &data[0]);
+	glfunc.glReadPixels(where.x(), where.y(), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &data[0]);
 	this->checkForGLErrors();
 	this->renderPreferences.style = oldRenderStyle;
 	this->update();
--- a/src/gl/partrenderer.h	Wed May 25 18:33:38 2022 +0300
+++ b/src/gl/partrenderer.h	Wed May 25 20:36:34 2022 +0300
@@ -24,7 +24,7 @@
 	void setRenderPreferences(const gl::RenderPreferences& newPreferences);
 	ldraw::id_t getHighlightedObject() const;
 protected:
-	ldraw::id_t pick(const QPoint& where);
+	ldraw::id_t pick(QPoint where);
 	void initializeGL() override;
 	void resizeGL(int width, int height) override;
 	void paintGL() override;

mercurial