/****************************************************************************
 *  License : All rights reserved for TES Electronic Solutions GmbH
 *            See included /docs/license.txt for details
 *  Project : D/AVE HD
 *  Purpose : Blendunit (BLU) related inline functions
 ****************************************************************************
 * Version Control Information :
 *  $Revision: 4771 $
 *  $Date: 2015-02-10 12:01:30 +0100 (Di, 10. Feb 2015) $
 *  $LastChangedBy: florian.zimmermann $
 ****************************************************************************
 * Change History (autogenerated):
 ****************************************************************************/    

#ifndef DAVEHD_DRIVER_BLU_INL_H_INCLUDED
#define DAVEHD_DRIVER_BLU_INL_H_INCLUDED
#include "davehd_registerparams.h"

/* PRQA S 3406 ++ *//* $Misra: #INLINE_FUNCTION_DEFINED_IN_HEADER $*/

/*----------------------------------------------------------------------------------------------------------*/
/* Query number of texture units. The number of texture units is an invariant hardware constraint. */
/* The function will return the number of texture units available using the given driver context.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/**/
/* Returns:*/
/*  An integer between 0 and 7*/
DHD_API_INLINE dhd_uint32_t dhd_get_texture_unit_count(dhd_handle_t a_device) {
  dhd_device_data_t *device = dhd_get_device( a_device );
  return device->m_description.m_num_tex_units;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Query number of color units. The number of color units is an invariant hardware constraint. */
/* The function will return the number of color units available using the given driver context.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/**/
/* Returns:*/
/*  An integer between 1 and 8*/
DHD_API_INLINE dhd_uint32_t dhd_get_color_unit_count(dhd_handle_t a_device) {
  dhd_device_data_t *device = dhd_get_device( a_device );
  return device->m_description.m_num_col_units;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Query number of pixel pipelines. The number of pixel pipelines is an invariant hardware constraint. */
/* The function will return the number of pixel pipelines present in the given driver context.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/**/
/* Returns:*/
/*  An integer between 1 and 16*/
DHD_API_INLINE dhd_uint32_t dhd_get_pipeline_count(dhd_handle_t a_device) {
  dhd_device_data_t *device = dhd_get_device( a_device );
  return device->m_description.m_num_pipelines;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Query number of constant color registers. The number of  constant color registers is an invariant */
/* hardware constraint. The function will return the number which is available using the given driver context.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/**/
/* Returns:*/
/*  An integer between 0 and 16*/
DHD_API_INLINE dhd_uint32_t dhd_get_const_col_count(dhd_handle_t a_device) {
  dhd_device_data_t *device = dhd_get_device( a_device );
  return device->m_description.m_num_const_cols;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Set blend factors for RGB part of blendunit. Blending the actual color unit output (source) with the */
/* existing framebuffer color (destination) depends on two factos and the blend function (see dhd_set_blend_func).*/
/* Note that the read decision should be set depending on the destination blend factor.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_srcfactor : Source operand factor 'f_src' (see dhd_blend_factor_t)*/
/*  a_dstfactor : Destination operand factor 'f_dst' (see dhd_blend_factor_t)*/
/* */
/* See Also:*/
/*  dhd_set_alpha_blending, dhd_set_blend_func, dhd_set_read_decision*/
DHD_API_INLINE void dhd_set_color_blending(dhd_handle_t a_device, dhd_blend_factor_t a_srcfactor, dhd_blend_factor_t a_dstfactor) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_color_src_blend_factor_select = a_srcfactor & 3;
  device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_color_dst_blend_factor_select = a_dstfactor & 3;
  device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_color_src_blend_factor_invert = (a_srcfactor >> 2) & 1;
  device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_color_dst_blend_factor_invert = (a_dstfactor >> 2) & 1;
  device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_color_src_blend_factor_use_alpha = (a_srcfactor >> 3) & 1;
  device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_color_dst_blend_factor_use_alpha = (a_dstfactor >> 3) & 1;
  device->m_pending_mask.m_named.m_blu_blend = 1;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Get blend factors for RGB part of blending. Retrieve the currently active blend factors (see dhd_set_color_blending*/
/* for details). Passing a null pointer indicates that a specific information is not requested.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_srcfactor : Pointer to dhd_blend_factor_t that will receive source operand factor (can be null)*/
/*  a_dstfactor : Pointer to dhd_blend_factor_t that will receive destination operand factor (can be null)*/
/* */
/* See Also:*/
/*  dhd_set_color_blending*/
DHD_API_INLINE void dhd_get_color_blending(dhd_handle_t a_device, dhd_blend_factor_t *a_srcfactor, dhd_blend_factor_t *a_dstfactor) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  if (a_srcfactor != 0) {
    dhd_uint32_t src_blend;

    src_blend = ( device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_color_src_blend_factor_select ) |
                ( device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_color_src_blend_factor_invert << 2 ) |
                ( device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_color_src_blend_factor_use_alpha << 3 );
    *a_srcfactor = (dhd_blend_factor_t) src_blend;
  }
  if (a_dstfactor != 0) {
    dhd_uint32_t dst_blend;

    dst_blend = ( device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_color_dst_blend_factor_select ) |
                ( device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_color_dst_blend_factor_invert << 2 ) |
                ( device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_color_dst_blend_factor_use_alpha << 3 );
    *a_dstfactor = (dhd_blend_factor_t) dst_blend;
  }
}

/*----------------------------------------------------------------------------------------------------------*/
/* Set blend factors for Alpha part of blendunit. Blending the actual color unit output (source) with the */
/* existing framebuffer color (destination) depends on two factos and the blend function (see dhd_set_blend_func).*/
/* Alpha blend factors can only be single channel values, therefore all factors containing _COLOR are invalid.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_srcfactor : Source operand factor 'f_src' (see dhd_blend_factor_t)*/
/*  a_dstfactor : Destination operand factor 'f_dst' (see dhd_blend_factor_t)*/
/* */
/* See Also:*/
/*  dhd_set_color_blending, dhd_set_blend_func, dhd_set_read_decision*/
DHD_API_INLINE void dhd_set_alpha_blending(dhd_handle_t a_device, dhd_blend_factor_t a_srcfactor, dhd_blend_factor_t a_dstfactor) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_alpha_src_blend_factor_select = a_srcfactor & 3;
  device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_alpha_dst_blend_factor_select = a_dstfactor & 3;
  device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_alpha_src_blend_factor_invert = (a_srcfactor >> 2) & 1;
  device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_alpha_dst_blend_factor_invert = (a_dstfactor >> 2) & 1;
  device->m_pending_mask.m_named.m_blu_blend = 1;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Get blend factors for Alpha part of blending. Retrieve the currently active blend factors (see dhd_set_alpha_blending*/
/* for details). Passing a null pointer indicates that a specific information is not requested.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_srcfactor : Pointer to dhd_blend_factor_t that will receive source operand factor (can be null)*/
/*  a_dstfactor : Pointer to dhd_blend_factor_t that will receive destination operand factor (can be null)*/
/* */
/* See Also:*/
/*  dhd_set_alpha_blending*/
DHD_API_INLINE void dhd_get_alpha_blending(dhd_handle_t a_device, dhd_blend_factor_t *a_srcfactor, dhd_blend_factor_t *a_dstfactor) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  if (a_srcfactor != 0) {
    dhd_uint32_t src_blend;

    src_blend = ( device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_alpha_src_blend_factor_select ) |
                ( device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_alpha_src_blend_factor_invert << 2 ) |
                8;
    *a_srcfactor = (dhd_blend_factor_t) src_blend;
  }
  if (a_dstfactor != 0) {
    dhd_uint32_t dst_blend;

    dst_blend = ( device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_alpha_dst_blend_factor_select ) |
                ( device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_alpha_dst_blend_factor_invert << 2 ) |
                8;
    *a_dstfactor = (dhd_blend_factor_t) dst_blend;
  }
}

/*----------------------------------------------------------------------------------------------------------*/
/* Select blend function. The basic operation performed during blending can be choosen by selecting the */
/* appropriate blend function. Details can be specified using dhd_set_color_blending (resp. */
/* dhd_set_alpha_blending)*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_colormode : Blend function used in the RGB part of blendunit (see dhd_blend_mode_t)*/
/*  a_alphamode : Blend function used in the Alpha part of blendunit (see dhd_blend_mode_t)*/
/**/
/* See Also:*/
/*  dhd_set_color_blending, dhd_set_alpha_blending*/
DHD_API_INLINE void dhd_set_blend_func(dhd_handle_t a_device, dhd_blend_mode_t a_colormode, dhd_blend_mode_t a_alphamode) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_color_blend_mode = a_colormode;
  device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_alpha_blend_mode = a_alphamode;
  device->m_pending_mask.m_named.m_blu_blend = 1;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Get blend function. Retrieve the currently active blend operation (see dhd_set_blend_func*/
/* for details). Passing a null pointer indicates that a specific information is not requested.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_colormode : Pointer to dhd_blend_mode_t that will receive RGB blend function (can be null)*/
/*  a_alphamode : Pointer to dhd_blend_mode_t that will receive Alpha blend function (can be null)*/
/* */
/* See Also:*/
/*  dhd_set_blend_func*/
DHD_API_INLINE void dhd_get_blend_func(dhd_handle_t a_device, dhd_blend_mode_t *a_colormode, dhd_blend_mode_t *a_alphamode) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  if (a_colormode != 0) {
    *a_colormode = (dhd_blend_mode_t) device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_color_blend_mode;
  }
  if (a_alphamode != 0) {
    *a_alphamode = (dhd_blend_mode_t) device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_alpha_blend_mode;
  }
}

/*----------------------------------------------------------------------------------------------------------*/
/* Enable output dithering. An ordered 2x2 dither can be added to the output color to improve color */
/* gradients in low bit depth rendertargets (e.g. 565). Usually the dither matrix is indexed using the */
/* pixel position. This can be offset by the specified xoffset and yoffset values.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_enable : Boolean flag. 0 to disable dithering.*/
/*  a_xoffset : Dithermatrix shift in x direction (ignored when dithering is disabled)*/
/*  a_yoffset : Dithermatrix shift in y direction (ignored when dithering is disabled)*/
/**/
/* See Also:*/
/*  dhd_set_dither_scale*/
DHD_API_INLINE void dhd_set_dither(dhd_handle_t a_device, dhd_bool_t a_enable, dhd_uint32_t a_xoffset, dhd_uint32_t a_yoffset) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  device->m_shadow_state.m_named.m_blu_dither.m_fields.m_blu_dither_enable = a_enable;
  device->m_shadow_state.m_named.m_blu_dither.m_fields.m_blu_dither_base = (a_xoffset & 3) | (a_yoffset << 2);
  device->m_pending_mask.m_named.m_blu_dither = 1;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Get dithering parameters. Retrieve the currently active output dithering options (see dhd_set_dither*/
/* for details). Passing a null pointer indicates that a specific information is not requested.*/
/* The most important information (if dithering is currently enabled) is returned directly.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_xoffset : Pointer to dhd_uint32_t that will receive dithermatrix shift in x direction (can be null)*/
/*  a_yoffset : Pointer to dhd_uint32_t that will receive dithermatrix shift in y direction (can be null)*/
/**/
/* Returns:*/
/*  DHD_TRUE if dithering is currently enabled, DHD_FALSE otherwise.*/
/* */
/* See Also:*/
/*  dhd_set_dither*/
DHD_API_INLINE dhd_bool_t dhd_get_dither(dhd_handle_t a_device, dhd_uint32_t *a_xoffset, dhd_uint32_t *a_yoffset) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  if (a_xoffset != 0) {
    *a_xoffset = device->m_shadow_state.m_named.m_blu_dither.m_fields.m_blu_dither_base & 3;
  }
  if (a_yoffset != 0) {
    *a_yoffset = (device->m_shadow_state.m_named.m_blu_dither.m_fields.m_blu_dither_base >> 2) & 3;
  }

  return device->m_shadow_state.m_named.m_blu_dither.m_fields.m_blu_dither_enable;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Scale output dithering. When output dithering is enabled (see dhd_set_dither) the amount of dithering can*/
/* be adjusted to the target bitdepth by selecting a dither scale. The default dithering amount is 4 bit*/
/* when rendering to a target that has more than 4 bits of precision in a channel, the dithering in this */
/* channel should be reduced by 4 - target depth bits.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_red : Number of bits to reduce red channel dithering (0..3)*/
/*  a_green : Number of bits to reduce green channel dithering (0..3)*/
/*  a_blue : Number of bits to reduce blue channel dithering (0..3)*/
/**/
/* See Also:*/
/*  dhd_set_dither*/
DHD_API_INLINE void dhd_set_dither_scale(dhd_handle_t a_device, dhd_uint32_t a_red, dhd_uint32_t a_green, dhd_uint32_t a_blue) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  device->m_shadow_state.m_named.m_blu_dither.m_fields.m_blu_dither_shift_red = a_red;
  device->m_shadow_state.m_named.m_blu_dither.m_fields.m_blu_dither_shift_green = a_green;
  device->m_shadow_state.m_named.m_blu_dither.m_fields.m_blu_dither_shift_blue = a_blue;
  device->m_pending_mask.m_named.m_blu_dither = 1;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Get output dither scaling. Retrieve the currently active dither scaling factors (see dhd_set_dither_scale*/
/* for details). Passing a null pointer indicates that a specific information is not requested.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_red : Pointer to dhd_uint32_t that will receive the number of bits red channel is reduced (can be null)*/
/*  a_green : Pointer to dhd_uint32_t that will receive the number of bits green channel is reduced (can be null)*/
/*  a_blue : Pointer to dhd_uint32_t that will receive the number of bits blue channel is reduced (can be null)*/
/* */
/* See Also:*/
/*  dhd_set_dither_scale*/
DHD_API_INLINE void dhd_get_dither_scale(dhd_handle_t a_device, dhd_uint32_t *a_red, dhd_uint32_t *a_green, dhd_uint32_t *a_blue) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  if (a_red != 0) {
    *a_red = device->m_shadow_state.m_named.m_blu_dither.m_fields.m_blu_dither_shift_red;
  }
  if (a_green != 0) {
    *a_green = device->m_shadow_state.m_named.m_blu_dither.m_fields.m_blu_dither_shift_green;
  }
  if (a_blue != 0) {
    *a_blue = device->m_shadow_state.m_named.m_blu_dither.m_fields.m_blu_dither_shift_blue;
  }
}

/*----------------------------------------------------------------------------------------------------------*/
/* Specify framebuffer format. The framebuffer format describes pixel organization (bits per channel and */
/* channel order) as well as channel counts (alpha and color, color only, alpha only, luminance and alpha..)*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_format : Pixel format (see dhd_pixel_org_t)*/
/**/
/* See Also:*/
/*  dhd_set_framebuffer_size, dhd_set_framebuffer_address, dhd_get_framebuffer_format*/
DHD_API_INLINE void dhd_set_framebuffer_format(dhd_handle_t a_device, dhd_pixel_org_t a_format) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  device->m_shadow_state.m_named.m_fb_pixel_org.m_fields.m_fb_pixel_org = a_format & 0xf; 
  device->m_shadow_state.m_named.m_fb_pixel_org.m_fields.m_blu_fb_limit_color_to_alpha = a_format >> 8; 
  device->m_pending_mask.m_named.m_fb_pixel_org = 1;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Retrieve framebuffer format. Returns the current framebuffer pixel organization (as set by */
/* dhd_set_framebuffer_format) */
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/**/
/* Returns:*/
/*  Pixel format (see dhd_pixel_org_t)*/
/**/
/* See Also:*/
/*  dhd_set_framebuffer_size*/
DHD_API_INLINE dhd_pixel_org_t dhd_get_framebuffer_format(dhd_handle_t a_device) {
  dhd_device_data_t *device = dhd_get_device( a_device );
  dhd_pixel_org_t fbformat;
  dhd_uint32_t u32fbformat;
    
  u32fbformat = device->m_shadow_state.m_named.m_fb_pixel_org.m_fields.m_fb_pixel_org & 0xf; 
  u32fbformat |= (dhd_uint32_t)(device->m_shadow_state.m_named.m_fb_pixel_org.m_fields.m_blu_fb_limit_color_to_alpha) << 8;
  
  fbformat = (dhd_pixel_org_t)(u32fbformat | DHD_PIXEL_ORG_FLAG);

  return fbformat;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Specify framebuffer size. The framebuffer (applies to the ZSA buffer as well) size and pitch. Pitch*/
/* can be equal or greater than the width to enable the use of subrectangles within a larger buffer.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_width : Width in pixels*/
/*  a_height : Height in pixels*/
/*  a_pitch : Number of pixels in one line (equals width in a continuous buffer)*/
/**/
/* See Also:*/
/*  dhd_set_framebuffer_format, dhd_set_framebuffer_address, dhd_get_framebuffer_size*/
DHD_API_INLINE void dhd_set_framebuffer_size(dhd_handle_t a_device, dhd_uint32_t a_width, dhd_uint32_t a_height, dhd_uint32_t a_pitch) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  device->m_shadow_state.m_named.m_fbs_pitch.m_fields.m_fbs_pitch = a_pitch;
  device->m_pending_mask.m_named.m_fbs_pitch = 1;
  device->m_shadow_state.m_named.m_zss_pitch.m_fields.m_zss_pitch = a_pitch;
  device->m_pending_mask.m_named.m_zss_pitch = 1;  
  device->m_shadow_state.m_named.m_psu_lim_max_coord.m_fields.m_lim_xmax = a_width - 1;
  device->m_shadow_state.m_named.m_psu_lim_max_coord.m_fields.m_lim_ymax = a_height - 1;
  device->m_pending_mask.m_named.m_psu_lim_max_coord = 1;
  
  device->m_framebuffer_width  = (dhd_uint16_t) a_width;
  device->m_framebuffer_height = (dhd_uint16_t) a_height;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Retrieve framebuffer size. The framebuffer (applies to the ZSA buffer as well) size and pitch as set by*/
/* dhd_set_framebuffer_size is written to the specified variables.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_width : Address for storage of width in pixels (or 0)*/
/*  a_height : Address for storage of height in pixels (or 0)*/
/*  a_pitch : Address for storage of the number of pixels in one line (or 0)*/
/**/
/* See Also:*/
/*  dhd_set_framebuffer_size*/
DHD_API_INLINE void dhd_get_framebuffer_size(dhd_handle_t a_device, dhd_uint32_t *a_width, dhd_uint32_t *a_height, dhd_uint32_t *a_pitch) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  if (a_width != 0) {
    *a_width = device->m_framebuffer_width;
  }
  if (a_height != 0) {
    *a_height = device->m_framebuffer_height;
  }
  if (a_pitch != 0) {
    *a_pitch = device->m_shadow_state.m_named.m_fbs_pitch.m_fields.m_fbs_pitch;
  }
}

/*----------------------------------------------------------------------------------------------------------*/
/* Specify framebuffer address. The address must be in GPU accessible memory and is usually obtained by a */
/* call to dhd_alloc_vidmem. Memory layout and pixel organization are specified separately using */
/* dhd_set_framebuffer_size and dhd_set_framebuffer_format.*/
/**/
/* The supplied address must always be aligned to the memory bus width of the GPU. Older HW revisions even */
/* require that the address is aligned to framebuffer cachelines. In case the address does not fulfill*/
/* the required alignment, it will not be set and an E_DHD_ERROR_INVALID_PTR is generated instead.*/
/* Whether or not the present device requires cacheline aligned framebuffer addresses can be queried using*/
/* dhd_get_bufferalignment_required.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_address : Address of the top left pixel inside framebuffer*/
/**/
/* Returns:*/
/*  E_DHD_OK if the address has been accepted or*/
/*  E_DHD_ERROR_INVALID_PTR if the address was not aligned correctly.*/
/**/
/* See Also:*/
/*  dhd_set_framebuffer_format, dhd_set_framebuffer_size, dhd_get_framebuffer_address, */
/*  dhd_get_bufferalignment_required*/
DHD_API_INLINE dhd_enum_t dhd_set_framebuffer_address(dhd_handle_t a_device, dhd_gpu_ptr_t a_address) { /* PRQA S 3673 *//* $Misra: #NECESSARY_FOR_API $*/
  dhd_device_data_t *device = dhd_get_device( a_device );
  dhd_size_t address_bits = (dhd_size_t) a_address;
  dhd_size_t fbc_line_length = (dhd_size_t)(device->m_description.m_bus_width * DHD_PARAM_FBCACHE_LINE_LENGTH);
  
  if ((device->m_avoid_burstsplit == 1) && 
      ((address_bits & (dhd_size_t)(fbc_line_length - 1)) != 0)) {
    return E_DHD_ERROR_INVALID_PTR;
  }

  /* even in case no alignment to bursts is required, we need to align to the bus width*/
  if ((address_bits & (dhd_size_t)(device->m_description.m_bus_width - 1)) != 0) {
    return E_DHD_ERROR_INVALID_PTR;
  }

  device->m_shadow_state.m_named.m_fbc_start_address.m_value = (dhd_uint32_t) (dhd_size_t) a_address;
  device->m_pending_mask.m_named.m_fbc_start_address = 1;

  return E_DHD_OK;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Retrieve framebuffer address. GPU side address of current framebuffer is returned as set by*/
/* dhd_set_framebuffer_address.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/**/
/* Returns:*/
/*  Address of the top left pixel inside framebuffer*/
/**/
/* See Also:*/
/*  dhd_set_framebuffer_address*/
DHD_API_INLINE dhd_gpu_ptr_t dhd_get_framebuffer_address(dhd_handle_t a_device) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  return (dhd_gpu_ptr_t) (dhd_size_t) device->m_shadow_state.m_named.m_fbc_start_address.m_value;  
}

/*----------------------------------------------------------------------------------------------------------*/
/* Select framebuffer write mask. All writes into the framebuffer (after blending) can be blocked by */
/* disabling their write mask.*/
/**/
/* Note: when some channels are masked the read decision should be E_DHD_READ_ALWAYS (see dhd_set_read_decision)*/
/* in order to ensure the masked channels can retain their old value.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_red : DHD_TRUE if the red channel should be written*/
/*  a_green : DHD_TRUE if the green channel should be written*/
/*  a_blue : DHD_TRUE if the blue channel should be written*/
/*  a_alpha : DHD_TRUE if the alpha channel should be written*/
DHD_API_INLINE void dhd_set_write_mask(dhd_handle_t a_device, dhd_bool_t a_red, dhd_bool_t a_green, dhd_bool_t a_blue, dhd_bool_t a_alpha) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_write_red   = a_red;
  device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_write_green = a_green;
  device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_write_blue  = a_blue;
  device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_write_alpha = a_alpha;
  device->m_pending_mask.m_named.m_blu_write = 1;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Get framebuffer write mask. Retrieve the currently active framebuffer writ emasks (see dhd_set_write_mask*/
/* for details). Passing a null pointer indicates that a specific information is not requested.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_red : Pointer to dhd_bool_t that will receive DHD_TRUE if red channel is to be written (can be null)*/
/*  a_green : Pointer to dhd_bool_t that will receive DHD_TRUE if green channel is to be written (can be null)*/
/*  a_blue : Pointer to dhd_bool_t that will receive DHD_TRUE if blue channel is to be written (can be null)*/
/*  a_alpha : Pointer to dhd_bool_t that will receive DHD_TRUE if alpha channel is to be written (can be null)*/
/* */
/* See Also:*/
/*  dhd_set_write_mask*/
DHD_API_INLINE void dhd_get_write_mask(dhd_handle_t a_device, dhd_bool_t *a_red, dhd_bool_t *a_green, dhd_bool_t *a_blue, dhd_bool_t *a_alpha) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  if (a_red != 0) {
    *a_red = device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_write_red;
  }
  if (a_green != 0) {
    *a_green = device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_write_green;
  }
  if (a_blue != 0) {
    *a_blue = device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_write_blue;
  }
  if (a_alpha != 0) {
    *a_alpha = device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_write_alpha;
  }
}

/*----------------------------------------------------------------------------------------------------------*/
/* Enable coverage blending. After regular blending has been performed the output color can be blended */
/* with the background using the current fragments coverage value. When enabled this will require a framebuffer*/
/* read so make sure dhd_set_read_decision is set correctly to allow this.*/
/* If you do your own coverage processing or do not use coverage anti aliasing at all you can disable this.*/
/* */
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_enable : Boolean flag. 0 to disable coverage blending.*/
DHD_API_INLINE void dhd_set_coverage_blend(dhd_handle_t a_device, dhd_bool_t a_enable) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_coverage_blending_enable = a_enable;
  device->m_pending_mask.m_named.m_blu_write = 1;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Get coverage blending status. Retrieve if coverage blending is currently active (see dhd_set_coverage_blend*/
/* for details). */
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/**/
/* Returns:*/
/*  DHD_TRUE if coverage blending is active, DHD_FALSE otherwise.*/
/**/
/* See Also:*/
/*  dhd_set_coverage_blend*/
DHD_API_INLINE dhd_bool_t dhd_get_coverage_blend(dhd_handle_t a_device) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  return device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_coverage_blending_enable;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Specify framebuffer read conditions. Depending on the selected blend function, blend factors and other*/
/* parameters the hardware will have to read the framebuffer in order to perform a correct blending.*/
/* The core uses a very simple decision logic instead of analysing all involved parameters directly.*/
/* If the decision can be mapped directly to the fragments alpha and or coverage you can specify this,*/
/* otherwise E_DHD_READ_ALWAYS or E_DHD_READ_NEVER has to be chosen as readmode.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_readmode : Select how the source alpha is affecting the read decision (see dhd_read_mode_t)*/
/*  a_covblend : Choose if source coverage is affecting the read decision (DHD_TRUE if coverage blending is enabled) */
DHD_API_INLINE void dhd_set_read_decision(dhd_handle_t a_device, dhd_read_mode_t a_readmode, dhd_bool_t a_covblend) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  device->m_shadow_state.m_named.m_fbd_config.m_fields.m_fbd_read_decision_flags = (dhd_uint32_t)a_readmode | (a_covblend << 2);
  device->m_pending_mask.m_named.m_fbd_config = 1;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Get framebuffer read conditions. Retrieve the currently active framebuffer read conditions (see */
/* dhd_set_read_decision for details). Passing a null pointer indicates that a specific information is not */
/* requested. The most important information (dhd_read_mode_t) is returned directly.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_covblend : Pointer to dhd_bool_t that will receive DHD_TRUE if coverage blending is enabled (can be null)*/
/**/
/* Returns:*/
/*  Active read decision mode (dhd_read_mode_t)*/
/* */
/* See Also:*/
/*  dhd_set_read_decision*/
DHD_API_INLINE dhd_read_mode_t dhd_get_read_decision(dhd_handle_t a_device, dhd_bool_t *a_covblend) {
  dhd_device_data_t *device = dhd_get_device( a_device );
  dhd_uint32_t decision = device->m_shadow_state.m_named.m_fbd_config.m_fields.m_fbd_read_decision_flags;

  if (a_covblend != 0) {
    *a_covblend = (decision >> 2) & 1;
  }
  return (dhd_read_mode_t) (decision & 3);
}

/*----------------------------------------------------------------------------------------------------------*/
/* Select alpha test. Fragments can be discarded based on their alpha value. If the current fragment does not*/
/* pass the specified test compared to the reference value it will be discarded.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_compare : Alpha compare function (see dhd_compare_op_t)*/
/*  a_ref : Reference value to compare against*/
/**/
DHD_API_INLINE void dhd_set_alpha_test(dhd_handle_t a_device, dhd_compare_op_t a_compare, dhd_uint8_t a_ref) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  device->m_shadow_state.m_named.m_fbd_config.m_fields.m_fbd_alpha_test_op = a_compare;
  device->m_shadow_state.m_named.m_fbd_config.m_fields.m_fbd_alpha_test_ref = a_ref;
  device->m_pending_mask.m_named.m_fbd_config = 1;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Get alpha test settings. Retrieve the currently active alpha test parameters (see dhd_set_alpha_test*/
/* for details). Passing a null pointer indicates that a specific information is not requested. */
/* The most important information (alpha compare function) is returned directly.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_ref : Pointer to dhd_uint8_t that will receive the reference value (can be null)*/
/**/
/* Returns:*/
/*  Alpha compare function (see dhd_compare_op_t)*/
/* */
/* See Also:*/
/*  dhd_set_alpha_test*/
DHD_API_INLINE dhd_compare_op_t dhd_get_alpha_test(dhd_handle_t a_device, dhd_uint8_t *a_ref) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  if (a_ref != 0) {
    *a_ref = (dhd_uint8_t) device->m_shadow_state.m_named.m_fbd_config.m_fields.m_fbd_alpha_test_ref;
  }

  return (dhd_compare_op_t) device->m_shadow_state.m_named.m_fbd_config.m_fields.m_fbd_alpha_test_op;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Enable pre multiply. Framebuffer content is converted to premultiplied format after reading automatically.*/
/* This is done by multiplying each color channel by the alpha channel.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_enable : Boolean flag. 0 to disable premultiply.*/
DHD_API_INLINE void dhd_set_fb_premultiply(dhd_handle_t a_device, dhd_bool_t a_enable) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_fb_premultiply_enable = a_enable;
  device->m_pending_mask.m_named.m_blu_blend = 1;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Get pre multiply status. Retrieve if framebuffer pre multiply blending is currently active (see dhd_set_fb_premultiply*/
/* for details). */
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/**/
/* Returns:*/
/*  DHD_TRUE if pre multiply is active, DHD_FALSE otherwise.*/
/**/
/* See Also:*/
/*  dhd_set_fb_premultiply*/
DHD_API_INLINE dhd_bool_t dhd_get_fb_premultiply(dhd_handle_t a_device) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  return device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_fb_premultiply_enable;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Enable post divide. Blendunit output is converted to non premultiplied format before writeback to the*/
/* framebuffer.This is done by dividing each color channel by the alpha channel.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_enable : Boolean flag. 0 to disable post divide.*/
DHD_API_INLINE void dhd_set_fb_postdivide(dhd_handle_t a_device, dhd_bool_t a_enable) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_fb_postdivide_enable = a_enable;
  device->m_pending_mask.m_named.m_blu_blend = 1;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Get post divide status. Retrieve if framebuffer post divideblending is currently active (see dhd_set_fb_postdivide*/
/* for details). */
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/**/
/* Returns:*/
/*  DHD_TRUE if post divide is active, DHD_FALSE otherwise.*/
/**/
/* See Also:*/
/*  dhd_set_fb_postdivide*/
DHD_API_INLINE dhd_bool_t dhd_get_fb_postdivide(dhd_handle_t a_device) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  return device->m_shadow_state.m_named.m_blu_blend.m_fields.m_blu_fb_postdivide_enable;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Enable pixelpipeline debugging.*/
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/*  a_mode : Debug mode to be activated (see dhd_debug_mode_t)*/
DHD_API_INLINE void dhd_set_debug_mode(dhd_handle_t a_device, dhd_debug_mode_t a_mode) {
  dhd_device_data_t *device = dhd_get_device( a_device );
  
  switch (a_mode) {
    case E_DHD_DEBUG_NONE:     
      device->m_shadow_state.m_named.m_tex_global.m_fields.m_txc_debug_mode = 0; /* E_TXC_DEBUG_MODE_NONE      */
      device->m_shadow_state.m_named.m_fbs_pitch.m_fields.m_fbs_debug_enable = 0;
      device->m_shadow_state.m_named.m_psu_debug_ctrl.m_fields.m_lim_debug = 0;
      device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_coverage_debug_enable = 0;
      break;
    case E_DHD_DEBUG_ENUMERATION:
      device->m_shadow_state.m_named.m_tex_global.m_fields.m_txc_debug_mode = 0; /* E_TXC_DEBUG_MODE_NONE    */
      device->m_shadow_state.m_named.m_fbs_pitch.m_fields.m_fbs_debug_enable = 0;
      device->m_shadow_state.m_named.m_psu_debug_ctrl.m_fields.m_lim_debug = 1;
      device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_coverage_debug_enable = 1;
      break;
    case E_DHD_DEBUG_FB_CACHE:  
      device->m_shadow_state.m_named.m_tex_global.m_fields.m_txc_debug_mode = 0; /* E_TXC_DEBUG_MODE_NONE      */
      device->m_shadow_state.m_named.m_fbs_pitch.m_fields.m_fbs_debug_enable = 1;
      device->m_shadow_state.m_named.m_psu_debug_ctrl.m_fields.m_lim_debug = 0;
      device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_coverage_debug_enable = 0;
      break;
    case E_DHD_DEBUG_TEX_SCHEDULING: 
      device->m_shadow_state.m_named.m_tex_global.m_fields.m_txc_debug_mode = 1; /* E_TXC_DEBUG_MODE_SCHEDULING      */
      device->m_shadow_state.m_named.m_fbs_pitch.m_fields.m_fbs_debug_enable = 0;
      device->m_shadow_state.m_named.m_psu_debug_ctrl.m_fields.m_lim_debug = 0;
      device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_coverage_debug_enable = 1;
      break;
    case E_DHD_DEBUG_TEX_WAIT_CYCLES:
      device->m_shadow_state.m_named.m_tex_global.m_fields.m_txc_debug_mode = 2; /* E_TXC_DEBUG_MODE_WAIT_CYCLES      */
      device->m_shadow_state.m_named.m_fbs_pitch.m_fields.m_fbs_debug_enable = 0;
      device->m_shadow_state.m_named.m_psu_debug_ctrl.m_fields.m_lim_debug = 0;
      device->m_shadow_state.m_named.m_blu_write.m_fields.m_blu_coverage_debug_enable = 1;
      break;    
  } /* PRQA S 2002 *//* $Misra: #DEFAULT_CASE_NOT_COVERARABLE $*/

  device->m_pending_mask.m_named.m_tex_global = 1;
  device->m_pending_mask.m_named.m_fbs_pitch = 1;
  device->m_pending_mask.m_named.m_psu_debug_ctrl = 1;
  device->m_pending_mask.m_named.m_blu_write = 1;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Get pixelpipeline debugging status. Retrieve currently active pixelpipeline debugging mode */
/* (see dhd_set_debug_mode for details). */
/**/
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init)*/
/**/
/* Returns:*/
/*  An enum from dhd_debug_mode_t.*/
/**/
/* See Also:*/
/*  dhd_set_debug_mode*/
DHD_API_INLINE dhd_debug_mode_t dhd_get_debug_mode(dhd_handle_t a_device) {
  dhd_device_data_t *device = dhd_get_device( a_device );

  switch (device->m_shadow_state.m_named.m_tex_global.m_fields.m_txc_debug_mode) {
    case 0:
      /* can be E_DHD_DEBUG_NONE, E_DHD_DEBUG_ENUMERATION or E_DHD_DEBUG_FB_CACHE*/
      if (device->m_shadow_state.m_named.m_psu_debug_ctrl.m_fields.m_lim_debug != 0) {
        return E_DHD_DEBUG_ENUMERATION;
      }
      if (device->m_shadow_state.m_named.m_fbs_pitch.m_fields.m_fbs_debug_enable != 0) {
        return E_DHD_DEBUG_FB_CACHE;
      }
      break;
    case 1:
      return E_DHD_DEBUG_TEX_SCHEDULING;
    case 2:
      return E_DHD_DEBUG_TEX_WAIT_CYCLES;          
  }/* PRQA S 2002 *//* $Misra: #DEFAULT_CASE_NOT_COVERARABLE $*/

  return E_DHD_DEBUG_NONE;
}

/*----------------------------------------------------------------------------------------------------------*/

#endif /*DAVEHD_DRIVER_BLU_INL_H_INCLUDED*/
