/*
 * gcc -I/usr/local/include/directfb -L/usr/local/lib/ -ldirectfb tt.c -o tt
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>

#include <directfb.h>

#define DBGINFO printf
#define DEF_DEBUG_DEMO

#define DEF_MOU_GLAYER_BUFMODE  DLBM_FRONTONLY
#define DEF_MOU_VLAYER_BUFMODE  DLBM_FRONTONLY

typedef struct
{
    IDirectFBSurface           *addr;
    DFBSurfacePixelFormat       fmt;
    DFBSurfaceCapabilities      caps;
    int                    pitch;
    DFBRectangle                rect;
} DEMO_SURFACE;

typedef struct
{
    IDirectFBDisplayLayer      *addr;
    DFBSurfacePixelFormat       fmt;
    DFBDisplayLayerDescription  desc;
} DEMO_LAYER;

typedef struct
{
    int                    init;
    DEMO_LAYER                   mlayer;
    DEMO_SURFACE                 msurface;
} DEMO_LCTL;

static IDirectFB                   *G_dfb = NULL;
static IDirectFBScreen             *G_screen = NULL;
static DFBGraphicsDeviceDescription G_dev_desc;
static int                     G_layer_count = 0;
/* Graphics Layer Control */
DEMO_LCTL                            G_gctl;

/* Video Layer Control */
DEMO_LCTL                            G_vctl;

int                            G_screen_width = 0;
int                            G_screen_height = 0;
void show_surface_caps(DFBSurfaceCapabilities caps)
{
    DBGINFO("[====]: SURFACE CAPS : ");
    if (caps & DSCAPS_PRIMARY)
    {
        DBGINFO(" PRIMARY");
    }
    if (caps & DSCAPS_SYSTEMONLY)
    {
        DBGINFO(" SYSTEMONLY");
    }
    if (caps & DSCAPS_VIDEOONLY)
    {
        DBGINFO(" VIDEOONLY");
    }
    if (caps & DSCAPS_DOUBLE)
    {
        DBGINFO(" DOUBLE");
    }
    if (caps & DSCAPS_SUBSURFACE)
    {
        DBGINFO(" SUBSURFACE");
    }
    if (caps & DSCAPS_INTERLACED)
    {
        DBGINFO(" INTERLACED");
    }
    if (caps & DSCAPS_SEPARATED)
    {
        DBGINFO(" SEPARATED");
    }
    if (caps & DSCAPS_STATIC_ALLOC)
    {
        DBGINFO(" STATIC_ALLOC");
    }
    if (caps & DSCAPS_TRIPLE)
    {
        DBGINFO(" TRIPLE");
    }
    if (caps & DSCAPS_PREMULTIPLIED)
    {
        DBGINFO(" PREMULTIPLIED");
    }
    if (caps & DSCAPS_DEPTH)
    {
        DBGINFO(" DEPTH");
    }
#if 0
    if (caps & DSCAPS_SHARED)
    {
        DBGINFO(" SHARED");
    }
#endif
    if (caps & DSCAPS_FLIPPING)
    {
        DBGINFO(" FLIPPING");
    }
    DBGINFO("\n");
}

void show_surface_accelation(DFBAccelerationMask mask)
{
    DBGINFO("[====]: AccelerationMask: ");
    if (mask & DFXL_FILLRECTANGLE)
    {
        DBGINFO(" FILLRECTANGLE");
    }
    if (mask & DFXL_DRAWRECTANGLE)
    {
        DBGINFO(" DRAWRECTANGLE");
    }
    if (mask & DFXL_DRAWLINE)
    {
        DBGINFO(" DRAWLINE");
    }
    if (mask & DFXL_FILLTRIANGLE)
    {
        DBGINFO(" FILLTRIANGLE");
    }
    if (mask & DFXL_BLIT)
    {
        DBGINFO(" BLIT");
    }
    if (mask & DFXL_STRETCHBLIT)
    {
        DBGINFO(" STRETCHBLIT");
    }
    if (mask & DFXL_TEXTRIANGLES)
    {
        DBGINFO(" TEXTRIANGLES");
    }
    if (mask & DFXL_DRAWSTRING)
    {
        DBGINFO(" DRAWSTRING");
    }
    DBGINFO("\n");
}

static void show_blitflags(DFBSurfaceBlittingFlags blitting_flags)
{
    DBGINFO("[====]: BlittingFlags : ");
    if (blitting_flags & DSBLIT_BLEND_ALPHACHANNEL)
    {
        DBGINFO(" BLEND_ALPHACHANNEL");
    }
    if (blitting_flags & DSBLIT_BLEND_COLORALPHA)
    {
        DBGINFO(" BLEND_COLORALPHA");
    }
    if (blitting_flags & DSBLIT_COLORIZE)
    {
        DBGINFO(" COLORIZE");
    }
    if (blitting_flags & DSBLIT_SRC_COLORKEY)
    {
        DBGINFO(" SRC_COLORKEY");
    }
    if (blitting_flags & DSBLIT_DST_COLORKEY)
    {
        DBGINFO(" DST_COLORKEY");
    }
    if (blitting_flags & DSBLIT_SRC_PREMULTIPLY)
    {
        DBGINFO(" SRC_PREMULTIPLY");
    }
    if (blitting_flags & DSBLIT_DST_PREMULTIPLY)
    {
        DBGINFO(" DST_PREMULTIPLY");
    }
    if (blitting_flags & DSBLIT_DEMULTIPLY)
    {
        DBGINFO(" DEMULTIPLY");
    }
    if (blitting_flags & DSBLIT_DEINTERLACE)
    {
        DBGINFO(" DEINTERLACE");
    }
    if (blitting_flags & DSBLIT_SRC_PREMULTCOLOR)
    {
        DBGINFO(" SRC_PREMULTCOLOR");
    }
    if (blitting_flags & DSBLIT_XOR)
    {
        DBGINFO(" XOR");
    }
    if (blitting_flags & DSBLIT_INDEX_TRANSLATION)
    {
        DBGINFO(" INDEX_TRANSLATION");
    }
#if 0
    if (blitting_flags & DSBLIT_ROTATE180)
    {
        DBGINFO(" ROTATE180");
    }
#endif
#if 0
    if (blitting_flags & DSBLIT_COLORKEY_PROTECT)
    {
        DBGINFO(" COLORKEY_PROTECT");
    }
#endif
#if 0
    if (blitting_flags & DSBLIT_SRC_MASK_ALPHA)
    {
        DBGINFO(" SRC_MASK_ALPHA");
    }
#endif
#if 0
    if (blitting_flags & DSBLIT_SRC_MASK_COLOR)
    {
        DBGINFO(" SRC_MASK_COLOR");
    }
#endif
    DBGINFO("\n");
}

static void show_drawflags(DFBSurfaceDrawingFlags drawing_flags)
{
    DBGINFO("[====]: DrawingFlags : ");
    if (drawing_flags & DSDRAW_BLEND)
    {
        DBGINFO(" BLEND");
    }
    if (drawing_flags & DSDRAW_DST_COLORKEY)
    {
        DBGINFO(" DST_COLORKEY");
    }
    if (drawing_flags & DSDRAW_SRC_PREMULTIPLY)
    {
        DBGINFO(" SRC_PREMULTIPLY");
    }
    if (drawing_flags & DSDRAW_DST_PREMULTIPLY)
    {
        DBGINFO(" DST_PREMULTIPLY");
    }
    if (drawing_flags & DSDRAW_DEMULTIPLY)
    {
        DBGINFO(" DEMULTIPLY");
    }
    if (drawing_flags & DSDRAW_XOR)
    {
        DBGINFO(" XOR");
    }

    DBGINFO("\n");
}

static void show_dev_spec(void)
{
    show_blitflags(G_dev_desc.blitting_flags);
    show_drawflags(G_dev_desc.drawing_flags);

    DBGINFO("[====]: video_memory: %d\n", G_dev_desc.video_memory);
    //printf("DFBGraphicsDeviceDescription:   name:                       %s\n", G_dev_desc.name);
    //printf("DFBGraphicsDeviceDescription:   vendor:                     %s\n", G_dev_desc.vendor);
    //printf("DFBGraphicsDeviceDescription:   driver.major:               %d\n", G_dev_desc.driver.major);
    //printf("DFBGraphicsDeviceDescription:   driver.minor:               %d\n", G_dev_desc.driver.minor);
    //printf("DFBGraphicsDeviceDescription:   driver.name:                %s\n", G_dev_desc.driver.name);
    //printf("DFBGraphicsDeviceDescription:   driver.vendor:              %s\n", G_dev_desc.driver.vendor);
}

static void show_layer_desc(DFBDisplayLayerDescription *const desc)
{
    DBGINFO("[====]: LAYER (%d): %s\n", desc->level, desc->name );

    DBGINFO("[====]: type: ");
    if (desc->type & DLTF_GRAPHICS)
    {
        DBGINFO(" GRAPHICS");
    }
    if (desc->type & DLTF_VIDEO)
    {
        DBGINFO(" VIDEO");
    }
    if (desc->type & DLTF_STILL_PICTURE)
    {
        DBGINFO(" STILL_PICTURE");
    }
    if (desc->type & DLTF_BACKGROUND)
    {
        DBGINFO(" BACKGROUND");
    }
    DBGINFO("\n");

    DBGINFO("[====]: caps: ");

    if (desc->caps & DLCAPS_SURFACE)
    {
        DBGINFO(" SURFACE");
    }
    if (desc->caps & DLCAPS_OPACITY)
    {
        DBGINFO(" OPACITY");
    }
    if (desc->caps & DLCAPS_ALPHACHANNEL)
    {
        DBGINFO(" ALPHACHANNEL");
    }
    if (desc->caps & DLCAPS_SCREEN_LOCATION)
    {
        DBGINFO(" SCREEN_LOCATION");
    }
    if (desc->caps & DLCAPS_FLICKER_FILTERING)
    {
        DBGINFO(" FLICKER_FILTERING");
    }
    if (desc->caps & DLCAPS_DEINTERLACING)
    {
        DBGINFO(" DEINTERLACING");
    }
    if (desc->caps & DLCAPS_SRC_COLORKEY)
    {
        DBGINFO(" SRC_COLORKEY");
    }
    if (desc->caps & DLCAPS_DST_COLORKEY)
    {
        DBGINFO(" DST_COLORKEY");
    }
    if (desc->caps & DLCAPS_BRIGHTNESS)
    {
        DBGINFO(" BRIGHTNESS");
    }
    if (desc->caps & DLCAPS_CONTRAST)
    {
        DBGINFO(" CONTRAST");
    }
    if (desc->caps & DLCAPS_HUE)
    {
        DBGINFO(" HUE");
    }
    if (desc->caps & DLCAPS_SATURATION)
    {
        DBGINFO(" SATURATION");
    }
    if (desc->caps & DLCAPS_LEVELS)
    {
        DBGINFO(" LEVELS");
    }
    if (desc->caps & DLCAPS_FIELD_PARITY)
    {
        DBGINFO(" FIELD_PARITY");
    }
    if (desc->caps & DLCAPS_WINDOWS)
    {
        DBGINFO(" WINDOWS");
    }
    if (desc->caps & DLCAPS_SOURCES)
    {
        DBGINFO(" SOURCES");
    }
    if (desc->caps & DLCAPS_ALPHA_RAMP)
    {
        DBGINFO(" DLCAPS_ALPHA_RAMP");
    }
    if (desc->caps & DLCAPS_PREMULTIPLIED)
    {
        DBGINFO(" PREMULTIPLIED");
    }
    if (desc->caps & DLCAPS_SCREEN_POSITION)
    {
        DBGINFO(" SCREEN_POSITION");
    }
    if (desc->caps & DLCAPS_SCREEN_SIZE)
    {
        DBGINFO(" SCREEN_SIZE");
    }
    if (desc->caps & DLCAPS_CLIP_REGIONS)
    {
        DBGINFO(" CLIP_REGIONS");
    }
    DBGINFO("\n");

    DBGINFO("[====]: regions: %d\n", desc->regions);
    DBGINFO("[====]: sources: %d\n", desc->sources);
    DBGINFO("[====]: clip_regions: %d\n", desc->clip_regions);
    DBGINFO("\n");
}

static int demo_msurface_get_info(DEMO_SURFACE *const msurface)
{
    int rt;
    void *vbuf;

    msurface->fmt = 0;
    msurface->caps = 0;
    msurface->pitch = 0;
    msurface->rect.x = 0;
    msurface->rect.y = 0;
    msurface->rect.w = 0;
    msurface->rect.h = 0;

    rt = msurface->addr->GetCapabilities(msurface->addr, &msurface->caps);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: GetCapabilities: ", rt);
        return (-1);
    }

#ifdef DEF_DEBUG_DEMO
    show_surface_caps(msurface->caps);
#endif

    rt = msurface->addr->GetPosition(msurface->addr, &msurface->rect.x, &msurface->rect.y);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: GetPosition: ", rt);
        return (-1);
    }

    rt = msurface->addr->GetSize(msurface->addr, &msurface->rect.w, &msurface->rect.h);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: GetSize: ", rt);
        return (-1);
    }

    rt = msurface->addr->GetPixelFormat(msurface->addr, &msurface->fmt);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: GetPixelFormat: ", rt);
        return (-1);
    }

    rt = msurface->addr->Lock(msurface->addr, DSLF_READ | DSLF_WRITE, &vbuf, &msurface->pitch);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: Lock: \n", rt);
        return (-1);
    }

    rt =  msurface->addr->Unlock(msurface->addr);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: Unlock: \n", rt);
        return (-1);
    }

    if (msurface->pitch < msurface->rect.w)
    {
        DBGINFO("[-ERR]: PITCH %d < %d\n", msurface->pitch, msurface->rect.w);
        return (-1);
    }

#ifdef DEF_DEBUG_DEMO
    DBGINFO("[====]: %08X   FMT     : %08X\n", (unsigned int)msurface, msurface->fmt);
    DBGINFO("[====]: %08X   PITCH   : %d\n", (unsigned int)msurface, msurface->pitch);
    DBGINFO("[====]: %08X   X       : %d\n", (unsigned int)msurface, msurface->rect.x);
    DBGINFO("[====]: %08X   Y       : %d\n", (unsigned int)msurface, msurface->rect.y);
    DBGINFO("[====]: %08X   W       : %d\n", (unsigned int)msurface, msurface->rect.w);
    DBGINFO("[====]: %08X   H       : %d\n", (unsigned int)msurface, msurface->rect.h);
#endif

    return (0);
}

static int demo_dev_init_glayer(int id)
{
    int rt;
    DFBDisplayLayerConfig layer_config;

    rt = G_dfb->GetDisplayLayer(G_dfb, id, &G_gctl.mlayer.addr);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal("[-ERR]: glayer GetDisplayLayer: ", rt);
        return (-1);
    }
    rt = G_gctl.mlayer.addr->GetDescription(G_gctl.mlayer.addr, &G_gctl.mlayer.desc);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal("[-ERR]: glayer GetDescription: ", rt);
        return (-1);
    }
#ifdef DEF_DEBUG_DEMO
    show_layer_desc(&G_gctl.mlayer.desc);
#endif
    rt = G_gctl.mlayer.addr->SetCooperativeLevel(G_gctl.mlayer.addr, DLSCL_EXCLUSIVE);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal("[-ERR]: glayer SetCooperativeLevel: ", rt);
        return (-1);
    }

    layer_config.flags = 0;
    layer_config.flags |= DLCONF_WIDTH | DLCONF_HEIGHT;
    layer_config.width = G_screen_width;
    layer_config.height = G_screen_height;
#ifdef DEF_DEMO_GLAYER_BUFMODE
    layer_config.flags |= DLCONF_BUFFERMODE;
    layer_config.buffermode = DEF_DEMO_GLAYER_BUFMODE;
#endif
    layer_config.flags |= DLCONF_PIXELFORMAT;
    layer_config.pixelformat = DSPF_ARGB;

    if (G_gctl.mlayer.desc.caps & DLCAPS_ALPHACHANNEL)
    {
        layer_config.flags |= DLCONF_OPTIONS;
        layer_config.options = DLOP_ALPHACHANNEL;
    }

    rt = G_gctl.mlayer.addr->SetConfiguration(G_gctl.mlayer.addr, &layer_config);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: glayer SetConfiguration: ", rt);
        return (-1);
    }
    rt = G_gctl.mlayer.addr->GetSurface(G_gctl.mlayer.addr, &G_gctl.msurface.addr);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: glayer GetSurface: ", rt);
        return (-1);
    }
    if (demo_msurface_get_info(&G_gctl.msurface) != 0)
    {
        return (-1);
    }
    rt = G_gctl.msurface.addr->SetBlittingFlags(G_gctl.msurface.addr, DSBLIT_NOFX);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: glayer SetBlittingFlags: ", rt);
        return (-1);
    }

    rt = G_gctl.msurface.addr->Clear(G_gctl.msurface.addr, 0, 0, 0, 0);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: glayer Clear: ", rt);
        return (-1);
    }
    rt = G_gctl.msurface.addr->Flip(G_gctl.msurface.addr, NULL, DSFLIP_ONSYNC);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: glayer Flip: ", rt);
        return (-1);
    }

    DBGINFO( "LAYER 0 -- INITED SUCCESSFUL\n");
    G_gctl.init = 1;
    G_gctl.mlayer.fmt = DSPF_ARGB;
    return (0);
}

static int demo_dev_init_vlayer(int id)
{
    int rt;
    DFBDisplayLayerConfig layer_config;

    rt = G_dfb->GetDisplayLayer(G_dfb, id, &G_vctl.mlayer.addr);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: vlayer GetDisplayLayer: ", rt);
        return (-1);
    }
    rt = G_vctl.mlayer.addr->GetDescription(G_vctl.mlayer.addr, &G_vctl.mlayer.desc);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal("[-ERR]: vlayer GetDescription: ", rt);
        return (-1);
    }
#ifdef DEF_DEBUG_DEMO
    show_layer_desc(&G_vctl.mlayer.desc);
#endif
    rt = G_vctl.mlayer.addr->SetCooperativeLevel(G_vctl.mlayer.addr, DLSCL_EXCLUSIVE);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: vlayer SetCooperativeLevel: ", rt);
        return (-1);
    }
    rt = G_vctl.mlayer.addr->EnableCursor(G_vctl.mlayer.addr, 0);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: vlayer EnableCursor: ", rt);
        return (-1);
    }
    layer_config.flags = DLCONF_OPTIONS | DLCONF_PIXELFORMAT | DLCONF_WIDTH | DLCONF_HEIGHT;
#ifdef DEF_DEMO_VLAYER_BUFMODE
    layer_config.flags |= DLCONF_BUFFERMODE;
    layer_config.buffermode = DEF_DEMO_VLAYER_BUFMODE;
#endif
    layer_config.pixelformat = DSPF_UYVY;
    layer_config.options = DLOP_NONE;
    layer_config.width = G_screen_width;
    layer_config.height = G_screen_height;

    rt = G_vctl.mlayer.addr->SetConfiguration(G_vctl.mlayer.addr, &layer_config);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: vlayer SetConfiguration: ", rt);
        return (-1);
    }
#if 0
    rt = G_vctl.mlayer.addr->SetLevel(G_vctl.mlayer.addr, -1);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: vlayer SetLevel: ", rt);
        return (-1);
    }
#endif

    rt = G_vctl.mlayer.addr->GetSurface(G_vctl.mlayer.addr, &G_vctl.msurface.addr);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: vlayer GetSurface: ", rt);
        return (-1);
    }
    if (demo_msurface_get_info(&G_vctl.msurface) != 0)
    {
        return (-1);
    }

    rt = G_vctl.msurface.addr->SetBlittingFlags(G_vctl.msurface.addr, DSBLIT_NOFX);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: vlayer SetBlittingFlags: ", rt);
        return (-1);
    }
    rt = G_vctl.msurface.addr->Clear(G_vctl.msurface.addr, 0, 0, 0, 0);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: vlayer Clear: ", rt);
        return (-1);
    }
    rt = G_vctl.msurface.addr->Flip(G_vctl.msurface.addr, NULL, DSFLIP_ONSYNC);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: vlayer Flip: ", rt);
        return (-1);
    }

    DBGINFO( "LAYER 1 -- INITED SUCCESSFUL\n");
    G_vctl.init = 1;
    G_vctl.mlayer.fmt = DSPF_UYVY;
    return (0);
}

void demo_msurface_free(DEMO_SURFACE *const msurface)
{
    if (msurface == NULL)
    {
        return;
    }

    if (msurface->addr != NULL)
    {
        msurface->addr->Release(msurface->addr);
    }

    memset(msurface, 0, sizeof(DEMO_SURFACE));
}

void demo_mlayer_free(DEMO_LAYER *const mlayer)
{
    if (mlayer == NULL)
    {
        return;
    }

    if (mlayer->addr != NULL)
    {
        mlayer->addr->Release(mlayer->addr);
    }

    memset(mlayer, 0, sizeof(DEMO_LAYER));
}

static void demo_free_lctl(void)
{
    demo_msurface_free(&G_gctl.msurface);
    demo_mlayer_free(&G_gctl.mlayer);

    demo_msurface_free(&G_vctl.msurface);
    demo_mlayer_free(&G_vctl.mlayer);

    memset(&G_gctl, 0, sizeof(DEMO_LCTL));
    memset(&G_vctl, 0, sizeof(DEMO_LCTL));
}

int main(int argc, char *argv[])
{
    int rt;

    memset(&G_gctl, 0, sizeof(DEMO_LCTL));
    memset(&G_vctl, 0, sizeof(DEMO_LCTL));

    /* init DirectFB */
    rt = DirectFBInit(&argc, &argv);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: DirectFBInit: ", rt);
        return (-1);
    }

    rt = DirectFBCreate(&G_dfb);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: DirectFBCreate: ", rt);
        return (-1);
    }

    rt = G_dfb->GetDeviceDescription(G_dfb, &G_dev_desc);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: GetDeviceDescription: ", rt);
        return (-1);
    }
#ifdef DEF_DEBUG_DEMO
    show_dev_spec();
#endif

    rt = G_dfb->GetScreen(G_dfb, DSCID_PRIMARY, &G_screen);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: GetScreen: ", rt);
        return (-1);
    }
    rt = G_screen->GetSize(G_screen, &G_screen_width, &G_screen_height);
    if (rt != DFB_OK)
    {
        DirectFBErrorFatal( "[-ERR]: GetSize: ", rt);
        return (-1);
    }
    DBGINFO("SCREEN: %d x %d\n", G_screen_width, G_screen_height);

    rt = demo_dev_init_glayer(0);
    if (rt < 0)
    {
        DBGINFO("demo_dev_init_glayer: failed: %08X\n", (unsigned int)rt);
        demo_free_lctl();
        return (rt);
    }

    rt = demo_dev_init_vlayer(1);
    if (rt < 0)
    {
        DBGINFO("demo_dev_init_vlayer: failed: %08X\n", (unsigned int)rt);
        demo_free_lctl();
        return (rt);
    }

    demo_free_lctl();
    if (G_dfb != NULL)
    {
        G_dfb->Release(G_dfb);
        G_dfb = NULL;
    }

    if (G_screen != NULL)
    {
        G_screen->Release(G_screen);
        G_screen = NULL;
    }
    return (0);
}
