GUACAMOLE-249: Defer draws to unrealized (server-side) buffers until they are actually needed client-side.

Though deferred creation of buffers is already intended, creation was
not actually being deferred in practice as the act of initializing the
buffer with a solid rect of color was causing the buffer to be realized,
even if that initialization process is the only drawing operation that
will ever occur to that buffer.
diff --git a/src/common/surface.c b/src/common/surface.c
index c31dfbf..ccac11d 100644
--- a/src/common/surface.c
+++ b/src/common/surface.c
@@ -260,58 +260,67 @@
 
 /**
  * Returns whether the given rectangle should be combined into the existing
- * dirty rectangle, to be eventually flushed as a "png" instruction.
+ * dirty rectangle, to be eventually flushed as image data, or would be best
+ * kept independent of the current rectangle.
  *
- * @param surface The surface to be queried.
- * @param rect The update rectangle.
- * @param rect_only Non-zero if this update, by its nature, contains only
- *                  metainformation about the update's rectangle, zero if
- *                  the update also contains image data.
- * @return Non-zero if the update should be combined with any existing update,
- *         zero otherwise.
+ * @param surface
+ *     The surface being updated.
+ *
+ * @param rect
+ *     The bounding rectangle of the updating being made to the surface.
+ *
+ * @param rect_only
+ *     Non-zero if this update, by its nature, contains only metainformation
+ *     about the update's bounding rectangle, zero if the update also contains
+ *     image data.
+ *
+ * @return
+ *     Non-zero if the update should be combined with any existing update, zero
+ *     otherwise.
  */
 static int __guac_common_should_combine(guac_common_surface* surface, const guac_common_rect* rect, int rect_only) {
 
-    if (surface->dirty) {
+    int combined_cost, dirty_cost, update_cost;
 
-        int combined_cost, dirty_cost, update_cost;
+    /* Always favor combining updates if surface is currently a purely
+     * server-side scratch area */
+    if (!surface->realized)
+        return 1;
 
-        /* Simulate combination */
-        guac_common_rect combined = surface->dirty_rect;
-        guac_common_rect_extend(&combined, rect);
+    /* Simulate combination */
+    guac_common_rect combined = surface->dirty_rect;
+    guac_common_rect_extend(&combined, rect);
 
-        /* Combine if result is still small */
-        if (combined.width <= GUAC_SURFACE_NEGLIGIBLE_WIDTH && combined.height <= GUAC_SURFACE_NEGLIGIBLE_HEIGHT)
+    /* Combine if result is still small */
+    if (combined.width <= GUAC_SURFACE_NEGLIGIBLE_WIDTH && combined.height <= GUAC_SURFACE_NEGLIGIBLE_HEIGHT)
+        return 1;
+
+    /* Estimate costs of the existing update, new update, and both combined */
+    combined_cost = GUAC_SURFACE_BASE_COST + combined.width * combined.height;
+    dirty_cost    = GUAC_SURFACE_BASE_COST + surface->dirty_rect.width * surface->dirty_rect.height;
+    update_cost   = GUAC_SURFACE_BASE_COST + rect->width * rect->height;
+
+    /* Reduce cost if no image data */
+    if (rect_only)
+        update_cost /= GUAC_SURFACE_DATA_FACTOR;
+
+    /* Combine if cost estimate shows benefit */
+    if (combined_cost <= update_cost + dirty_cost)
+        return 1;
+
+    /* Combine if increase in cost is negligible */
+    if (combined_cost - dirty_cost <= dirty_cost / GUAC_SURFACE_NEGLIGIBLE_INCREASE)
+        return 1;
+
+    if (combined_cost - update_cost <= update_cost / GUAC_SURFACE_NEGLIGIBLE_INCREASE)
+        return 1;
+
+    /* Combine if we anticipate further updates, as this update follows a common fill pattern */
+    if (rect->x == surface->dirty_rect.x && rect->y == surface->dirty_rect.y + surface->dirty_rect.height) {
+        if (combined_cost <= (dirty_cost + update_cost) * GUAC_SURFACE_FILL_PATTERN_FACTOR)
             return 1;
-
-        /* Estimate costs of the existing update, new update, and both combined */
-        combined_cost = GUAC_SURFACE_BASE_COST + combined.width * combined.height;
-        dirty_cost    = GUAC_SURFACE_BASE_COST + surface->dirty_rect.width * surface->dirty_rect.height;
-        update_cost   = GUAC_SURFACE_BASE_COST + rect->width * rect->height;
-
-        /* Reduce cost if no image data */
-        if (rect_only)
-            update_cost /= GUAC_SURFACE_DATA_FACTOR;
-
-        /* Combine if cost estimate shows benefit */
-        if (combined_cost <= update_cost + dirty_cost)
-            return 1;
-
-        /* Combine if increase in cost is negligible */
-        if (combined_cost - dirty_cost <= dirty_cost / GUAC_SURFACE_NEGLIGIBLE_INCREASE)
-            return 1;
-
-        if (combined_cost - update_cost <= update_cost / GUAC_SURFACE_NEGLIGIBLE_INCREASE)
-            return 1;
-
-        /* Combine if we anticipate further updates, as this update follows a common fill pattern */
-        if (rect->x == surface->dirty_rect.x && rect->y == surface->dirty_rect.y + surface->dirty_rect.height) {
-            if (combined_cost <= (dirty_cost + update_cost) * GUAC_SURFACE_FILL_PATTERN_FACTOR)
-                return 1;
-        }
-
     }
-    
+
     /* Otherwise, do not combine */
     return 0;