dpxswu (diff, doesn't expire)
diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index c503ad6a6..722122b66 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -298,7 +298,7 @@ ephyrShadowUpdate(ScreenPtr pScreen, shadowBufPtr pBuf)
      * pBuf->pDamage  regions
      */
     shadowUpdateRotatePacked(pScreen, pBuf);
-    hostx_paint_rect(screen, 0, 0, 0, 0, screen->width, screen->height);
+    hostx_paint_rect(screen, 0, 0, 0, 0, screen->width*SCALE, screen->height*SCALE);
 }
 
 static void
@@ -918,8 +918,8 @@ ephyrProcessMouseMotion(xcb_generic_event_t *xev)
         int x = 0, y = 0;
 
         EPHYR_LOG("enqueuing mouse motion:%d\n", screen->pScreen->myNum);
-        x = motion->event_x;
-        y = motion->event_y;
+        x = motion->event_x / SCALE;
+        y = motion->event_y / SCALE;
         EPHYR_LOG("initial (x,y):(%d,%d)\n", x, y);
 
         /* convert coords into desktop-wide coordinates.
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index a5b2e344e..07868a38f 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -618,8 +618,8 @@ hostx_init(void)
                               scrpriv->win,
                               scrpriv->win_pre_existing,
                               0,0,
-                              scrpriv->win_width,
-                              scrpriv->win_height,
+                              scrpriv->win_width * SCALE,
+                              scrpriv->win_height * SCALE,
                               0,
                               XCB_WINDOW_CLASS_COPY_FROM_PARENT,
                               HostX.visual->visual_id,
@@ -904,15 +904,15 @@ hostx_screen_init(KdScreenInfo *screen,
 
     if (!ephyr_glamor && HostX.have_shm) {
         scrpriv->ximg = xcb_image_create_native(HostX.conn,
-                                                width,
-                                                buffer_height,
+                                                width * SCALE,
+                                                buffer_height * SCALE,
                                                 XCB_IMAGE_FORMAT_Z_PIXMAP,
                                                 HostX.depth,
                                                 NULL,
                                                 ~0,
                                                 NULL);
 
-        scrpriv->shmsize = scrpriv->ximg->stride * buffer_height;
+        scrpriv->shmsize = scrpriv->ximg->stride * buffer_height * SCALE;
         if (!hostx_create_shm_segment(&scrpriv->shminfo,
                                       scrpriv->shmsize)) {
             EPHYR_DBG
@@ -931,8 +931,8 @@ hostx_screen_init(KdScreenInfo *screen,
         EPHYR_DBG("Creating image %dx%d for screen scrpriv=%p\n",
                   width, buffer_height, scrpriv);
         scrpriv->ximg = xcb_image_create_native(HostX.conn,
-                                                    width,
-                                                    buffer_height,
+                                                    width * SCALE,
+                                                    buffer_height * SCALE,
                                                     XCB_IMAGE_FORMAT_Z_PIXMAP,
                                                     HostX.depth,
                                                     NULL,
@@ -945,21 +945,21 @@ hostx_screen_init(KdScreenInfo *screen,
             scrpriv->ximg->byte_order = IMAGE_BYTE_ORDER;
 
         scrpriv->ximg->data =
-            xallocarray(scrpriv->ximg->stride, buffer_height);
+            xallocarray(scrpriv->ximg->stride, buffer_height * SCALE);
     }
 
     if (!HostX.size_set_from_configure)
     {
         uint32_t mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
-        uint32_t values[2] = {width, height};
+        uint32_t values[2] = {width * SCALE, height * SCALE};
         xcb_configure_window(HostX.conn, scrpriv->win, mask, values);
     }
 
     if (scrpriv->win_pre_existing == None && !EphyrWantResize) {
         /* Ask the WM to keep our size static */
         xcb_size_hints_t size_hints = {0};
-        size_hints.max_width = size_hints.min_width = width;
-        size_hints.max_height = size_hints.min_height = height;
+        size_hints.max_width = size_hints.min_width = width * SCALE;
+        size_hints.max_height = size_hints.min_height = height * SCALE;
         size_hints.flags = (XCB_ICCCM_SIZE_HINT_P_MIN_SIZE |
                             XCB_ICCCM_SIZE_HINT_P_MAX_SIZE);
         xcb_icccm_set_wm_normal_hints(HostX.conn, scrpriv->win,
@@ -991,6 +991,7 @@ hostx_screen_init(KdScreenInfo *screen,
     scrpriv->win_x = x;
     scrpriv->win_y = y;
 
+    if (SCALE != 1) assert(scrpriv->ximg->bpp == 32);
 #ifdef GLAMOR
     if (ephyr_glamor) {
         *bytes_per_line = 0;
@@ -999,7 +1000,7 @@ hostx_screen_init(KdScreenInfo *screen,
         return NULL;
     } else
 #endif
-    if (host_depth_matches_server(scrpriv)) {
+    if (SCALE == 1 && host_depth_matches_server(scrpriv)) {
         *bytes_per_line = scrpriv->ximg->stride;
         *bits_per_pixel = scrpriv->ximg->bpp;
 
@@ -1007,11 +1008,12 @@ hostx_screen_init(KdScreenInfo *screen,
         return scrpriv->ximg->data;
     }
     else {
-        int bytes_per_pixel = scrpriv->server_depth >> 3;
+        int server_depth = scrpriv->server_depth == 24 ? 32 : scrpriv->server_depth;
+        int bytes_per_pixel = server_depth >> 3;
         int stride = (width * bytes_per_pixel + 0x3) & ~0x3;
 
         *bytes_per_line = stride;
-        *bits_per_pixel = scrpriv->server_depth;
+        *bits_per_pixel = server_depth;
 
         EPHYR_DBG("server bpp %i", bytes_per_pixel);
         scrpriv->fb_data = xallocarray (stride, buffer_height);
@@ -1091,34 +1093,52 @@ hostx_paint_rect(KdScreenInfo *screen,
 
                     host_pixel = (r << 16) | (g << 8) | (b);
 
-                    xcb_image_put_pixel(scrpriv->ximg, x, y, host_pixel);
+                    for (int yp = 0; yp < SCALE; ++yp)
+                        for (int xp = 0; xp < SCALE; ++xp)
+                            xcb_image_put_pixel(scrpriv->ximg, x*SCALE+xp, y*SCALE+yp, host_pixel);
                     break;
                 }
                 case 8:
                 {
                     unsigned char pixel =
                         *(unsigned char *) (scrpriv->fb_data + idx);
-                    xcb_image_put_pixel(scrpriv->ximg, x, y,
-                                        scrpriv->cmap[pixel]);
+                    host_pixel = scrpriv->cmap[pixel];
+
+                    for (int yp = 0; yp < SCALE; ++yp)
+                        for (int xp = 0; xp < SCALE; ++xp)
+                            xcb_image_put_pixel(scrpriv->ximg, x*SCALE+xp, y*SCALE+yp, host_pixel);
                     break;
                 }
                 default:
                     break;
                 }
             }
+    } else if (SCALE != 1) {
+        uint32_t* dst = (uint32_t*) scrpriv->ximg->data;
+        uint32_t* src = (uint32_t*) scrpriv->fb_data;
+        size_t src_stride = scrpriv->win_width;
+        size_t dst_stride = scrpriv->ximg->stride/4;
+        for (int y = sy; y < sy + height; ++y)
+            for (int x = sx; x < sx + width; ++x) {
+                uint32_t val = src[y * src_stride + x];
+                for (int yp = 0; yp < SCALE; ++yp)
+                    for (int xp = 0; xp < SCALE; ++xp)
+                        dst[(y*SCALE+yp) * dst_stride + (x*SCALE+xp)] = val;
+            }
     }
 
     if (HostX.have_shm) {
         xcb_image_shm_put(HostX.conn, scrpriv->win,
                           HostX.gc, scrpriv->ximg,
                           scrpriv->shminfo,
-                          sx, sy, dx, dy, width, height, FALSE);
+                          sx*SCALE, sy*SCALE, dx*SCALE, dy*SCALE,
+                          width*SCALE, height*SCALE, FALSE);
     }
     else {
-        xcb_image_t *subimg = xcb_image_subimage(scrpriv->ximg, sx, sy,
-                                                 width, height, 0, 0, 0);
+        xcb_image_t *subimg = xcb_image_subimage(scrpriv->ximg, sx*SCALE, sy*SCALE,
+                                                 width*SCALE, height*SCALE, 0, 0, 0);
         xcb_image_t *img = xcb_image_native(HostX.conn, subimg, 1);
-        xcb_image_put(HostX.conn, scrpriv->win, HostX.gc, img, dx, dy, 0);
+        xcb_image_put(HostX.conn, scrpriv->win, HostX.gc, img, dx*SCALE, dy*SCALE, 0);
         if (subimg != img)
             xcb_image_destroy(img);
         xcb_image_destroy(subimg);
@@ -1133,7 +1153,10 @@ hostx_paint_debug_rect(KdScreenInfo *screen,
 {
     EphyrScrPriv *scrpriv = screen->driver;
     struct timespec tspec;
-    xcb_rectangle_t rect = { .x = x, .y = y, .width = width, .height = height };
+    xcb_rectangle_t rect = {
+        .x = x * SCALE, .y = y * SCALE,
+        .width = width * SCALE, .height = height * SCALE
+    };
     xcb_void_cookie_t cookie;
     xcb_generic_error_t *e;
 
@@ -1471,7 +1494,7 @@ hostx_create_window(int a_screen_number,
                       win,
                       hostx_get_window (a_screen_number),
                       a_geometry->x, a_geometry->y,
-                      a_geometry->width, a_geometry->height, 0,
+                      a_geometry->width * SCALE, a_geometry->height * SCALE, 0,
                       XCB_WINDOW_CLASS_COPY_FROM_PARENT,
                       a_visual_id, winmask, attrs);
 
@@ -1514,8 +1537,8 @@ hostx_set_window_geometry(int a_win, EphyrBox * a_geo)
 
     values[0] = a_geo->x;
     values[1] = a_geo->y;
-    values[2] = a_geo->width;
-    values[3] = a_geo->height;
+    values[2] = a_geo->width * SCALE;
+    values[3] = a_geo->height * SCALE;
     xcb_configure_window(HostX.conn, a_win, mask, values);
 
     EPHYR_LOG("leave\n");
diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h
index 4b2678e58..cfce75d30 100644
--- a/hw/kdrive/ephyr/hostx.h
+++ b/hw/kdrive/ephyr/hostx.h
@@ -32,6 +32,8 @@
 #include <xcb/render.h>
 #include "ephyr.h"
 
+#define SCALE 2
+
 #define EPHYR_WANT_DEBUG 0
 
 #if (EPHYR_WANT_DEBUG)