render_slices.c
changeset 19 d18606bb6f20
parent 18 86f2e5b7191b
child 22 4627760fc0d1
--- a/render_slices.c	Mon Jun 09 18:58:39 2008 +0300
+++ b/render_slices.c	Tue Jun 17 16:39:55 2008 +0300
@@ -13,16 +13,13 @@
         free(ctx);
 }
 
-int render_slices_deinit (struct render_slices *ctx) {
-    // if it's not initialized, just ignore
-    if (!ctx->rowbuf)
-        return 1;
-
-    free(ctx->rowbuf);
+void render_slices_deinit (struct render_slices *ctx) {
+    if (ctx->rowbuf) {
+        free(ctx->rowbuf);
+        ctx->rowbuf = NULL;
+    }
     
     render_png_deinit(&ctx->png_info);
-
-    return 0;
 }
 
 #define HALF(a, b) (( a + b) / 2)
@@ -113,41 +110,40 @@
 
 int render_slices_segment_done (struct render_slices *ctx, int index) {
     assert(index >= 0 && index < ctx->num_slices);
+    assert(ctx->render_row >= 0);
+    assert(ctx->segments_done >= 0 && ctx->segments_done < ctx->num_slices);
     
     // our return status
-    int status = 0;
+    int i, status = 0;
 
-    // keep track of the number of full segments in this row
-    ctx->segments_done++;
-    
-    // is this row complete?
-    if (ctx->segments_done == ctx->num_slices) {
+    // is this row now complete?
+    if (++ctx->segments_done == ctx->num_slices) {
         // the row is complete
         ctx->segments_done = 0;
     
         // once we fill up a row we can always call process_row
         status |= SLICE_PROCESS_ROW;
         
-        // is the other row still waiting for it to get processed?
+        // is the other row already rendered?
         if (ctx->done_row < 0) {
-            // no, point the done_row at this row, point the render buffers to the unused row
+            // yes, point the done_row at this row, point the render buffers to the unused row
             ctx->done_row = ctx->render_row;
             ctx->render_row = (ctx->render_row == 0 ? 1 : 0);
             
-            int i ;
-
+            // can now continue rendering as well as call process_row
+            status |= SLICE_CONTINUE;
+            
             // update the remaining render buffers
             for (i = 0; i < ctx->num_slices; i++) {
                 ctx->slices[i].info.render_buf = ctx->rows[ctx->render_row] + ctx->slices[i].row_offset;
             }
-            
-            // can now continue rendering as well as call process_row
-            status |= SLICE_CONTINUE;
 
         } else {
             // cannot continue rendering, need to have process_row complete first
+            
+            ctx->render_row = -1;
+        }
 
-        }
 
     } else {
         // the row is not complete, do not render the next segment, do not call process_row
@@ -160,15 +156,39 @@
 int render_slices_process_row (struct render_slices *ctx) {
     assert(ctx->done_row >= 0);
 
+    int i;
+
     // pass the data to render_png, this results in calls to _render_multi_png_data
     if (render_png_row(&ctx->png_info, ctx->rows[ctx->done_row]))
         ERROR("render_png_row");
     
-    // mark the row as processed
-    ctx->done_row = -1;
-    
-    // ok, but don't call me again until I tell you to.
-    return SLICE_CONTINUE;
+    // is the other row still in the process of being assembled?
+    if (ctx->render_row == -1) {
+        // no, both rows were full
+        ctx->render_row = ctx->done_row;
+        ctx->done_row = (ctx->done_row == 0 ? 1 : 0);
+        
+        // update the remaining render buffers
+        for (i = 0; i < ctx->num_slices; i++) {
+            ctx->slices[i].info.render_buf = ctx->rows[ctx->render_row] + ctx->slices[i].row_offset;
+        }
+        
+        // you can call me again, but also segment_done
+        return SLICE_PROCESS_ROW | SLICE_CONTINUE;
+
+    } else {
+        // yes, so that still needs to be finished
+        ctx->done_row = -1;
+
+        if (ctx->segments_done == 0) {
+            // that row is empty, then we can continue
+            return SLICE_CONTINUE;
+
+        } else {
+            // that row is partially built, so some segment is still on the way - don't resume the other slices until that's arrived!
+            return 0;
+        }
+    }
 
 error:
     // user needs to deinit/free us
@@ -178,7 +198,7 @@
 int render_slices_done (struct render_slices *ctx) {
     // finish off render_png
     if (render_png_done(&ctx->png_info))
-        ERROR("render_png_done");
+        goto error;
     
     return 0;
 
@@ -186,3 +206,4 @@
     render_slices_free(ctx);
     return -1;
 }
+