diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index f15b942..740f21e 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -1,12 +1,28 @@
+# Zero-Clause BSD License
+
+# Copyright (C) 2023 Toitware ApS.
+
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted.
+
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+# FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
 name: Publish package
 on:
   push:
     tags:
-    - 'v*'
+    - 'v[0-9]+.[0-9]+.[0-9]+'
+    - 'v[0-9]+.[0-9]+.[0-9]+-*'
 jobs:
   create-release:
     name: Create new release
     runs-on: ubuntu-latest
     steps:
       - name: Publish
-        uses: toitlang/pkg-publish@v1.0.2
+        uses: toitlang/pkg-publish@v1.3.0
diff --git a/src/four_gray.toit b/src/four_gray.toit
index 7a2ae81..f300e5c 100644
--- a/src/four_gray.toit
+++ b/src/four_gray.toit
@@ -117,7 +117,7 @@ class OpaquePixmapTexture extends BitmapTextureBase_:
     bitmap_zap bytes_ color & 1
     bitmap_zap bytes_2_ (color & 2) >> 1
 
-  write2_ canvas/Canvas:
+  write2_ canvas/TwoBitCanvas_:
     transform_.xywh x_ y_ w_ h_: | x2 y2 w2 h2 |
       x := x2 - canvas.x_offset_
       y := y2 - canvas.y_offset_
@@ -126,7 +126,7 @@ class OpaquePixmapTexture extends BitmapTextureBase_:
       bitmap_rectangle x y 0 w2 h2 canvas.plane_1_ canvas.width_
     super canvas  // Calls draw_
 
-  draw_ bx by orientation canvas/Canvas:
+  draw_ bx by orientation canvas/TwoBitCanvas_:
     // The area was already zeroed, add in the 1s as needed.
     bitmap_draw_bitmap bx by 1 orientation bytes_ 0 w canvas.plane_0_ canvas.width_ false
     bitmap_draw_bitmap bx by 1 orientation bytes_2_ 0 w canvas.plane_1_ canvas.width_ false
@@ -161,8 +161,8 @@ class RoundedCornerWindow extends RoundedCornerWindow_:
   constructor x y w h transform corner_radius .background_color:
     super x y w h transform corner_radius
 
-  make_alpha_map_ canvas/Canvas padding:
-    return ByteArray (canvas.width_ + padding) * (canvas.height_ + padding)
+  make_alpha_map_ canvas/TwoBitCanvas_ padding:
+    return ByteArray ((canvas.width_ + padding) * (canvas.height_ + padding)) >> 3
 
   make_opaque_ x y w h map map_width --frame/bool:
     assert: not frame
@@ -175,11 +175,11 @@ class RoundedCornerWindow extends RoundedCornerWindow_:
       if 0 <= y_offset < map.size:
         map[x + y_offset] = opacity
 
-  draw_background canvas/Canvas:
+  draw_background canvas/TwoBitCanvas_:
     bytemap_zap canvas.plane_0_ (background_color & 1)
     bytemap_zap canvas.plane_1_ (background_color & 2) >> 1
 
-  draw_frame canvas/Canvas:
+  draw_frame canvas/TwoBitCanvas_:
     throw "UNREACHABLE"
 
 class DropShadowWindow extends DropShadowWindow_:
@@ -192,7 +192,7 @@ class DropShadowWindow extends DropShadowWindow_:
     max_shadow_opacity_ = (shadow_opacity_percent * 2.5500001).to_int
     super x y w h transform corner_radius blur_radius drop_distance_x drop_distance_y
 
-  make_alpha_map_ canvas/Canvas padding:
+  make_alpha_map_ canvas/TwoBitCanvas_ padding:
     return ByteArray (canvas.width_ + padding) * (canvas.height_ + padding)
 
   make_opaque_ x y w h map map_width --frame/bool:
@@ -207,10 +207,10 @@ class DropShadowWindow extends DropShadowWindow_:
         else:
           map[x + y_offset] = opacity
 
-  draw_background canvas/Canvas:
+  draw_background canvas/TwoBitCanvas_:
     bytemap_zap canvas.plane_0_ (background_color & 1)
     bytemap_zap canvas.plane_1_ (background_color & 2) >> 1
 
-  draw_frame canvas/Canvas:
+  draw_frame canvas/TwoBitCanvas_:
     bytemap_zap canvas.plane_0_ 0
     bytemap_zap canvas.plane_1_ 0
diff --git a/src/pixel_display.toit b/src/pixel_display.toit
index c3aaf73..3547dcf 100644
--- a/src/pixel_display.toit
+++ b/src/pixel_display.toit
@@ -345,13 +345,12 @@ abstract class PixelDisplay implements Window:
     speed_ = speed
     if speed < 10 or driver_.flags & FLAG_PARTIAL_UPDATES == 0:
       draw_entire_display_
+      if dirty_: bitmap_zap dirty_ CLEAN_
       return
 
     // Send data for the whole screen, even if only part of it changed.
     if speed < 50: all_is_dirty_
 
-    // TODO(kasper): Once we've started a partial update, we need to make sure we refresh,
-    // because otherwise the lock in the display code in the kernel will not be released.
     driver_.start_partial_update speed
     refreshed := false
     try:
diff --git a/tests/texture_test_slow.toit b/tests/texture_test_slow.toit
index 160d776..6588320 100644
--- a/tests/texture_test_slow.toit
+++ b/tests/texture_test_slow.toit
@@ -11,6 +11,7 @@ import pixel_display.histogram show *
 import pixel_display.texture show *
 
 import pixel_display.four_gray
+import pixel_display.two_bit_texture as two_bit
 import pixel_display.three_color
 import pixel_display.true_color
 import pixel_display.two_color