diff --git a/src/camera.cpp b/src/camera.cpp
index 4a87ed3..35b03d0 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -216,8 +216,10 @@ cameraSync(ObjectWithFrame *obj)
 	inv.at.x = -inv.at.x;
 	inv.pos.x = -inv.pos.x;
 
-	float32 xscl = 1.0f/(2.0f*cam->viewWindow.x);
-	float32 yscl = 1.0f/(2.0f*cam->viewWindow.y);
+	V2d dpiScale = engine->device.dpiScale(cam->frameBuffer->width, cam->frameBuffer->height);
+
+	float32 xscl = 1.0f/(2.0f*cam->viewWindow.x*dpiScale.x);
+	float32 yscl = 1.0f/(2.0f*cam->viewWindow.y*dpiScale.y);
 
 	proj.flags = 0;
 	proj.right.x = xscl;
diff --git a/src/engine.cpp b/src/engine.cpp
index 74dae02..cb36bec 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -559,6 +559,7 @@ Device renderdevice = {
 	null::im3DRenderPrimitive,
 	null::im3DRenderIndexedPrimitive,
 	null::im3DEnd,
+	null::dpiScale,
 	null::deviceSystem
 };
 
diff --git a/src/gl/gl3device.cpp b/src/gl/gl3device.cpp
index 6d1f95a..a0ed4b9 100644
--- a/src/gl/gl3device.cpp
+++ b/src/gl/gl3device.cpp
@@ -1253,8 +1253,9 @@ beginUpdate(Camera *cam)
 	setViewMatrix(view);
 
 	// Projection Matrix
-	float32 invwx = 1.0f/cam->viewWindow.x;
-	float32 invwy = 1.0f/cam->viewWindow.y;
+	V2d dpiScale = engine->device.dpiScale(cam->frameBuffer->width, cam->frameBuffer->height);
+	float32 invwx = 1.0f/cam->viewWindow.x/dpiScale.x;
+	float32 invwy = 1.0f/cam->viewWindow.y/dpiScale.y;
 	float32 invz = 1.0f/(cam->farPlane-cam->nearPlane);
 
 	proj[0] = invwx;
@@ -1381,6 +1382,16 @@ showRaster(Raster *raster, uint32 flags)
 #endif
 }
 
+static V2d dpiScale(float x, float y)
+{
+	V2d v;
+	int w = 0;
+        int h = 0;
+        glfwGetFramebufferSize(glGlobals.window, &w, &h);
+	v.set(w / x, h / y);
+	return v;
+}
+
 static bool32
 rasterRenderFast(Raster *raster, int32 x, int32 y)
 {
@@ -1388,6 +1399,7 @@ rasterRenderFast(Raster *raster, int32 x, int32 y)
 	Raster *dst = Raster::getCurrentContext();
 	Gl3Raster *natdst = PLUGINOFFSET(Gl3Raster, dst, nativeRasterOffset);
 	Gl3Raster *natsrc = PLUGINOFFSET(Gl3Raster, src, nativeRasterOffset);
+	V2d dpiScale = engine->device.dpiScale(src->width, src->height);
 
 	switch(dst->type){
 	case Raster::NORMAL:
@@ -1398,7 +1410,7 @@ rasterRenderFast(Raster *raster, int32 x, int32 y)
 			setActiveTexture(0);
 			glBindTexture(GL_TEXTURE_2D, natdst->texid);
 			glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x, (dst->height-src->height)-y,
-				0, 0, src->width, src->height);
+				src->width/dpiScale.x, src->height/dpiScale.y, src->width, src->height);
 			glBindTexture(GL_TEXTURE_2D, boundTexture[0]);
 			return 1;
 		}
@@ -2032,6 +2044,7 @@ Device renderdevice = {
 	gl3::im3DRenderPrimitive,
 	gl3::im3DRenderIndexedPrimitive,
 	gl3::im3DEnd,
+	gl3::dpiScale,
 #ifdef LIBRW_SDL2
 	gl3::deviceSystemSDL2
 #else
diff --git a/src/rwengine.h b/src/rwengine.h
index a84aa3a..97eaea4 100644
--- a/src/rwengine.h
+++ b/src/rwengine.h
@@ -66,6 +66,7 @@ struct Device
 	void (*im3DRenderIndexedPrimitive)(PrimitiveType primType, void *indices, int32 numIndices);
 	void (*im3DEnd)(void);
 
+	V2d (*dpiScale)(float x, float y);
 	DeviceSystem *system;
 };
 
@@ -255,6 +256,13 @@ namespace null {
 	void im3DRenderIndexedPrimitive(PrimitiveType primType, void *indices, int32 numIndices);
 	void im3DEnd(void);
 
+	inline V2d dpiScale(float,float)
+	{
+		V2d s;
+		s.set(1.f, 1.f);
+		return s;
+	}
+
 	int deviceSystem(DeviceReq req, void *arg0, int32 n);
 
 	extern Device renderdevice;