diff -u b/src/st/st-theme-node-drawing.c b/src/st/st-theme-node-drawing.c
--- b/src/st/st-theme-node-drawing.c
+++ b/src/st/st-theme-node-drawing.c
@@ -209,7 +209,9 @@
 
   /* We ignore the material color, which encodes the overall opacity of the
    * actor, so setting an ancestor of the shadow to partially opaque won't
-   * work. The easiest way to fix this would be to override paint(). */
+   * work. The easiest way to fix this would be to not set the combine or constant color
+   * here, then in paint set the material color to the shadow_spec_color *
+   * paint_opacity.*/
   cogl_material_set_layer_combine (material, 0,
                                    "RGBA = MODULATE (CONSTANT, TEXTURE[A])",
                                    NULL);
@@ -328,7 +330,7 @@
 static char *
 corner_to_string (StCornerSpec *corner)
 {
-  return g_strdup_printf ("st-theme-node-corner:%u%u%u%u,%u%u%u%u,%u%u%u%u,%u,%u,%u",
+  return g_strdup_printf ("st-theme-node-corner:%02x%02x%02x%02x,%02x%02x%02x%02x,%02x%02x%02x%02x,%u,%u,%u",
                           corner->color.red, corner->color.blue, corner->color.green, corner->color.alpha,
                           corner->border_color_1.red, corner->border_color_1.green, corner->border_color_1.blue, corner->border_color_1.alpha,
                           corner->border_color_2.red, corner->border_color_2.green, corner->border_color_2.blue, corner->border_color_2.alpha,
@@ -459,27 +461,27 @@
 }
 
 static void
-get_background_allocation (StThemeNode             *self,
-                           const ClutterActorBox   *allocation,
-                           ClutterActorBox         *box)
+get_background_position (StThemeNode             *self,
+                         const ClutterActorBox   *allocation,
+                         ClutterActorBox         *result)
 {
   gfloat w, h;
 
-  box->x1 = box->y1 = 0;
-  box->x2 = allocation->x2 - allocation->x1;
-  box->y2 = allocation->y2 - allocation->y1;
+  result->x1 = result->y1 = 0;
+  result->x2 = allocation->x2 - allocation->x1;
+  result->y2 = allocation->y2 - allocation->y1;
 
   w = cogl_texture_get_width (self->background_texture);
   h = cogl_texture_get_height (self->background_texture);
 
   /* scale the background into the allocated bounds */
-  if (w > box->x2 || h > box->y2)
+  if (w > result->x2 || h > result->y2)
     {
       gint new_h, new_w, offset;
       gint box_w, box_h;
 
-      box_w = (int) box->x2;
-      box_h = (int) box->y2;
+      box_w = (int) result->x2;
+      box_h = (int) result->y2;
 
       /* scale to fit */
       new_h = (int)((h / w) * ((gfloat) box_w));
@@ -489,28 +491,28 @@
         {
           /* center for new width */
           offset = ((box_w) - new_w) * 0.5;
-          box->x1 = offset;
-          box->x2 = offset + new_w;
+          result->x1 = offset;
+          result->x2 = offset + new_w;
 
-          box->y2 = box_h;
+          result->y2 = box_h;
         }
       else
         {
           /* center for new height */
           offset = ((box_h) - new_h) * 0.5;
-          box->y1 = offset;
-          box->y2 = offset + new_h;
+          result->y1 = offset;
+          result->y2 = offset + new_h;
 
-          box->x2 = box_w;
+          result->x2 = box_w;
         }
     }
   else
     {
       /* center the background on the widget */
-      box->x1 = (int)(((allocation->x2 - allocation->x1) / 2) - (w / 2));
-      box->y1 = (int)(((allocation->y2 - allocation->y1) / 2) - (h / 2));
-      box->x2 = box->x1 + w;
-      box->y2 = box->y1 + h;
+      result->x1 = (int)(((allocation->x2 - allocation->x1) / 2) - (w / 2));
+      result->y1 = (int)(((allocation->y2 - allocation->y1) / 2) - (h / 2));
+      result->x2 = result->x1 + w;
+      result->y2 = result->y1 + h;
     }
 }
 
@@ -529,7 +531,8 @@
     {
       if (width)
         *width = w;
-      st_theme_node_get_border_color (node, ST_SIDE_TOP, color);
+      if (color)
+        st_theme_node_get_border_color (node, ST_SIDE_TOP, color);
       return TRUE;
     }
 
@@ -666,10 +669,9 @@
                                         rowstride,
                                         data);
 
-  g_free (data);
-  cairo_surface_destroy (surface);
-
   cairo_destroy (cr);
+  cairo_surface_destroy (surface);
+  g_free (data);
 
   return texture;
 }
@@ -727,9 +729,6 @@
 
       filename = st_border_image_get_filename (border_image);
 
-      /* `border-image' takes precedence over `background-image'.
-       * Firefox lets the background-image shine thru when border-image has
-       * alpha an channel, maybe that would be an option for the future. */
       node->border_texture = st_texture_cache_load_file_to_cogl_texture (texture_cache, filename);
     }
   else if (node->background_gradient_type != ST_GRADIENT_NONE)
@@ -759,6 +758,14 @@
                             ClutterActorBox *box,
                             guint8           paint_opacity)
 {
+  if (paint_opacity == 255)
+    {
+      /* https://bugzilla.gnome.org/show_bug.cgi?id=607500#c47 */
+      cogl_set_source_texture (texture);
+      cogl_rectangle (box->x1, box->y1, box->x2, box->y2);
+      return;
+    }
+
   CoglHandle material;
 
   material = cogl_material_new ();
@@ -846,8 +853,6 @@
   /* corners */
   if (node->corner_texture != COGL_INVALID_HANDLE)
     {
-      guint i;
-
       material = cogl_material_new ();
       cogl_material_set_layer (material, 0, node->corner_texture);
       cogl_material_set_color4ub (material,
@@ -855,24 +860,10 @@
 
       cogl_set_source (material);
 
-      for (i = 0; i < 4; i++)
-        {
-          switch (i)
-            {
-              case ST_CORNER_TOPLEFT:
-                cogl_rectangle_with_texture_coords (0, 0, max_width_radius, max_width_radius, 0, 0, 0.5, 0.5);
-                break;
-              case ST_CORNER_TOPRIGHT:
-                cogl_rectangle_with_texture_coords (width - max_width_radius, 0, width, max_width_radius, 0.5, 0, 1, 0.5);
-                break;
-              case ST_CORNER_BOTTOMRIGHT:
-                cogl_rectangle_with_texture_coords (width - max_width_radius, height - max_width_radius, width, height, 0.5, 0.5, 1, 1);
-                break;
-              case ST_CORNER_BOTTOMLEFT:
-                cogl_rectangle_with_texture_coords (0, height - max_width_radius, max_width_radius, height, 0, 0.5, 0.5, 1);
-                break;
-            }
-        }
+      cogl_rectangle_with_texture_coords (0, 0, max_width_radius, max_width_radius, 0, 0, 0.5, 0.5);
+      cogl_rectangle_with_texture_coords (width - max_width_radius, 0, width, max_width_radius, 0.5, 0, 1, 0.5);
+      cogl_rectangle_with_texture_coords (width - max_width_radius, height - max_width_radius, width, height, 0.5, 0.5, 1, 1);
+      cogl_rectangle_with_texture_coords (0, height - max_width_radius, max_width_radius, height, 0, 0.5, 0.5, 1);
 
       cogl_handle_unref (material);
     }
@@ -1067,7 +1058,7 @@
     {
       ClutterActorBox background_box;
 
-      get_background_allocation (node, &allocation, &background_box);
+      get_background_position (node, &allocation, &background_box);
 
       /* CSS based drop shadows
        *
@@ -1081,7 +1072,7 @@
        * image (we could exend this in the future to take other CSS properties
        * like boder and background color into account).
        */
-      if (node->shadow_material)
+      if (node->shadow_material != COGL_INVALID_HANDLE)
         {
           StShadow *shadow_spec;
           ClutterActorBox shadow_box;

