I notice that my full screen surface (1280x720 pixel) doesn't fit to my TV's screen. The (0,0) and (1279,719) are seemed to be drawn outside the visible of my TV's screen at somewhere (-20,-15) and (1300, 735) instead.
We have seen a problem when the parts drawn outside the TV screen are mixed back with subsequent FillRectangle() on visible TV screen when DSPD_SRC_OVER rule is used. This happened only if hardware accel is used. Below is the code that we see the issue. The off screen part of the red rectangle are mixed back with the two gradient bars.
#include <stdio.h>
#include <unistd.h>
#include <directfb.h>
static IDirectFB *dfb = NULL;
static IDirectFBSurface *primary = NULL;
static int screen_width = 0;
static int screen_height = 0;
#define DFBCHECK(x...) \
{ \
DFBResult err = x; \
\
if (err != DFB_OK) \
{ \
fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
DirectFBErrorFatal( #x, err ); \
} \
}
static IDirectFBSurface *logo = NULL;
static IDirectFBSurface *offscreen = NULL;
int main (int argc, char **argv)
{
int i;
DFBSurfaceDescription dsc;
DFBCHECK (DirectFBInit (&argc, &argv));
DFBCHECK (DirectFBCreate (&dfb));
DFBCHECK (dfb->SetCooperativeLevel (dfb, DFSCL_FULLSCREEN));
// create primary surface
dsc.flags = DSDESC_CAPS;
dsc.caps = (DFBSurfaceCapabilities)(DSCAPS_PRIMARY | DSCAPS_FLIPPING);
dsc.pixelformat = DSPF_ARGB;
DFBCHECK (dfb->CreateSurface( dfb, &dsc, &primary ));
DFBCHECK (primary->GetSize (primary, &screen_width, &screen_height));
// clear primary surface
primary->SetColor (primary, 0xff, 0xff, 0xff, 0xff);
DFBCHECK (primary->FillRectangle (primary, 0, 0, screen_width, screen_height));
// create offscreen surface
dsc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_WIDTH | DSDESC_HEIGHT);
dsc.width = screen_width;
dsc.height = screen_height;
DFBCHECK (dfb->CreateSurface( dfb, &dsc, &offscreen ));
offscreen->SetColor (offscreen, 0xff, 0xff, 0xff, 0xff);
DFBCHECK (offscreen->FillRectangle (offscreen, 0, 0, screen_width, screen_height));
// draw red rectangle on Offscreen
offscreen->SetColor (offscreen, 0xff, 0x00, 0x00, 0xff);
DFBCHECK (offscreen->FillRectangle (offscreen, 300, 0, 500, 100));
offscreen->SetColor (offscreen, 0x00, 0x00, 0xff, 0xff);
DFBCHECK (offscreen->FillRectangle (offscreen, 0, 460, 500, 50));
// create gradient bar
dsc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_WIDTH | DSDESC_HEIGHT);
dsc.width = 1;
dsc.height = 128;
DFBCHECK(dfb->CreateSurface( dfb, &dsc, &logo ));
{
// Create the gradient by writing directly to the surface
void* data;
int pitch;
DFBCHECK(logo->Lock(logo, DSLF_WRITE, &data, &pitch));
for (int i=0; i < 128; i++)
{
unsigned char* line = &((unsigned char*)data)[i*pitch];
unsigned char r = 0x50 + (0xff-0x50)*i/128;
unsigned char g = 0x80 + (0xff-0x80)*i/128;
unsigned char b = 0xa0 + (0xff-0xa0)*i/128;
unsigned char a = 0x30 + (0xff-0x30)*i/128;
unsigned int color = b;
color |= g << 8;
color |= r << 16;
color |= a << 24;
*((unsigned int*)line) = color;
}
DFBCHECK(logo->Unlock(logo));
}
// Set render flags
unsigned char opacity = (unsigned char)(0.6f * 255);
offscreen->SetColor(offscreen, opacity, opacity, opacity, opacity);
offscreen->SetPorterDuff(offscreen, DSPD_SRC_OVER);
offscreen->SetBlittingFlags(offscreen, (DFBSurfaceBlittingFlags)(DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA | DSBLIT_SRC_PREMULTCOLOR));
offscreen->SetRenderOptions(offscreen, (DFBSurfaceRenderOptions)(DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE));
//Blit two gradient bars to offscreen surf
DFBRectangle srec = {0, 0, 1, 128};
DFBRectangle drec = {0, 486, 1280, 15};
DFBCHECK (offscreen->StretchBlit (offscreen, logo, &srec, &drec));
drec.x = 0; drec.y = 426; drec.w = 1280; drec.h = 15;
DFBCHECK (offscreen->StretchBlit (offscreen, logo, &srec, &drec));
// flip Offscreen to primary
DFBCHECK (primary->Blit (primary, offscreen, NULL, 0, 0));
DFBCHECK (primary->Flip (primary, NULL, DSFLIP_BLIT));
sleep (60);
offscreen->Release (offscreen);
logo->Release (logo);
primary->Release (primary);
dfb->Release (dfb);
return 0;
}