1 /* 2 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.scenario.effect.compiler.backend.sw.java; 27 28 import java.util.Arrays; 29 import java.util.HashMap; 30 import java.util.List; 31 import java.util.Map; 32 import com.sun.scenario.effect.compiler.model.CoreSymbols; 33 import com.sun.scenario.effect.compiler.model.FuncImpl; 34 import com.sun.scenario.effect.compiler.model.Function; 35 import com.sun.scenario.effect.compiler.model.Type; 36 import com.sun.scenario.effect.compiler.tree.Expr; 37 import com.sun.scenario.effect.compiler.tree.VariableExpr; 38 39 import static com.sun.scenario.effect.compiler.model.Type.*; 40 41 /** 42 * Contains the pure Java implementations for all core (built-in) functions. 43 */ 44 class JSWFuncImpls { 45 46 private static Map<Function, FuncImpl> funcs = new HashMap<Function, FuncImpl>(); 47 48 static FuncImpl get(Function func) { 49 return funcs.get(func); 50 } 51 52 static { 53 // float4 sample(sampler s, float2 loc) 54 declareFunctionSample(SAMPLER); 55 56 // float4 sample(lsampler s, float2 loc) 57 declareFunctionSample(LSAMPLER); 58 59 // float4 sample(fsampler s, float2 loc) 60 declareFunctionSample(FSAMPLER); 61 62 // int intcast(float x) 63 declareFunctionIntCast(); 64 65 // <ftype> min(<ftype> x, <ftype> y) 66 // <ftype> min(<ftype> x, float y) 67 declareOverloadsMinMax("min", "(x_tmp$1 < y_tmp$2) ? x_tmp$1 : y_tmp$2"); 68 69 // <ftype> max(<ftype> x, <ftype> y) 70 // <ftype> max(<ftype> x, float y) 71 declareOverloadsMinMax("max", "(x_tmp$1 > y_tmp$2) ? x_tmp$1 : y_tmp$2"); 72 73 // <ftype> clamp(<ftype> val, <ftype> min, <ftype> max) 74 // <ftype> clamp(<ftype> val, float min, float max) 75 declareOverloadsClamp(); 76 77 // <ftype> smoothstep(<ftype> min, <ftype> max, <ftype> val) 78 // <ftype> smoothstep(float min, float max, <ftype> val) 79 declareOverloadsSmoothstep(); 80 81 // <ftype> abs(<ftype> x) 82 declareOverloadsSimple("abs", "Math.abs(x_tmp$1)"); 83 84 // <ftype> floor(<ftype> x) 85 declareOverloadsSimple("floor", "(float)Math.floor(x_tmp$1)"); 86 87 // <ftype> ceil(<ftype> x) 88 declareOverloadsSimple("ceil", "(float)Math.ceil(x_tmp$1)"); 89 90 // <ftype> fract(<ftype> x) 91 declareOverloadsSimple("fract", "(x_tmp$1 - (float)Math.floor(x_tmp$1))"); 92 93 // <ftype> sign(<ftype> x) 94 declareOverloadsSimple("sign", "Math.signum(x_tmp$1)"); 95 96 // <ftype> sqrt(<ftype> x) 97 declareOverloadsSimple("sqrt", "(float)Math.sqrt(x_tmp$1)"); 98 99 // <ftype> sin(<ftype> x) 100 declareOverloadsSimple("sin", "(float)Math.sin(x_tmp$1)"); 101 102 // <ftype> cos(<ftype> x) 103 declareOverloadsSimple("cos", "(float)Math.cos(x_tmp$1)"); 104 105 // <ftype> tan(<ftype> x) 106 declareOverloadsSimple("tan", "(float)Math.tan(x_tmp$1)"); 107 108 // <ftype> pow(<ftype> x, <ftype> y) 109 declareOverloadsSimple2("pow", "(float)Math.pow(x_tmp$1, y_tmp$2)"); 110 111 // <ftype> mod(<ftype> x, <ftype> y) 112 // <ftype> mod(<ftype> x, float y) 113 declareOverloadsMinMax("mod", "(x_tmp$1 % y_tmp$2)"); 114 115 // float dot(<ftype> x, <ftype> y) 116 declareOverloadsDot(); 117 118 // float distance(<ftype> x, <ftype> y) 119 declareOverloadsDistance(); 120 121 // <ftype> mix(<ftype> x, <ftype> y, <ftype> a) 122 // <ftype> mix(<ftype> x, <ftype> y, float a) 123 declareOverloadsMix(); 124 125 // <ftype> normalize(<ftype> x) 126 declareOverloadsNormalize(); 127 128 // <ftype> ddx(<ftype> p) 129 declareOverloadsSimple("ddx", "<ddx() not implemented for sw backends>"); 130 131 // <ftype> ddy(<ftype> p) 132 declareOverloadsSimple("ddy", "<ddy() not implemented for sw backends>"); 133 } 134 135 private static void declareFunction(FuncImpl impl, 136 String name, Type... ptypes) 137 { 138 Function f = CoreSymbols.getFunction(name, Arrays.asList(ptypes)); 139 if (f == null) { 140 throw new InternalError("Core function not found (have you declared the function in CoreSymbols?)"); 141 } 142 funcs.put(f, impl); 143 } 144 145 /** 146 * Used to declare sample function: 147 * float4 sample([l,f]sampler s, float2 loc) 148 */ 149 private static void declareFunctionSample(final Type type) { 150 FuncImpl fimpl = new FuncImpl() { 151 @Override 152 public String getPreamble(List<Expr> params) { 153 String s = getSamplerName(params); 154 // TODO: this bounds checking is way too costly... 155 String p = getPosName(params); 156 if (type == LSAMPLER) { 157 return 158 "lsample(" + s + ", loc_tmp_x, loc_tmp_y,\n" + 159 " " + p + "w, " + p + "h, " + p + "scan,\n" + 160 " " + s + "_vals);\n"; 161 } else if (type == FSAMPLER) { 162 return 163 "fsample(" + s + ", loc_tmp_x, loc_tmp_y,\n" + 164 " " + p + "w, " + p + "h, " + p + "scan,\n" + 165 " " + s + "_vals);\n"; 166 } else { 167 return 168 "int " + s + "_tmp;\n" + 169 "if (loc_tmp_x >= 0 && loc_tmp_y >= 0) {\n" + 170 " int iloc_tmp_x = (int)(loc_tmp_x*" + p + "w);\n" + 171 " int iloc_tmp_y = (int)(loc_tmp_y*" + p + "h);\n" + 172 " boolean out =\n" + 173 " iloc_tmp_x >= " + p + "w ||\n" + 174 " iloc_tmp_y >= " + p + "h;\n" + 175 " " + s + "_tmp = out ? 0 :\n" + 176 " " + s + "[iloc_tmp_y*" + p + "scan + iloc_tmp_x];\n" + 177 "} else {\n" + 178 " " + s + "_tmp = 0;\n" + 179 "}\n"; 180 } 181 } 182 public String toString(int i, List<Expr> params) { 183 String s = getSamplerName(params); 184 if (type == LSAMPLER || type == FSAMPLER) { 185 return (i < 0 || i > 3) ? null : s + "_vals[" + i + "]"; 186 } else { 187 switch (i) { 188 case 0: 189 return "(((" + s + "_tmp >> 16) & 0xff) / 255f)"; 190 case 1: 191 return "(((" + s + "_tmp >> 8) & 0xff) / 255f)"; 192 case 2: 193 return "(((" + s + "_tmp ) & 0xff) / 255f)"; 194 case 3: 195 return "(((" + s + "_tmp >>> 24) ) / 255f)"; 196 default: 197 return null; 198 } 199 } 200 } 201 private String getSamplerName(List<Expr> params) { 202 VariableExpr e = (VariableExpr)params.get(0); 203 return e.getVariable().getName(); 204 } 205 private String getPosName(List<Expr> params) { 206 VariableExpr e = (VariableExpr)params.get(0); 207 return "src" + e.getVariable().getReg(); 208 } 209 }; 210 declareFunction(fimpl, "sample", type, FLOAT2); 211 } 212 213 /** 214 * Used to declare intcast function: 215 * int intcast(float x) 216 */ 217 private static void declareFunctionIntCast() { 218 FuncImpl fimpl = new FuncImpl() { 219 public String toString(int i, List<Expr> params) { 220 return "((int)x_tmp)"; 221 } 222 }; 223 declareFunction(fimpl, "intcast", FLOAT); 224 } 225 226 /** 227 * Used to declare simple functions of the following form: 228 * <ftype> name(<ftype> x) 229 */ 230 private static void declareOverloadsSimple(String name, final String pattern) { 231 for (Type type : new Type[] {FLOAT, FLOAT2, FLOAT3, FLOAT4}) { 232 final boolean useSuffix = (type != FLOAT); 233 FuncImpl fimpl = new FuncImpl() { 234 public String toString(int i, List<Expr> params) { 235 String sfx = useSuffix ? JSWBackend.getSuffix(i) : ""; 236 String s = pattern; 237 s = s.replace("$1", sfx); 238 return s; 239 } 240 }; 241 declareFunction(fimpl, name, type); 242 } 243 } 244 245 /** 246 * Used to declare simple two parameter functions of the following form: 247 * <ftype> name(<ftype> x, <ftype> y) 248 */ 249 private static void declareOverloadsSimple2(String name, final String pattern) { 250 for (Type type : new Type[] {FLOAT, FLOAT2, FLOAT3, FLOAT4}) { 251 // declare (vectype,vectype) variants 252 final boolean useSuffix = (type != FLOAT); 253 FuncImpl fimpl = new FuncImpl() { 254 public String toString(int i, List<Expr> params) { 255 String sfx = useSuffix ? JSWBackend.getSuffix(i) : ""; 256 String s = pattern; 257 s = s.replace("$1", sfx); 258 s = s.replace("$2", sfx); 259 return s; 260 } 261 }; 262 declareFunction(fimpl, name, type, type); 263 } 264 } 265 266 /** 267 * Used to declare normalize functions of the following form: 268 * <ftype> normalize(<ftype> x) 269 */ 270 private static void declareOverloadsNormalize() { 271 final String name = "normalize"; 272 final String pattern = "x_tmp$1 / denom"; 273 for (Type type : new Type[] {FLOAT, FLOAT2, FLOAT3, FLOAT4}) { 274 int n = type.getNumFields(); 275 final String preamble; 276 if (n == 1) { 277 preamble = "float denom = x_tmp;\n"; 278 } else { 279 String s = "(x_tmp_x * x_tmp_x)"; 280 s += "+\n(x_tmp_y * x_tmp_y)"; 281 if (n > 2) s += "+\n(x_tmp_z * x_tmp_z)"; 282 if (n > 3) s += "+\n(x_tmp_w * x_tmp_w)"; 283 preamble = "float denom = (float)Math.sqrt(" + s + ");\n"; 284 } 285 286 final boolean useSuffix = (type != FLOAT); 287 FuncImpl fimpl = new FuncImpl() { 288 @Override 289 public String getPreamble(List<Expr> params) { 290 return preamble; 291 } 292 public String toString(int i, List<Expr> params) { 293 String sfx = useSuffix ? JSWBackend.getSuffix(i) : ""; 294 String s = pattern; 295 s = s.replace("$1", sfx); 296 return s; 297 } 298 }; 299 declareFunction(fimpl, name, type); 300 } 301 } 302 303 /** 304 * Used to declare dot functions of the following form: 305 * float dot(<ftype> x, <ftype> y) 306 */ 307 private static void declareOverloadsDot() { 308 final String name = "dot"; 309 for (final Type type : new Type[] {FLOAT, FLOAT2, FLOAT3, FLOAT4}) { 310 int n = type.getNumFields(); 311 String s; 312 if (n == 1) { 313 s = "(x_tmp * y_tmp)"; 314 } else { 315 s = "(x_tmp_x * y_tmp_x)"; 316 s += "+\n(x_tmp_y * y_tmp_y)"; 317 if (n > 2) s += "+\n(x_tmp_z * y_tmp_z)"; 318 if (n > 3) s += "+\n(x_tmp_w * y_tmp_w)"; 319 } 320 final String str = s; 321 FuncImpl fimpl = new FuncImpl() { 322 public String toString(int i, List<Expr> params) { 323 return str; 324 } 325 }; 326 declareFunction(fimpl, name, type, type); 327 } 328 } 329 330 /** 331 * Used to declare distance functions of the following form: 332 * float distance(<ftype> x, <ftype> y) 333 */ 334 private static void declareOverloadsDistance() { 335 final String name = "distance"; 336 for (final Type type : new Type[] {FLOAT, FLOAT2, FLOAT3, FLOAT4}) { 337 int n = type.getNumFields(); 338 String s; 339 if (n == 1) { 340 s = "(x_tmp - y_tmp) * (x_tmp - y_tmp)"; 341 } else { 342 s = "((x_tmp_x - y_tmp_x) * (x_tmp_x - y_tmp_x))"; 343 s += "+\n((x_tmp_y - y_tmp_y) * (x_tmp_y - y_tmp_y))"; 344 if (n > 2) s += "+\n((x_tmp_z - y_tmp_z) * (x_tmp_z - y_tmp_z))"; 345 if (n > 3) s += "+\n((x_tmp_w - y_tmp_w) * (x_tmp_w - y_tmp_w))"; 346 } 347 final String str = "(float)Math.sqrt(" + s + ")"; 348 FuncImpl fimpl = new FuncImpl() { 349 public String toString(int i, List<Expr> params) { 350 return str; 351 } 352 }; 353 declareFunction(fimpl, name, type, type); 354 } 355 } 356 357 /** 358 * Used to declare min/max functions of the following form: 359 * <ftype> name(<ftype> x, <ftype> y) 360 * <ftype> name(<ftype> x, float y) 361 * 362 * TODO: this is currently geared to simple functions like 363 * min and max; we should make this more general... 364 */ 365 private static void declareOverloadsMinMax(String name, final String pattern) { 366 for (Type type : new Type[] {FLOAT, FLOAT2, FLOAT3, FLOAT4}) { 367 // declare (vectype,vectype) variants 368 final boolean useSuffix = (type != FLOAT); 369 FuncImpl fimpl = new FuncImpl() { 370 public String toString(int i, List<Expr> params) { 371 String sfx = useSuffix ? JSWBackend.getSuffix(i) : ""; 372 String s = pattern; 373 s = s.replace("$1", sfx); 374 s = s.replace("$2", sfx); 375 return s; 376 } 377 }; 378 declareFunction(fimpl, name, type, type); 379 380 if (type == FLOAT) { 381 continue; 382 } 383 384 // declare (vectype,float) variants 385 fimpl = new FuncImpl() { 386 public String toString(int i, List<Expr> params) { 387 String sfx = JSWBackend.getSuffix(i); 388 String s = pattern; 389 s = s.replace("$1", sfx); 390 s = s.replace("$2", ""); 391 return s; 392 } 393 }; 394 declareFunction(fimpl, name, type, FLOAT); 395 } 396 } 397 398 /** 399 * Used to declare clamp functions of the following form: 400 * <ftype> clamp(<ftype> val, <ftype> min, <ftype> max) 401 * <ftype> clamp(<ftype> val, float min, float max) 402 */ 403 private static void declareOverloadsClamp() { 404 final String name = "clamp"; 405 final String pattern = 406 "(val_tmp$1 < min_tmp$2) ? min_tmp$2 : \n" + 407 "(val_tmp$1 > max_tmp$2) ? max_tmp$2 : val_tmp$1"; 408 409 for (Type type : new Type[] {FLOAT, FLOAT2, FLOAT3, FLOAT4}) { 410 // declare (vectype,vectype,vectype) variants 411 final boolean useSuffix = (type != FLOAT); 412 FuncImpl fimpl = new FuncImpl() { 413 public String toString(int i, List<Expr> params) { 414 String sfx = useSuffix ? JSWBackend.getSuffix(i) : ""; 415 String s = pattern; 416 s = s.replace("$1", sfx); 417 s = s.replace("$2", sfx); 418 return s; 419 } 420 }; 421 declareFunction(fimpl, name, type, type, type); 422 423 if (type == FLOAT) { 424 continue; 425 } 426 427 // declare (vectype,float,float) variants 428 fimpl = new FuncImpl() { 429 public String toString(int i, List<Expr> params) { 430 String sfx = JSWBackend.getSuffix(i); 431 String s = pattern; 432 s = s.replace("$1", sfx); 433 s = s.replace("$2", ""); 434 return s; 435 } 436 }; 437 declareFunction(fimpl, name, type, FLOAT, FLOAT); 438 } 439 } 440 441 /** 442 * Used to declare smoothstep functions of the following form: 443 * <ftype> smoothstep(<ftype> min, <ftype> max, <ftype> val) 444 * <ftype> smoothstep(float min, float max, <ftype> val) 445 */ 446 private static void declareOverloadsSmoothstep() { 447 final String name = "smoothstep"; 448 // TODO - the smoothstep function is defined to use Hermite interpolation 449 final String pattern = 450 "(val_tmp$1 < min_tmp$2) ? 0.0f : \n" + 451 "(val_tmp$1 > max_tmp$2) ? 1.0f : \n" + 452 "(val_tmp$1 / (max_tmp$2 - min_tmp$2))"; 453 454 for (Type type : new Type[] {FLOAT, FLOAT2, FLOAT3, FLOAT4}) { 455 // declare (vectype,vectype,vectype) variants 456 final boolean useSuffix = (type != FLOAT); 457 FuncImpl fimpl = new FuncImpl() { 458 public String toString(int i, List<Expr> params) { 459 String sfx = useSuffix ? JSWBackend.getSuffix(i) : ""; 460 String s = pattern; 461 s = s.replace("$1", sfx); 462 s = s.replace("$2", sfx); 463 return s; 464 } 465 }; 466 declareFunction(fimpl, name, type, type, type); 467 468 if (type == FLOAT) { 469 continue; 470 } 471 472 // declare (float,float,vectype) variants 473 fimpl = new FuncImpl() { 474 public String toString(int i, List<Expr> params) { 475 String sfx = JSWBackend.getSuffix(i); 476 String s = pattern; 477 s = s.replace("$1", sfx); 478 s = s.replace("$2", ""); 479 return s; 480 } 481 }; 482 declareFunction(fimpl, name, FLOAT, FLOAT, type); 483 } 484 } 485 486 /** 487 * Used to declare mix functions of the following form: 488 * <ftype> mix(<ftype> x, <ftype> y, <ftype> a) 489 * <ftype> mix(<ftype> x, <ftype> y, float a) 490 */ 491 private static void declareOverloadsMix() { 492 final String name = "mix"; 493 final String pattern = 494 "(x_tmp$1 * (1.0f - a_tmp$2) + y_tmp$1 * a_tmp$2)"; 495 496 for (Type type : new Type[] {FLOAT, FLOAT2, FLOAT3, FLOAT4}) { 497 // declare (vectype,vectype,vectype) variants 498 final boolean useSuffix = (type != FLOAT); 499 FuncImpl fimpl = new FuncImpl() { 500 public String toString(int i, List<Expr> params) { 501 String sfx = useSuffix ? JSWBackend.getSuffix(i) : ""; 502 String s = pattern; 503 s = s.replace("$1", sfx); 504 s = s.replace("$2", sfx); 505 return s; 506 } 507 }; 508 declareFunction(fimpl, name, type, type, type); 509 510 if (type == FLOAT) { 511 continue; 512 } 513 514 // declare (vectype,vectype,float) variants 515 fimpl = new FuncImpl() { 516 public String toString(int i, List<Expr> params) { 517 String sfx = JSWBackend.getSuffix(i); 518 String s = pattern; 519 s = s.replace("$1", sfx); 520 s = s.replace("$2", ""); 521 return s; 522 } 523 }; 524 declareFunction(fimpl, name, type, type, FLOAT); 525 } 526 } 527 }