/*****************************************************************************/
/* Copyright (c) 2009 NXP B.V.                                               */
/*                                                                           */
/* This library is free software; you can redistribute it and/or             */
/* modify it under the terms of the GNU Lesser General Public                */
/* License as published by the Free Software Foundation, using               */
/* version 2.1 of the License.                                               */
/*                                                                           */
/* This library is distributed in the hope that it will be useful,           */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU          */
/* Lesser General Public License for more details.                           */
/*                                                                           */
/* You should have received a copy of the GNU Lesser General Public          */
/* License along with this library; if not, write to the Free Software       */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA   */
/*                                                                           */
/*****************************************************************************/
/**
    @file   phStbDFB_Layers.c
    @brief  Common Layer code of the graphics driver for DirectFB.

@b  Component:  phStbDFB.

*//*

Rev Date        Author      Comments
--------------------------------------------------------------------------------
  1 20050711    batelaan    First implementation.
  2 20050713    batelaan    Crosscheck fixes
  3 20050714    laird       More screen impl details
  4 20050715    laird       More details.
  5 20050719    laird       Making it use the FBDev Driver if it is graphics and layer 4
  6 20050719    laird       Use old driver data when calling old functions.
  7 20050720    laird       Fixing my bug with window stack destroy.
  8 20050720    laird       Setting the BG colour of the framebuffer to be black alpha.
  9 20050721    laird       Fixing the set region code to work better.
 10 20050721    laird       XCheck rework.
10.1.1 20050823  charrett    Reorganise the code
10.1.2 20050826  charrett    Fix bug in layer code todo with multiple apps.
  11 20050817    laird       Need to get FB to support ScreenPositon/location etc for NTSC
  12 20050826    laird       Merged 'phStbDFB_Layers.c=11' with 'phStbDFB_Layers.c=10.1.3'.
  13 20050901    neill       Implement source rectangle setting
  14 20050901    neill       Remove checking of width and height for setting source rectangle
  15 20050908    laird       Common InitLayer Code for non FBdev layers
  16 20050913    laird       Support for QVCP2L
  17 20050928    laird       Adding support for STILL_PICTURE layers
  18 20050928    laird       XCheck rework.
  19 20050929    laird       Adding support for Flicker Filtering.
  20 20051003    laird       Adding support for setting brightness
  21 20051014    laird       Adding support for per pixel alpha setting.
  22 20051108    laird       Adding support for getting and setting the Z Order.
  23 20051124    laird       Changing How i set Z-Order.
  24 20051124    laird       BugFix
  25 20051208    laird       Increasing the checking on Source/Destination rectangles.
  26 20051209    laird       ZOrder logic very wrong correcting for PR380.
  27 20051214    laird       Adding utility function to get the current type of a layer.
  28 20060328    mpage       Layer showing
  29 20060329    mpage       Checking pointer for NULL before assigning
  30 20060617    laird       Changing how to disable/enable a layer.
  31 20060727    laird       Removing Asserts.
  32 20060801    laird       Removing Flicker Filter warning.
-----------------------------STB225---------------------------------------------
  31 20070112    laird       Moving to STB225
  32 20070116    laird       Crosscheck Rework.
  33 20070502    burningh    Update for DirectFB 1.0
  34 20070619    neill       Add Z ordering
  35 20070704    neill       Correct Z ordering
  36 20070815    neill       Enable video layer opacity setting
  37 20070921    neill       Add support for HD framebuffers
  38 20071016    burningh    Tidy up & fix phStbVideoRenderer API
  39 20071029    burningh    Improve QA C confidence factor
  40 20080124    neill       Add support for Video layer zooming
  41 20080709    neill       Add force param to blank output
  42 20080804    neill       Improve resolution changing
  43 20080902    laird       Remove dead functions.
  44 20090120    batelaan    Update file copyright/license text
--------------------------------------------------------------------------------
    For consistency and standardisation retain the Section Separators.
*/

/***********************************************
* INCLUDE FILES                                *
************************************************/

#include <phStbDFB_Local.h>
#include <core/core.h>
#include <core/layer_control.h>
#include <core/windowstack.h>
#include <fusion/object.h>
#include <string.h>

/***********************************************
* LOCAL MACROS                                 *
* recommendation only: <MODULE><_WORD>+        *
************************************************/


/******************************************************************
* LOCAL TYPEDEFS                                                  *
* recommendation only:                [p]phStbTemplate_<Word>+_t  *
*******************************************************************/

/******************************************************************
* STATIC DATA                  g[k|p|kp|pk|kpk]<Module>_<Word>+   *
*******************************************************************/
static DFBResult StbDFB_GetLayerData(int layerId,
                                     phStbDFB_LayerData_t **ppLayerData);


static const int StbDFB_directFB2VidRendLayer[] = {
    phStbVideoRenderer_Layers_Graphics1,
    phStbVideoRenderer_Layers_Graphics2,
    phStbVideoRenderer_Layers_Display1,
    phStbVideoRenderer_Layers_Display2
};

/*********************************************************(((((((**********
* EXPORTED DATA                     g[k|p|kp|pk|kpk]phStbTemplate_<Word>+ *
***************************************************************************/

/*******************************************************************************
* FUNCTION IMPLEMENTATION  <Module>[_<Word>+] for static functions             *
*                          tm[<layer>]<Module>[_<Word>+] for exported functions*
********************************************************************************/

/******************************************************************************/

int phStbDFB_LayerDataSize(void)
{
     return 0;
}

/******************************************************************************/
DFBResult phStbDFB_LayerInit(CoreLayer                  *layer,
                             void                       *driver_data,
                             void                       *layer_data,
                             DFBDisplayLayerDescription *description,
                             DFBDisplayLayerConfig      *config,
                             DFBColorAdjustment         *adjustment
                             )
{
    DFBResult     result = DFB_FAILURE;
    tmErrorCode_t err;
    /*phStbVideoTypes_PixelFormat_t pixelFormat;*/
    phStbDFB_LayerData_t     *pLayerData = (phStbDFB_LayerData_t*)driver_data;
    phStbDFB_ScreenData_t    *pScreenData    = (phStbDFB_ScreenData_t*)layer->screen->screen_data;

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s: layerId=%u renderInst %p", __FUNCTION__, pLayerData->layerId));

    // NAB TODO: This looks like a bug, since pLayerData->layerId != phStbVideoRenderer_Layers.
    // It's obviously a bug that's being "coped with" though...
    err = phStbVideoRenderer_GetVideoLayer( pLayerData->layerId,
                                            &pLayerData->pLayer,
                                            pLayerData->name);
    if (err != 0)
    {
        DBG_ASSERT2(err == 0, ("err=0x%x\n", err));
        goto RETURN;
    }

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_LEVEL_1, "%s: layerId=%u => '%s  '",
               __FUNCTION__,
               pLayerData->layerId,
               pLayerData->name));

    /* set capabilities and type */
    description->caps =
        DLCAPS_NONE
        | DLCAPS_SURFACE
        | DLCAPS_OPACITY
        | DLCAPS_DEINTERLACING
        | DLCAPS_BRIGHTNESS
        | DLCAPS_CONTRAST
        //| DLCAPS_HUE TODO not yet supported in VideoRenderer
        | DLCAPS_SATURATION
        | DLCAPS_LEVELS
        | DLCAPS_SCREEN_POSITION
        | DLCAPS_SCREEN_SIZE
        | DLCAPS_SCREEN_LOCATION;

    /*Set the correct layer type*/
    description->type = pLayerData->layerType;

    /* set name */
    snprintf(description->name, DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, pLayerData->name);

    /* Which fields of the configuration are we setting here? */
    config->flags =
        DLCONF_WIDTH |
        DLCONF_HEIGHT |
        DLCONF_PIXELFORMAT |
        DLCONF_BUFFERMODE |
        DLCONF_OPTIONS;

    /*
     * Get layer size: This is set to be a useful default
     * and as such will use the size from screen data.
     */
    config->width       = pScreenData->screenWidth;
    config->height      = pScreenData->screenHeight;

    /* Get pixel format from the renderer. */
    config->buffermode  = DLBM_FRONTONLY;

    /* TODO DO this when supported in the Video Renderer. */
#if 0
    err = phStbVideoRenderer_Layer_GetPixelFormat(pLayerData->pLayer, &pixelFormat);
    if (err != 0)
    {
        DBG_ASSERT2(err == 0, ("phStbVideoRenderer_Layer_GetPixelFormat failed => err=0x%x\n", err));
        goto RETURN;
    }

    /* set the pixel format */
    config->pixelformat = CONVERT_TO_DFB_PIXELFORMAT(pixelFormat);
#endif
    config->pixelformat = DSPF_UYVY;

    /**
     * Decide if we are supporting a per pixel alpha setting.
     */
    switch(config->pixelformat)
    {
        case DSPF_UYVY:
        case DSPF_YUY2:
        case DSPF_RGB32:
        case DSPF_XRGB4444:
        case DSPF_XRGB1555:
        case DSPF_RGB16:
            description->caps &= ~DLCAPS_ALPHACHANNEL;
            break;

        case DSPF_ARGB:
        case DSPF_ARGB4444:
        case DSPF_ARGB1555:
            description->caps |= DLCAPS_ALPHACHANNEL;
            break;
        default:
            result = DFB_FAILURE;
            DBG_ASSERT2((result == DFB_OK), (""));
            break;
    }

    /* Used to enable some capabilities: */
    config->options     = PH_STBDFB_DEFAULT_DLOP_SUPPORTED;

    /*
     *  fill out default color adjustment,
     *  only fields set in flags will be accepted from applications
     *  DCAF_HUE not yet supported in VideoRenderer
     */
    adjustment->flags      = DCAF_BRIGHTNESS | DCAF_CONTRAST | DCAF_SATURATION;

    /*Set defaults to mid range of UInt16*/
    adjustment->brightness = 0x8000;
    adjustment->contrast   = 0x8000;
    adjustment->saturation = 0x8000;

    result = DFB_OK;

RETURN:
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%x", __FUNCTION__,result));
    return result;
}

/******************************************************************************/
DFBResult phStbDFB_SetColorAdjustment(CoreLayer          *layer,
                                      void               *driver_data,
                                      void               *layer_data,
                                      DFBColorAdjustment *adj)
{
    phStbDFB_LayerData_t       *pLayerData = (phStbDFB_LayerData_t*) driver_data;
    phStbVideoRenderer_Layer_t *pLayer     = pLayerData->pLayer;
    tmErrorCode_t err;
    DFBResult result = DFB_OK;

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s: layer='%s'", __FUNCTION__, pLayerData->name));

    if (adj->flags & DCAF_BRIGHTNESS)
    {
        result = DFB_OK;
        /* Not currently working a known bug in Renderer Code */
        err = phStbVideoRenderer_Layer_SetBrightness(
            pLayer, adj->brightness >> DFB2VIDEORENDERER_BRIGHTNESS_ADJ_SHIFT);
        if (err != 0)
        {
            DBG_ASSERT2(err == 0, ("err=0x%x\n", err));
            result = DFB_FAILURE;
        }
    }

    if (adj->flags & DCAF_CONTRAST)
    {
        err = phStbVideoRenderer_Layer_SetContrast(
            pLayer, adj->contrast >> DFB2VIDEORENDERER_COLOR_ADJ_SHIFT);
        if (err != 0)
        {
            DBG_ASSERT2(err == 0, ("err=0x%x\n", err));
            result = DFB_FAILURE;
        }
    }

    if (adj->flags & DCAF_HUE)
    {
        err = phStbVideoRenderer_Layer_SetHue(
            pLayer, adj->hue >> DFB2VIDEORENDERER_COLOR_ADJ_SHIFT);
        if (err != 0)
        {
            DBG_ASSERT2(err == 0, ("err=0x%x\n", err));
            result = DFB_FAILURE;
        }
    }

    if (adj->flags & DCAF_SATURATION)
    {
        err = phStbVideoRenderer_Layer_SetSaturation(
            pLayer, adj->saturation >> DFB2VIDEORENDERER_COLOR_ADJ_SHIFT);
        if (err != 0)
        {
            DBG_ASSERT2(err == 0, ("err=0x%x\n", err));
            result = DFB_FAILURE;
        }
    }

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%x", __FUNCTION__, result));
    return result;
}

/******************************************************************************/
DFBResult phStbDFB_TestRegion(CoreLayer                  *layer,
                              void                       *driver_data,
                              void                       *layer_data,
                              CoreLayerRegionConfig      *config,
                              CoreLayerRegionConfigFlags *failed,
                              CoreSurface                *surface)
{
    DFBResult result = DFB_OK;
    phStbDFB_LayerData_t      *pLayerData = (phStbDFB_LayerData_t*) driver_data;
    CoreLayerRegionConfigFlags fail = CLRCF_NONE;

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s: layer='%s'", __FUNCTION__, pLayerData->name));

    /* check for unsupported options */
    if (config->options & ~PH_STBDFB_DLOP_SUPPORTED)
    {
        fail |= CLRCF_OPTIONS;
    }
    if((config->options & DLCONF_WIDTH) ||
       (config->options & DLCONF_HEIGHT))
    {
        CoreScreen *pScreen = layer->screen;
        int screenWidth;
        int screenHeight;

        pScreen->funcs->GetScreenSize(NULL, NULL, NULL, &screenWidth, &screenHeight);

        /* Minimum size 16 pixels
           config->width config->height
           config->source.x,
           config->source.y,
           config->source.x + config->source.w,
           config->source.y + config->source.h);
        */
        if ((config->width < PH_STBVIDEORENDERER_LAYER_MIN_RECT_SIZE) ||
            (config->source.x < 0) ||
            (config->source.w < PH_STBVIDEORENDERER_LAYER_MIN_RECT_SIZE ) ||
            (config->source.x % 2 ) ||
            ((config->source.x + config->source.w) % 2 ))
        {
            fail |= (CLRCF_WIDTH | CLRCF_SOURCE);
        }

        if ((config->height < PH_STBVIDEORENDERER_LAYER_MIN_RECT_SIZE) ||
            (config->source.y < 0 ) ||
            (config->source.h < PH_STBVIDEORENDERER_LAYER_MIN_RECT_SIZE ) ||
            (config->source.y % 2 ) ||
            ((config->source.y + config->source.h) % 2 ))
        {
            fail |= (CLRCF_HEIGHT | CLRCF_SOURCE);
        }
        /* Minimum size 16 pixels
           config->dest.x,
           config->dest.y,
           config->dest.x + config->dest.w,
           config->dest.y + config->dest.h);
         */
        if ((config->width < PH_STBVIDEORENDERER_LAYER_MIN_RECT_SIZE) ||
            (config->dest.x < 0 ) ||
            (config->dest.w < PH_STBVIDEORENDERER_LAYER_MIN_RECT_SIZE ) ||
            (config->dest.x % 2 ) ||
            ((config->dest.x + config->dest.w) % 2 ) ||
            ((config->dest.x + config->dest.w) > screenWidth))
        {
            fail |= (CLRCF_WIDTH | CLRCF_DEST);
        }

        if ((config->height < PH_STBVIDEORENDERER_LAYER_MIN_RECT_SIZE) ||
            (config->dest.y < 0 ) ||
            (config->dest.h < PH_STBVIDEORENDERER_LAYER_MIN_RECT_SIZE ) ||
            (config->dest.y % 2 ) ||
            ((config->dest.y + config->dest.h) % 2 ) ||
            ((config->dest.y + config->dest.h) > screenHeight))
        {
            fail |= (CLRCF_HEIGHT | CLRCF_DEST);
        }
    }

    /* return failure if any field failed */
    if (fail)
    {
        if(failed)
        {
            *failed = fail;
        }
        result = DFB_UNSUPPORTED;
    }

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%x", __FUNCTION__, result));

    return result;
}

/******************************************************************************/
DFBResult phStbDFB_SetRegion(CoreLayer                  *layer,
                             void                       *driver_data,
                             void                       *layer_data,
                             void                       *region_data,
                             CoreLayerRegionConfig      *config,
                             CoreLayerRegionConfigFlags  updated,
                             CoreSurface                *surface,
                             CorePalette                *palette )
{
    phStbDFB_LayerData_t       *pLayerData = (phStbDFB_LayerData_t*) driver_data;
    phStbVideoRenderer_Layer_t *pLayer     = pLayerData->pLayer;
    tmErrorCode_t err;
    DFBResult result = DFB_OK;

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s: layer='%s'", __FUNCTION__, pLayerData->name));

    /* remember configuration */
    pLayerData->config = *config;

    if(updated & CLRCF_OPACITY)
    {
        if(config->opacity == 0)
        {
            /* Hide layer */
            err = phStbVideoRenderer_Layer_BlankOutput(pLayer, true, false);
            DBG_ASSERT2(err == 0, ("err=0x%x\n", err));
        }
        else
        {
            /* Show layer. */
            err = phStbVideoRenderer_Layer_BlankOutput(pLayer, false, false);
            DBG_ASSERT2(err == 0, ("err=0x%x\n", err));

            err = phStbVideoRenderer_Layer_SetAlphaLevel(pLayer, config->opacity);
            if (err != 0)
            {
                DBG_ASSERT2(err == 0, ("err=0x%x\n", err));
                result = DFB_FAILURE;
            }
        }
    }

    if(updated & CLRCF_SOURCE)
    {
        err = phStbVideoRenderer_Layer_SetSrcRectangle(
            pLayer,
            (uint32_t)config->source.x,
            (uint32_t)config->source.y,
            (uint32_t)(config->source.x + config->source.w),
            (uint32_t)(config->source.y + config->source.h),
            true);
        if (err != 0)
        {
            DBG_ASSERT2(err == 0, ("err=0x%x\n", err));
            result = DFB_FAILURE;
        }
    }

    if(updated & (CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_DEST))
    {
        err = phStbVideoRenderer_Layer_SetDestRectangle(
            pLayer,
            (uint32_t)config->dest.x,
            (uint32_t)config->dest.y,
            (uint32_t)(config->dest.x + config->dest.w),
            (uint32_t)(config->dest.y + config->dest.h));
        if (err != 0)
        {
            DBG_ASSERT2(err == 0, ("err=0x%x\n", err));
            result = DFB_FAILURE;
        }
    }

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%x", __FUNCTION__, result));
    return result;
}

/******************************************************************************/
DFBResult phStbDFB_RemoveRegion(CoreLayer *layer,
                                void      *driver_data,
                                void      *layer_data,
                                void      *region_data )
{
    phStbDFB_LayerData_t       *pLayerData = (phStbDFB_LayerData_t*) driver_data;
    /*phStbVideoRenderer_Layer_t *pLayer     = pLayerData->pLayer;
    tmErrorCode_t err; */
    DFBResult result = DFB_OK;

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s: layer='%s'", __FUNCTION__, pLayerData->name));

    /* TODO: implement me */

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%x", __FUNCTION__, result));
    return result;
}

/******************************************************************************/

static int phStbDFB_GetZOrder(int layer)
{
    tmErrorCode_t err = TM_OK;
    phStbVideoRenderer_t *pVideoRenderer;
    int current = 0;
    err = phStbVideoRenderer_GetInstance(0, &pVideoRenderer);

    layer = StbDFB_directFB2VidRendLayer[layer];

    if (err == TM_OK)
    {
        int i;
        phStbVideoRenderer_Plane_t layers[phStbVideoRenderer_Planes_Count];

        err = phStbVideoRenderer_GetPlaneStack(pVideoRenderer, layers);

        for(i = 0; i < phStbVideoRenderer_Planes_Count; i++)
        {
            if (layers[i].layer == layer)
            {
                current = i;
                i = phStbVideoRenderer_Planes_Count;
            }
        }
    }
    return current;
}

/******************************************************************************/
static tmErrorCode_t phStbDFB_Zreorder(int currentPosition, int newPosition, int mixer)
{
    tmErrorCode_t err = TM_OK;
    phStbVideoRenderer_t *pVideoRenderer;
    err = phStbVideoRenderer_GetInstance(mixer, &pVideoRenderer);

    if (err == TM_OK)
    {
        phStbVideoRenderer_Plane_t layers[phStbVideoRenderer_Planes_Count];
        err = phStbVideoRenderer_GetPlaneStack(pVideoRenderer, layers);

        if (err == TM_OK)
        {
            int i;
            phStbVideoRenderer_Layers_t thisLayer;
            bool thisEnable;

            thisLayer = layers[currentPosition].layer;
            thisEnable = layers[currentPosition].enabled;

            /* Extract layer from list */
            for(i=currentPosition; i>0; i--)
            {
                layers[i].enabled = layers[i-1].enabled;
                layers[i].layer = layers[i-1].layer;
            }

            /* Insert layer into list */
            for(i=0; i<newPosition; i++)
            {
                layers[i].enabled = layers[i+1].enabled;
                layers[i].layer = layers[i+1].layer;
            }

            layers[newPosition].enabled = thisEnable;
            layers[newPosition].layer = thisLayer;

            err = phStbVideoRenderer_SetPlaneStack(pVideoRenderer, layers);
        }
    }
    return err;
}


/******************************************************************************/
static DFBResult phStbDFB_SetZOrder(int layer, int value)
{
    tmErrorCode_t err;
    int current = phStbDFB_GetZOrder(layer);

    err = phStbDFB_Zreorder(current, value, 0);
    if (err != TM_OK)
    {
        return DFB_FAILURE;
    }
    err = phStbDFB_Zreorder(current, value, 1);
    if (err != TM_OK)
    {
        return DFB_FAILURE;
    }

    return DFB_OK;
}

/******************************************************************************/
DFBResult phStbDFB_GetLevel(CoreLayer              *layer,
                            void                   *driver_data,
                            void                   *layer_data,
                            int                    *level )
{
    DFBResult result = DFB_OK;
    phStbDFB_LayerData_t *pLayerData = (phStbDFB_LayerData_t*) driver_data;

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s: layer='%s'", __FUNCTION__, pLayerData->name));

    /* NAB: layer_id is an unsigned int, contrary to everything else in the world. */
    *level = phStbDFB_GetZOrder((int)layer->shared->layer_id);

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: ZOrder Position is %d => 0x%x", __FUNCTION__, *level, result));
    return result;
}

/******************************************************************************/
DFBResult phStbDFB_SetLevel(CoreLayer              *layer,
                            void                   *driver_data,
                            void                   *layer_data,
                            int                     level )
{
    DFBResult result = DFB_OK;
    phStbDFB_LayerData_t *pLayerData = (phStbDFB_LayerData_t*) driver_data;
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s: layer='%s' layer %d Z - Order to %d", __FUNCTION__, pLayerData->name, layer->shared->layer_id, level));

    if ((level > phStbVideoRenderer_Planes_Bottom) || (level < phStbVideoRenderer_Planes_Top))
    {
        result = DFB_INVARG;
    }
    else
    {
        /* NAB: layer_id is an unsigned int, contrary to everything else in the world. */
        result = phStbDFB_SetZOrder((int)layer->shared->layer_id, level);
    }
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%x", __FUNCTION__, result));
    return result;
}

/******************************************************************************/
DFBResult phStbDFB_GetLayerId(CoreSurface  *surface,
                              int *layerId)
{
    unsigned int i;
    DFBResult result = DFB_ITEMNOTFOUND;
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s: surface = %p", __FUNCTION__, surface));

    for (i = 0; (i < PH_STBDFB_NUM_LAYERS_USED) && (result != DFB_OK); i ++)
    {
        if (gpphStbDFB_DeviceData->layers[i].surface == surface)
        {
            *layerId = gpphStbDFB_DeviceData->layers[i].layerId;
            result = DFB_OK;
        }
    }
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%0x unitId=%d layerId=%d", __FUNCTION__, result, *layerId));
    return result;
}
/******************************************************************************/
static DFBResult StbDFB_GetLayerData(int layerId,
                                     phStbDFB_LayerData_t **ppLayerData)
{
    unsigned int i;
    DFBResult result = DFB_ITEMNOTFOUND;
    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s", __FUNCTION__);

    for (i = 0; (i < PH_STBDFB_NUM_LAYERS_USED) && (result != DFB_OK); i ++)
    {
        if ((gpphStbDFB_DeviceData->layers[i].layerId == layerId))
        {
            *ppLayerData = &gpphStbDFB_DeviceData->layers[i];
            result = DFB_OK;
        }
    }
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%0x", __FUNCTION__, result));
    return result;
}
/******************************************************************************/

