diff --git a/driver.h b/driver.h
index 20029c5d8b..94ebb10437 100644
--- a/driver.h
+++ b/driver.h
@@ -183,6 +183,8 @@ typedef struct input_driver
    const char *ident;
 } input_driver_t;
 
+struct rarch_viewport;
+
 typedef struct video_driver
 {
    void *(*init)(const video_info_t *video, const input_driver_t **input, void **input_data); 
@@ -206,7 +208,7 @@ typedef struct video_driver
 #endif
 
    void (*set_rotation)(void *data, unsigned rotation);
-   void (*viewport_size)(void *data, unsigned *width, unsigned *height);
+   void (*viewport_info)(void *data, struct rarch_viewport *vp);
 
    // Reads out in BGR byte order (24bpp).
    bool (*read_viewport)(void *data, uint8_t *buffer);
@@ -323,7 +325,7 @@ extern const input_driver_t input_null;
 #define video_set_shader_func(type, path)       driver.video->set_shader(driver.video_data, type, path)
 #define video_set_rotation_func(rotate)         driver.video->set_rotation(driver.video_data, rotate)
 #define video_set_aspect_ratio_func(aspect_idx) driver.video->set_aspect_ratio(driver.video_data, aspect_idx)
-#define video_viewport_size_func(width, height) driver.video->viewport_size(driver.video_data, width, height)
+#define video_viewport_info_func(info)          driver.video->viewport_info(driver.video_data, info)
 #define video_read_viewport_func(buffer)        driver.video->read_viewport(driver.video_data, buffer)
 #define video_free_func()                       driver.video->free(driver.video_data)
 
diff --git a/general.h b/general.h
index 7825cc07c0..41976335a9 100644
--- a/general.h
+++ b/general.h
@@ -213,26 +213,26 @@ enum rarch_game_type
    RARCH_CART_SUFAMI
 };
 
-typedef struct
+typedef struct rarch_boolean_state
 {
    bool enable;
    unsigned value;
 } rarch_boolean_state_t;
 
-typedef struct
+typedef struct rarch_frame_count
 {
    bool is_expired;
    unsigned expire_frame;
    unsigned current;
 } rarch_frame_count_t;
 
-typedef struct
+typedef struct rarch_resolution
 {
    unsigned idx;
    unsigned id;
 } rarch_resolution_t;
 
-typedef struct
+typedef struct rarch_viewport
 {
    int x;
    int y;
diff --git a/gfx/d3d9/d3d9.cpp b/gfx/d3d9/d3d9.cpp
index 6f6154fa24..723a5ecbc4 100644
--- a/gfx/d3d9/d3d9.cpp
+++ b/gfx/d3d9/d3d9.cpp
@@ -156,10 +156,12 @@ void D3DVideo::set_rotation(unsigned rot)
    rotation = rot;
 }
 
-void D3DVideo::viewport_size(unsigned &width, unsigned &height)
+void D3DVideo::viewport_size(rarch_viewport &vp)
 {
-   width  = final_viewport.Width;
-   height = final_viewport.Height;
+   vp.x      = final_viewport.X;
+   vp.y      = final_viewport.Y;
+   vp.width  = final_viewport.Width;
+   vp.height = final_viewport.Height;
 }
 
 bool D3DVideo::read_viewport(uint8_t *buffer)
@@ -981,9 +983,9 @@ static void d3d9_free(void *data)
    delete reinterpret_cast<D3DVideo*>(data);
 }
 
-static void d3d9_viewport_size(void *data, unsigned *width, unsigned *height)
+static void d3d9_viewport_info(void *data, struct rarch_viewport *vp)
 {
-   reinterpret_cast<D3DVideo*>(data)->viewport_size(*width, *height);
+   reinterpret_cast<D3DVideo*>(data)->viewport_info(*vp);
 }
 
 static bool d3d9_read_viewport(void *data, uint8_t *buffer)
@@ -1008,7 +1010,7 @@ const video_driver_t video_d3d9 = {
    "d3d9",
 
    d3d9_set_rotation,
-   d3d9_viewport_size,
+   d3d9_viewport_info,
    d3d9_read_viewport,
 };
 
diff --git a/gfx/d3d9/d3d9.hpp b/gfx/d3d9/d3d9.hpp
index b075e8446c..5e54638217 100644
--- a/gfx/d3d9/d3d9.hpp
+++ b/gfx/d3d9/d3d9.hpp
@@ -44,7 +44,7 @@ class D3DVideo
       bool focus() const;
       void set_nonblock_state(bool state);
       void set_rotation(unsigned rot);
-      void viewport_size(unsigned &width, unsigned &height);
+      void viewport_info(rarch_viewport &vp);
       bool read_viewport(uint8_t *buffer);
 
    private:
diff --git a/gfx/ext_gfx.c b/gfx/ext_gfx.c
index 0d85052a6b..a5d4c50cac 100644
--- a/gfx/ext_gfx.c
+++ b/gfx/ext_gfx.c
@@ -384,10 +384,15 @@ static void video_set_rotation(void *data, unsigned rot)
    ext->driver->set_rotation(ext->handle, rot);
 }
 
-static void video_viewport_size(void *data, unsigned *width, unsigned *height)
+static void video_viewport_info(void *data, struct rarch_viewport *vp)
 {
    ext_t *ext = (ext_t*)data;
-   ext->driver->viewport_size(ext->handle, width, height);
+
+   unsigned width = 0, height = 0;
+   ext->driver->viewport_size(ext->handle, &width, &height);
+   vp->x = vp->y = 0;
+   vp->width     = width;
+   vp->height    = height;
 }
 
 static bool video_read_viewport(void *data, uint8_t *buffer)
@@ -420,7 +425,7 @@ const video_driver_t video_ext = {
 #endif
 
    video_set_rotation,
-   video_viewport_size,
+   video_viewport_info,
    video_read_viewport,
 };
 
diff --git a/gfx/fonts/freetype.c b/gfx/fonts/freetype.c
index 53170ad4ae..548d4e9fab 100644
--- a/gfx/fonts/freetype.c
+++ b/gfx/fonts/freetype.c
@@ -206,9 +206,9 @@ static void calculate_font_coords(gl_t *gl,
    GLfloat scale_factor = scale;
 
    GLfloat lx = pos_x;
-   GLfloat hx = (GLfloat)gl->font_last_width * scale_factor / gl->vp_width + lx;
+   GLfloat hx = (GLfloat)gl->font_last_width * scale_factor / gl->vp.width + lx;
    GLfloat ly = pos_y;
-   GLfloat hy = (GLfloat)gl->font_last_height * scale_factor / gl->vp_height + ly;
+   GLfloat hy = (GLfloat)gl->font_last_height * scale_factor / gl->vp.height + ly;
 
    font_vertex[0] = lx;
    font_vertex[2] = hx;
@@ -219,8 +219,8 @@ static void calculate_font_coords(gl_t *gl,
    font_vertex[5] = ly;
    font_vertex[7] = ly;
 
-   GLfloat shift_x = 2.0f / gl->vp_width;
-   GLfloat shift_y = 2.0f / gl->vp_height;
+   GLfloat shift_x = 2.0f / gl->vp.width;
+   GLfloat shift_y = 2.0f / gl->vp.height;
    for (unsigned i = 0; i < 4; i++)
    {
       font_vertex_dark[2 * i + 0] = font_vertex[2 * i + 0] - shift_x;
@@ -318,7 +318,7 @@ void gl_render_msg(void *data, const char *msg)
 #ifdef HAVE_FREETYPE
    gl_t *gl = (gl_t*)data;
    setup_font(data, msg,
-         g_settings.video.font_scale ? (GLfloat)gl->vp_width / (GLfloat)gl->full_x : 1.0f,
+         g_settings.video.font_scale ? (GLfloat)gl->vp.width / (GLfloat)gl->full_x : 1.0f,
          g_settings.video.msg_pos_x, g_settings.video.msg_pos_y);
 #endif
 }
diff --git a/gfx/gl.c b/gfx/gl.c
index 991eae49c7..6daaddcf44 100644
--- a/gfx/gl.c
+++ b/gfx/gl.c
@@ -689,12 +689,13 @@ void gl_set_viewport(gl_t *gl, unsigned width, unsigned height, bool force_full,
    }
 
    glViewport(x, y, width, height);
+   gl->vp.x      = x;
+   gl->vp.y      = y;
+   gl->vp.width  = width;
+   gl->vp.height = height;
 
    gl_set_projection(gl, &ortho, allow_rotate);
 
-   gl->vp_width  = width;
-   gl->vp_height = height;
-
    // Set last backbuffer viewport.
    if (!force_full)
    {
@@ -808,7 +809,7 @@ static void gl_frame_fbo(gl_t *gl, const struct gl_tex_info *tex_info)
       gl_set_viewport(gl, rect->img_width, rect->img_height, true, false);
       gl_shader_set_params(prev_rect->img_width, prev_rect->img_height, 
             prev_rect->width, prev_rect->height, 
-            gl->vp_width, gl->vp_height, gl->frame_count, 
+            gl->vp.width, gl->vp.height, gl->frame_count, 
             tex_info, gl->prev_info, fbo_tex_info, fbo_tex_info_cnt);
 
       gl_shader_set_coords(&gl->coords, &gl->mvp);
@@ -835,7 +836,7 @@ static void gl_frame_fbo(gl_t *gl, const struct gl_tex_info *tex_info)
    gl_set_viewport(gl, gl->win_width, gl->win_height, false, true);
    gl_shader_set_params(prev_rect->img_width, prev_rect->img_height, 
          prev_rect->width, prev_rect->height, 
-         gl->vp_width, gl->vp_height, gl->frame_count, 
+         gl->vp.width, gl->vp.height, gl->frame_count, 
          tex_info, gl->prev_info, fbo_tex_info, fbo_tex_info_cnt);
 
    gl->coords.vertex = vertex_ptr;
@@ -1121,7 +1122,7 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei
    glClear(GL_COLOR_BUFFER_BIT);
    gl_shader_set_params(width, height,
          gl->tex_w, gl->tex_h,
-         gl->vp_width, gl->vp_height,
+         gl->vp.width, gl->vp.height,
          gl->frame_count, 
          &tex_info, gl->prev_info, NULL, 0);
 
@@ -1498,24 +1499,17 @@ static bool gl_set_shader(void *data, enum rarch_shader_type type, const char *p
 #endif
 
 #ifndef NO_GL_READ_VIEWPORT
-static void gl_viewport_size(void *data, unsigned *width, unsigned *height)
+static void gl_viewport_info(void *data, struct rarch_viewport *vp)
 {
-   (void)data;
-
-   GLint vp[4];
-   glGetIntegerv(GL_VIEWPORT, vp);
-
-   *width  = vp[2];
-   *height = vp[3];
+   gl_t *gl = (gl_t*)data;
+   *vp = gl->vp;
 }
 
 static bool gl_read_viewport(void *data, uint8_t *buffer)
 {
-   (void)data;
+   gl_t *gl = (gl_t*)data;
 
-   GLint vp[4];
-   glGetIntegerv(GL_VIEWPORT, vp);
-   glPixelStorei(GL_PACK_ALIGNMENT, get_alignment(vp[2] * 3));
+   glPixelStorei(GL_PACK_ALIGNMENT, 1);
 
 #ifdef HAVE_OPENGLES
    glReadPixels(vp[0], vp[1],
@@ -1523,7 +1517,7 @@ static bool gl_read_viewport(void *data, uint8_t *buffer)
          GL_RGB, GL_UNSIGNED_BYTE, buffer);
 
    uint8_t *pixels = (uint8_t*)buffer;
-   unsigned num_pixels = vp[2] * vp[3];
+   unsigned num_pixels = gl->vp.width * gl->vp.height;
    // Convert RGB to BGR. Formats are byte ordered, so just swap 1st and 3rd byte.
    for (unsigned i = 0; i <= num_pixels; pixels += 3, i++)
    {
@@ -1532,10 +1526,10 @@ static bool gl_read_viewport(void *data, uint8_t *buffer)
       pixels[0] = tmp;
    }
 #else
-   glPixelStorei(GL_PACK_ROW_LENGTH, vp[2]);
+   glPixelStorei(GL_PACK_ROW_LENGTH, gl->vp.width);
 
-   glReadPixels(vp[0], vp[1],
-         vp[2], vp[3],
+   glReadPixels(gl->vp.x, gl->vp.y,
+         gl->vp.width, gl->vp.height,
          GL_BGR, GL_UNSIGNED_BYTE, buffer);
 #endif
 
@@ -1681,7 +1675,7 @@ const video_driver_t video_gl = {
    gl_set_rotation,
 
 #ifndef NO_GL_READ_VIEWPORT
-   gl_viewport_size,
+   gl_viewport_info,
    gl_read_viewport,
 #else
    NULL,
diff --git a/gfx/gl_common.h b/gfx/gl_common.h
index 9f5af902b2..1f58e0f1b7 100644
--- a/gfx/gl_common.h
+++ b/gfx/gl_common.h
@@ -202,8 +202,9 @@ typedef struct gl
 
    unsigned win_width;
    unsigned win_height;
-   unsigned vp_width, vp_out_width;
-   unsigned vp_height, vp_out_height;
+   struct rarch_viewport vp;
+   unsigned vp_out_width;
+   unsigned vp_out_height;
    unsigned last_width[TEXTURES];
    unsigned last_height[TEXTURES];
    unsigned tex_w, tex_h;
diff --git a/input/input_common.c b/input/input_common.c
index 942b70bf32..c6d98eda69 100644
--- a/input/input_common.c
+++ b/input/input_common.c
@@ -148,3 +148,27 @@ bool input_joypad_hat_raw(const rarch_joypad_driver_t *driver,
    return driver->button(joypad, HAT_MAP(hat, hat_dir));
 }
 
+bool input_translate_coord_viewport(int mouse_x, int mouse_y,
+      int16_t *res_x, int16_t *res_y)
+{
+   struct rarch_viewport vp = {0};
+   if (driver.video->viewport_info)
+      video_viewport_info_func(&vp);
+   else
+      return false;
+
+   mouse_x -= vp.x;
+   mouse_y -= vp.y;
+
+   int scaled_x = (2 * mouse_x * 0x7fff) / (int)vp.width - 0x7fff;
+   int scaled_y = (2 * mouse_y * 0x7fff) / (int)vp.height - 0x7fff;
+   if (scaled_x < -0x7fff || scaled_x > 0x7fff)
+      scaled_x = -0x8000; // OOB
+   if (scaled_y < -0x7fff || scaled_y > 0x7fff)
+      scaled_y = -0x8000; // OOB
+
+   *res_x = scaled_x;
+   *res_y = scaled_y;
+   return true;
+}
+
diff --git a/input/input_common.h b/input/input_common.h
index 5120028223..7adc0f2435 100644
--- a/input/input_common.h
+++ b/input/input_common.h
@@ -46,6 +46,8 @@ static inline void input_conv_analog_id_to_bind_id(unsigned index, unsigned id,
    }
 }
 
+bool input_translate_coord_viewport(int mouse_x, int mouse_y, int16_t *res_x, int16_t *res_y);
+
 typedef struct rarch_joypad_driver
 {
    bool (*init)(void);
diff --git a/input/x11_input.c b/input/x11_input.c
index 6d28c3ee64..5d50b68bcc 100644
--- a/input/x11_input.c
+++ b/input/x11_input.c
@@ -208,6 +208,34 @@ static int16_t x_mouse_state(x11_input_t *x11, unsigned id)
    }
 }
 
+static int16_t x_pointer_state(x11_input_t *x11, unsigned id)
+{
+   int16_t res_x = 0, res_y = 0;
+
+   bool valid = input_translate_coord_viewport(x11->mouse_x, x11->mouse_y, &res_x, &res_y);
+
+   if (!valid)
+      return 0;
+
+   bool inside = (res_x >= -0x7fff) && (res_x <= 0x7fff) &&
+      (res_y >= -0x7fff) && (res_y <= 0x7fff);
+
+   if (!inside)
+      return 0;
+
+   switch (id)
+   {
+      case RETRO_DEVICE_ID_POINTER_X:
+         return res_x;
+      case RETRO_DEVICE_ID_POINTER_Y:
+         return res_y;
+      case RETRO_DEVICE_ID_POINTER_PRESSED:
+         return x11->mouse_l;
+      default:
+         return 0;
+   }
+}
+
 static int16_t x_lightgun_state(x11_input_t *x11, unsigned id)
 {
    switch (id)
@@ -250,6 +278,9 @@ static int16_t x_input_state(void *data, const struct retro_keybind **binds, uns
       case RETRO_DEVICE_MOUSE:
          return x_mouse_state(x11, id);
 
+      case RETRO_DEVICE_POINTER:
+         return x_pointer_state(x11, id);
+
       case RETRO_DEVICE_LIGHTGUN:
          return x_lightgun_state(x11, id);
 
@@ -284,8 +315,8 @@ static void x_input_poll_mouse(x11_input_t *x11)
             &win_x, &win_y,
             &mask);
 
-   x11->mouse_x = root_x;
-   x11->mouse_y = root_y;
+   x11->mouse_x = win_x;
+   x11->mouse_y = win_y;
    x11->mouse_l = mask & Button1Mask; 
    x11->mouse_m = mask & Button2Mask; 
    x11->mouse_r = mask & Button3Mask; 
diff --git a/libretro-test/libretro-test.c b/libretro-test/libretro-test.c
index f589aca059..a579efae29 100644
--- a/libretro-test/libretro-test.c
+++ b/libretro-test/libretro-test.c
@@ -135,6 +135,12 @@ static void update_input(void)
    if (mouse_r)
       fprintf(stderr, "Mouse R pressed.\n");
 
+   bool pointer_pressed = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED);
+   int16_t pointer_x = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
+   int16_t pointer_y = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y);
+   if (pointer_pressed)
+      fprintf(stderr, "Pointer: (%6d, %6d).\n", pointer_x, pointer_y); 
+
    dir_x += input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X) / 2000;
    dir_y += input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) / 2000;
    //dir_x += input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X) / 2000;
diff --git a/libretro.h b/libretro.h
index 3eef758841..f077a17915 100755
--- a/libretro.h
+++ b/libretro.h
@@ -19,7 +19,7 @@ extern "C" {
 #endif
 
 // Used for checking API/ABI mismatches that can break libretro implementations.
-// It is not incremented for compatible changes.
+// It is not incremented for compatible changes to the API.
 #define RETRO_API_VERSION         1
 
 // Libretro's fundamental device abstractions.
@@ -50,6 +50,23 @@ extern "C" {
 // Only use ANALOG type when polling for analog values of the axes.
 #define RETRO_DEVICE_ANALOG       5
 
+// Abstracts the concept of a pointing mechanism, e.g. touch.
+// This allows libretro to query in absolute coordinates where on the screen a mouse (or something similar) is being placed.
+// For a touch centric device, coordinates reported are the coordinates of the press.
+//
+// Coordinates in X and Y are reported as:
+// [-0x7fff, 0x7fff]: -0x7fff corresponds to the far left/top of the screen,
+// and 0x7fff corresponds to the far right/bottom of the screen.
+// The "screen" is here defined as area that is passed to the frontend and later displayed on the monitor.
+// The frontend is free to scale/resize this screen as it sees fit, however,
+// (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the game image, etc.
+//
+// To check if the pointer coordinates are valid (e.g. a touch display actually being touched),
+// PRESSED returns 1 or 0.
+// If using a mouse, PRESSED will usually correspond to the left mouse button.
+// PRESSED will only return 1 if the pointer is inside the game screen.
+#define RETRO_DEVICE_POINTER      6
+
 // These device types are specializations of the base types above.
 // They should only be used in retro_set_controller_type() to inform libretro implementations
 // about use of a very specific device type.
@@ -101,6 +118,11 @@ extern "C" {
 #define RETRO_DEVICE_ID_LIGHTGUN_PAUSE    5
 #define RETRO_DEVICE_ID_LIGHTGUN_START    6
 
+// Id values for POINTER.
+#define RETRO_DEVICE_ID_POINTER_X         0
+#define RETRO_DEVICE_ID_POINTER_Y         1
+#define RETRO_DEVICE_ID_POINTER_PRESSED   2
+
 // Returned from retro_get_region().
 #define RETRO_REGION_NTSC  0
 #define RETRO_REGION_PAL   1
diff --git a/retroarch.c b/retroarch.c
index 6db7446fbe..90e61ed76b 100644
--- a/retroarch.c
+++ b/retroarch.c
@@ -91,10 +91,11 @@ static void set_fast_forward_button(bool new_button_state, bool new_hold_button_
 #if defined(HAVE_SCREENSHOTS) && !defined(_XBOX)
 static bool take_screenshot_viewport(void)
 {
+   struct rarch_viewport vp = {0};
    unsigned width = 0, height = 0;
-   video_viewport_size_func(&width, &height);
+   video_viewport_info_func(&vp);
 
-   if (!width || !height)
+   if (!vp.width || !vp.height)
       return false;
 
    uint8_t *buffer = (uint8_t*)malloc(width * height * 3);
@@ -110,7 +111,7 @@ static bool take_screenshot_viewport(void)
    // Data read from viewport is in bottom-up order, suitable for BMP.
    if (!screenshot_dump(g_settings.screenshot_directory,
          buffer,
-         width, height, width * 3, true))
+         vp.width, vp.height, vp.width * 3, true))
    {
       free(buffer);
       return false;
@@ -141,7 +142,7 @@ static void take_screenshot(void)
 
    bool ret = false;
 
-   if (g_settings.video.gpu_screenshot && driver.video->read_viewport && driver.video->viewport_size)
+   if (g_settings.video.gpu_screenshot && driver.video->read_viewport && driver.video->viewport_info)
       ret = take_screenshot_viewport();
    else if (g_extern.frame_cache.data)
       ret = take_screenshot_raw();
@@ -197,9 +198,9 @@ static void recording_dump_frame(const void *data, unsigned width, unsigned heig
 
    if (g_extern.record_gpu_buffer)
    {
-      unsigned gpu_w = 0, gpu_h = 0;
-      video_viewport_size_func(&gpu_w, &gpu_h);
-      if (!gpu_w || !gpu_h)
+      struct rarch_viewport vp = {0};
+      video_viewport_info_func(&vp);
+      if (!vp.width || !vp.height)
       {
          RARCH_WARN("Viewport size calculation failed! Will continue using raw data. This will probably not work right ...\n");
          free(g_extern.record_gpu_buffer);
@@ -210,7 +211,7 @@ static void recording_dump_frame(const void *data, unsigned width, unsigned heig
       }
 
       // User has resized. We're kinda fucked now.
-      if (gpu_w != g_extern.record_gpu_width || gpu_h != g_extern.record_gpu_height)
+      if (vp.width != g_extern.record_gpu_width || vp.height != g_extern.record_gpu_height)
       {
          static const char msg[] = "Recording terminated due to resize.";
          RARCH_WARN("%s\n", msg);
@@ -1262,10 +1263,10 @@ static void init_recording(void)
 
    if (g_settings.video.gpu_record && driver.video->read_viewport)
    {
-      unsigned width = 0, height = 0;
-      video_viewport_size_func(&width, &height);
+      struct rarch_viewport vp = {0};
+      video_viewport_info_func(&vp);
 
-      if (!width || !height)
+      if (!vp.width || !vp.height)
       {
          RARCH_ERR("Failed to get viewport information from video driver. "
                "Cannot start recording ...\n");
@@ -1273,19 +1274,24 @@ static void init_recording(void)
          return;
       }
 
-      params.out_width           = width;
-      params.out_height          = height;
-      params.fb_width            = next_pow2(width);
-      params.fb_height           = next_pow2(height);
-      params.aspect_ratio        = (float)width / height;
+      params.out_width           = vp.width;
+      params.out_height          = vp.height;
+      params.fb_width            = next_pow2(vp.width);
+      params.fb_height           = next_pow2(vp.height);
+
+      if (g_settings.video.force_aspect && (g_settings.video.aspect_ratio > 0.0f))
+         params.aspect_ratio  = g_settings.video.aspect_ratio;
+      else
+         params.aspect_ratio  = (float)vp.width / vp.height;
+
       params.pix_fmt             = FFEMU_PIX_BGR24;
-      g_extern.record_gpu_width  = width;
-      g_extern.record_gpu_height = height;
+      g_extern.record_gpu_width  = vp.width;
+      g_extern.record_gpu_height = vp.height;
 
       RARCH_LOG("Detected viewport of %u x %u\n",
-            width, height);
+            vp.width, vp.height);
 
-      g_extern.record_gpu_buffer = (uint8_t*)malloc(width * height * 3);
+      g_extern.record_gpu_buffer = (uint8_t*)malloc(vp.width * vp.height * 3);
       if (!g_extern.record_gpu_buffer)
       {
          RARCH_ERR("Failed to allocate GPU record buffer.\n");