Fixed race condition where Android touch events could get scaled by a render target's viewport
authorSam Lantinga <slouken@libsdl.org>
Mon, 18 Jun 2018 13:13:56 -0700
changeset 120213239c8ad2986
parent 12020 7f3c9bffada4
child 12022 b1de5ecf0c99
Fixed race condition where Android touch events could get scaled by a render target's viewport
src/render/SDL_render.c
src/render/SDL_sysrender.h
     1.1 --- a/src/render/SDL_render.c	Thu Jun 14 00:51:45 2018 -0700
     1.2 +++ b/src/render/SDL_render.c	Mon Jun 18 13:13:56 2018 -0700
     1.3 @@ -132,6 +132,16 @@
     1.4  #endif
     1.5  }
     1.6  
     1.7 +static void GetWindowViewportValues(SDL_Renderer *renderer, int *logical_w, int *logical_h, SDL_Rect *viewport, SDL_FPoint *scale)
     1.8 +{
     1.9 +    SDL_LockMutex(renderer->target_mutex);
    1.10 +    *logical_w = renderer->target ? renderer->logical_w_backup : renderer->logical_w;
    1.11 +    *logical_h = renderer->target ? renderer->logical_h_backup : renderer->logical_h;
    1.12 +    *viewport = renderer->target ? renderer->viewport_backup : renderer->viewport;
    1.13 +    *scale = renderer->target ? renderer->scale_backup : renderer->scale;
    1.14 +    SDL_UnlockMutex(renderer->target_mutex);
    1.15 +}
    1.16 +
    1.17  static int SDLCALL
    1.18  SDL_RendererEventWatch(void *userdata, SDL_Event *event)
    1.19  {
    1.20 @@ -197,35 +207,51 @@
    1.21          }
    1.22      } else if (event->type == SDL_MOUSEMOTION) {
    1.23          SDL_Window *window = SDL_GetWindowFromID(event->motion.windowID);
    1.24 -        if (renderer->logical_w && window == renderer->window) {
    1.25 -            event->motion.x -= (int)(renderer->viewport.x * renderer->dpi_scale.x);
    1.26 -            event->motion.y -= (int)(renderer->viewport.y * renderer->dpi_scale.y);
    1.27 -            event->motion.x = (int)(event->motion.x / (renderer->scale.x * renderer->dpi_scale.x));
    1.28 -            event->motion.y = (int)(event->motion.y / (renderer->scale.y * renderer->dpi_scale.y));
    1.29 -            if (event->motion.xrel > 0) {
    1.30 -                event->motion.xrel = SDL_max(1, (int)(event->motion.xrel / (renderer->scale.x * renderer->dpi_scale.x)));
    1.31 -            } else if (event->motion.xrel < 0) {
    1.32 -                event->motion.xrel = SDL_min(-1, (int)(event->motion.xrel / (renderer->scale.x * renderer->dpi_scale.x)));
    1.33 -            }
    1.34 -            if (event->motion.yrel > 0) {
    1.35 -                event->motion.yrel = SDL_max(1, (int)(event->motion.yrel / (renderer->scale.y * renderer->dpi_scale.y)));
    1.36 -            } else if (event->motion.yrel < 0) {
    1.37 -                event->motion.yrel = SDL_min(-1, (int)(event->motion.yrel / (renderer->scale.y * renderer->dpi_scale.y)));
    1.38 +        if (window == renderer->window) {
    1.39 +            int logical_w, logical_h;
    1.40 +            SDL_Rect viewport;
    1.41 +            SDL_FPoint scale;
    1.42 +            GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
    1.43 +            if (logical_w) {
    1.44 +                event->motion.x -= (int)(viewport.x * renderer->dpi_scale.x);
    1.45 +                event->motion.y -= (int)(viewport.y * renderer->dpi_scale.y);
    1.46 +                event->motion.x = (int)(event->motion.x / (scale.x * renderer->dpi_scale.x));
    1.47 +                event->motion.y = (int)(event->motion.y / (scale.y * renderer->dpi_scale.y));
    1.48 +                if (event->motion.xrel > 0) {
    1.49 +                    event->motion.xrel = SDL_max(1, (int)(event->motion.xrel / (scale.x * renderer->dpi_scale.x)));
    1.50 +                } else if (event->motion.xrel < 0) {
    1.51 +                    event->motion.xrel = SDL_min(-1, (int)(event->motion.xrel / (scale.x * renderer->dpi_scale.x)));
    1.52 +                }
    1.53 +                if (event->motion.yrel > 0) {
    1.54 +                    event->motion.yrel = SDL_max(1, (int)(event->motion.yrel / (scale.y * renderer->dpi_scale.y)));
    1.55 +                } else if (event->motion.yrel < 0) {
    1.56 +                    event->motion.yrel = SDL_min(-1, (int)(event->motion.yrel / (scale.y * renderer->dpi_scale.y)));
    1.57 +                }
    1.58              }
    1.59          }
    1.60      } else if (event->type == SDL_MOUSEBUTTONDOWN ||
    1.61                 event->type == SDL_MOUSEBUTTONUP) {
    1.62          SDL_Window *window = SDL_GetWindowFromID(event->button.windowID);
    1.63 -        if (renderer->logical_w && window == renderer->window) {
    1.64 -            event->button.x -= (int)(renderer->viewport.x * renderer->dpi_scale.x);
    1.65 -            event->button.y -= (int)(renderer->viewport.y * renderer->dpi_scale.y);
    1.66 -            event->button.x = (int)(event->button.x / (renderer->scale.x * renderer->dpi_scale.x));
    1.67 -            event->button.y = (int)(event->button.y / (renderer->scale.y * renderer->dpi_scale.y));
    1.68 +        if (window == renderer->window) {
    1.69 +            int logical_w, logical_h;
    1.70 +            SDL_Rect viewport;
    1.71 +            SDL_FPoint scale;
    1.72 +            GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
    1.73 +            if (logical_w) {
    1.74 +                event->button.x -= (int)(viewport.x * renderer->dpi_scale.x);
    1.75 +                event->button.y -= (int)(viewport.y * renderer->dpi_scale.y);
    1.76 +                event->button.x = (int)(event->button.x / (scale.x * renderer->dpi_scale.x));
    1.77 +                event->button.y = (int)(event->button.y / (scale.y * renderer->dpi_scale.y));
    1.78 +            }
    1.79          }
    1.80      } else if (event->type == SDL_FINGERDOWN ||
    1.81                 event->type == SDL_FINGERUP ||
    1.82                 event->type == SDL_FINGERMOTION) {
    1.83 -        if (renderer->logical_w) {
    1.84 +        int logical_w, logical_h;
    1.85 +        SDL_Rect viewport;
    1.86 +        SDL_FPoint scale;
    1.87 +        GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
    1.88 +        if (logical_w) {
    1.89              int w = 1;
    1.90              int h = 1;
    1.91              SDL_GetRendererOutputSize(renderer, &w, &h);
    1.92 @@ -233,18 +259,18 @@
    1.93              event->tfinger.x *= (w - 1);
    1.94              event->tfinger.y *= (h - 1);
    1.95  
    1.96 -            event->tfinger.x -= (renderer->viewport.x * renderer->dpi_scale.x);
    1.97 -            event->tfinger.y -= (renderer->viewport.y * renderer->dpi_scale.y);
    1.98 -            event->tfinger.x = (event->tfinger.x / (renderer->scale.x * renderer->dpi_scale.x));
    1.99 -            event->tfinger.y = (event->tfinger.y / (renderer->scale.y * renderer->dpi_scale.y));
   1.100 +            event->tfinger.x -= (viewport.x * renderer->dpi_scale.x);
   1.101 +            event->tfinger.y -= (viewport.y * renderer->dpi_scale.y);
   1.102 +            event->tfinger.x = (event->tfinger.x / (scale.x * renderer->dpi_scale.x));
   1.103 +            event->tfinger.y = (event->tfinger.y / (scale.y * renderer->dpi_scale.y));
   1.104  
   1.105 -            if (renderer->logical_w > 1) {
   1.106 -                event->tfinger.x = event->tfinger.x / (renderer->logical_w - 1);
   1.107 +            if (logical_w > 1) {
   1.108 +                event->tfinger.x = event->tfinger.x / (logical_w - 1);
   1.109              } else {
   1.110                  event->tfinger.x = 0.5f;
   1.111              }
   1.112 -            if (renderer->logical_h > 1) {
   1.113 -                event->tfinger.y = event->tfinger.y / (renderer->logical_h - 1);
   1.114 +            if (logical_h > 1) {
   1.115 +                event->tfinger.y = event->tfinger.y / (logical_h - 1);
   1.116              } else {
   1.117                  event->tfinger.y = 0.5f;
   1.118              }
   1.119 @@ -345,6 +371,7 @@
   1.120      if (renderer) {
   1.121          renderer->magic = &renderer_magic;
   1.122          renderer->window = window;
   1.123 +        renderer->target_mutex = SDL_CreateMutex();
   1.124          renderer->scale.x = 1.0f;
   1.125          renderer->scale.y = 1.0f;
   1.126          renderer->dpi_scale.x = 1.0f;
   1.127 @@ -392,6 +419,7 @@
   1.128  
   1.129      if (renderer) {
   1.130          renderer->magic = &renderer_magic;
   1.131 +        renderer->target_mutex = SDL_CreateMutex();
   1.132          renderer->scale.x = 1.0f;
   1.133          renderer->scale.y = 1.0f;
   1.134  
   1.135 @@ -1203,6 +1231,8 @@
   1.136          }
   1.137      }
   1.138  
   1.139 +    SDL_LockMutex(renderer->target_mutex);
   1.140 +
   1.141      if (texture && !renderer->target) {
   1.142          /* Make a backup of the viewport */
   1.143          renderer->viewport_backup = renderer->viewport;
   1.144 @@ -1215,6 +1245,7 @@
   1.145      renderer->target = texture;
   1.146  
   1.147      if (renderer->SetRenderTarget(renderer, texture) < 0) {
   1.148 +        SDL_UnlockMutex(renderer->target_mutex);
   1.149          return -1;
   1.150      }
   1.151  
   1.152 @@ -1237,6 +1268,9 @@
   1.153          renderer->logical_w = renderer->logical_w_backup;
   1.154          renderer->logical_h = renderer->logical_h_backup;
   1.155      }
   1.156 +
   1.157 +    SDL_UnlockMutex(renderer->target_mutex);
   1.158 +
   1.159      if (renderer->UpdateViewport(renderer) < 0) {
   1.160          return -1;
   1.161      }
   1.162 @@ -2106,6 +2140,10 @@
   1.163      /* It's no longer magical... */
   1.164      renderer->magic = NULL;
   1.165  
   1.166 +    /* Free the target mutex */
   1.167 +    SDL_DestroyMutex(renderer->target_mutex);
   1.168 +    renderer->target_mutex = NULL;
   1.169 +
   1.170      /* Free the renderer instance */
   1.171      renderer->DestroyRenderer(renderer);
   1.172  }
     2.1 --- a/src/render/SDL_sysrender.h	Thu Jun 14 00:51:45 2018 -0700
     2.2 +++ b/src/render/SDL_sysrender.h	Mon Jun 18 13:13:56 2018 -0700
     2.3 @@ -25,6 +25,7 @@
     2.4  
     2.5  #include "SDL_render.h"
     2.6  #include "SDL_events.h"
     2.7 +#include "SDL_mutex.h"
     2.8  #include "SDL_yuv_sw_c.h"
     2.9  
    2.10  /* The SDL 2D rendering system */
    2.11 @@ -172,6 +173,7 @@
    2.12      /* The list of textures */
    2.13      SDL_Texture *textures;
    2.14      SDL_Texture *target;
    2.15 +    SDL_mutex *target_mutex;
    2.16  
    2.17      Uint8 r, g, b, a;                   /**< Color for drawing operations values */
    2.18      SDL_BlendMode blendMode;            /**< The drawing blend mode */