--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/render_slices.c Mon Jun 09 03:15:34 2008 +0300
@@ -0,0 +1,171 @@
+#include <stdlib.h>
+#include <assert.h>
+
+#include "common.h"
+#include "render_struct.h"
+#include "render_slices_struct.h"
+#include "render_slices.h"
+
+void render_slices_free (struct render_slices *ctx) {
+ render_slices_deinit(ctx);
+
+ if (ctx->owned_by_me)
+ 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);
+
+ render_png_deinit(&ctx->png_info);
+
+ return 0;
+}
+
+#define HALF(a, b) (( a + b) / 2)
+
+int render_slices_init (struct render_slices *ctx, struct render *render) {
+ // initialize the slices
+ // for now, just split it in half into two render_ts
+ ctx->slices[0].info.index = 0;
+ ctx->slices[0].info.render_info = &ctx->slices[0].render_info;
+ ctx->slices[0].self = ctx;
+ ctx->slices[0].row_offset = 0;
+
+ ctx->slices[1].info.index = 1;
+ ctx->slices[1].info.render_info = &ctx->slices[1].render_info;
+ ctx->slices[1].self = ctx;
+ ctx->slices[1].row_offset = render->img_w / 2;
+
+ ctx->num_slices = 2;
+ ctx->render_row = 0;
+ ctx->done_row = -1;
+
+ assert(RENDER_SLICES_MAX >= 2);
+
+ if (
+ render_init (&ctx->slices[0].render_info, RENDER_RAW)
+ || render_init (&ctx->slices[1].render_info, RENDER_RAW)
+
+ || render_set_size (&ctx->slices[0].render_info, render->img_w / 2, render->img_h)
+ || render_set_size (&ctx->slices[1].render_info, render->img_w / 2 + render->img_w % 2, render->img_h)
+
+ || render_region_raw (&ctx->slices[0].render_info, render->x1, render->y1, HALF(render->x1, render->x2), render->y2)
+ || render_region_raw (&ctx->slices[1].render_info, HALF(render->x1, render->x2), render->y1, render->x2, render->y2)
+ )
+ ERROR("render_{init,set_size,set_region_raw}");
+
+ // allocate the rowbuf
+ if (!(ctx->rowbuf = malloc(render->img_w * 2)))
+ ERROR("malloc");
+
+ // update the slice_buf pointers
+ ctx->rows[0] = ctx->rowbuf;
+ ctx->rows[1] = ctx->rowbuf + render->img_w;
+ ctx->slices[0].info.render_buf = ctx->rows[ctx->render_row] + ctx->slices[0].row_offset;
+ ctx->slices[1].info.render_buf = ctx->rows[ctx->render_row] + ctx->slices[1].row_offset;
+
+ // png info
+ if (render_png_init(&ctx->png_info, render))
+ ERROR("render_png_init");
+
+ // great success!
+ return 0;
+
+error:
+ render_slices_deinit(ctx);
+ return -1;
+}
+
+struct render_slices *render_slices_alloc (struct render *render) {
+ struct render_slices *ctx = NULL;
+
+ // allocate it
+ if (!(ctx = calloc(1, sizeof(*ctx))))
+ ERROR("calloc");
+
+ // mark it for free()ing
+ ctx->owned_by_me = 1;
+
+ // initialize it
+ if (render_slices_init(ctx, render))
+ goto error;
+
+ return ctx;
+
+error :
+ render_slices_free(ctx);
+ return NULL;
+}
+
+int render_slices_get_count (struct render_slices *ctx) {
+ return ctx->num_slices;
+}
+
+struct render_slice_info *render_slices_get_slice_info (struct render_slices *ctx, int index) {
+ assert(index >= 0 && index < ctx->num_slices);
+
+ return &ctx->slices[index].info;
+}
+
+int render_slices_segment_done (struct render_slices *ctx, int index) {
+ assert(index >= 0 && index < ctx->num_slices);
+ assert(ctx->slices_done < ctx->num_slices);
+
+ // keep track of the number of full slices
+ ctx->slices_done++;
+
+ // is the row complete?
+ if (ctx->slices_done == ctx->num_slices) {
+ // the row is complete
+ ctx->slices_done = 0;
+
+ // is the other row waiting for it to get processed?
+ if (ctx->done_row < 0) {
+ // no, 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 ;
+ 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
+ return SLICE_PROCESS_ROW & SLICE_CONTINUE;
+
+ } else {
+ // cannot continue rendering, need to have process_row complete first
+ return SLICE_PROCESS_ROW;
+
+ }
+
+ } else {
+ // the row is not complete, do not render the next segment, do not call process_row
+ return 0;
+
+ }
+}
+
+int render_slices_process_row (struct render_slices *ctx) {
+ assert(ctx->done_row >= 0);
+
+ // 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;
+
+error:
+ // user needs to deinit/free us
+ return -1;
+}
+
+