/*****************************************************************************/
/* 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_VidLayer.c
    @brief  Video Layer specific part of graphics driver for DirectFB.

@b  Component:  phStbDFB.

*//*

Rev Date        Author      Comments
--------------------------------------------------------------------------------
  1 20050823    charrett    Re-organisation of code
  2 20050826    charrett    Fix bug with layers when using multiple applications
  3 20050907    laird       Changed Macro Name.
  4 20050908    laird       Common InitLayer function.
  5 20050919    laird       Support for 2 screens
  6 20050920    laird       Support for images on video layers via STILL_PICTURE support
  7 20050929    laird       removing allocate/deallocate surface functions.
  8 20051005    laird       Storing CoreLayer
----------------------------STB225----------------------------------------------
  9 20070109    laird       Moving to STB225
 10 20070116    laird       Crosscheck rework.
 11 20071017    burningh    Fix QA C coverage errors
 12 20071029    burningh    Improve QA C confidence factor
 13 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_context.h>
#include <core/layer_control.h>
#include <core/windowstack.h>
#include <fusion/object.h>

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

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

/******************************************************************
* STATIC FUNCTION PROTOTYPES                  <Module>_<Word>+    *
*******************************************************************/
static DFBResult phStbDFB_VidLayerAllocateSurface(CoreLayer              *layer,
                                                  void                   *driver_data,
                                                  void                   *layer_data,
                                                  void                   *region_data,
                                                  CoreLayerRegionConfig  *config,
                                                  CoreSurface           **ret_surface);

/******************************************************************
* STATIC DATA                  g[k|p|kp|pk|kpk]<Module>_<Word>+   *
*******************************************************************/
/**
 * Function lookup table for the video layers.
 */
static DisplayLayerFuncs gphStbDFB_VideoLayerFuncs = {
    /*.LayerDataSize         = */ phStbDFB_LayerDataSize,
    /*.RegionDataSize        = */ 0,
    /*.InitLayer             = */ phStbDFB_LayerInit,
    /*.InitSource            = */ 0,
    /*.GetCurrentOutputField = */ 0,
    /*.GetLevel              = */ phStbDFB_GetLevel,
    /*.SetLevel              = */ phStbDFB_SetLevel,
    /*.SetColorAdjustment    = */ phStbDFB_SetColorAdjustment,
    /*.TestRegion            = */ phStbDFB_TestRegion,
    /*.AddRegion             = */ 0,
    /*.SetRegion             = */ phStbDFB_SetRegion,
    /*.RemoveRegion          = */ phStbDFB_RemoveRegion,
    /*.FlipRegion            = */ 0,
    /*.UpdateRegion          = */ 0,
    /*.SetInputField         = */ 0,
    /*.AllocateSurface       = */ phStbDFB_VidLayerAllocateSurface,
    /*.ReallocateSurface     = */ 0,
    /*.DeallocateSurface     = */ 0
};

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

/*******************************************************************************
* FUNCTION IMPLEMENTATION  <Module>[_<Word>+] for static functions             *
*                          tm[<layer>]<Module>[_<Word>+] for exported functions*
********************************************************************************/
void phStbDFB_VidLayerRegister(void)
{
    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s: Installing Video layers", __FUNCTION__);
    /*
     * We use the device data to store information on the layer,
     * as only the master instance of directfb will initialise layers.
     * Slave instance are passed this information but the layers are not reinitialised.
     */
    gpphStbDFB_DeviceData->layers[PH_STBDFB_SCREEN_MAIN_DISPLAY1].layerId = phStbVideoRenderer_Layers_Display1;
    gpphStbDFB_DeviceData->layers[PH_STBDFB_SCREEN_MAIN_DISPLAY1].layerType = DLTF_VIDEO;

    /*This function is called for every DirectFB application so only set the currentType to the default if
      a value is not currently set*/
    if(gpphStbDFB_DeviceData->layers[PH_STBDFB_SCREEN_MAIN_DISPLAY1].currentType == DLTF_NONE)
    {
        gpphStbDFB_DeviceData->layers[PH_STBDFB_SCREEN_MAIN_DISPLAY1].currentType = DLTF_VIDEO;
    }

    gpphStbDFB_DeviceData->layers[PH_STBDFB_SCREEN_MAIN_DISPLAY2].layerId = phStbVideoRenderer_Layers_Display2;
    gpphStbDFB_DeviceData->layers[PH_STBDFB_SCREEN_MAIN_DISPLAY2].layerType = DLTF_VIDEO;
    if(gpphStbDFB_DeviceData->layers[PH_STBDFB_SCREEN_MAIN_DISPLAY2].currentType == DLTF_NONE)
    {
        gpphStbDFB_DeviceData->layers[PH_STBDFB_SCREEN_MAIN_DISPLAY2].currentType = DLTF_VIDEO;
    }

    dfb_layers_register( dfb_screens_at(PH_STBDFB_SCREEN_MAIN),
                         &gpphStbDFB_DeviceData->layers[PH_STBDFB_SCREEN_MAIN_DISPLAY1],
                         &gphStbDFB_VideoLayerFuncs);

    dfb_layers_register( dfb_screens_at(PH_STBDFB_SCREEN_MAIN),
                         &gpphStbDFB_DeviceData->layers[PH_STBDFB_SCREEN_MAIN_DISPLAY2],
                         &gphStbDFB_VideoLayerFuncs);

    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: Layers installed", __FUNCTION__);
}

/******************************************************************************/
DFBResult phStbDFB_VidLayerAllocateSurface(CoreLayer              *layer,
                                           void                   *driver_data,
                                           void                   *layer_data,
                                           void                   *region_data,
                                           CoreLayerRegionConfig  *config,
                                           CoreSurface           **ret_surface)
{
    DFBResult                  result     = DFB_OK;
    phStbDFB_LayerData_t *pLayerData  = (phStbDFB_LayerData_t*) driver_data;
    CoreDFB                   *core       = NULL;
    CoreLayerContext          *context;

    /*Set the surface to be stored in System Memory only not Video*/
    DFBSurfaceCapabilities caps = DSCAPS_SYSTEMONLY;

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

    /* This will create a surface, currently it has height and width but no front, back buffer etc
       The CSP_SYSTEMONLY refers to the type of memory to use and it is set to be SYSTEMMemory not
       video memory.*/
    result = dfb_surface_create_preallocated(core,
                                             config->width,
                                             config->height,
                                             config->format,
                                             CSP_SYSTEMONLY,
                                             caps,
                                             NULL,
                                             NULL,
                                             NULL,
                                             0,
                                             0,
                                             ret_surface);

    if (result) {
         fusion_object_destroy( &(*ret_surface)->object );
         return result;
    }
    /*We have to store this as it is used by image providers*/
    (*ret_surface)->front_buffer->video.pitch = (config->width * 4);

    /*We cannot use a window stack on a video layer so we must destroy it to be clean
      and then set it to NULL.  Not doing this means it starts trying to fill rectangles etc
      and this will not work as we have not actually allocated the memory.*/
    result =  dfb_layer_get_active_context( layer, &context );
    if(context->stack != NULL)
    {
        dfb_windowstack_destroy(context->stack);
        context->stack=NULL;
    }
    dfb_layer_context_unref(context);
    /*Store the surface pointer so that it can be found*/
    pLayerData->surface = *ret_surface;
    pLayerData->layer = layer;

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

