/****************************************************************************
 *  License : All rights reserved for TES Electronic Solutions GmbH
 *            See included /docs/license.txt for details
 *  Project : D/AVE HD
 *  Purpose : Inline utility function bodies
 ****************************************************************************
 * Version Control Information :
 *  $Revision: 13280 $
 *  $Date: 2017-04-11 14:49:15 +0200 (Di, 11. Apr 2017) $
 *  $LastChangedBy: florian.zimmermann $
 ****************************************************************************
 * Change History (autogenerated):
 ****************************************************************************/    

#ifndef DAVEHD_UTIL_INL_H_INCLUDED
#define DAVEHD_UTIL_INL_H_INCLUDED

#include "davehd_util.h"
#include "davehd_internal.h"

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

/* --------------------------------------------------------------------------------------------------------------------------------------*/
/* Setup an edge from two points without AA or tie breaking. This function is faster than*/
/* dhd_setup_edge_noaa (actually it is the fastest possible way to setup an arbitrary edge) but will not*/
/* automatically ensure gapless rendering for shared edges. The application has to specify E_DHD_INVERT*/
/* flag on one part of a shared edge pair to ensure gapless rendering.*/
/* */
/* All points in screenspace pixel coordinates using 4 bit fraction.*/
/* */
/* */
/* */
/* Also note that non antialiased edges are limited to a width/height of 2048 pixels (see <link !!Basics_Geometry, Specifying Geometry>).*/
/*                                                                                                         */
/* Parameters:*/
/*  a_dst :  dhd_edge_data_t structure the result is written into*/
/*  a_x1 :   First point on the edge (with 4 bit subpixel precision)*/
/*  a_y1 :   First point on the edge (with 4 bit subpixel precision)*/
/*  a_x2 :   Second point on the edge (with 4 bit subpixel precision)*/
/*  a_y2 :   Second point on the edge (with 4 bit subpixel precision)*/
/*  a_xo :   Point at which the enumeration starts (with 4 bit subpixel precision)*/
/*  a_yo :   Point at which the enumeration starts (with 4 bit subpixel precision)*/
/*                                                                                                         */
/* See Also:*/
/*  dhd_setup_edge_noaa, dhd_setup_edge_aa, dhd_setup_edge_aa2*/
DHD_API_INLINE void dhd_setup_edge_noaa_notie(dhd_edge_data_t *a_dst, dhd_fx28_4_t a_x1, dhd_fx28_4_t a_y1, dhd_fx28_4_t a_x2, dhd_fx28_4_t a_y2, 
                                              dhd_fx28_4_t a_xo, dhd_fx28_4_t a_yo) {
  dhd_int32_t dx = a_x2 - a_x1;
  dhd_int32_t dy = a_y2 - a_y1;  

  /* we can simply ignore the fixedpoint scale as we don't have to apply any norm  */
  a_dst->m_dx    = -dy * 16;
  a_dst->m_dy    =  dx * 16;
  a_dst->m_start = ((a_x1-a_xo)*dy) - ((a_y1-a_yo)*dx);
}

/*----------------------------------------------------------------------------------------------------------*/
/* Setup an edge from two points with Antialiasing. */
/* Uses a quick approximation to the vector length. If more accuracy is required use dhd_setup_edge_aa2.*/
/* Tie breaking rules are not applied as antialiased edges are never shared.*/
/**/
/* All points in screenspace pixel coordinates using 4 bit fraction. */
/**/
/* Parameters:*/
/*  a_dst : dhd_edge_data_t structure the result is written into*/
/*  a_x1 : First point on the edge (with 4 bit subpixel precision)*/
/*  a_y1 : First point on the edge (with 4 bit subpixel precision)*/
/*  a_x2 : Second point on the edge (with 4 bit subpixel precision)*/
/*  a_y2 : Second point on the edge (with 4 bit subpixel precision)*/
/*  a_xo : Point at which the enumeration starts (with 4 bit subpixel precision)*/
/*  a_yo : Point at which the enumeration starts (with 4 bit subpixel precision)*/
/*  a_blur : additional scaling factor (set to 1.0 / size of aa gradient in pixels ; defaults to 1.0)*/
/**/
/* See Also:*/
/*  dhd_setup_edge_noaa, dhd_setup_edge_noaa_notie, dhd_setup_edge_aa2*/
DHD_API_INLINE void dhd_setup_edge_aa(dhd_edge_data_t *a_dst, dhd_fx28_4_t a_x1, dhd_fx28_4_t a_y1, dhd_fx28_4_t a_x2, dhd_fx28_4_t a_y2, 
                                      dhd_fx28_4_t a_xo, dhd_fx28_4_t a_yo, dhd_float32_t a_blur) {
  dhd_float32_t dx = (dhd_float32_t) (a_x2 - a_x1);
  dhd_float32_t dy = (dhd_float32_t) (a_y2 - a_y1);  
  dhd_float32_t l, l_half, l_inv, start;  
  union fltconvert_t {                                            
    dhd_float32_t m_float;  /* PRQA S 3629 *//* $Misra: Union containing float is used locally to compute 1/sqrt (12.12/3629). $*/
    dhd_int32_t   m_int;
  } fltconvert;
  const dhd_float32_t scale = (dhd_float32_t)( 1 << 18 );       /* scaling factor used to get to 18 fractional bits in the int representation*/
  const dhd_float32_t half       = 0.5f * scale;                /* constants used in isqrt approximation (prescaled)*/
  const dhd_float32_t threehalfs = 1.5f * scale;
  const dhd_int32_t center       = 1 << 17;                     /* visual center of AA gradient on ideal edge ( 0.5 *scale)*/
                       
  /* approximate length of edge normal*/
  l = (dx*dx) + (dy*dy);
  l_half = l * half;
  fltconvert.m_float = l;                                       /* good old 1/sqrt estimate by reinterpretation as integer                           */
  fltconvert.m_int = 0x5f375a86 - ( fltconvert.m_int >> 1 );    /* PRQA S 0502 *//* $Misra: #PERF_ARITHMETIC_SHIFT_RIGHT $*/  /* google for magic number 0x5f375a86 to find details*/
  l_inv = fltconvert.m_float;
  l_inv = l_inv * ( threehalfs - ( l_half * l_inv * l_inv ) );  /* one iteration newton/rhapson (can be changed to just l_inv *= scale;*/
                                                                /* as a speed/quality tradeoff, l_half is not required in that case)  */

  /* normalize edge to 1/blur px range and prepare for 18 fractional bits*/
  l_inv *= a_blur;
  dx *= l_inv;
  dy *= l_inv;

  /* setup integer limiters*/
  a_dst->m_dx    = (dhd_int32_t) -dy; 
  a_dst->m_dy    = (dhd_int32_t)  dx;
  start          = ((a_x1-a_xo)*dy) - ((a_y1-a_yo)*dx);     /* PRQA S 3763 *//* $Misra: #CONVERSION_INT_TO_FLOAT_COMPILER_SPEC $*/
  a_dst->m_start = ((dhd_int32_t)(start * 0.0625f) ) + center;  /* 1/16 = 0.0625*/
}


/*----------------------------------------------------------------------------------------------------------*/
/* Setup an edge from two points with Antialiasing. */
/* Is slower than dhd_setup_edge_aa but uses a more accurate edge normalization.*/
/* Tie breaking rules are not applied as antialiased edges are never shared.*/
/**/
/* All points in screenspace pixel coordinates using 4 bit fraction. */
/**/
/* Parameters:*/
/*  a_dst : dhd_edge_data_t structure the result is written into*/
/*  a_x1 : First point on the edge (with 4 bit subpixel precision)*/
/*  a_y1 : First point on the edge (with 4 bit subpixel precision)*/
/*  a_x2 : Second point on the edge (with 4 bit subpixel precision)*/
/*  a_y2 : Second point on the edge (with 4 bit subpixel precision)*/
/*  a_xo : Point at which the enumeration starts (with 4 bit subpixel precision)*/
/*  a_yo : Point at which the enumeration starts (with 4 bit subpixel precision)*/
/*  a_blur : additional scaling factor (set to 1.0 / size of aa gradient in pixels ; defaults to 1.0)*/
/**/
/* See Also:*/
/*  dhd_setup_edge_noaa, dhd_setup_edge_noaa_notie, dhd_setup_edge_aa*/
DHD_API_INLINE void dhd_setup_edge_aa2(dhd_edge_data_t *a_dst, dhd_fx28_4_t a_x1, dhd_fx28_4_t a_y1, dhd_fx28_4_t a_x2, dhd_fx28_4_t a_y2, 
                                      dhd_fx28_4_t a_xo, dhd_fx28_4_t a_yo, dhd_float32_t a_blur) {
  dhd_float32_t dx = (dhd_float32_t) (a_x2 - a_x1);
  dhd_float32_t dy = (dhd_float32_t) (a_y2 - a_y1);  
  dhd_float32_t l, l_half, l_inv, start;  
  union fltconvert_t {                                            
    dhd_float32_t m_float;  /* PRQA S 3629 *//* $Misra: Union containing float is used locally to compute 1/sqrt. $*/
    dhd_int32_t   m_int;
  } fltconvert;
  const dhd_float32_t scale = (dhd_float32_t)( 1 << 18 );       /* scaling factor used to get to 18 fractional bits in the int representation  */
  const dhd_int32_t center  = 1 << 17;                          /* visual center of AA gradient on ideal edge ( 0.5 * scale)*/
                       
  /* approximate length of edge normal*/
  l = (dx*dx) + (dy*dy);
  l_half = l * 0.5f;
  fltconvert.m_float = l;                                       /* good old 1/sqrt estimate by reinterpretation as integer                           */
  fltconvert.m_int = 0x5f375a86 - ( fltconvert.m_int >> 1 );    /* PRQA S 0502 *//* $Misra: #PERF_ARITHMETIC_SHIFT_RIGHT $*/  /* google for magic number 0x5f375a86 to find details   */
  l_inv = fltconvert.m_float;  
  l_inv = l_inv * ( 1.5f - ( l_half * l_inv * l_inv ) );        /* two iterations newton/rhapson */
  l_inv = l_inv * ( 1.5f - ( l_half * l_inv * l_inv ) );      
  l_inv *= scale;

  /* normalize edge to 1/blur px range and prepare for 18 fractional bits*/
  l_inv *= a_blur;
  dx *= l_inv;
  dy *= l_inv;

  /* setup integer limiters*/
  a_dst->m_dx    = (dhd_int32_t) -dy; 
  a_dst->m_dy    = (dhd_int32_t)  dx;  
  start          = ((a_x1-a_xo)*dy) - ((a_y1-a_yo)*dx);   /* PRQA S 3763 *//* $Misra: #CONVERSION_INT_TO_FLOAT_COMPILER_SPEC $*/
  a_dst->m_start = ((dhd_int32_t)(start * 0.0625f) ) + center;  /* 1/16 = 0.0625*/
}


/* --------------------------------------------------------------------------------------------------------------------------------------*/
/* Setup an edge from two points without AA. This function is slower than dhd_setup_edge_noaa_notie but*/
/* will apply tie breaking rules to ensure gapless rendering for shared edges, even when the application*/
/* can not (or does not want to) use E_DHD_INVERT flags.*/
/* */
/* All points in screenspace pixel coordinates using 4 bit fraction.*/
/* */
/* */
/* */
/* Also note that non antialiased edges are limited to a width/height of 2048 pixels (see <link !!Basics_Geometry, Specifying Geometry>).*/
/*                                                                                                         */
/* Parameters:*/
/*  a_dst :  dhd_edge_data_t structure the result is written into*/
/*  a_x1 :   First point on the edge (with 4 bit subpixel precision)*/
/*  a_y1 :   First point on the edge (with 4 bit subpixel precision)*/
/*  a_x2 :   Second point on the edge (with 4 bit subpixel precision)*/
/*  a_y2 :   Second point on the edge (with 4 bit subpixel precision)*/
/*  a_xo :   Point at which the enumeration starts (with 4 bit subpixel precision)*/
/*  a_yo :   Point at which the enumeration starts (with 4 bit subpixel precision)*/
/*                                                                                                         */
/* See Also:*/
/*  dhd_setup_edge_noaa_notie, dhd_setup_edge_aa, dhd_setup_edge_aa2*/
DHD_API_INLINE void dhd_setup_edge_noaa(dhd_edge_data_t *a_dst, dhd_fx28_4_t a_x1, dhd_fx28_4_t a_y1, dhd_fx28_4_t a_x2, dhd_fx28_4_t a_y2, 
                                        dhd_fx28_4_t a_xo, dhd_fx28_4_t a_yo) {
  dhd_int32_t dx = a_x2 - a_x1;
  dhd_int32_t dy = a_y2 - a_y1;  
  dhd_int32_t tie;

  /* detect top/left or bottom/right edges*/
  if ( dy < 0 ) {    
    /* upward edge is always top/left */
    tie = 0;
  } else {
    if ( dy == 0 ) {
      /* horizontal edge, tie break on dx*/
      tie = (dx > 0);
    } else {
      /* downward edge is always bottom/right*/
      tie = 1;
    }
  }

  /* we can simply ignore the fixedpoint scale as we don't have to apply any norm  */
  a_dst->m_dx    = -dy * 16;
  a_dst->m_dy    =  dx * 16;
  a_dst->m_start = (((a_x1-a_xo)*dy) - ((a_y1-a_yo)*dx)) - tie;
}


/*----------------------------------------------------------------------------------------------------------*/
/* Find bounding box of triangle. The function fills the bounding box information of a a dhd_prim_data_t */
/* structure (m_xmin, m_xmax, m_ymin, m_ymax and m_ystart) with correct data for the given triangle.*/
/* Triangle orientation does not matter.*/
/* All points in screenspace pixel coordinates using 4 bit fraction. */
/**/
/* Parameters:*/
/*  a_dst : dhd_prim_data_t structure the result is written into*/
/*  x1 : First point of the triangle (with 4 bit subpixel precision)*/
/*  y1 : First point of the triangle (with 4 bit subpixel precision)*/
/*  x2 : Second point of the triangle (with 4 bit subpixel precision)*/
/*  y2 : Second point of the triangle (with 4 bit subpixel precision)*/
/*  x3 : Third point of the triangle (with 4 bit subpixel precision)*/
/*  y3 : Third point of the triangle (with 4 bit subpixel precision)*/
/**/
DHD_API_INLINE void dhd_bound_tri(dhd_prim_data_t *a_dst, dhd_fx28_4_t x1, dhd_fx28_4_t y1, dhd_fx28_4_t x2, dhd_fx28_4_t y2, dhd_fx28_4_t x3, dhd_fx28_4_t y3) {
  dhd_int32_t xmin,xmax;
  dhd_int32_t ymin,ymax;
  dhd_int32_t ystart;

  /* find bounding box and ystart (wc. 3 compares per axis)*/
  if (x1 < x2) {    
    if (x2 < x3) {      
      xmin = x1; xmax = x3; ystart = y1;  /* x1,x2,x3*/
    } else {
      if (x1 < x3) {        
        xmin = x1; xmax = x2; ystart = y1;  /* x1,x3,x2*/
      } else {        
        xmin = x3; xmax = x2; ystart = y3;  /* x3,x1,x2*/
      }
    }
  } else {    
    if (x2 < x3) {
      if (x1 < x3) {        
        xmin = x2; xmax = x3; ystart = y2;  /* x2,x1,x3*/
      } else {        
        xmin = x2; xmax = x1; ystart = y2;  /* x2,x3,x1*/
      }
    } else {      
      xmin = x3; xmax = x1; ystart = y3;  /* x3,x2,x1*/
    }
  }

  if (y1 < y2) {    
    if (y2 < y3) {      
      ymin = y1; ymax = y3;               /* y1,y2,y3*/
    } else {      
      if (y1 < y3) {        
        ymin = y1; ymax = y2;               /* y1,y3,y2*/
      } else {        
        ymin = y3; ymax = y2;               /* y3,y1,y2*/
      }
    }
  } else {    
    if (y2 < y3) {
      if (y1 < y3) {        
        ymin = y2; ymax = y3;               /* y2,y1,y3*/
      } else {        
        ymin = y2; ymax = y1;               /* y2,y3,y1*/
      }
    } else {      
      ymin = y3; ymax = y1;               /* y3,y2,y1*/
    }
  }
  
  /* snap bounding box to integer grid*/
  a_dst->m_xmin = (dhd_uint16_t) (xmin >> 4);         /* PRQA S 0502 *//* $Misra: #ARITHMETIC_SHIFT_RIGHT_NECESSARY $*/
  a_dst->m_ymin = (dhd_uint16_t) (ymin >> 4);         /* PRQA S 0502 *//* $Misra: #ARITHMETIC_SHIFT_RIGHT_NECESSARY $*/
  a_dst->m_xmax = (dhd_uint16_t) ((xmax + 15) >> 4);  /* PRQA S 0502 *//* $Misra: #ARITHMETIC_SHIFT_RIGHT_NECESSARY $*/
  a_dst->m_ymax = (dhd_uint16_t) ((ymax + 15) >> 4);  /* PRQA S 0502 *//* $Misra: #ARITHMETIC_SHIFT_RIGHT_NECESSARY $*/

  a_dst->m_ystart = (dhd_uint16_t) (ystart >> 4);     /* PRQA S 0502 *//* $Misra: #ARITHMETIC_SHIFT_RIGHT_NECESSARY $*/
}


/*----------------------------------------------------------------------------------------------------------*/
/* Find bounding box of quad. The function fills the bounding box information of a a dhd_prim_data_t */
/* structure (m_xmin, m_xmax, m_ymin, m_ymax and m_ystart) with correct data for the given quad.*/
/**/
/**/
/* Parameters:*/
/*  a_dst : dhd_prim_data_t structure the result is written into*/
/*  x1 : First point of the quad (with 4 bit subpixel precision)*/
/*  y1 : First point of the quad (with 4 bit subpixel precision)*/
/*  x2 : Second point of the quad (with 4 bit subpixel precision)*/
/*  y2 : Second point of the quad (with 4 bit subpixel precision)*/
/*  x3 : Third point of the quad (with 4 bit subpixel precision)*/
/*  y3 : Third point of the quad (with 4 bit subpixel precision)*/
/*  x4 : Fourth point of the quad (with 4 bit subpixel precision)*/
/*  y4 : Fourth point of the quad (with 4 bit subpixel precision)*/
DHD_API_INLINE void dhd_bound_quad(dhd_prim_data_t *a_dst, dhd_fx28_4_t x1, dhd_fx28_4_t y1, dhd_fx28_4_t x2, dhd_fx28_4_t y2, dhd_fx28_4_t x3, dhd_fx28_4_t y3, dhd_fx28_4_t x4, dhd_fx28_4_t y4) {
  dhd_int32_t xmin,xmax;
  dhd_int32_t ymin,ymax;
  dhd_int32_t ystart;

  /* find bounding box and ystart (wc. 3 compares per axis)*/
  if (x1 < x2) {    
    if (x2 < x3) {      
      xmin = x1; xmax = x3; ystart = y1;  /* x1,x2,x3*/
    } else {
      if (x1 < x3) {        
        xmin = x1; xmax = x2; ystart = y1;  /* x1,x3,x2*/
      } else {        
        xmin = x3; xmax = x2; ystart = y3;  /* x3,x1,x2*/
      }
    }
  } else {    
    if (x2 < x3) {
      if (x1 < x3) {        
        xmin = x2; xmax = x3; ystart = y2;  /* x2,x1,x3*/
      } else {        
        xmin = x2; xmax = x1; ystart = y2;  /* x2,x3,x1*/
      }
    } else {      
      xmin = x3; xmax = x1; ystart = y3;  /* x3,x2,x1*/
    }
  }
  if (x4 < xmin) {
    xmin = x4; ystart = y4;
  }
  if (x4 > xmax) {
    xmax = x4;
  }

  if (y1 < y2) {    
    if (y2 < y3) {      
      ymin = y1; ymax = y3;               /* y1,y2,y3*/
    } else {      
      if (y1 < y3) {        
        ymin = y1; ymax = y2;               /* y1,y3,y2*/
      } else {        
        ymin = y3; ymax = y2;               /* y3,y1,y2*/
      }
    }
  } else {    
    if (y2 < y3) {
      if (y1 < y3) {        
        ymin = y2; ymax = y3;               /* y2,y1,y3*/
      } else {        
        ymin = y2; ymax = y1;               /* y2,y3,y1*/
      }
    } else {      
      ymin = y3; ymax = y1;               /* y3,y2,y1*/
    }
  }
  if (y4 < ymin) {
    ymin = y4;
  }
  if (y4 > ymax) {
    ymax = y4;
  }
  
  /* snap bounding box to integer grid*/
  a_dst->m_xmin = (dhd_uint16_t) (xmin >> 4);         /* PRQA S 0502 *//* $Misra: #ARITHMETIC_SHIFT_RIGHT_NECESSARY $*/
  a_dst->m_ymin = (dhd_uint16_t) (ymin >> 4);         /* PRQA S 0502 *//* $Misra: #ARITHMETIC_SHIFT_RIGHT_NECESSARY $*/
  a_dst->m_xmax = (dhd_uint16_t) ((xmax + 15) >> 4);  /* PRQA S 0502 *//* $Misra: #ARITHMETIC_SHIFT_RIGHT_NECESSARY $*/
  a_dst->m_ymax = (dhd_uint16_t) ((ymax + 15) >> 4);  /* PRQA S 0502 *//* $Misra: #ARITHMETIC_SHIFT_RIGHT_NECESSARY $*/

  a_dst->m_ystart = (dhd_uint16_t) (ystart >> 4);     /* PRQA S 0502 *//* $Misra: #ARITHMETIC_SHIFT_RIGHT_NECESSARY $*/
}


/*----------------------------------------------------------------------------------------------------------*/
/* Find bounding box of an axis aligned rectangle. The function fills the bounding box information of a */
/* dhd_prim_data_t  structure (m_xmin, m_xmax, m_ymin, m_ymax and m_ystart) with correct data for the box.*/
/**/
/* Parameters:*/
/*  a_dst : dhd_prim_data_t structure the result is written into*/
/*  x1 : First point of the rectangle (with 4 bit subpixel precision)*/
/*  y1 : First point of the rectangle (with 4 bit subpixel precision)*/
/*  x2 : Second point of the rectangle (with 4 bit subpixel precision)*/
/*  y2 : Second point of the rectangle (with 4 bit subpixel precision)*/
DHD_API_INLINE void dhd_bound_aab(dhd_prim_data_t *a_dst, dhd_fx28_4_t x1,dhd_fx28_4_t y1, dhd_fx28_4_t x2, dhd_fx28_4_t y2) {
  dhd_int32_t xmin, ymin, xmax, ymax;

  /* bound axis aligned quad*/
  if (x1 < x2) {
    xmin = x1;
    xmax = x2;
  } else {
    xmin = x2;
    xmax = x1;
  }
  if (y1 < y2) {
    ymin = y1;
    ymax = y2;
  } else {
    ymin = y2;
    ymax = y1;
  }

  /* snap bounding box to integer grid*/
  a_dst->m_xmin = (dhd_uint16_t) (xmin >> 4);         /* PRQA S 0502 *//* $Misra: #ARITHMETIC_SHIFT_RIGHT_NECESSARY $*/
  a_dst->m_ymin = (dhd_uint16_t) (ymin >> 4);         /* PRQA S 0502 *//* $Misra: #ARITHMETIC_SHIFT_RIGHT_NECESSARY $*/
  a_dst->m_xmax = (dhd_uint16_t) ((xmax + 15) >> 4);  /* PRQA S 0502 *//* $Misra: #ARITHMETIC_SHIFT_RIGHT_NECESSARY $*/
  a_dst->m_ymax = (dhd_uint16_t) ((ymax + 15) >> 4);  /* PRQA S 0502 *//* $Misra: #ARITHMETIC_SHIFT_RIGHT_NECESSARY $*/
  
  a_dst->m_ystart = a_dst->m_ymin;
}

/*----------------------------------------------------------------------------------------------------------*/
/* Clip a bounding box to the current framebuffer and optionally to the defined clip rect.*/
/* Returns false if the resulting box is fully outside the framebuffer.*/
/* */
/* Parameters:*/
/*  a_device : Driver context handle (as returned by dhd_init).*/
/*  a_prim : Bounding box definition to clip.*/
/*  a_mode: Clipping mode to apply (no mask, single mode only).*/
/**/
/* See Also:*/
/*  dhd_set_util_cliprect*/
DHD_API_INLINE dhd_bool_t dhd_clip_bbox(dhd_handle_t a_device, dhd_prim_data_t *a_prim, dhd_util_clipmode_t a_mode) {
  dhd_device_data_t *device = (dhd_device_data_t *) a_device;

  if (a_mode != E_DHD_CLIP_NONE) {
    dhd_int32_t xmin, ymin, xmax, ymax;
    /* get framebuffer target rect*/
    xmin = 0;
    ymin = 0;
    xmax = (dhd_int32_t) device->m_framebuffer_width - 1;
    ymax = (dhd_int32_t) device->m_framebuffer_height - 1;
    /* merge with utility rect if requested*/
    if (a_mode == E_DHD_CLIP_UTILRECT) {
      if (xmin < device->m_util_xmin) {
        xmin = (dhd_int32_t) device->m_util_xmin;
      }
      if (ymin < device->m_util_ymin) {
        ymin = (dhd_int32_t) device->m_util_ymin;
      }
      if (xmax > device->m_util_xmax) {
        xmax = (dhd_int32_t) device->m_util_xmax;
      }
      if (ymax > device->m_util_ymax) {
        ymax = (dhd_int32_t) device->m_util_ymax;
      }
      /* reject empty cliprects*/
      if ((xmax < xmin) || (ymax < ymin)) {
        return DHD_FALSE;
      }
    }    
    /* quick reject */
    if ((((dhd_int16_t) a_prim->m_xmax) < xmin ) ||
        (((dhd_int16_t) a_prim->m_ymax) < ymin ) ||
        (((dhd_int16_t) a_prim->m_xmin) > xmax ) ||
        (((dhd_int16_t) a_prim->m_ymin) > ymax )) {
      return DHD_FALSE;
    }
    /* normal clipping */
    if (((dhd_int16_t) a_prim->m_xmin) < xmin) a_prim->m_xmin = (dhd_uint16_t) xmin;
    if (((dhd_int16_t) a_prim->m_ymin) < ymin) a_prim->m_ymin = (dhd_uint16_t) ymin;  
    if (a_prim->m_xmax > xmax ) a_prim->m_xmax = (dhd_uint16_t) (xmax);
    if (a_prim->m_ymax > ymax ) a_prim->m_ymax = (dhd_uint16_t) (ymax);
  }

  /* reject degenerate bbox*/
  if ((a_prim->m_xmax < a_prim->m_xmin) || (a_prim->m_ymax < a_prim->m_ymin)) return DHD_FALSE; 

  /* update ystart*/
  if (((dhd_int16_t) a_prim->m_ystart) < a_prim->m_ymin) a_prim->m_ystart = a_prim->m_ymin;
  if (((dhd_int16_t) a_prim->m_ystart) > a_prim->m_ymax) a_prim->m_ystart = a_prim->m_ymax;  

  return DHD_TRUE;
}

#endif /*DAVEHD_UTIL_INL_H_INCLUDED*/
