Index: uspace/lib/guigfx/private/canvas.h
===================================================================
--- uspace/lib/guigfx/private/canvas.h	(revision cea9f0cdb1a2d2752bc931602d11342eb862c44e)
+++ uspace/lib/guigfx/private/canvas.h	(revision f8375f741d0ccd376851c593af6a16c2591aa927)
@@ -48,4 +48,6 @@
 /** Actual structure of canvas GC. */
 struct canvas_gc {
+	/** Memory GC */
+	mem_gc_t *mgc;
 	/** Base graphic context */
 	gfx_context_t *gc;
@@ -54,17 +56,5 @@
 	/** Surface */
 	surface_t *surface;
-	/** Memory GC */
-	mem_gc_t *mgc;
-	/** Base GC for memory GC */
-	gfx_context_t *mbgc;
 };
-
-/** Bitmap in canvas GC */
-typedef struct {
-	/** Containing canvas GC */
-	struct canvas_gc *cgc;
-	/** Memory GC bitmap */
-	gfx_bitmap_t *mbitmap;
-} canvas_gc_bitmap_t;
 
 #endif
Index: uspace/lib/guigfx/src/canvas.c
===================================================================
--- uspace/lib/guigfx/src/canvas.c	(revision cea9f0cdb1a2d2752bc931602d11342eb862c44e)
+++ uspace/lib/guigfx/src/canvas.c	(revision f8375f741d0ccd376851c593af6a16c2591aa927)
@@ -49,55 +49,5 @@
 //#include "../../private/color.h"
 
-static errno_t canvas_gc_set_color(void *, gfx_color_t *);
-static errno_t canvas_gc_fill_rect(void *, gfx_rect_t *);
-static errno_t canvas_gc_bitmap_create(void *, gfx_bitmap_params_t *,
-    gfx_bitmap_alloc_t *, void **);
-static errno_t canvas_gc_bitmap_destroy(void *);
-static errno_t canvas_gc_bitmap_render(void *, gfx_rect_t *, gfx_coord2_t *);
-static errno_t canvas_gc_bitmap_get_alloc(void *, gfx_bitmap_alloc_t *);
-
-gfx_context_ops_t canvas_gc_ops = {
-	.set_color = canvas_gc_set_color,
-	.fill_rect = canvas_gc_fill_rect,
-	.bitmap_create = canvas_gc_bitmap_create,
-	.bitmap_destroy = canvas_gc_bitmap_destroy,
-	.bitmap_render = canvas_gc_bitmap_render,
-	.bitmap_get_alloc = canvas_gc_bitmap_get_alloc
-};
-
-/** Set color on canvas GC.
- *
- * Set drawing color on canvas GC.
- *
- * @param arg Canvas GC
- * @param color Color
- *
- * @return EOK on success or an error code
- */
-static errno_t canvas_gc_set_color(void *arg, gfx_color_t *color)
-{
-	canvas_gc_t *cgc = (canvas_gc_t *) arg;
-
-	return gfx_set_color(cgc->mbgc, color);
-}
-
-/** Fill rectangle on canvas GC.
- *
- * @param arg Canvas GC
- * @param rect Rectangle
- *
- * @return EOK on success or an error code
- */
-static errno_t canvas_gc_fill_rect(void *arg, gfx_rect_t *rect)
-{
-	canvas_gc_t *cgc = (canvas_gc_t *) arg;
-	errno_t rc;
-
-	rc = gfx_fill_rect(cgc->mbgc, rect);
-	if (rc == EOK)
-		update_canvas(cgc->canvas, cgc->surface);
-
-	return rc;
-}
+static void canvas_gc_update_cb(void *, gfx_rect_t *);
 
 /** Create canvas GC.
@@ -115,5 +65,4 @@
 {
 	canvas_gc_t *cgc = NULL;
-	gfx_context_t *gc = NULL;
 	surface_coord_t w, h;
 	gfx_rect_t rect;
@@ -129,8 +78,4 @@
 	}
 
-	rc = gfx_context_new(&canvas_gc_ops, cgc, &gc);
-	if (rc != EOK)
-		goto error;
-
 	rect.p0.x = 0;
 	rect.p0.y = 0;
@@ -142,11 +87,11 @@
 	alloc.pixels = surface_direct_access(surface);
 
-	rc = mem_gc_create(&rect, &alloc, &cgc->mgc);
+	rc = mem_gc_create(&rect, &alloc, canvas_gc_update_cb,
+	    (void *)cgc, &cgc->mgc);
 	if (rc != EOK)
 		goto error;
 
-	cgc->mbgc = mem_gc_get_ctx(cgc->mgc);
+	cgc->gc = mem_gc_get_ctx(cgc->mgc);
 
-	cgc->gc = gc;
 	cgc->canvas = canvas;
 	cgc->surface = surface;
@@ -154,6 +99,4 @@
 	return EOK;
 error:
-	if (gc != NULL)
-		gfx_context_delete(gc);
 	if (cgc != NULL)
 		free(cgc);
@@ -189,85 +132,14 @@
 }
 
-/** Create bitmap in canvas GC.
+/** Canvas GC update callback called by memory GC.
  *
  * @param arg Canvas GC
- * @param params Bitmap params
- * @param alloc Bitmap allocation info or @c NULL
- * @param rbm Place to store pointer to new bitmap
- * @return EOK on success or an error code
+ * @param rect Rectangle to update
  */
-errno_t canvas_gc_bitmap_create(void *arg, gfx_bitmap_params_t *params,
-    gfx_bitmap_alloc_t *alloc, void **rbm)
+static void canvas_gc_update_cb(void *arg, gfx_rect_t *rect)
 {
-	canvas_gc_t *cgc = (canvas_gc_t *) arg;
-	canvas_gc_bitmap_t *cbm = NULL;
-	errno_t rc;
+	canvas_gc_t *cgc = (canvas_gc_t *)arg;
 
-	cbm = calloc(1, sizeof(canvas_gc_bitmap_t));
-	if (cbm == NULL)
-		return ENOMEM;
-
-	rc = gfx_bitmap_create(cgc->mbgc, params, alloc, &cbm->mbitmap);
-	if (rc != EOK)
-		goto error;
-
-	cbm->cgc = cgc;
-	*rbm = (void *)cbm;
-	return EOK;
-error:
-	if (cbm != NULL)
-		free(cbm);
-	return rc;
-}
-
-/** Destroy bitmap in canvas GC.
- *
- * @param bm Bitmap
- * @return EOK on success or an error code
- */
-static errno_t canvas_gc_bitmap_destroy(void *bm)
-{
-	canvas_gc_bitmap_t *cbm = (canvas_gc_bitmap_t *)bm;
-	errno_t rc;
-
-	rc = gfx_bitmap_destroy(cbm->mbitmap);
-	if (rc != EOK)
-		return rc;
-
-	free(cbm);
-	return EOK;
-}
-
-/** Render bitmap in canvas GC.
- *
- * @param bm Bitmap
- * @param srect0 Source rectangle or @c NULL
- * @param offs0 Offset or @c NULL
- * @return EOK on success or an error code
- */
-static errno_t canvas_gc_bitmap_render(void *bm, gfx_rect_t *srect0,
-    gfx_coord2_t *offs0)
-{
-	canvas_gc_bitmap_t *cbm = (canvas_gc_bitmap_t *)bm;
-	errno_t rc;
-
-	rc = gfx_bitmap_render(cbm->mbitmap, srect0, offs0);
-	if (rc == EOK)
-		update_canvas(cbm->cgc->canvas, cbm->cgc->surface);
-
-	return rc;
-}
-
-/** Get allocation info for bitmap in canvas GC.
- *
- * @param bm Bitmap
- * @param alloc Place to store allocation info
- * @return EOK on success or an error code
- */
-static errno_t canvas_gc_bitmap_get_alloc(void *bm, gfx_bitmap_alloc_t *alloc)
-{
-	canvas_gc_bitmap_t *cbm = (canvas_gc_bitmap_t *)bm;
-
-	return gfx_bitmap_get_alloc(cbm->mbitmap, alloc);
+	update_canvas(cgc->canvas, cgc->surface);
 }
 
Index: uspace/lib/memgfx/include/memgfx/memgc.h
===================================================================
--- uspace/lib/memgfx/include/memgfx/memgc.h	(revision cea9f0cdb1a2d2752bc931602d11342eb862c44e)
+++ uspace/lib/memgfx/include/memgfx/memgc.h	(revision f8375f741d0ccd376851c593af6a16c2591aa927)
@@ -40,5 +40,4 @@
 #include <types/gfx/bitmap.h>
 #include <types/gfx/context.h>
-#include <types/gfx/coord.h>
 #include <types/gfx/ops/context.h>
 #include <types/memgfx/memgc.h>
@@ -46,9 +45,8 @@
 extern gfx_context_ops_t mem_gc_ops;
 
-extern errno_t mem_gc_create(gfx_rect_t *, gfx_bitmap_alloc_t *, mem_gc_t **);
+extern errno_t mem_gc_create(gfx_rect_t *, gfx_bitmap_alloc_t *,
+    mem_gc_update_cb_t, void *, mem_gc_t **);
 extern errno_t mem_gc_delete(mem_gc_t *);
 extern gfx_context_t *mem_gc_get_ctx(mem_gc_t *);
-extern void mem_gc_get_update_rect(mem_gc_t *, gfx_rect_t *);
-extern void mem_gc_clear_update_rect(mem_gc_t *);
 
 #endif
Index: uspace/lib/memgfx/include/types/memgfx/memgc.h
===================================================================
--- uspace/lib/memgfx/include/types/memgfx/memgc.h	(revision cea9f0cdb1a2d2752bc931602d11342eb862c44e)
+++ uspace/lib/memgfx/include/types/memgfx/memgc.h	(revision f8375f741d0ccd376851c593af6a16c2591aa927)
@@ -37,6 +37,10 @@
 #define _MEMGFX_TYPES_MEMGC_H
 
+#include <types/gfx/coord.h>
+
 struct mem_gc;
 typedef struct mem_gc mem_gc_t;
+
+typedef void (*mem_gc_update_cb_t)(void *, gfx_rect_t *);
 
 #endif
Index: uspace/lib/memgfx/private/memgc.h
===================================================================
--- uspace/lib/memgfx/private/memgc.h	(revision cea9f0cdb1a2d2752bc931602d11342eb862c44e)
+++ uspace/lib/memgfx/private/memgc.h	(revision f8375f741d0ccd376851c593af6a16c2591aa927)
@@ -49,8 +49,10 @@
 	/** Bounding rectangle */
 	gfx_rect_t rect;
-	/** Update rectangle */
-	gfx_rect_t upd_rect;
 	/** Allocation info */
 	gfx_bitmap_alloc_t alloc;
+	/** Update callback */
+	mem_gc_update_cb_t update;
+	/** Argument to callback */
+	void *cb_arg;
 	/** Current drawing color */
 	pixel_t color;
Index: uspace/lib/memgfx/src/memgc.c
===================================================================
--- uspace/lib/memgfx/src/memgc.c	(revision cea9f0cdb1a2d2752bc931602d11342eb862c44e)
+++ uspace/lib/memgfx/src/memgc.c	(revision f8375f741d0ccd376851c593af6a16c2591aa927)
@@ -123,4 +123,6 @@
  * @param rect Bounding rectangle
  * @param alloc Allocation info
+ * @param update_cb Function called to update a rectangle
+ * @param cb_arg Argument to callback function
  * @param rgc Place to store pointer to new memory GC
  *
@@ -128,5 +130,5 @@
  */
 errno_t mem_gc_create(gfx_rect_t *rect, gfx_bitmap_alloc_t *alloc,
-    mem_gc_t **rgc)
+    mem_gc_update_cb_t update_cb, void *cb_arg, mem_gc_t **rgc)
 {
 	mem_gc_t *mgc = NULL;
@@ -159,5 +161,6 @@
 	assert(alloc->pitch == rect->p1.x * (int)sizeof(uint32_t));
 
-	mem_gc_clear_update_rect(mgc);
+	mgc->update = update_cb;
+	mgc->cb_arg = cb_arg;
 
 	*rgc = mgc;
@@ -198,21 +201,5 @@
 static void mem_gc_invalidate_rect(mem_gc_t *mgc, gfx_rect_t *rect)
 {
-	gfx_rect_t nrect;
-
-	gfx_rect_envelope(&mgc->upd_rect, rect, &nrect);
-	mgc->upd_rect = nrect;
-}
-
-void mem_gc_get_update_rect(mem_gc_t *mgc, gfx_rect_t *rect)
-{
-	*rect = mgc->upd_rect;
-}
-
-void mem_gc_clear_update_rect(mem_gc_t *mgc)
-{
-	mgc->upd_rect.p0.x = 0;
-	mgc->upd_rect.p0.y = 0;
-	mgc->upd_rect.p1.x = 0;
-	mgc->upd_rect.p1.y = 0;
+	mgc->update(mgc->cb_arg, rect);
 }
 
Index: uspace/lib/memgfx/test/memgfx.c
===================================================================
--- uspace/lib/memgfx/test/memgfx.c	(revision cea9f0cdb1a2d2752bc931602d11342eb862c44e)
+++ uspace/lib/memgfx/test/memgfx.c	(revision f8375f741d0ccd376851c593af6a16c2591aa927)
@@ -34,4 +34,5 @@
 #include <gfx/render.h>
 #include <io/pixelmap.h>
+#include <mem.h>
 #include <memgfx/memgc.h>
 #include <pcut/pcut.h>
@@ -40,4 +41,13 @@
 
 PCUT_TEST_SUITE(memgfx);
+
+static void test_update_rect(void *arg, gfx_rect_t *rect);
+
+typedef struct {
+	/** True if update was called */
+	bool update_called;
+	/** Update rectangle */
+	gfx_rect_t rect;
+} test_update_t;
 
 /** Test creating and deleting a memory GC */
@@ -59,5 +69,5 @@
 	PCUT_ASSERT_NOT_NULL(alloc.pixels);
 
-	rc = mem_gc_create(&rect, &alloc, &mgc);
+	rc = mem_gc_create(&rect, &alloc, NULL, NULL, &mgc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -72,5 +82,4 @@
 	gfx_rect_t rect;
 	gfx_rect_t frect;
-	gfx_rect_t urect;
 	gfx_bitmap_alloc_t alloc;
 	gfx_context_t *gc;
@@ -80,4 +89,5 @@
 	pixel_t pixel;
 	pixel_t expected;
+	test_update_t update;
 	errno_t rc;
 
@@ -93,5 +103,5 @@
 	PCUT_ASSERT_NOT_NULL(alloc.pixels);
 
-	rc = mem_gc_create(&rect, &alloc, &mgc);
+	rc = mem_gc_create(&rect, &alloc, test_update_rect, &update, &mgc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -111,4 +121,6 @@
 	frect.p1.x = 5;
 	frect.p1.y = 5;
+
+	memset(&update, 0, sizeof(update));
 
 	rc = gfx_fill_rect(gc, &frect);
@@ -130,14 +142,9 @@
 
 	/* Check that the update rect is equal to the filled rect */
-	mem_gc_get_update_rect(mgc, &urect);
-	PCUT_ASSERT_INT_EQUALS(frect.p0.x, urect.p0.x);
-	PCUT_ASSERT_INT_EQUALS(frect.p0.y, urect.p0.y);
-	PCUT_ASSERT_INT_EQUALS(frect.p1.x, urect.p1.x);
-	PCUT_ASSERT_INT_EQUALS(frect.p1.y, urect.p1.y);
-
-	/* Check that mem_gc_clear_update_rect() clears the update rect */
-	mem_gc_clear_update_rect(mgc);
-	mem_gc_get_update_rect(mgc, &urect);
-	PCUT_ASSERT_TRUE(gfx_rect_is_empty(&urect));
+	PCUT_ASSERT_TRUE(update.update_called);
+	PCUT_ASSERT_INT_EQUALS(frect.p0.x, update.rect.p0.x);
+	PCUT_ASSERT_INT_EQUALS(frect.p0.y, update.rect.p0.y);
+	PCUT_ASSERT_INT_EQUALS(frect.p1.x, update.rect.p1.x);
+	PCUT_ASSERT_INT_EQUALS(frect.p1.y, update.rect.p1.y);
 
 	/* TODO: Check clipping once memgc can support pitch != width etc. */
@@ -152,5 +159,4 @@
 	mem_gc_t *mgc;
 	gfx_rect_t rect;
-	gfx_rect_t urect;
 	gfx_bitmap_alloc_t alloc;
 	gfx_context_t *gc;
@@ -163,4 +169,5 @@
 	pixel_t pixel;
 	pixel_t expected;
+	test_update_t update;
 	errno_t rc;
 
@@ -176,5 +183,5 @@
 	PCUT_ASSERT_NOT_NULL(alloc.pixels);
 
-	rc = mem_gc_create(&rect, &alloc, &mgc);
+	rc = mem_gc_create(&rect, &alloc, test_update_rect, &update, &mgc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -211,4 +218,6 @@
 	dpmap.height = rect.p1.y - rect.p0.y;
 	dpmap.data = alloc.pixels;
+
+	memset(&update, 0, sizeof(update));
 
 	/* Render the bitmap */
@@ -229,14 +238,9 @@
 
 	/* Check that the update rect is equal to the filled rect */
-	mem_gc_get_update_rect(mgc, &urect);
-	PCUT_ASSERT_INT_EQUALS(params.rect.p0.x, urect.p0.x);
-	PCUT_ASSERT_INT_EQUALS(params.rect.p0.y, urect.p0.y);
-	PCUT_ASSERT_INT_EQUALS(params.rect.p1.x, urect.p1.x);
-	PCUT_ASSERT_INT_EQUALS(params.rect.p1.y, urect.p1.y);
-
-	/* Check that mem_gc_clear_update_rect() clears the update rect */
-	mem_gc_clear_update_rect(mgc);
-	mem_gc_get_update_rect(mgc, &urect);
-	PCUT_ASSERT_TRUE(gfx_rect_is_empty(&urect));
+	PCUT_ASSERT_TRUE(update.update_called);
+	PCUT_ASSERT_INT_EQUALS(params.rect.p0.x, update.rect.p0.x);
+	PCUT_ASSERT_INT_EQUALS(params.rect.p0.y, update.rect.p0.y);
+	PCUT_ASSERT_INT_EQUALS(params.rect.p1.x, update.rect.p1.x);
+	PCUT_ASSERT_INT_EQUALS(params.rect.p1.y, update.rect.p1.y);
 
 	/* TODO: Check clipping once memgc can support pitch != width etc. */
@@ -246,3 +250,12 @@
 }
 
+/** Called by memory GC when a rectangle is updated. */
+static void test_update_rect(void *arg, gfx_rect_t *rect)
+{
+	test_update_t *update = (test_update_t *)arg;
+
+	update->update_called = true;
+	update->rect = *rect;
+}
+
 PCUT_EXPORT(memgfx);
