예제 #1
0
void
MoonEGLContext::SetupVertexData (const double *matrix,
				 double       x,
				 double       y,
				 double       width,
				 double       height)
{
	Target         *target = Top ()->GetTarget ();
	MoonSurface    *ms;
	Rect           r = target->GetData (&ms);
	MoonEGLSurface *dst = (MoonEGLSurface *) ms;
	double         m[16];

	if (matrix)
		Matrix3D::Init (m, matrix);
	else
		Matrix3D::Identity (m);

	GLContext::SetupVertexData (m, x, y, width, height);

	if (dst->GetEGLDisplay ()) {
		int i;

		for (i = 0; i < 4; i++) {
			GLfloat v = vertices[i][1] + vertices[i][3];

			vertices[i][1] = vertices[i][3] - v;
		}
	}

	ms->unref ();
}
예제 #2
0
void
MoonEGLContext::SetScissor ()
{
	Target      *target = Top ()->GetTarget ();
	MoonSurface *ms;
	Rect        r = target->GetData (&ms);
	MoonEGLSurface  *dst = (MoonEGLSurface *) ms;
	Rect        clip;

	Top ()->GetClip (&clip);

	clip.x -= r.x;
	clip.y -= r.y;

	if (dst->GetEGLDisplay ()) {
		glScissor (clip.x,
			   dst->Height () - (clip.y + clip.height),
			   clip.width,
			   clip.height);
	}
	else {
		GLContext::SetScissor ();
	}

	ms->unref ();
}
예제 #3
0
void
MoonEGLContext::Paint (Color *color)
{
	Target      *target = Top ()->GetTarget ();
	MoonSurface *ms;
	Rect        r = target->GetData (&ms);
	Rect        clip;

	// avoid GL rendering to target without previously
	// allocated hardware drawable	
	if (!HasDrawable ()) {
		Context::Paint (color);
		ms->unref ();
		return;
	}

	Top ()->GetClip (&clip);

	if (!target->GetInit () && r == clip) {
		// mark target as initialized
		target->SetInit (ms);
	}

	ForceCurrent ();

	GLContext::Paint (color);

	ms->unref ();
}
예제 #4
0
Rect
MoonEGLContext::Pop (MoonSurface **ref)
{
	Context::Node *prev = (Context::Node *) Top ()->prev;

	g_assert (prev);

	if (Top ()->GetTarget () != prev->GetTarget ()) {
		Target      *target = Top ()->GetTarget ();
		MoonSurface *init = target->GetInit ();
		MoonSurface *ms;
		Rect        r = target->GetData (&ms);
		MoonSurface *data = init != ms ? init : NULL;

		ms->unref ();
		ForceCurrent ();

		// return reference to initial state surface instead
		// of the target surface itself
		if (data) {
			Node *node = (Node *) Stack::Pop ();

			*ref = data->ref ();
			delete node;
			return r;
		}
		else {
			SyncDrawable ();
		}
	}

	return GLContext::Pop (ref);
}
예제 #5
0
void
CGLContext::BlitVUY2 (unsigned char *data)
{
	Target      *target = Top ()->GetTarget ();
	MoonSurface *ms;
	Rect        r = target->GetData (&ms);
	OpengGLSurface *dst = (OpenGLSurface *) ms;
	int         size[] = { dst->Width (), dst->Height () };
	GLuint texture = dst->Texture ();

	// no support for clipping
	g_assert (GetClip () == r);

	// no support for blit to drawable at the moment
	g_assert (!dst->HasDrawable ());

	// mark target as initialized
	target->SetInit (ms);

	glBindTexture (GL_TEXTURE_2D, texture);
	glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, size [0], size [1], 0, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, data);
	glBindTexture (GL_TEXTURE_2D, 0);

	ms->unref ();
}
예제 #6
0
void
MoonEGLContext::Blit (unsigned char *data,
		  int           stride)
{
	Target      *target = Top ()->GetTarget ();
	MoonSurface *ms;
	Rect        r = target->GetData (&ms);
	MoonEGLSurface  *dst = (MoonEGLSurface *) ms;
	unsigned char *buffer = data;
	int           buffer_stride = stride;

	ForceCurrent ();

	// no support for clipping
	g_assert (GetClip () == r);

	// no support for blit to drawable at the moment
	g_assert (!dst->GetEGLDisplay ());

	// mark target as initialized
	target->SetInit (ms);

	if (PixelRowLength (stride, dst->Width (), 4) != dst->Width ()) {
		buffer_stride = dst->Width () * 4;
		buffer =  (unsigned char *)
			g_malloc (buffer_stride * dst->Height ());

		for (int y = 0; y < dst->Height (); y++)
			memcpy (buffer + (y * buffer_stride),
				data + (y * stride),
				buffer_stride);
	}

	glPixelStorei (GL_UNPACK_ALIGNMENT, PixelAlignment (buffer_stride));
	glBindTexture (GL_TEXTURE_2D, dst->Texture ());
	glTexSubImage2D (GL_TEXTURE_2D,
			 0,
			 0,
			 0,
			 dst->Width (),
			 dst->Height (),
			 GL_RGBA,
			 GL_UNSIGNED_BYTE,
			 buffer);
	glBindTexture (GL_TEXTURE_2D, 0);
	glPixelStorei (GL_UNPACK_ALIGNMENT, 4);

	if (buffer != data)
		g_free (buffer);

	ms->unref ();
}
예제 #7
0
cairo_t *
MoonEGLContext::Push (Cairo extents)
{
	Target *target = Top ()->GetTarget ();
	Target *cairo = target->GetCairoTarget ();
	Rect   box;

	Top ()->GetClip (&box);

	box = box.Intersection (extents.r);

	if (box.IsEmpty ())
		return Context::Push (extents);

	if (cairo) {
		Rect   r = cairo->GetData (NULL);
		Region *region = new Region (r);

		if (region->RectIn (box) != CAIRO_REGION_OVERLAP_IN) {
			ForceCurrent ();
			SyncDrawable ();
		}

		delete region;
	}

	if (!target->GetCairoTarget ()) {
		MoonSurface *ms;
		Rect        r = target->GetData (&ms);

		if (HasDrawable ()) {
			MoonEGLSurface *surface = new MoonEGLSurface (box.width,
							      box.height);
			Target     *cairo = new Target (surface, box);

			target->SetCairoTarget (cairo);

			cairo->unref ();
			surface->unref ();
		}
		else {
			// mark target contents as initialized
			target->SetInit (ms);
		}

		ms->unref ();
	}

	return Context::Push (extents);
}
예제 #8
0
void
MoonEGLContext::SetFramebuffer ()
{
	Target      *target = Top ()->GetTarget ();
	MoonSurface *ms;
	Rect        r = target->GetData (&ms);
	MoonEGLSurface  *dst = (MoonEGLSurface *) ms;

	SyncDrawable ();

	if (!dst->GetEGLDisplay ())
		GLContext::SetFramebuffer ();

	ms->unref ();
}
예제 #9
0
gboolean
MoonEGLContext::HasDrawable ()
{
	Target      *target = Top ()->GetTarget ();
	MoonSurface *ms;
	Rect        r = target->GetData (&ms);
	MoonEGLSurface  *dst = (MoonEGLSurface *) ms;
	gboolean    status = FALSE;

	if (dst->GetEGLDisplay () || dst->HasTexture ())
		status = TRUE;

	ms->unref ();

	return status;
}
예제 #10
0
void
MoonEGLContext::BlitYV12 (unsigned char *data[],
		     int           stride[])
{
	Target      *target = Top ()->GetTarget ();
	MoonSurface *ms;
	Rect        r = target->GetData (&ms);
	MoonEGLSurface  *dst = (MoonEGLSurface *) ms;
	int           size[] = { dst->Width (), dst->Height () };
	int           width[] = { size[0], size[0] / 2, size[0] / 2 };
	int           height[] = { size[1], size[1] / 2, size[1] / 2 };
	unsigned char *buffer[] = { data[0], data[1], data[2] };
	int           buffer_stride[] = { stride[0], stride[1], stride[2] };

	ForceCurrent ();

	// no support for blit to drawable at the moment
	g_assert (!dst->GetEGLDisplay ());

	// mark target as initialized
	target->SetInit (ms);

	for (int i = 0; i < 3; i++) {
		if (PixelRowLength (stride[i], width[i], 1) != width[i]) {
			buffer_stride[i] = width[i];
			buffer[i] = (unsigned char *)
				g_malloc (buffer_stride[i] * height[i]);

			for (int y = 0; y < height[i]; y++)
				memcpy (buffer[i] + y * buffer_stride[i],
					data[i] + y * stride[i],
					buffer_stride[i]);
		}
	}

	GLContext::BlitYV12 (buffer, buffer_stride);

	for (int i = 0; i < 3; i++)
		if (buffer[i] != data[i])
			g_free (buffer[i]);


	ms->unref ();
}
예제 #11
0
void
CairoContext::Push (Group extents)
{
    cairo_surface_t *parent = Top ()->GetTarget ()->Cairo ();
    Rect            r = extents.r.RoundOut ();
    cairo_surface_t *data =
        cairo_surface_create_similar (parent,
                                      CAIRO_CONTENT_COLOR_ALPHA,
                                      r.width,
                                      r.height);
    MoonSurface     *surface = new CairoSurface (data, r.width, r.height);
    Target          *target = new Target (surface, extents.r);
    cairo_matrix_t  matrix;

    Top ()->GetMatrix (&matrix);

    Stack::Push (new Context::Node (target, &matrix, &extents.r));

    target->unref ();
    surface->unref ();

    cairo_surface_destroy (data);
}
예제 #12
0
void
WriteableBitmap::Render (UIElement *element, Transform *transform)
{
	MoonSurface *src;
	Context     *ctx;

	if (!element)
		return;

	cairo_surface_t *surface = GetImageSurface ();
	if (!surface)
		return;

	Rect bounds (0, 0, GetPixelWidth (), GetPixelHeight ());

#ifdef USE_GALLIUM
	struct pipe_resource pt, *texture;
	GalliumSurface       *target;
	struct pipe_screen   *screen =
		swrast_screen_create (null_sw_create ());

	memset (&pt, 0, sizeof (pt));
	pt.target = PIPE_TEXTURE_2D;
	pt.format = PIPE_FORMAT_B8G8R8A8_UNORM;
	pt.width0 = 1;
	pt.height0 = 1;
	pt.depth0 = 1;
	pt.last_level = 0;
	pt.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_TRANSFER_WRITE |
		PIPE_BIND_TRANSFER_READ;

	texture = (*screen->resource_create) (screen, &pt);

	target = new GalliumSurface (texture);
	pipe_resource_reference (&texture, NULL);
	ctx = new GalliumContext (target);
	target->unref ();
#else
	CairoSurface *target;

	target = new CairoSurface (1, 1);
	ctx = new CairoContext (target);
	target->unref ();
#endif

	ctx->Push (Context::Group (bounds));

	cairo_matrix_t xform;
	cairo_matrix_init_identity (&xform);

	if (transform)
		transform->GetTransform (&xform);

	FrameworkElement *fe = (FrameworkElement *)element;
	if (fe->GetFlowDirection () == FlowDirectionRightToLeft) {
		cairo_matrix_translate (&xform, fe->GetActualWidth (), 0.0);
		cairo_matrix_scale (&xform, -1, 1);
	}

	element->Paint (ctx, bounds, &xform);

	bounds = ctx->Pop (&src);
	if (!bounds.IsEmpty ()) {
		cairo_surface_t *image = src->Cairo ();
		cairo_t         *cr = cairo_create (surface);

		cairo_set_source_surface (cr, image, 0, 0);
		cairo_paint (cr);
		cairo_destroy (cr);
		cairo_surface_destroy (image);
		src->unref ();
	}

	delete ctx;

#ifdef USE_GALLIUM
	screen->destroy (screen);
#endif

}
예제 #13
0
void
MoonEGLContext::SyncDrawable ()
{
	Target      *target = Top ()->GetTarget ();
	Target      *cairo = target->GetCairoTarget ();
	MoonSurface *ms;
	Rect        r = target->GetData (&ms);
	MoonEGLSurface  *dst = (MoonEGLSurface  *) ms;

	// clear target contents
	if (!target->GetInit ()) {
		if (!dst->GetEGLDisplay ())
			GLContext::SetFramebuffer ();

		glClearColor (0.0, 0.0, 0.0, 0.0);
		glClear (GL_COLOR_BUFFER_BIT);

		// mark target contents as initialized
		target->SetInit (ms);
	}

	// initialize target contents with surface
	if (target->GetInit () != ms) {
		MoonEGLSurface *src = (MoonEGLSurface  *) target->GetInit ();
		GLuint     texture0 = src->Texture ();
		GLuint     program = GetProjectProgram (1.0, 0);
		GLsizei    width0 = src->Width ();
		GLsizei    height0 = src->Height ();

		if (!dst->GetEGLDisplay ())
			GLContext::SetFramebuffer ();

		SetViewport ();

		glUseProgram (program);

		SetupVertexData (NULL, 0, 0, width0, height0);
		SetupTexCoordData ();

		glVertexAttribPointer (0, 4,
				       GL_FLOAT, GL_FALSE, 0,
				       vertices);
		glVertexAttribPointer (1, 4,
				       GL_FLOAT, GL_FALSE, 0,
				       texcoords);

		glBindTexture (GL_TEXTURE_2D, texture0);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
				 GL_NEAREST);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
				 GL_NEAREST);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
				 GL_CLAMP_TO_EDGE);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
				 GL_CLAMP_TO_EDGE);
		glUniform1i (glGetUniformLocation (program, "sampler0"), 0);

		glEnableVertexAttribArray (0);
		glEnableVertexAttribArray (1);

		glDrawArrays (GL_TRIANGLE_FAN, 0, 4);

		glDisableVertexAttribArray (1);
		glDisableVertexAttribArray (0);

		glBindTexture (GL_TEXTURE_2D, 0);

		glUseProgram (0);

		glBindFramebuffer (GL_FRAMEBUFFER, 0);

		// mark target contents as initialized
		target->SetInit (ms);
	}

	// render any cairo contents onto target
	if (cairo) {
		MoonSurface *mSrc;
		Rect        rSrc = cairo->GetData (&mSrc);
		MoonEGLSurface  *src = (MoonEGLSurface  *) mSrc;
		GLuint      texture0 = src->Texture ();
		GLuint      program = GetProjectProgram (1.0, 0);
		GLsizei     width0 = src->Width ();
		GLsizei     height0 = src->Height ();

		if (!dst->GetEGLDisplay ())
			GLContext::SetFramebuffer ();

		SetViewport ();

		glUseProgram (program);

		SetupVertexData (NULL, rSrc.x - r.x, rSrc.y - r.y, width0, height0);
		SetupTexCoordData ();

		glVertexAttribPointer (0, 4,
				       GL_FLOAT, GL_FALSE, 0,
				       vertices);
		glVertexAttribPointer (1, 4,
				       GL_FLOAT, GL_FALSE, 0,
				       texcoords);

		glBindTexture (GL_TEXTURE_2D, texture0);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
				 GL_NEAREST);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
				 GL_NEAREST);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
				 GL_CLAMP_TO_EDGE);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
				 GL_CLAMP_TO_EDGE);
		glUniform1i (glGetUniformLocation (program, "sampler0"), 0);

		glEnableVertexAttribArray (0);
		glEnableVertexAttribArray (1);

		glEnable (GL_BLEND);
		glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

		glDrawArrays (GL_TRIANGLE_FAN, 0, 4);

		glDisable (GL_BLEND);

		glDisableVertexAttribArray (1);
		glDisableVertexAttribArray (0);

		glBindTexture (GL_TEXTURE_2D, 0);

		glUseProgram (0);

		glBindFramebuffer (GL_FRAMEBUFFER, 0);

		mSrc->unref ();

		target->SetCairoTarget (NULL);
	}

	ms->unref ();
}
예제 #14
0
int
main (int argc, char **argv)
{
	Context *ctx;
	CairoSurface *target;
	MoonSurface *surface;
	cairo_surface_t *dst, *src;
	TransformEffect *effect;
	Matrix3D *matrix;
	DoubleCollection *values;
	int stride = width * 4;
	Rect bounds = Rect (0, 0, width, height);
	gpointer data;
	bool status = true;
	int count = 1;

	if (argc < 2) {
		printf ("usage: %s MATRIX [COUNT]\n", argv[0]);
		return 1;
	}

	gtk_init (&argc, &argv);

	runtime_init_desktop ();

	values = DoubleCollection::FromStr (argv[1]);
	if (!values) {
		printf ("usage: %s MATRIX [COUNT]\n", argv[0]);
		return 1;
	}

	if (values->GetCount () != 16) {
		printf ("usage: %s MATRIX [COUNT]\n", argv[0]);
		values->unref ();
		return 1;
	}

	data = g_malloc0 (height * stride);
	dst = cairo_image_surface_create_for_data ((unsigned char *) data,
						   CAIRO_FORMAT_ARGB32,
						   width, height, stride);
	target = new CairoSurface (dst);
	cairo_surface_destroy (dst);
	ctx = new CairoContext (target);
	target->unref ();

	src = cairo_surface_create_similar (dst,
					    CAIRO_CONTENT_COLOR_ALPHA,
					    width, height);
	surface = new CairoSurface (src);
	cairo_surface_destroy (src);

	effect = new TransformEffect ();

	matrix = new Matrix3D ();
	matrix->SetM11 (values->GetValueAt (0)->AsDouble ());
	matrix->SetM12 (values->GetValueAt (1)->AsDouble ());
	matrix->SetM13 (values->GetValueAt (2)->AsDouble ());
	matrix->SetM14 (values->GetValueAt (3)->AsDouble ());
	matrix->SetM21 (values->GetValueAt (4)->AsDouble ());
	matrix->SetM22 (values->GetValueAt (5)->AsDouble ());
	matrix->SetM23 (values->GetValueAt (6)->AsDouble ());
	matrix->SetM24 (values->GetValueAt (7)->AsDouble ());
	matrix->SetM31 (values->GetValueAt (8)->AsDouble ());
	matrix->SetM32 (values->GetValueAt (9)->AsDouble ());
	matrix->SetM33 (values->GetValueAt (10)->AsDouble ());
	matrix->SetM34 (values->GetValueAt (11)->AsDouble ());
	matrix->SetOffsetX (values->GetValueAt (12)->AsDouble ());
	matrix->SetOffsetY (values->GetValueAt (13)->AsDouble ());
	matrix->SetOffsetZ (values->GetValueAt (14)->AsDouble ());
	matrix->SetM44 (values->GetValueAt (15)->AsDouble ());

	values->unref ();

	if (argc > 2) {
		count = atoi (argv[2]);
		if (count > 1) {
			signal (SIGALRM, projection_alarm_handler);
			alarm (5);
		}
	}

	while (status && count-- > 0) {
		status = effect->Render (ctx,
					 surface,
					 (double *) matrix->GetMatrixValues (),
					 0, 0, width, height);

		frames++;
	}

	matrix->unref ();

	surface->unref ();
	delete ctx;
	g_free (data);

	runtime_shutdown ();

	return status != true;
}
예제 #15
0
void
MoonWindowGtk::PaintToDrawable (GdkDrawable *drawable, GdkVisual *visual, GdkEventExpose *event, int off_x, int off_y, bool transparent, bool clear_transparent)
{
// 	LOG_UI ("Surface::PaintToDrawable (%p, %p, (%d,%d %d,%d), %d, %d, %d, %d)\n",
// 		drawable, visual, event->area.x, event->area.y, event->area.width, event->area.height,
// 		off_x, off_y, transparent, clear_transparent);
	
	SetCurrentDeployment ();

#if 0
#if TIME_REDRAW
	STARTTIMER (expose, "redraw");
#endif
	if (cache_size_multiplier == -1)
		cache_size_multiplier = gdk_drawable_get_depth (drawable) / 8 + 1;
#endif
	int width, height;
	gdk_drawable_get_size (drawable, &width, &height);
	Context *ctx;
	GdkRectangle area = event->area;
	MoonSurface *src;
	Rect r = Rect (area.x, area.y, area.width, area.height);

	if (!native)
		native = CreateCairoSurface (drawable, visual, true, width, height);
	cairo_xlib_surface_set_drawable (native,
					 gdk_x11_drawable_get_xid (drawable),
					 width, height);
	cairo_surface_set_device_offset (native, off_x, off_y);

	Region *region = new Region ();
	int count = 0;
	GdkRectangle *rects;
	gdk_region_get_rectangles (event->region, &rects, &count);
	while (count--) {
		GdkRectangle c = rects[count];
		region->Union (Rect (c.x, c.y, c.width, c.height));
	}

#ifdef USE_GALLIUM
	if (gctx) {
		ctx = gctx;
	}
	else {
		struct pipe_resource pt, *texture;
		GalliumSurface       *target;

		memset (&pt, 0, sizeof (pt));
		pt.target = PIPE_TEXTURE_2D;
		pt.format = PIPE_FORMAT_B8G8R8A8_UNORM;
		pt.width0 = width;
		pt.height0 = height;
		pt.depth0 = 1;
		pt.last_level = 0;
		pt.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_TRANSFER_WRITE |
			PIPE_BIND_TRANSFER_READ;

		g_assert (screen);

		texture = (*screen->resource_create) (screen, &pt);

		target = new GalliumSurface (texture);
		pipe_resource_reference (&texture, NULL);
		ctx = new GalliumContext (target);
		target->unref ();

		if (gctxn < CONTEXT_CACHE_SIZE) {
			gctxn++;
			gctx = ctx;
		}
	}
#else
	CairoSurface *target = new CairoSurface (1, 1);
	ctx = new CairoContext (target);
	target->unref ();
#endif

	ctx->Push (Context::Group (r));
	/* if we are redirecting to an image surface clear that first */
	surface->Paint (ctx, region, transparent, true);

	r = ctx->Pop (&src);
	if (!r.IsEmpty ()) {
		cairo_surface_t *image = src->Cairo ();
		cairo_t         *cr = cairo_create (native);

		cairo_surface_flush (image);

		cairo_set_source_surface (cr, image, r.x, r.y);
		cairo_set_operator (cr, clear_transparent ? CAIRO_OPERATOR_SOURCE : CAIRO_OPERATOR_OVER);

		region->Draw (cr);
		cairo_fill (cr);

		cairo_destroy (cr);
		cairo_surface_destroy (image);
		src->unref ();
	}

#ifdef USE_GALLIUM
	if (ctx != gctx)
#endif
		delete ctx;

	delete region;

#if TIME_REDRAW
	ENDTIMER (expose, "redraw");
#endif

}
예제 #16
0
/**
 * @fn	   void PaintToDrawable (GdkVisual *visual, cairo_t *cr_t, GtkAllocation &allocation, bool transparent, bool clear_transparent);
 * @brief   Paints to moonlight window drawable and sets transparency to display the video
 *		   and sends the video-rect event  to uniplayer
 * @param   visual			GdkVisual
 * @param   cr_t       		cairo_t
 * @param   allocation   	GtkAllocation
 * @param   transparent			bool
 * @param   clear_transparent	bool
 * @return  void
 */
void
MoonWindowGtk::PaintToDrawable (GdkVisual *visual, cairo_t *cr_t, GtkAllocation &allocation, bool transparent, bool clear_transparent)
{
	SetCurrentDeployment ();

#if 0
#if TIME_REDRAW
	STARTTIMER (expose, "redraw");
#endif
	if (cache_size_multiplier == -1)
	{
		cache_size_multiplier = gdk_drawable_get_depth (drawable) / 8 + 1;
	}
#endif

	Context *ctx;

	cairo_rectangle_int_t area;
	area.x = allocation.x;
	area.y = allocation.y;
	area.width = allocation.width;
	area.height = allocation.height;

	MoonSurface *src;
	Rect r = Rect (area.x, area.y, area.width, area.height);

	Region *region = new Region ();
	int count = 0;

	cairo_region_t *t_region  = cairo_region_create_rectangle(&area);
	count = cairo_region_num_rectangles (t_region);
	cairo_rectangle_int_t rects[count];
	
	for(int i=0;i<count;i++)
	{
		cairo_region_get_rectangle (t_region, i, &rects[i]);
	}

	while (count--)
	{
		cairo_rectangle_int_t c = rects[count];
		region->Union (Rect (c.x, c.y, c.width, c.height));
	}

#ifdef USE_GALLIUM
	if (gctx)
	{
			ctx = gctx;
	}
	else
	{
		struct pipe_resource pt, *texture;
		GalliumSurface       *target;

		memset (&pt, 0, sizeof (pt));
		pt.target = PIPE_TEXTURE_2D;
		pt.format = PIPE_FORMAT_B8G8R8A8_UNORM;
		pt.width0 = width;
		pt.height0 = height;
		pt.depth0 = 1;
		pt.last_level = 0;
		pt.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_TRANSFER_WRITE |
				PIPE_BIND_TRANSFER_READ;

		g_assert (screen);

		texture = (*screen->resource_create) (screen, &pt);

		target = new GalliumSurface (texture);
		pipe_resource_reference (&texture, NULL);
		ctx = new GalliumContext (target);
		target->unref ();

		if (gctxn < CONTEXT_CACHE_SIZE)
		{
			gctxn++;
			gctx = ctx;
		}
	}
#else
    CairoSurface *target = new CairoSurface (1, 1);
	ctx = new CairoContext (target);
	target->unref ();
#endif
	ctx->Push (Context::Group (r));
	surface->Paint (ctx, region, transparent, true);

	r = ctx->Pop (&src);
	if (!r.IsEmpty ())
	{
		cairo_surface_t *image = (cairo_surface_t*) src->Cairo ();
	
			cairo_surface_flush (image);
			cairo_set_source_surface (cr_t, image, r.x, r.y); 
			cairo_set_operator (cr_t, clear_transparent ? CAIRO_OPERATOR_SOURCE : CAIRO_OPERATOR_OVER);
		region->Draw (cr_t);
		cairo_fill (cr_t);

		cairo_surface_destroy (image);
		src->unref ();
	}


#ifdef USE_GALLIUM
    if (ctx != gctx)
#endif
	    delete ctx;

        delete region;

#if TIME_REDRAW
        ENDTIMER (expose, "redraw");
#endif
}