Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright (C) 2008-2009 Nicolai Haehnle.
  3.  *
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining
  7.  * a 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, sublicense, 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
  16.  * portions of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  21.  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
  22.  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  23.  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  24.  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  */
  27.  
  28. #include "radeon_program_pair.h"
  29.  
  30. #include "radeon_compiler_util.h"
  31.  
  32. #include <stdlib.h>
  33.  
  34. /**
  35.  * Return the source slot where we installed the given register access,
  36.  * or -1 if no slot was free anymore.
  37.  */
  38. int rc_pair_alloc_source(struct rc_pair_instruction *pair,
  39.         unsigned int rgb, unsigned int alpha,
  40.         rc_register_file file, unsigned int index)
  41. {
  42.         int candidate = -1;
  43.         int candidate_quality = -1;
  44.         unsigned int alpha_used = 0;
  45.         unsigned int rgb_used = 0;
  46.         int i;
  47.  
  48.         if ((!rgb && !alpha) || file == RC_FILE_NONE)
  49.                 return 0;
  50.  
  51.         /* Make sure only one presubtract operation is used per instruction. */
  52.         if (file == RC_FILE_PRESUB) {
  53.                 if (rgb && pair->RGB.Src[RC_PAIR_PRESUB_SRC].Used
  54.                         && index != pair->RGB.Src[RC_PAIR_PRESUB_SRC].Index) {
  55.                                 return -1;
  56.                 }
  57.  
  58.                 if (alpha && pair->Alpha.Src[RC_PAIR_PRESUB_SRC].Used
  59.                         && index != pair->Alpha.Src[RC_PAIR_PRESUB_SRC].Index) {
  60.                                 return -1;
  61.                 }
  62.         }
  63.  
  64.         for(i = 0; i < 3; ++i) {
  65.                 int q = 0;
  66.                 if (rgb) {
  67.                         if (pair->RGB.Src[i].Used) {
  68.                                 if (pair->RGB.Src[i].File != file ||
  69.                                     pair->RGB.Src[i].Index != index) {
  70.                                         rgb_used++;
  71.                                         continue;
  72.                                 }
  73.                                 q++;
  74.                         }
  75.                 }
  76.                 if (alpha) {
  77.                         if (pair->Alpha.Src[i].Used) {
  78.                                 if (pair->Alpha.Src[i].File != file ||
  79.                                     pair->Alpha.Src[i].Index != index) {
  80.                                         alpha_used++;
  81.                                         continue;
  82.                                 }
  83.                                 q++;
  84.                         }
  85.                 }
  86.                 if (q > candidate_quality) {
  87.                         candidate_quality = q;
  88.                         candidate = i;
  89.                 }
  90.         }
  91.  
  92.         if (file == RC_FILE_PRESUB) {
  93.                 candidate = RC_PAIR_PRESUB_SRC;
  94.         } else if (candidate < 0 || (rgb && rgb_used > 2)
  95.                         || (alpha && alpha_used > 2)) {
  96.                 return -1;
  97.         }
  98.  
  99.         /* candidate >= 0 */
  100.  
  101.         if (rgb) {
  102.                 pair->RGB.Src[candidate].Used = 1;
  103.                 pair->RGB.Src[candidate].File = file;
  104.                 pair->RGB.Src[candidate].Index = index;
  105.                 if (candidate == RC_PAIR_PRESUB_SRC) {
  106.                         /* For registers with the RC_FILE_PRESUB file,
  107.                          * the index stores the presubtract op. */
  108.                         int src_regs = rc_presubtract_src_reg_count(index);
  109.                         for(i = 0; i < src_regs; i++) {
  110.                                 pair->RGB.Src[i].Used = 1;
  111.                         }
  112.                 }
  113.         }
  114.         if (alpha) {
  115.                 pair->Alpha.Src[candidate].Used = 1;
  116.                 pair->Alpha.Src[candidate].File = file;
  117.                 pair->Alpha.Src[candidate].Index = index;
  118.                 if (candidate == RC_PAIR_PRESUB_SRC) {
  119.                         /* For registers with the RC_FILE_PRESUB file,
  120.                          * the index stores the presubtract op. */
  121.                         int src_regs = rc_presubtract_src_reg_count(index);
  122.                         for(i=0; i < src_regs; i++) {
  123.                                 pair->Alpha.Src[i].Used = 1;
  124.                         }
  125.                 }
  126.         }
  127.  
  128.         return candidate;
  129. }
  130.  
  131. static void pair_foreach_source_callback(
  132.         struct rc_pair_instruction * pair,
  133.         void * data,
  134.         rc_pair_foreach_src_fn cb,
  135.         unsigned int swz,
  136.         unsigned int src)
  137. {
  138.         /* swz > 3 means that the swizzle is either not used, or a constant
  139.          * swizzle (e.g. 0, 1, 0.5). */
  140.         if(swz > 3)
  141.                 return;
  142.  
  143.         if(swz == RC_SWIZZLE_W) {
  144.                 if (src == RC_PAIR_PRESUB_SRC) {
  145.                         unsigned int i;
  146.                         unsigned int src_count = rc_presubtract_src_reg_count(
  147.                                 pair->Alpha.Src[RC_PAIR_PRESUB_SRC].Index);
  148.                         for(i = 0; i < src_count; i++) {
  149.                                 cb(data, &pair->Alpha.Src[i]);
  150.                         }
  151.                 } else {
  152.                         cb(data, &pair->Alpha.Src[src]);
  153.                 }
  154.         } else {
  155.                 if (src == RC_PAIR_PRESUB_SRC) {
  156.                         unsigned int i;
  157.                         unsigned int src_count = rc_presubtract_src_reg_count(
  158.                                 pair->RGB.Src[RC_PAIR_PRESUB_SRC].Index);
  159.                         for(i = 0; i < src_count; i++) {
  160.                                 cb(data, &pair->RGB.Src[i]);
  161.                         }
  162.                 }
  163.                 else {
  164.                         cb(data, &pair->RGB.Src[src]);
  165.                 }
  166.         }
  167. }
  168.  
  169. void rc_pair_foreach_source_that_alpha_reads(
  170.         struct rc_pair_instruction * pair,
  171.         void * data,
  172.         rc_pair_foreach_src_fn cb)
  173. {
  174.         unsigned int i;
  175.         const struct rc_opcode_info * info =
  176.                                 rc_get_opcode_info(pair->Alpha.Opcode);
  177.         for(i = 0; i < info->NumSrcRegs; i++) {
  178.                 pair_foreach_source_callback(pair, data, cb,
  179.                                         GET_SWZ(pair->Alpha.Arg[i].Swizzle, 0),
  180.                                         pair->Alpha.Arg[i].Source);
  181.         }
  182. }
  183.  
  184. void rc_pair_foreach_source_that_rgb_reads(
  185.         struct rc_pair_instruction * pair,
  186.         void * data,
  187.         rc_pair_foreach_src_fn cb)
  188. {
  189.         unsigned int i;
  190.         const struct rc_opcode_info * info =
  191.                                 rc_get_opcode_info(pair->RGB.Opcode);
  192.         for(i = 0; i < info->NumSrcRegs; i++) {
  193.                 unsigned int chan;
  194.                 unsigned int swz = RC_SWIZZLE_UNUSED;
  195.                 /* Find a swizzle that is either X,Y,Z,or W.  We assume here
  196.                  * that if one channel swizzles X,Y, or Z, then none of the
  197.                  * other channels swizzle W, and vice-versa. */
  198.                 for(chan = 0; chan < 4; chan++) {
  199.                         swz = GET_SWZ(pair->RGB.Arg[i].Swizzle, chan);
  200.                         if(swz == RC_SWIZZLE_X || swz == RC_SWIZZLE_Y
  201.                         || swz == RC_SWIZZLE_Z || swz == RC_SWIZZLE_W)
  202.                                 continue;
  203.                 }
  204.                 pair_foreach_source_callback(pair, data, cb,
  205.                                         swz,
  206.                                         pair->RGB.Arg[i].Source);
  207.         }
  208. }
  209.  
  210. struct rc_pair_instruction_source * rc_pair_get_src(
  211.         struct rc_pair_instruction * pair_inst,
  212.         struct rc_pair_instruction_arg * arg)
  213. {
  214.         unsigned int type;
  215.  
  216.         type = rc_source_type_swz(arg->Swizzle);
  217.  
  218.         if (type & RC_SOURCE_RGB) {
  219.                 return &pair_inst->RGB.Src[arg->Source];
  220.         } else if (type & RC_SOURCE_ALPHA) {
  221.                 return &pair_inst->Alpha.Src[arg->Source];
  222.         } else {
  223.                 return NULL;
  224.         }
  225. }
  226.  
  227. int rc_pair_get_src_index(
  228.         struct rc_pair_instruction * pair_inst,
  229.         struct rc_pair_instruction_source * src)
  230. {
  231.         int i;
  232.         for (i = 0; i < 3; i++) {
  233.                 if (&pair_inst->RGB.Src[i] == src
  234.                         || &pair_inst->Alpha.Src[i] == src) {
  235.                         return i;
  236.                 }
  237.         }
  238.         return -1;
  239. }
  240.