diff --git a/addons/primitives/CMakeLists.txt b/addons/primitives/CMakeLists.txt
index 8a65a82..043b80f 100644
--- a/addons/primitives/CMakeLists.txt
+++ b/addons/primitives/CMakeLists.txt
@@ -10,6 +10,7 @@ set(PRIMITIVES_SOURCES
     prim_util.c
     primitives.c
     triangulator.c
+    cache.c
     )
 
 if(WIN32)
diff --git a/addons/primitives/allegro5/allegro_primitives.h b/addons/primitives/allegro5/allegro_primitives.h
index 76af6b9..0f0e12a 100644
--- a/addons/primitives/allegro5/allegro_primitives.h
+++ b/addons/primitives/allegro5/allegro_primitives.h
@@ -217,6 +217,12 @@ ALLEGRO_PRIM_FUNC(void, al_draw_polygon_with_holes, (const float* vertices, int
 ALLEGRO_PRIM_FUNC(void, al_draw_filled_polygon, (const float* vertices, int vertex_count, ALLEGRO_COLOR color));
 ALLEGRO_PRIM_FUNC(void, al_draw_filled_polygon_with_holes, (const float* vertices, int vertex_count, const int* holes, int hole_count, ALLEGRO_COLOR color));
 
+/*
+ * Deferred drawing
+ */
+ALLEGRO_PRIM_FUNC(void, al_hold_primitive_drawing, (bool hold));
+ALLEGRO_PRIM_FUNC(bool, al_is_primitive_drawing_held, (void));
+
 
 #ifdef __cplusplus
 }
diff --git a/addons/primitives/allegro5/internal/aintern_prim.h b/addons/primitives/allegro5/internal/aintern_prim.h
index 5188eec..3807ae2 100644
--- a/addons/primitives/allegro5/internal/aintern_prim.h
+++ b/addons/primitives/allegro5/internal/aintern_prim.h
@@ -47,6 +47,13 @@ void _al_prim_cache_flush(ALLEGRO_PRIM_VERTEX_CACHE* cache);
 void _al_prim_cache_push_point(ALLEGRO_PRIM_VERTEX_CACHE* cache, const float* v);
 void _al_prim_cache_push_triangle(ALLEGRO_PRIM_VERTEX_CACHE* cache, const float* v0, const float* v1, const float* v2);
 
+/* Deferred drawing */
+void _al_init_high_primitives_cache(void);
+void _al_shutdown_high_primitives_cache(void);
+void _al_fill_fan_indices(int* indices, int start_index, size_t num_vertices);
+
+bool _al_get_cache(bool draw_lines, size_t num_vertices, size_t num_indices, ALLEGRO_VERTEX** vertices, int** indices, int* start_index);
+void _al_premupltiply_transform(ALLEGRO_VERTEX* vertices, size_t num_vertices);
 
 /* Internal functions. */
 float     _al_prim_get_scale(void);
diff --git a/addons/primitives/cache.c b/addons/primitives/cache.c
new file mode 100644
index 0000000..da1349e
--- /dev/null
+++ b/addons/primitives/cache.c
@@ -0,0 +1,226 @@
+/*         ______   ___    ___
+ *        /\  _  \ /\_ \  /\_ \
+ *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
+ *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
+ *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
+ *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
+ *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
+ *                                           /\____/
+ *                                           \_/__/
+ *
+ * Vertex cache used for deferred drawing of the primitives.
+ */
+
+#include "allegro5/allegro.h"
+#include "allegro5/allegro_primitives.h"
+#include <string.h>
+
+typedef struct
+{
+   ALLEGRO_DISPLAY* display;
+   
+   ALLEGRO_VERTEX* vertices;
+   size_t num_vertices;
+   size_t vertices_capacity;
+   
+   int* indices;
+   size_t num_indices;
+   size_t indices_capacity;
+   
+   bool draw_lines;
+   bool multiply_transform;
+   ALLEGRO_TRANSFORM last_transform;
+} CACHE_ENTRY;
+
+static CACHE_ENTRY* cache_entries;
+static int num_cache_entries = 0;
+static ALLEGRO_MUTEX* cache_mutex;
+static bool drawing_held = false;
+
+void _al_init_high_primitives_cache(void)
+{
+   if(!cache_mutex)
+      cache_mutex = al_create_mutex();
+}
+
+void _al_shutdown_high_primitives_cache(void)
+{
+   int ii;
+   al_destroy_mutex(cache_mutex);
+   
+   for(ii = 0; ii < num_cache_entries; ii++) {
+      al_free(cache_entries[ii].vertices);
+      al_free(cache_entries[ii].indices);
+   }
+   al_free(cache_entries);
+   
+   cache_entries = NULL;
+   num_cache_entries = 0;
+   cache_mutex = NULL;
+}
+
+static void reset_entry(CACHE_ENTRY* entry, ALLEGRO_DISPLAY* display, const ALLEGRO_TRANSFORM* transform)
+{
+   entry->display = display;
+   
+   entry->vertices = NULL;
+   entry->num_vertices = 0;
+   entry->vertices_capacity = 0;
+   
+   entry->indices = NULL;
+   entry->num_indices = 0;
+   entry->indices_capacity = 0;
+   
+   entry->draw_lines = false;
+   entry->multiply_transform = false;
+   al_copy_transform(&entry->last_transform, transform);
+}
+
+static bool transforms_equal(const ALLEGRO_TRANSFORM* a, const ALLEGRO_TRANSFORM* b)
+{
+   return memcmp(a, b, sizeof(ALLEGRO_TRANSFORM)) == 0;
+}
+
+static void flush_cache(CACHE_ENTRY* entry)
+{
+   ALLEGRO_TRANSFORM old_trans;
+   const ALLEGRO_TRANSFORM* cur_trans = al_get_current_transform();
+   al_copy_transform(&old_trans, cur_trans);
+   al_use_transform(&entry->last_transform);
+   
+   if(entry->draw_lines)
+      al_draw_indexed_prim(entry->vertices, NULL, NULL, entry->indices, entry->num_indices, ALLEGRO_PRIM_LINE_LIST);
+   else
+      al_draw_indexed_prim(entry->vertices, NULL, NULL, entry->indices, entry->num_indices, ALLEGRO_PRIM_TRIANGLE_LIST);
+   
+   al_use_transform(&old_trans);
+
+   entry->num_vertices = 0;
+   entry->num_indices = 0;
+   entry->multiply_transform = false;
+}
+
+static void premultiply_transform(const ALLEGRO_TRANSFORM* transform, ALLEGRO_VERTEX* vertices, size_t num_vertices)
+{
+   ALLEGRO_VERTEX* end = vertices + num_vertices;
+   while(vertices != end) {
+      al_transform_coordinates(transform, &vertices[0].x, &vertices[0].y);
+      vertices++;
+   }
+}
+
+static CACHE_ENTRY* get_entry(ALLEGRO_DISPLAY* cur_display)
+{
+   int ii;
+   for(ii = 0; ii < num_cache_entries; ii++)
+      if(cache_entries[ii].display == cur_display)
+         return &cache_entries[ii];
+   return NULL;
+}
+
+void _al_premupltiply_transform(ALLEGRO_VERTEX* vertices, size_t num_vertices)
+{
+   const ALLEGRO_TRANSFORM* cur_trans = al_get_current_transform();
+   premultiply_transform(cur_trans, vertices, num_vertices);
+}
+
+void _al_fill_fan_indices(int* indices, int start_index, size_t num_vertices)
+{
+	int idx = 0;
+	int ii;
+	for(ii = 0; ii < num_vertices - 2; ii++) {
+		indices[idx + 0] = start_index;
+		indices[idx + 1] = start_index + ii + 1;
+		indices[idx + 2] = start_index + ii + 2;
+		idx += 3;
+	}
+}
+
+/*
+ * Returns two pointers that can be used to draw primitives. start_index is the index that points to the first
+ * returned vertex. Returns true if the vertices need to be pre-multiplied before they can be drawn.
+ */
+bool _al_get_cache(bool draw_lines, size_t num_vertices, size_t num_indices, ALLEGRO_VERTEX** vertices, int** indices, int* start_index)
+{
+   CACHE_ENTRY* entry = NULL;
+   ALLEGRO_DISPLAY* cur_display = al_get_current_display();
+   const ALLEGRO_TRANSFORM* cur_trans = al_get_current_transform();
+
+   al_lock_mutex(cache_mutex);
+   
+   /* Try finding a matching entry */
+   entry = get_entry(cur_display);
+   
+   /* Add a new entry, if not found */
+   if(!entry) {
+      num_cache_entries++;
+      cache_entries = al_realloc(cache_entries, sizeof(CACHE_ENTRY) * num_cache_entries);
+      entry = &cache_entries[num_cache_entries - 1];
+      reset_entry(entry, cur_display, cur_trans);
+   }
+   
+   /* Flush if needed */
+   if((draw_lines != entry->draw_lines) || (entry->num_vertices + num_vertices > 5000)) {
+      flush_cache(entry);
+      entry->draw_lines = draw_lines;
+   }
+   
+   /* Check premultiplication */
+   if(!entry->multiply_transform && entry->num_vertices > 0 
+      && !transforms_equal(cur_trans, &entry->last_transform)) {
+      entry->multiply_transform = true;
+      /* Premultiply old transform */
+      premultiply_transform(&entry->last_transform, entry->vertices, entry->num_vertices);
+      al_identity_transform(&entry->last_transform);
+   }
+   
+   *start_index = entry->num_vertices;
+   
+   if(entry->num_vertices == 0)
+      al_copy_transform(&entry->last_transform, cur_trans);
+   
+   /* Allocate enough space for the vertices */
+   if(entry->num_vertices + num_vertices > entry->vertices_capacity) {
+      entry->vertices_capacity = (entry->num_vertices + num_vertices) * 3/2;
+      entry->vertices = al_realloc(entry->vertices, sizeof(ALLEGRO_VERTEX) * entry->vertices_capacity);
+      ALLEGRO_ASSERT(entry->vertices);
+   }
+   *vertices = entry->vertices + entry->num_vertices;
+   entry->num_vertices += num_vertices;
+   
+   /* Allocate enough space for the indices */
+   if(entry->num_indices + num_indices > entry->indices_capacity) {
+      entry->indices_capacity = (entry->num_indices + num_indices) * 3/2;
+      entry->indices = al_realloc(entry->indices, sizeof(ALLEGRO_VERTEX) * entry->indices_capacity);
+      ALLEGRO_ASSERT(entry->indices);
+   }
+   *indices = entry->indices + entry->num_indices;
+   entry->num_indices += num_indices;
+   
+   al_unlock_mutex(cache_mutex);
+   
+   return entry->multiply_transform;
+}
+
+void al_hold_primitive_drawing(bool hold)
+{
+   drawing_held = hold;
+   if(!drawing_held) {
+      ALLEGRO_DISPLAY* cur_display = al_get_current_display();
+      CACHE_ENTRY* entry = NULL;
+
+      al_lock_mutex(cache_mutex);
+   
+      /* Try finding a matching entry */
+      entry = get_entry(cur_display);
+      if(entry)
+         flush_cache(entry);
+      
+      al_unlock_mutex(cache_mutex);
+   }
+}
+
+bool al_is_primitive_drawing_held(void)
+{
+   return drawing_held;
+}
diff --git a/addons/primitives/high_primitives.c b/addons/primitives/high_primitives.c
index 1bfcf30..0d23ff5 100644
--- a/addons/primitives/high_primitives.c
+++ b/addons/primitives/high_primitives.c
@@ -321,9 +321,12 @@ void al_draw_triangle(float x1, float y1, float x2, float y2,
  */
 void al_draw_filled_triangle(float x1, float y1, float x2, float y2,
    float x3, float y3, ALLEGRO_COLOR color)
-{
-   ALLEGRO_VERTEX vtx[3];
-
+{  
+   ALLEGRO_VERTEX* vtx;
+   int* indices;
+   int start_index;
+   bool need_premultiply = _al_get_cache(false, 3, 3, &vtx, &indices, &start_index);
+   
    vtx[0].x = x1; vtx[0].y = y1;
    vtx[1].x = x2; vtx[1].y = y2;
    vtx[2].x = x3; vtx[2].y = y3;
@@ -336,7 +339,15 @@ void al_draw_filled_triangle(float x1, float y1, float x2, float y2,
    vtx[1].z = 0;
    vtx[2].z = 0;
    
-   al_draw_prim(vtx, 0, 0, 0, 3, ALLEGRO_PRIM_TRIANGLE_LIST);
+   indices[0] = start_index + 0;
+   indices[1] = start_index + 1;
+   indices[2] = start_index + 2;
+   
+   if(need_premultiply)
+      _al_premupltiply_transform(vtx, 3);
+   
+   if(!al_is_primitive_drawing_held())
+      al_hold_primitive_drawing(false);
 }
 
 /* Function: al_draw_rectangle
@@ -730,6 +741,7 @@ void al_draw_ellipse(float cx, float cy, float rx, float ry,
 void al_draw_filled_ellipse(float cx, float cy, float rx, float ry,
    ALLEGRO_COLOR color)
 {
+#if 0
    LOCAL_VERTEX_CACHE;
    int num_segments, ii;
    float scale = get_scale();
@@ -758,6 +770,42 @@ void al_draw_filled_ellipse(float cx, float cy, float rx, float ry,
    }
    
    al_draw_prim(vertex_cache, 0, 0, 0, num_segments + 1, ALLEGRO_PRIM_TRIANGLE_FAN);
+#endif
+   ALLEGRO_VERTEX* vtx;
+   int* indices;
+   int start_index;
+   bool need_premultiply;
+   int num_segments, ii;
+   float scale = get_scale();
+
+   ASSERT(rx >= 0);
+   ASSERT(ry >= 0);
+   
+   num_segments = ALLEGRO_PRIM_QUALITY * scale * sqrtf((rx + ry) / 2.0f);
+
+   /* In case rx and ry are both close to 0. If al_calculate_arc is passed
+    * 0 or 1 it will assert.
+    */
+   if (num_segments < 2)
+      return;
+   
+   need_premultiply = _al_get_cache(false, num_segments + 1, (num_segments - 1) * 3, &vtx, &indices, &start_index);
+      
+   al_calculate_arc(&(vtx[1].x), sizeof(ALLEGRO_VERTEX), cx, cy, rx, ry, 0, ALLEGRO_PI * 2, 0, num_segments);
+   vtx[0].x = cx; vtx[0].y = cy;
+   
+   for (ii = 0; ii < num_segments + 1; ii++) {
+      vtx[ii].color = color;
+      vtx[ii].z = 0;
+   }
+   
+   _al_fill_fan_indices(indices, start_index, num_segments + 1);
+   
+   if(need_premultiply)
+      _al_premupltiply_transform(vtx, num_segments + 1);
+   
+   if(!al_is_primitive_drawing_held())
+      al_hold_primitive_drawing(false);
 }
 
 /* Function: al_draw_circle
diff --git a/addons/primitives/primitives.c b/addons/primitives/primitives.c
index 4a272fe..9e6d26c 100644
--- a/addons/primitives/primitives.c
+++ b/addons/primitives/primitives.c
@@ -49,6 +49,7 @@ bool al_init_primitives_addon(void)
 {
    bool ret = true;
    ret &= _al_init_d3d_driver();
+   _al_init_high_primitives_cache();
    
    addon_initialized = ret;
    
@@ -61,6 +62,7 @@ bool al_init_primitives_addon(void)
  */
 void al_shutdown_primitives_addon(void)
 {
+   _al_shutdown_high_primitives_cache();
    _al_shutdown_d3d_driver();
    addon_initialized = false;
 }
