Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2012 VMware, Inc.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. #include "pipe/p_state.h"
  29. #include "util/u_debug.h"
  30.  
  31. #include "gallivm/lp_bld_type.h"
  32. #include "gallivm/lp_bld_arit.h"
  33.  
  34. #include "lp_bld_blend.h"
  35.  
  36. /**
  37.  * Is (a OP b) == (b OP a)?
  38.  */
  39. boolean
  40. lp_build_blend_func_commutative(unsigned func)
  41. {
  42.    switch (func) {
  43.    case PIPE_BLEND_ADD:
  44.    case PIPE_BLEND_MIN:
  45.    case PIPE_BLEND_MAX:
  46.       return TRUE;
  47.    case PIPE_BLEND_SUBTRACT:
  48.    case PIPE_BLEND_REVERSE_SUBTRACT:
  49.       return FALSE;
  50.    default:
  51.       assert(0);
  52.       return TRUE;
  53.    }
  54. }
  55.  
  56.  
  57. /**
  58.  * Whether the blending functions are the reverse of each other.
  59.  */
  60. boolean
  61. lp_build_blend_func_reverse(unsigned rgb_func, unsigned alpha_func)
  62. {
  63.    if(rgb_func == alpha_func)
  64.       return FALSE;
  65.    if(rgb_func == PIPE_BLEND_SUBTRACT && alpha_func == PIPE_BLEND_REVERSE_SUBTRACT)
  66.       return TRUE;
  67.    if(rgb_func == PIPE_BLEND_REVERSE_SUBTRACT && alpha_func == PIPE_BLEND_SUBTRACT)
  68.       return TRUE;
  69.    return FALSE;
  70. }
  71.  
  72.  
  73. /**
  74.  * Whether the blending factors are complementary of each other.
  75.  */
  76. static INLINE boolean
  77. lp_build_blend_factor_complementary(unsigned src_factor, unsigned dst_factor)
  78. {
  79.    return dst_factor == (src_factor ^ 0x10);
  80. }
  81.  
  82.  
  83. /**
  84.  * @sa http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquationSeparate.xml
  85.  */
  86. LLVMValueRef
  87. lp_build_blend_func(struct lp_build_context *bld,
  88.                     unsigned func,
  89.                     LLVMValueRef term1,
  90.                     LLVMValueRef term2)
  91. {
  92.    switch (func) {
  93.    case PIPE_BLEND_ADD:
  94.       return lp_build_add(bld, term1, term2);
  95.    case PIPE_BLEND_SUBTRACT:
  96.       return lp_build_sub(bld, term1, term2);
  97.    case PIPE_BLEND_REVERSE_SUBTRACT:
  98.       return lp_build_sub(bld, term2, term1);
  99.    case PIPE_BLEND_MIN:
  100.       return lp_build_min(bld, term1, term2);
  101.    case PIPE_BLEND_MAX:
  102.       return lp_build_max(bld, term1, term2);
  103.    default:
  104.       assert(0);
  105.       return bld->zero;
  106.    }
  107. }
  108.  
  109.  
  110. /**
  111.  * Performs optimisations and blending independent of SoA/AoS
  112.  *
  113.  * @param func                   the blend function
  114.  * @param factor_src             PIPE_BLENDFACTOR_xxx
  115.  * @param factor_dst             PIPE_BLENDFACTOR_xxx
  116.  * @param src                    source rgba
  117.  * @param dst                    dest rgba
  118.  * @param src_factor             src factor computed value
  119.  * @param dst_factor             dst factor computed value
  120.  * @param not_alpha_dependent    same factors accross all channels of src/dst
  121.  *
  122.  * not_alpha_dependent should be:
  123.  *  SoA: always true as it is only one channel at a time
  124.  *  AoS: rgb_src_factor == alpha_src_factor && rgb_dst_factor == alpha_dst_factor
  125.  *
  126.  * Note that pretty much every possible optimisation can only be done on non-unorm targets
  127.  * due to unorm values not going above 1.0 meaning factorisation can change results.
  128.  * e.g. (0.9 * 0.9) + (0.9 * 0.9) != 0.9 * (0.9 + 0.9) as result of + is always <= 1.
  129.  */
  130. LLVMValueRef
  131. lp_build_blend(struct lp_build_context *bld,
  132.                unsigned func,
  133.                unsigned factor_src,
  134.                unsigned factor_dst,
  135.                LLVMValueRef src,
  136.                LLVMValueRef dst,
  137.                LLVMValueRef src_factor,
  138.                LLVMValueRef dst_factor,
  139.                boolean not_alpha_dependent,
  140.                boolean optimise_only)
  141. {
  142.    LLVMValueRef result, src_term, dst_term;
  143.  
  144.    /* If we are not alpha dependent we can mess with the src/dst factors */
  145.    if (not_alpha_dependent) {
  146.       if (lp_build_blend_factor_complementary(factor_src, factor_dst)) {
  147.          if (func == PIPE_BLEND_ADD) {
  148.             if (factor_src < factor_dst) {
  149.                return lp_build_lerp(bld, src_factor, dst, src, 0);
  150.             } else {
  151.                return lp_build_lerp(bld, dst_factor, src, dst, 0);
  152.             }
  153.          } else if(bld->type.floating && func == PIPE_BLEND_SUBTRACT) {
  154.             result = lp_build_add(bld, src, dst);
  155.  
  156.             if (factor_src < factor_dst) {
  157.                result = lp_build_mul(bld, result, src_factor);
  158.                return lp_build_sub(bld, result, dst);
  159.             } else {
  160.                result = lp_build_mul(bld, result, dst_factor);
  161.                return lp_build_sub(bld, src, result);
  162.             }
  163.          } else if(bld->type.floating && func == PIPE_BLEND_REVERSE_SUBTRACT) {
  164.             result = lp_build_add(bld, src, dst);
  165.  
  166.             if (factor_src < factor_dst) {
  167.                result = lp_build_mul(bld, result, src_factor);
  168.                return lp_build_sub(bld, dst, result);
  169.             } else {
  170.                result = lp_build_mul(bld, result, dst_factor);
  171.                return lp_build_sub(bld, result, src);
  172.             }
  173.          }
  174.       }
  175.  
  176.       if (bld->type.floating && factor_src == factor_dst) {
  177.          if (func == PIPE_BLEND_ADD ||
  178.              func == PIPE_BLEND_SUBTRACT ||
  179.              func == PIPE_BLEND_REVERSE_SUBTRACT) {
  180.             LLVMValueRef result;
  181.             result = lp_build_blend_func(bld, func, src, dst);
  182.             return lp_build_mul(bld, result, src_factor);
  183.          }
  184.       }
  185.    }
  186.  
  187.    if (optimise_only)
  188.       return NULL;
  189.  
  190.    src_term = lp_build_mul(bld, src, src_factor);
  191.    dst_term = lp_build_mul(bld, dst, dst_factor);
  192.    return lp_build_blend_func(bld, func, src_term, dst_term);
  193. }
  194.