From 875366184553360b0c17a3fc43222597956c98df Mon Sep 17 00:00:00 2001
From: Reinhold Gschweicher <pyro4hell@gmail.com>
Date: Wed, 3 May 2023 22:28:17 +0200
Subject: [PATCH] Handle MONITOR_ZOOM for screen transitions and captures

Something must have changed, but now the MONITOR_ZOOM factor must be
considered when calling `SDL_RenderReadPixels`. Always calling with a
monitor width and height of 240 results in a segmentation fault in said
function.

Fixes: https://github.com/InfiniTimeOrg/InfiniSim/issues/95
---
 main.cpp                     | 18 ++++++++++--------
 sim/displayapp/LittleVgl.cpp |  9 +++++----
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/main.cpp b/main.cpp
index 68ece27..9c61966 100644
--- a/main.cpp
+++ b/main.cpp
@@ -141,16 +141,17 @@ void saveScreenshot()
   for (int i = 0; i < height; i++) {
       row_pointers[i] = (png_bytep)png_malloc(png_ptr, width*4);
   }
+  constexpr size_t zoom = MONITOR_ZOOM;
   const Uint32 format = SDL_PIXELFORMAT_RGBA8888;
-  SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, format);
+  SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, width*zoom, height*zoom, 32, format);
   SDL_RenderReadPixels(renderer, NULL, format, surface->pixels, surface->pitch);
   png_bytep pixels = (png_bytep)surface->pixels;
   for (int hi = 0; hi < height; hi++) {
     for (int wi = 0; wi < width; wi++) {
       int c = wi * 4;
-      row_pointers.at(hi)[wi*4+0] = pixels[hi*surface->pitch + wi*4 + 3]; // red
-      row_pointers.at(hi)[wi*4+1] = pixels[hi*surface->pitch + wi*4 + 2]; // greeen
-      row_pointers.at(hi)[wi*4+2] = pixels[hi*surface->pitch + wi*4 + 1]; // blue
+      row_pointers.at(hi)[wi*4+0] = pixels[hi*surface->pitch*zoom + wi*4*zoom + 3]; // red
+      row_pointers.at(hi)[wi*4+1] = pixels[hi*surface->pitch*zoom + wi*4*zoom + 2]; // greeen
+      row_pointers.at(hi)[wi*4+2] = pixels[hi*surface->pitch*zoom + wi*4*zoom + 1]; // blue
       row_pointers.at(hi)[wi*4+3] = 255; // alpha
     }
   }
@@ -223,17 +224,18 @@ public:
     {
       last_frame = std::chrono::system_clock::now();
       auto renderer = monitor.renderer;
+      constexpr size_t zoom = MONITOR_ZOOM;
       const Uint32 format = SDL_PIXELFORMAT_RGBA8888;
-      SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, sdl_width, sdl_height, 32, format);
+      SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, sdl_width*zoom, sdl_height*zoom, 32, format);
       SDL_RenderReadPixels(renderer, NULL, format, surface->pixels, surface->pitch);
       uint8_t *pixels = (uint8_t*) surface->pixels;
 
       std::array<uint8_t, 240*240*4> image;
       for (int hi = 0; hi < sdl_height; hi++) {
         for (int wi = 0; wi < sdl_width; wi++) {
-          auto red   = pixels[hi*surface->pitch + wi*4 + 3]; // red
-          auto green = pixels[hi*surface->pitch + wi*4 + 2]; // green
-          auto blue  = pixels[hi*surface->pitch + wi*4 + 1]; // blue
+          auto red   = pixels[hi*surface->pitch*zoom + wi*4*zoom + 3]; // red
+          auto green = pixels[hi*surface->pitch*zoom + wi*4*zoom + 2]; // green
+          auto blue  = pixels[hi*surface->pitch*zoom + wi*4*zoom + 1]; // blue
           image[(hi * sdl_width + wi)*4 + 0] = red;
           image[(hi * sdl_width + wi)*4 + 1] = green;
           image[(hi * sdl_width + wi)*4 + 2] = blue;
diff --git a/sim/displayapp/LittleVgl.cpp b/sim/displayapp/LittleVgl.cpp
index 04a7482..088accf 100644
--- a/sim/displayapp/LittleVgl.cpp
+++ b/sim/displayapp/LittleVgl.cpp
@@ -194,17 +194,18 @@ void MoveScreen(lv_disp_drv_t *disp_drv, int16_t height) {
   const int sdl_height = 240;
   auto renderer = monitor.renderer;
 
+  constexpr size_t zoom = MONITOR_ZOOM;
   const Uint32 format = SDL_PIXELFORMAT_RGBA8888;
-  SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, sdl_width, sdl_height, 32, format);
+  SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, sdl_width*zoom, sdl_height*zoom, 32, format);
   SDL_RenderReadPixels(renderer, NULL, format, surface->pixels, surface->pitch);
   uint8_t *pixels = (uint8_t*) surface->pixels;
 
   std::array<lv_color16_t, 240*240> color_p;
   for (int hi = 0; hi < sdl_height; hi++) {
     for (int wi = 0; wi < sdl_width; wi++) {
-      auto red   = pixels[hi*surface->pitch + wi*4 + 3]; // red
-      auto green = pixels[hi*surface->pitch + wi*4 + 2]; // greeen
-      auto blue  = pixels[hi*surface->pitch + wi*4 + 1]; // blue
+      auto red   = pixels[hi*surface->pitch*zoom + wi*4*zoom + 3]; // red
+      auto green = pixels[hi*surface->pitch*zoom + wi*4*zoom + 2]; // greeen
+      auto blue  = pixels[hi*surface->pitch*zoom + wi*4*zoom + 1]; // blue
       color_p.at(hi * sdl_width + wi) = LV_COLOR_MAKE(red, green, blue);
     }
   }