1 /* 2 * Copyright (C) 2008-2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <malloc.h> 18 19 #include "RenderScript.h" 20 #include "rsCppInternal.h" 21 22 using namespace android; 23 using namespace RSC; 24 25 ScriptIntrinsic::ScriptIntrinsic(sp<RS> rs, int id, sp<const Element> e) 26 : Script(nullptr, rs) { 27 mID = createDispatch(rs, RS::dispatch->ScriptIntrinsicCreate(rs->getContext(), id, 28 e != nullptr ? e->getID() : 0)); 29 mElement = e; 30 } 31 32 ScriptIntrinsic::~ScriptIntrinsic() { 33 34 } 35 36 sp<ScriptIntrinsic3DLUT> ScriptIntrinsic3DLUT::create(sp<RS> rs, sp<const Element> e) { 37 if (e->isCompatible(Element::U8_4(rs)) == false) { 38 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Element not supported for intrinsic"); 39 return nullptr; 40 } 41 return new ScriptIntrinsic3DLUT(rs, e); 42 } 43 44 ScriptIntrinsic3DLUT::ScriptIntrinsic3DLUT(sp<RS> rs, sp<const Element> e) 45 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_3DLUT, e) { 46 47 } 48 void ScriptIntrinsic3DLUT::forEach(sp<Allocation> ain, sp<Allocation> aout) { 49 if (ain->getType()->getElement()->isCompatible(mElement) == false || 50 aout->getType()->getElement()->isCompatible(mElement) == false) { 51 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "3DLUT forEach element mismatch"); 52 return; 53 } 54 Script::forEach(0, ain, aout, nullptr, 0); 55 } 56 void ScriptIntrinsic3DLUT::setLUT(sp<Allocation> lut) { 57 sp<const Type> t = lut->getType(); 58 if (!t->getElement()->isCompatible(mElement)) { 59 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "setLUT element does not match"); 60 return; 61 } 62 if (t->getZ() == 0) { 63 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "setLUT Allocation must be 3D"); 64 return; 65 } 66 67 Script::setVar(0, lut); 68 } 69 70 sp<ScriptIntrinsicBlend> ScriptIntrinsicBlend::create(sp<RS> rs, sp<const Element> e) { 71 if (e->isCompatible(Element::U8_4(rs)) == false) { 72 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Element not supported for intrinsic"); 73 return nullptr; 74 } 75 return new ScriptIntrinsicBlend(rs, e); 76 } 77 78 ScriptIntrinsicBlend::ScriptIntrinsicBlend(sp<RS> rs, sp<const Element> e) 79 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_BLEND, e) { 80 } 81 82 void ScriptIntrinsicBlend::forEachClear(sp<Allocation> in, sp<Allocation> out) { 83 if (in->getType()->getElement()->isCompatible(mElement) == false || 84 out->getType()->getElement()->isCompatible(mElement) == false) { 85 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 86 } 87 Script::forEach(0, in, out, nullptr, 0); 88 } 89 90 void ScriptIntrinsicBlend::forEachSrc(sp<Allocation> in, sp<Allocation> out) { 91 if (in->getType()->getElement()->isCompatible(mElement) == false || 92 out->getType()->getElement()->isCompatible(mElement) == false) { 93 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 94 } 95 Script::forEach(1, in, out, nullptr, 0); 96 } 97 98 void ScriptIntrinsicBlend::forEachDst(sp<Allocation> in, sp<Allocation> out) { 99 if (in->getType()->getElement()->isCompatible(mElement) == false || 100 out->getType()->getElement()->isCompatible(mElement) == false) { 101 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 102 } 103 Script::forEach(2, in, out, nullptr, 0); 104 } 105 106 void ScriptIntrinsicBlend::forEachSrcOver(sp<Allocation> in, sp<Allocation> out) { 107 if (in->getType()->getElement()->isCompatible(mElement) == false || 108 out->getType()->getElement()->isCompatible(mElement) == false) { 109 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 110 } 111 Script::forEach(3, in, out, nullptr, 0); 112 } 113 114 void ScriptIntrinsicBlend::forEachDstOver(sp<Allocation> in, sp<Allocation> out) { 115 if (in->getType()->getElement()->isCompatible(mElement) == false || 116 out->getType()->getElement()->isCompatible(mElement) == false) { 117 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 118 } 119 Script::forEach(4, in, out, nullptr, 0); 120 } 121 122 void ScriptIntrinsicBlend::forEachSrcIn(sp<Allocation> in, sp<Allocation> out) { 123 if (in->getType()->getElement()->isCompatible(mElement) == false || 124 out->getType()->getElement()->isCompatible(mElement) == false) { 125 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 126 } 127 Script::forEach(5, in, out, nullptr, 0); 128 } 129 130 void ScriptIntrinsicBlend::forEachDstIn(sp<Allocation> in, sp<Allocation> out) { 131 if (in->getType()->getElement()->isCompatible(mElement) == false || 132 out->getType()->getElement()->isCompatible(mElement) == false) { 133 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 134 } 135 Script::forEach(6, in, out, nullptr, 0); 136 } 137 138 void ScriptIntrinsicBlend::forEachSrcOut(sp<Allocation> in, sp<Allocation> out) { 139 if (in->getType()->getElement()->isCompatible(mElement) == false || 140 out->getType()->getElement()->isCompatible(mElement) == false) { 141 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 142 } 143 Script::forEach(7, in, out, nullptr, 0); 144 } 145 146 void ScriptIntrinsicBlend::forEachDstOut(sp<Allocation> in, sp<Allocation> out) { 147 if (in->getType()->getElement()->isCompatible(mElement) == false || 148 out->getType()->getElement()->isCompatible(mElement) == false) { 149 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 150 } 151 Script::forEach(8, in, out, nullptr, 0); 152 } 153 154 void ScriptIntrinsicBlend::forEachSrcAtop(sp<Allocation> in, sp<Allocation> out) { 155 if (in->getType()->getElement()->isCompatible(mElement) == false || 156 out->getType()->getElement()->isCompatible(mElement) == false) { 157 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 158 } 159 Script::forEach(9, in, out, nullptr, 0); 160 } 161 162 void ScriptIntrinsicBlend::forEachDstAtop(sp<Allocation> in, sp<Allocation> out) { 163 if (in->getType()->getElement()->isCompatible(mElement) == false || 164 out->getType()->getElement()->isCompatible(mElement) == false) { 165 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 166 } 167 Script::forEach(10, in, out, nullptr, 0); 168 } 169 170 void ScriptIntrinsicBlend::forEachXor(sp<Allocation> in, sp<Allocation> out) { 171 if (in->getType()->getElement()->isCompatible(mElement) == false || 172 out->getType()->getElement()->isCompatible(mElement) == false) { 173 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 174 } 175 Script::forEach(11, in, out, nullptr, 0); 176 } 177 178 void ScriptIntrinsicBlend::forEachMultiply(sp<Allocation> in, sp<Allocation> out) { 179 if (in->getType()->getElement()->isCompatible(mElement) == false || 180 out->getType()->getElement()->isCompatible(mElement) == false) { 181 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 182 } 183 Script::forEach(14, in, out, nullptr, 0); 184 } 185 186 void ScriptIntrinsicBlend::forEachAdd(sp<Allocation> in, sp<Allocation> out) { 187 if (in->getType()->getElement()->isCompatible(mElement) == false || 188 out->getType()->getElement()->isCompatible(mElement) == false) { 189 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 190 } 191 Script::forEach(34, in, out, nullptr, 0); 192 } 193 194 void ScriptIntrinsicBlend::forEachSubtract(sp<Allocation> in, sp<Allocation> out) { 195 if (in->getType()->getElement()->isCompatible(mElement) == false || 196 out->getType()->getElement()->isCompatible(mElement) == false) { 197 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); 198 } 199 Script::forEach(35, in, out, nullptr, 0); 200 } 201 202 203 204 205 sp<ScriptIntrinsicBlur> ScriptIntrinsicBlur::create(sp<RS> rs, sp<const Element> e) { 206 if ((e->isCompatible(Element::U8_4(rs)) == false) && 207 (e->isCompatible(Element::U8(rs)) == false)) { 208 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blur"); 209 return nullptr; 210 } 211 return new ScriptIntrinsicBlur(rs, e); 212 } 213 214 ScriptIntrinsicBlur::ScriptIntrinsicBlur(sp<RS> rs, sp<const Element> e) 215 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_BLUR, e) { 216 217 } 218 219 void ScriptIntrinsicBlur::setInput(sp<Allocation> in) { 220 if (in->getType()->getElement()->isCompatible(mElement) == false) { 221 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blur input"); 222 return; 223 } 224 Script::setVar(1, in); 225 } 226 227 void ScriptIntrinsicBlur::forEach(sp<Allocation> out) { 228 if (out->getType()->getElement()->isCompatible(mElement) == false) { 229 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blur output"); 230 return; 231 } 232 Script::forEach(0, nullptr, out, nullptr, 0); 233 } 234 235 void ScriptIntrinsicBlur::setRadius(float radius) { 236 if (radius > 0.f && radius <= 25.f) { 237 Script::setVar(0, &radius, sizeof(float)); 238 } else { 239 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Blur radius out of 0-25 pixel bound"); 240 } 241 } 242 243 244 245 sp<ScriptIntrinsicColorMatrix> ScriptIntrinsicColorMatrix::create(sp<RS> rs) { 246 return new ScriptIntrinsicColorMatrix(rs, Element::RGBA_8888(rs)); 247 } 248 249 ScriptIntrinsicColorMatrix::ScriptIntrinsicColorMatrix(sp<RS> rs, sp<const Element> e) 250 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_COLOR_MATRIX, e) { 251 float add[4] = {0.f, 0.f, 0.f, 0.f}; 252 setAdd(add); 253 254 } 255 256 void ScriptIntrinsicColorMatrix::forEach(sp<Allocation> in, sp<Allocation> out) { 257 if (!(in->getType()->getElement()->isCompatible(Element::U8(mRS))) && 258 !(in->getType()->getElement()->isCompatible(Element::U8_2(mRS))) && 259 !(in->getType()->getElement()->isCompatible(Element::U8_3(mRS))) && 260 !(in->getType()->getElement()->isCompatible(Element::U8_4(mRS))) && 261 !(in->getType()->getElement()->isCompatible(Element::F32(mRS))) && 262 !(in->getType()->getElement()->isCompatible(Element::F32_2(mRS))) && 263 !(in->getType()->getElement()->isCompatible(Element::F32_3(mRS))) && 264 !(in->getType()->getElement()->isCompatible(Element::F32_4(mRS)))) { 265 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for ColorMatrix"); 266 return; 267 } 268 269 if (!(out->getType()->getElement()->isCompatible(Element::U8(mRS))) && 270 !(out->getType()->getElement()->isCompatible(Element::U8_2(mRS))) && 271 !(out->getType()->getElement()->isCompatible(Element::U8_3(mRS))) && 272 !(out->getType()->getElement()->isCompatible(Element::U8_4(mRS))) && 273 !(out->getType()->getElement()->isCompatible(Element::F32(mRS))) && 274 !(out->getType()->getElement()->isCompatible(Element::F32_2(mRS))) && 275 !(out->getType()->getElement()->isCompatible(Element::F32_3(mRS))) && 276 !(out->getType()->getElement()->isCompatible(Element::F32_4(mRS)))) { 277 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for ColorMatrix"); 278 return; 279 } 280 281 Script::forEach(0, in, out, nullptr, 0); 282 } 283 284 void ScriptIntrinsicColorMatrix::setAdd(float* add) { 285 Script::setVar(1, (void*)add, sizeof(float) * 4); 286 } 287 288 void ScriptIntrinsicColorMatrix::setColorMatrix3(float* m) { 289 float temp[16]; 290 temp[0] = m[0]; 291 temp[1] = m[1]; 292 temp[2] = m[2]; 293 temp[3] = 0.f; 294 295 temp[4] = m[3]; 296 temp[5] = m[4]; 297 temp[6] = m[5]; 298 temp[7] = 0.f; 299 300 temp[8] = m[6]; 301 temp[9] = m[7]; 302 temp[10] = m[8]; 303 temp[11] = 0.f; 304 305 temp[12] = 0.f; 306 temp[13] = 0.f; 307 temp[14] = 0.f; 308 temp[15] = 1.f; 309 310 setColorMatrix4(temp); 311 } 312 313 314 void ScriptIntrinsicColorMatrix::setColorMatrix4(float* m) { 315 Script::setVar(0, (void*)m, sizeof(float) * 16); 316 } 317 318 319 void ScriptIntrinsicColorMatrix::setGreyscale() { 320 float matrix[] = {0.299f, 0.299f, 0.299f,0.587f,0.587f,0.587f,0.114f,0.114f, 0.114f}; 321 setColorMatrix3(matrix); 322 } 323 324 325 void ScriptIntrinsicColorMatrix::setRGBtoYUV() { 326 float matrix[] = { 0.299f, -0.14713f, 0.615f, 0.587f, -0.28886f, -0.51499f, 0.114f, 0.436f, -0.10001f}; 327 setColorMatrix3(matrix); 328 } 329 330 331 void ScriptIntrinsicColorMatrix::setYUVtoRGB() { 332 float matrix[] = {1.f, 1.f, 1.f, 0.f, -0.39465f, 2.03211f, 1.13983f, -0.5806f, 0.f}; 333 setColorMatrix3(matrix); 334 } 335 336 337 338 sp<ScriptIntrinsicConvolve3x3> ScriptIntrinsicConvolve3x3::create(sp<RS> rs, sp<const Element> e) { 339 if (!(e->isCompatible(Element::U8(rs))) && 340 !(e->isCompatible(Element::U8_2(rs))) && 341 !(e->isCompatible(Element::U8_3(rs))) && 342 !(e->isCompatible(Element::U8_4(rs))) && 343 !(e->isCompatible(Element::F32(rs))) && 344 !(e->isCompatible(Element::F32_2(rs))) && 345 !(e->isCompatible(Element::F32_3(rs))) && 346 !(e->isCompatible(Element::F32_4(rs)))) { 347 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Convolve3x3"); 348 return nullptr; 349 } 350 351 return new ScriptIntrinsicConvolve3x3(rs, e); 352 } 353 354 ScriptIntrinsicConvolve3x3::ScriptIntrinsicConvolve3x3(sp<RS> rs, sp<const Element> e) 355 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_3x3, e) { 356 357 } 358 359 void ScriptIntrinsicConvolve3x3::setInput(sp<Allocation> in) { 360 if (!(in->getType()->getElement()->isCompatible(mElement))) { 361 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve3x3"); 362 return; 363 } 364 Script::setVar(1, in); 365 } 366 367 void ScriptIntrinsicConvolve3x3::forEach(sp<Allocation> out) { 368 if (!(out->getType()->getElement()->isCompatible(mElement))) { 369 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve3x3"); 370 return; 371 } 372 Script::forEach(0, nullptr, out, nullptr, 0); 373 } 374 375 void ScriptIntrinsicConvolve3x3::setCoefficients(float* v) { 376 Script::setVar(0, (void*)v, sizeof(float) * 9); 377 } 378 379 sp<ScriptIntrinsicConvolve5x5> ScriptIntrinsicConvolve5x5::create(sp<RS> rs, sp<const Element> e) { 380 if (!(e->isCompatible(Element::U8(rs))) && 381 !(e->isCompatible(Element::U8_2(rs))) && 382 !(e->isCompatible(Element::U8_3(rs))) && 383 !(e->isCompatible(Element::U8_4(rs))) && 384 !(e->isCompatible(Element::F32(rs))) && 385 !(e->isCompatible(Element::F32_2(rs))) && 386 !(e->isCompatible(Element::F32_3(rs))) && 387 !(e->isCompatible(Element::F32_4(rs)))) { 388 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Convolve5x5"); 389 return nullptr; 390 } 391 392 return new ScriptIntrinsicConvolve5x5(rs, e); 393 } 394 395 ScriptIntrinsicConvolve5x5::ScriptIntrinsicConvolve5x5(sp<RS> rs, sp<const Element> e) 396 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_5x5, e) { 397 398 } 399 400 void ScriptIntrinsicConvolve5x5::setInput(sp<Allocation> in) { 401 if (!(in->getType()->getElement()->isCompatible(mElement))) { 402 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve5x5 input"); 403 return; 404 } 405 Script::setVar(1, in); 406 } 407 408 void ScriptIntrinsicConvolve5x5::forEach(sp<Allocation> out) { 409 if (!(out->getType()->getElement()->isCompatible(mElement))) { 410 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve5x5 output"); 411 return; 412 } 413 414 Script::forEach(0, nullptr, out, nullptr, 0); 415 } 416 417 void ScriptIntrinsicConvolve5x5::setCoefficients(float* v) { 418 Script::setVar(0, (void*)v, sizeof(float) * 25); 419 } 420 421 sp<ScriptIntrinsicHistogram> ScriptIntrinsicHistogram::create(sp<RS> rs, sp<const Element> e) { 422 return new ScriptIntrinsicHistogram(rs, e); 423 } 424 425 ScriptIntrinsicHistogram::ScriptIntrinsicHistogram(sp<RS> rs, sp<const Element> e) 426 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_HISTOGRAM, e) { 427 428 } 429 430 void ScriptIntrinsicHistogram::setOutput(sp<Allocation> out) { 431 if (!(out->getType()->getElement()->isCompatible(Element::U32(mRS))) && 432 !(out->getType()->getElement()->isCompatible(Element::U32_2(mRS))) && 433 !(out->getType()->getElement()->isCompatible(Element::U32_3(mRS))) && 434 !(out->getType()->getElement()->isCompatible(Element::U32_4(mRS))) && 435 !(out->getType()->getElement()->isCompatible(Element::I32(mRS))) && 436 !(out->getType()->getElement()->isCompatible(Element::I32_2(mRS))) && 437 !(out->getType()->getElement()->isCompatible(Element::I32_3(mRS))) && 438 !(out->getType()->getElement()->isCompatible(Element::I32_4(mRS)))) { 439 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Histogram output"); 440 return; 441 } 442 443 if (out->getType()->getX() != 256 || 444 out->getType()->getY() != 0 || 445 out->getType()->hasMipmaps()) { 446 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid Allocation type for Histogram output"); 447 return; 448 } 449 mOut = out; 450 Script::setVar(1, out); 451 } 452 453 void ScriptIntrinsicHistogram::setDotCoefficients(float r, float g, float b, float a) { 454 if ((r < 0.f) || (g < 0.f) || (b < 0.f) || (a < 0.f)) { 455 return; 456 } 457 if ((r + g + b + a) > 1.f) { 458 return; 459 } 460 461 FieldPacker fp(16); 462 fp.add(r); 463 fp.add(g); 464 fp.add(b); 465 fp.add(a); 466 Script::setVar(0, fp.getData(), fp.getLength()); 467 468 } 469 470 void ScriptIntrinsicHistogram::forEach(sp<Allocation> ain) { 471 if (ain->getType()->getElement()->getVectorSize() < 472 mOut->getType()->getElement()->getVectorSize()) { 473 mRS->throwError(RS_ERROR_INVALID_PARAMETER, 474 "Input vector size must be >= output vector size"); 475 return; 476 } 477 478 if (!(ain->getType()->getElement()->isCompatible(Element::U8(mRS))) && 479 !(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) { 480 mRS->throwError(RS_ERROR_INVALID_ELEMENT, 481 "Input allocation to Histogram must be U8 or U8_4"); 482 return; 483 } 484 485 Script::forEach(0, ain, nullptr, nullptr, 0); 486 } 487 488 489 void ScriptIntrinsicHistogram::forEach_dot(sp<Allocation> ain) { 490 if (mOut->getType()->getElement()->getVectorSize() != 1) { 491 mRS->throwError(RS_ERROR_INVALID_PARAMETER, 492 "Output Histogram allocation must have vector size of 1 " \ 493 "when used with forEach_dot"); 494 return; 495 } 496 if (!(ain->getType()->getElement()->isCompatible(Element::U8(mRS))) && 497 !(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) { 498 mRS->throwError(RS_ERROR_INVALID_ELEMENT, 499 "Input allocation to Histogram must be U8 or U8_4"); 500 return; 501 } 502 503 Script::forEach(1, ain, nullptr, nullptr, 0); 504 } 505 506 sp<ScriptIntrinsicLUT> ScriptIntrinsicLUT::create(sp<RS> rs, sp<const Element> e) { 507 if (!(e->isCompatible(Element::U8_4(rs)))) { 508 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for LUT"); 509 return nullptr; 510 } 511 return new ScriptIntrinsicLUT(rs, e); 512 } 513 514 ScriptIntrinsicLUT::ScriptIntrinsicLUT(sp<RS> rs, sp<const Element> e) 515 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_LUT, e), mDirty(true) { 516 LUT = Allocation::createSized(rs, Element::U8(rs), 1024); 517 for (int i = 0; i < 256; i++) { 518 mCache[i] = i; 519 mCache[i+256] = i; 520 mCache[i+512] = i; 521 mCache[i+768] = i; 522 } 523 setVar(0, LUT); 524 } 525 526 void ScriptIntrinsicLUT::forEach(sp<Allocation> ain, sp<Allocation> aout) { 527 if (mDirty) { 528 LUT->copy1DFrom((void*)mCache); 529 mDirty = false; 530 } 531 if (!(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS))) || 532 !(aout->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) { 533 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for LUT"); 534 return; 535 } 536 Script::forEach(0, ain, aout, nullptr, 0); 537 538 } 539 540 void ScriptIntrinsicLUT::setTable(unsigned int offset, unsigned char base, unsigned int length, unsigned char* lutValues) { 541 if ((base + length) > 256 || length == 0) { 542 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "LUT out of range"); 543 return; 544 } 545 mDirty = true; 546 for (unsigned int i = 0; i < length; i++) { 547 mCache[offset + base + i] = lutValues[i]; 548 } 549 } 550 551 void ScriptIntrinsicLUT::setRed(unsigned char base, unsigned int length, unsigned char* lutValues) { 552 setTable(0, base, length, lutValues); 553 } 554 555 void ScriptIntrinsicLUT::setGreen(unsigned char base, unsigned int length, unsigned char* lutValues) { 556 setTable(256, base, length, lutValues); 557 } 558 559 void ScriptIntrinsicLUT::setBlue(unsigned char base, unsigned int length, unsigned char* lutValues) { 560 setTable(512, base, length, lutValues); 561 } 562 563 void ScriptIntrinsicLUT::setAlpha(unsigned char base, unsigned int length, unsigned char* lutValues) { 564 setTable(768, base, length, lutValues); 565 } 566 567 ScriptIntrinsicLUT::~ScriptIntrinsicLUT() { 568 569 } 570 571 sp<ScriptIntrinsicResize> ScriptIntrinsicResize::create(sp<RS> rs) { 572 return new ScriptIntrinsicResize(rs, nullptr); 573 } 574 575 ScriptIntrinsicResize::ScriptIntrinsicResize(sp<RS> rs, sp<const Element> e) 576 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_RESIZE, e) { 577 578 } 579 void ScriptIntrinsicResize::forEach_bicubic(sp<Allocation> aout) { 580 if (aout == mInput) { 581 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Resize Input and Ouput cannot be the same"); 582 } 583 584 if (!(mInput->getType()->getElement()->isCompatible(aout->getType()->getElement()))) { 585 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Resize forEach element mismatch"); 586 return; 587 } 588 Script::forEach(0, nullptr, aout, nullptr, 0); 589 } 590 void ScriptIntrinsicResize::setInput(sp<Allocation> ain) { 591 if (!(ain->getType()->getElement()->isCompatible(Element::U8(mRS))) && 592 !(ain->getType()->getElement()->isCompatible(Element::U8_2(mRS))) && 593 !(ain->getType()->getElement()->isCompatible(Element::U8_3(mRS))) && 594 !(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS))) && 595 !(ain->getType()->getElement()->isCompatible(Element::F32(mRS))) && 596 !(ain->getType()->getElement()->isCompatible(Element::F32_2(mRS))) && 597 !(ain->getType()->getElement()->isCompatible(Element::F32_3(mRS))) && 598 !(ain->getType()->getElement()->isCompatible(Element::F32_4(mRS)))) { 599 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Resize Input"); 600 return; 601 } 602 603 mInput = ain; 604 Script::setVar(0, ain); 605 } 606 607 608 sp<ScriptIntrinsicYuvToRGB> ScriptIntrinsicYuvToRGB::create(sp<RS> rs, sp<const Element> e) { 609 if (!(e->isCompatible(Element::U8_4(rs)))) { 610 rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for YuvToRGB"); 611 return nullptr; 612 } 613 return new ScriptIntrinsicYuvToRGB(rs, e); 614 } 615 616 ScriptIntrinsicYuvToRGB::ScriptIntrinsicYuvToRGB(sp<RS> rs, sp<const Element> e) 617 : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_YUV_TO_RGB, e) { 618 619 } 620 621 void ScriptIntrinsicYuvToRGB::setInput(sp<Allocation> in) { 622 if (!(in->getType()->getElement()->isCompatible(Element::YUV(mRS)))) { 623 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for input in YuvToRGB"); 624 return; 625 } 626 Script::setVar(0, in); 627 } 628 629 void ScriptIntrinsicYuvToRGB::forEach(sp<Allocation> out) { 630 if (!(out->getType()->getElement()->isCompatible(mElement))) { 631 mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for output in YuvToRGB"); 632 return; 633 } 634 635 Script::forEach(0, nullptr, out, nullptr, 0); 636 }