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