I have written a very simple little program to test the global opacity capability of my custom gfxdriver for the PXA27x.

I am trying to set a background image into a base layer, and then blit another image to another overlay that supports global opacity. I need to see that the background image shows through the foreground image, of varying amounts controlled by layer->SetOpacity().

Attached is the simple program to test this. If I comment out the call to setup_fg_image(), I can see the background image, and if I comment out the call to setup_bg_image(), I can see the foreground image. But not both at the same time, it seems blitting the foreground image always erases the background image first. Which makes me think that when I ->Blit and ->Flip the foreground surface, the surface is actually getting sent to the backround layer, not the foreground layer.

So I don't really understand how to associate a Surface with a DisplayLayer. I am using layer->GetSurface() and I assume that is one way to make the surface <--> layer association, or am I wrong?

Thanks in advance for the help.
Steve


#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <directfb.h>

/* macro for a safe call to DirectFB functions */
#define DFBCHECK(x...)							\
	err = x;							\
	if (err != DFB_OK) {						\
		fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ );	\
		DirectFBErrorFatal (#x, err);				\
	}

#define BACKGROUND_NAME  "background.jpg"
#define FOREGROUND_NAME  "apple-red.png"

static IDirectFB        *dfb;

static IDirectFBDisplayLayer  *bg_layer = NULL;
static IDirectFBDisplayLayer  *fg_layer = NULL;

static DFBResult         err;


static void
exit_application(int exitcode)
{
	/* Release the layers. */
	if (fg_layer)
		fg_layer->Release( fg_layer );
	if (bg_layer)
		bg_layer->Release( bg_layer );

	dfb->Release (dfb);

	exit(exitcode);
}

static DFBEnumerationResult
display_layer_callback( DFBDisplayLayerID           id,
                        DFBDisplayLayerDescription  desc,
                        void                       *arg )
{
	if (!bg_layer && (desc.type & DLTF_BACKGROUND)) {
		printf( "Using %s for background\n", desc.name );
		DFBCHECK(dfb->GetDisplayLayer( dfb, id, &bg_layer ));
	} else if (!fg_layer && (desc.caps & DLCAPS_OPACITY)) {
		printf( "Using %s for opacity-supported foreground\n",
			desc.name );
		DFBCHECK(dfb->GetDisplayLayer( dfb, id, &fg_layer ));
	}

	return DFB_OK;
}

static void
setup_bg_image(IDirectFBDisplayLayer *layer)
{
	DFBDisplayLayerConfig config;
	IDirectFBImageProvider *provider;
	DFBSurfaceDescription desc;
	IDirectFBSurface *background;

	layer->SetCooperativeLevel( layer, DLSCL_ADMINISTRATIVE );

	DFBCHECK(dfb->CreateImageProvider( dfb, BACKGROUND_NAME,
					   &provider ));

	layer->GetConfiguration( layer, &config );

	desc.flags = DSDESC_WIDTH | DSDESC_HEIGHT;
	desc.width = config.width;
	desc.height = config.height;

	DFBCHECK(dfb->CreateSurface( dfb, &desc, &background ) );
	provider->RenderTo( provider, background, NULL );
	provider->Release( provider );

	config.flags = DLCONF_BUFFERMODE;
	config.buffermode = DLBM_BACKSYSTEM;
	layer->SetConfiguration( layer, &config );

	layer->SetBackgroundImage( layer, background );
	layer->SetBackgroundMode( layer, DLBM_IMAGE );

	background->Release (background);
}

static void
setup_fg_image(IDirectFBDisplayLayer *layer)
{
	DFBDisplayLayerConfig config;
	IDirectFBImageProvider *provider;
	DFBSurfaceDescription sdesc;
	IDirectFBSurface *foreground;
	IDirectFBSurface *image;

	layer->SetCooperativeLevel( layer, DLSCL_EXCLUSIVE );

	DFBCHECK(dfb->CreateImageProvider (dfb, FOREGROUND_NAME,
					   &provider));
	DFBCHECK(provider->GetSurfaceDescription (provider, &sdesc));
	DFBCHECK(dfb->CreateSurface (dfb, &sdesc, &image));

	provider->RenderTo (provider, image, NULL);
	provider->Release (provider);

	/* Get the screen size etc. */
	layer->GetConfiguration( layer, &config );
	config.flags = DLCONF_BUFFERMODE;
	config.buffermode = DLBM_BACKSYSTEM;
	layer->SetConfiguration( layer, &config );

	layer->GetSurface( layer, &foreground );

	layer->SetScreenRectangle(layer, config.width/2, config.height/2,
				  sdesc.width, sdesc.height);
	
	/* set to half-opaque */
	layer->SetOpacity( layer, 0x80 );

	foreground->Blit( foreground, image, NULL, 0, 0);
	foreground->Flip( foreground, NULL, 0 );
	
	image->Release (image);
	foreground->Release (foreground);
}

void handler (int sn)
{
	fprintf(stderr, "SIGINT caught\n");
	exit_application(0);
}

int main (int argc, char **argv)
{
	struct sigaction sa;
	DFBResult ret;

	memset (&sa, 0, sizeof(sa));
	sa.sa_handler = &handler;

	DFBCHECK (DirectFBInit (&argc, &argv));

	/* create the super interface */
	DFBCHECK (DirectFBCreate (&dfb));

	ret = dfb->EnumDisplayLayers( dfb, display_layer_callback, NULL );
	if (ret)
		DirectFBError( "IDirectFBScreen::EnumDisplayLayers", ret );

	if (!bg_layer) {
		printf( "No background-supporting layer found\n");
		exit_application(1);
	}

	if (!fg_layer) {
		printf( "No global opacity-supporting layer found\n");
		exit_application(1);
	}
  
	/* setup background layer and load background image to it */
	setup_bg_image(bg_layer);
	/* setup foreground layer and load image to it, with global opacity */
	setup_fg_image(fg_layer);

	/* wait for user to hit Ctrl-C */
	printf("Hit Ctrl-C to quit\n");
	sigaction(SIGINT, &sa, NULL);
	while(1) pause();

	exit_application(0);
}
_______________________________________________
directfb-dev mailing list
[email protected]
http://mail.directfb.org/cgi-bin/mailman/listinfo/directfb-dev

Reply via email to