Hi Robert,

Thanks for the reply.  Your suggestion helped me diagnose the problem.  The
clutter functions are working fine.  As far as I can tell, the problem is
with my data source.

I wrote a test program (attached) like you suggested and that cleared things
up.

Thanks a lot,
Uday

On Fri, Feb 5, 2010 at 3:50 AM, Robert Bragg <[email protected]> wrote:

> Hi Uday,
>
> Excerpts from Uday Verma's message of Fri Feb 05 06:15:40 +0000 2010:
>
> >I am trying to upload RGB24 data onto a ClutterTexture
> >using clutter_texture_set_area_from_rgb_data function.  I am getting this
> >data from a top-down source device.  When I upload this data, things work
> >great but the color and the image are inverted.  I think this is expected
> >since the data layout for OGL textures is a little different.
> ClutterTexture and the underlying CoglTexture both consider (0,0) to be
> the top left and (1,1) the bottom right of your texture. When uploading
> data from a pointer, the pointer should reference the first, top-left
> texel.
>
> From what you are saying it *sounds* like a bug in Clutter. I think it
> would help a lot if you are able to write a small test demonstrating
> exactly what you are trying (just runtime generating dummy source device
> data via malloc + a couple of for(;;) loops)
>
> If you could then attach the test to a bug on bugzilla:
> http://bugzilla.o-hand.com/enter_bug.cgi?product=Clutter
> I think that would really help us understand where the problem lies.
>
> kind regards,
> - Robert
> --
> Robert Bragg, Intel Open Source Technology Center
>
/* test-texture.c
   Test texture fill functions */

#include <clutter/clutter.h>
#include <string.h>

static ClutterActor *texture_full, *texture_slices;
static guchar *image_buf; /* 512x768 buffer, left to right: black to red, top to bottom: black to green */

static int min (int x, int y) {
  return x < y ? x : y;
}

static ClutterActor *
create_empty_texture (int width, 
		      int height)
{
  ClutterActor *ret = NULL;
  GError *error = NULL;
  guchar *buf = NULL;
  gint row_stride;
  gboolean fill_result;

  row_stride = ((width * 3) + 3) & ~3;
  
  buf = (guchar *) g_slice_alloc0 (row_stride * height);
  g_assert (buf);

  ret = clutter_texture_new ();
  fill_result = 
    clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (ret),
				       buf,
				       FALSE,
				       width, height,
				       row_stride,
				       3,
				       CLUTTER_TEXTURE_NONE,
				       &error);

  g_assert (fill_result);

  g_slice_free1 (row_stride * height, buf);
  return ret;
}

static void
create_image_buf (int width, int height) {
  gint row_stride = ((width * 3) + 3) & ~3;
  gint y, x;
  guchar *ptr, *pix;
  
  image_buf = (guchar *) g_slice_alloc0 (row_stride * height);
  g_assert (image_buf);

  for (y = 0 ; y < height ; y ++) {
    ptr = image_buf + row_stride * y;
    for (x = 0 ; x < width ; x ++) {
      *ptr ++ = (x * 255) / width;
      *ptr ++ = (y * 255) / height;
      *ptr ++ = 0;
    }
  }
}


static void
fill_single (ClutterTexture *tex) 
{
  gboolean fill_status;

  fill_status = 
    clutter_texture_set_from_rgb_data (tex,
				       image_buf,
				       FALSE,
				       512,
				       768,
				       ((512 * 3) + 3) & ~3,
				       3,
				       CLUTTER_TEXTURE_NONE,
				       NULL);
  g_assert (fill_status);
}

static void
fill_slices (ClutterTexture *tex, gint swidth, gint sheight) {
  const int bs = 64;
  gint y, x;

  gint bsbytes = bs * bs * 3;
  guchar *dest = g_slice_alloc (bsbytes);
  guchar *sptr, *dptr;
  
  gint src_row_stride = ((swidth * 3) + 3) & ~3;
  gint dest_row_stride = bs * 3;

  g_assert (dest);

  for (y = 0 ; y < sheight ; y += bs) {
    for (x = 0 ; x < swidth ; x += bs) {
      gint w = min (bs, swidth - x);
      gint h = min (bs, sheight - x);
      gint hi;

      gboolean fill_status;

      sptr = image_buf + (src_row_stride * y) + x * 3;
      dptr = dest;

      for (hi = 0 ; hi < h ; hi ++) {
	memcpy (dptr, sptr, bs * 3);

	dptr += dest_row_stride;
	sptr += src_row_stride;
      }

      /* now write this buffer to our texture */
      fill_status =
	clutter_texture_set_area_from_rgb_data (tex,
						dest,
						FALSE,
						x, y,
						w, h,
						dest_row_stride,
						3,
						CLUTTER_TEXTURE_NONE,
						NULL);
      g_assert (fill_status);
    }
  }

  g_slice_free1 (bsbytes, dest);
}

int main (int argc, char **argv) {
  ClutterActor *stage;

  clutter_init (&argc, &argv);

  stage = clutter_stage_get_default ();
  clutter_actor_set_size (stage, 1024, 768);

  texture_full = create_empty_texture (512, 768);
  texture_slices = create_empty_texture (512, 768);

  clutter_container_add (CLUTTER_CONTAINER (stage),
			 texture_full,
			 texture_slices, NULL);

  clutter_actor_set_position (texture_full, 0, 0);
  clutter_actor_set_position (texture_slices, 512, 0);

  clutter_actor_set_size (texture_full, 512, 768);
  clutter_actor_set_size (texture_slices, 512, 768);

  /* 512x768 buffer, left to right: black to red, top to bottom: black to green */
  create_image_buf (512, 768);

  fill_single (CLUTTER_TEXTURE (texture_full));
  fill_slices (CLUTTER_TEXTURE (texture_slices), 512, 768);

  clutter_actor_show_all (stage);

  clutter_main ();

  return 0;
}

Reply via email to