diff options
Diffstat (limited to 'cpp')
| -rw-r--r-- | cpp/Allocation.cpp | 92 | ||||
| -rw-r--r-- | cpp/Element.cpp | 2 | ||||
| -rw-r--r-- | cpp/RenderScript.cpp | 4 | ||||
| -rw-r--r-- | cpp/Script.cpp | 11 | ||||
| -rw-r--r-- | cpp/ScriptIntrinsics.cpp | 263 | ||||
| -rw-r--r-- | cpp/rsCppInternal.h | 25 | ||||
| -rw-r--r-- | cpp/rsCppStructs.h | 13 |
7 files changed, 361 insertions, 49 deletions
diff --git a/cpp/Allocation.cpp b/cpp/Allocation.cpp index f05b005d..9727a6e4 100644 --- a/cpp/Allocation.cpp +++ b/cpp/Allocation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Android Open Source Project + * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ #include "RenderScript.h" +#include "rsCppInternal.h" using namespace android; using namespace RSC; @@ -139,71 +140,77 @@ void Allocation::syncAll(RsAllocationUsageType srcLocation) { case RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS: case RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE: case RS_ALLOCATION_USAGE_GRAPHICS_VERTEX: + case RS_ALLOCATION_USAGE_SHARED: break; default: - ALOGE("Source must be exactly one usage type."); + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Source must be exactly one usage type."); + return; } - RS::dispatch->AllocationSyncAll(mRS->getContext(), getIDSafe(), srcLocation); + tryDispatch(mRS, RS::dispatch->AllocationSyncAll(mRS->getContext(), getIDSafe(), srcLocation)); } void Allocation::ioSendOutput() { #ifndef RS_COMPATIBILITY_LIB if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) { - ALOGE("Can only send buffer if IO_OUTPUT usage specified."); + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only send buffer if IO_OUTPUT usage specified."); + return; } - RS::dispatch->AllocationIoSend(mRS->getContext(), getID()); + tryDispatch(mRS, RS::dispatch->AllocationIoSend(mRS->getContext(), getID())); #endif } void Allocation::ioGetInput() { #ifndef RS_COMPATIBILITY_LIB if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) { - ALOGE("Can only send buffer if IO_OUTPUT usage specified."); + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only send buffer if IO_OUTPUT usage specified."); + return; } - RS::dispatch->AllocationIoReceive(mRS->getContext(), getID()); + tryDispatch(mRS, RS::dispatch->AllocationIoReceive(mRS->getContext(), getID())); #endif } void Allocation::generateMipmaps() { - RS::dispatch->AllocationGenerateMipmaps(mRS->getContext(), getID()); + tryDispatch(mRS, RS::dispatch->AllocationGenerateMipmaps(mRS->getContext(), getID())); } void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const void *data) { if(count < 1) { - ALOGE("Count must be >= 1."); + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1."); return; } if((off + count) > mCurrentCount) { ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off); + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified"); return; } - RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD, count, data, - count * mType->getElement()->getSizeBytes()); + tryDispatch(mRS, RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD, + count, data, count * mType->getElement()->getSizeBytes())); } void Allocation::copy1DRangeTo(uint32_t off, size_t count, void *data) { if(count < 1) { - ALOGE("Count must be >= 1."); + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1."); return; } if((off + count) > mCurrentCount) { ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off); + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified"); return; } - RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD, count, data, - count * mType->getElement()->getSizeBytes()); + tryDispatch(mRS, RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD, + count, data, count * mType->getElement()->getSizeBytes())); } void Allocation::copy1DRangeFrom(uint32_t off, size_t count, sp<const Allocation> data, uint32_t dataOff) { - RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), off, 0, - mSelectedLOD, mSelectedFace, - count, 1, data->getIDSafe(), dataOff, 0, - data->mSelectedLOD, data->mSelectedFace); + tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), off, 0, + mSelectedLOD, mSelectedFace, + count, 1, data->getIDSafe(), dataOff, 0, + data->mSelectedLOD, data->mSelectedFace)); } void Allocation::copy1DFrom(const void* data) { @@ -220,7 +227,7 @@ void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint3 } else { if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) { - ALOGE("Updated region larger than allocation."); + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation."); } } } @@ -228,31 +235,36 @@ void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint3 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data) { validate2DRange(xoff, yoff, w, h); - RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, - w, h, data, w * h * mType->getElement()->getSizeBytes(), w * mType->getElement()->getSizeBytes()); + tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, + yoff, mSelectedLOD, mSelectedFace, + w, h, data, w * h * mType->getElement()->getSizeBytes(), + w * mType->getElement()->getSizeBytes())); } void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff) { validate2DRange(xoff, yoff, w, h); - RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff, - mSelectedLOD, mSelectedFace, - w, h, data->getIDSafe(), dataXoff, dataYoff, - data->mSelectedLOD, data->mSelectedFace); + tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff, + mSelectedLOD, mSelectedFace, + w, h, data->getIDSafe(), dataXoff, dataYoff, + data->mSelectedLOD, data->mSelectedFace)); } void Allocation::copy2DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, void* data) { validate2DRange(xoff, yoff, w, h); - RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, - w, h, data, w * h * mType->getElement()->getSizeBytes(), w * mType->getElement()->getSizeBytes()); + tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, + mSelectedLOD, mSelectedFace, w, h, data, + w * h * mType->getElement()->getSizeBytes(), + w * mType->getElement()->getSizeBytes())); } void Allocation::copy2DStridedFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data, size_t stride) { validate2DRange(xoff, yoff, w, h); - RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, - w, h, data, w * h * mType->getElement()->getSizeBytes(), stride); + tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, + mSelectedLOD, mSelectedFace, w, h, data, + w * h * mType->getElement()->getSizeBytes(), stride)); } void Allocation::copy2DStridedFrom(const void* data, size_t stride) { @@ -262,8 +274,9 @@ void Allocation::copy2DStridedFrom(const void* data, size_t stride) { void Allocation::copy2DStridedTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, void *data, size_t stride) { validate2DRange(xoff, yoff, w, h); - RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, - w, h, data, w * h * mType->getElement()->getSizeBytes(), stride); + tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, + mSelectedLOD, mSelectedFace, w, h, data, + w * h * mType->getElement()->getSizeBytes(), stride)); } void Allocation::copy2DStridedTo(void* data, size_t stride) { @@ -272,9 +285,12 @@ void Allocation::copy2DStridedTo(void* data, size_t stride) { sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, RsAllocationMipmapControl mips, uint32_t usage) { - void *id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, 0); + void *id = 0; + if (rs->getError() == RS_SUCCESS) { + id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, 0); + } if (id == 0) { - ALOGE("Allocation creation failed."); + rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed"); return NULL; } return new Allocation(id, rs, type, usage); @@ -283,10 +299,14 @@ sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, RsAllocationMipmapControl mips, uint32_t usage, void *pointer) { - void *id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, - (uintptr_t)pointer); + void *id = 0; + if (rs->getError() == RS_SUCCESS) { + id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, + (uintptr_t)pointer); + } if (id == 0) { - ALOGE("Allocation creation failed."); + rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed"); + return NULL; } return new Allocation(id, rs, type, usage); } diff --git a/cpp/Element.cpp b/cpp/Element.cpp index df7b5a0f..d6855950 100644 --- a/cpp/Element.cpp +++ b/cpp/Element.cpp @@ -331,7 +331,7 @@ android::RSC::sp<const Element> Element::createPixel(android::RSC::sp<RS> rs, Rs return new Element(id, rs, dt, dk, true, size); } -bool Element::isCompatible(android::RSC::sp<const Element>e) { +bool Element::isCompatible(android::RSC::sp<const Element>e) const { // Try strict BaseObj equality to start with. if (this == e.get()) { return true; diff --git a/cpp/RenderScript.cpp b/cpp/RenderScript.cpp index 561b58f9..6ab22404 100644 --- a/cpp/RenderScript.cpp +++ b/cpp/RenderScript.cpp @@ -506,6 +506,10 @@ void RS::throwError(RSError error, const char *errMsg) { } } +RSError RS::getError() { + return mCurrentError; +} + void * RS::threadProc(void *vrsc) { RS *rs = static_cast<RS *>(vrsc); diff --git a/cpp/Script.cpp b/cpp/Script.cpp index 29fe12d0..8e1af549 100644 --- a/cpp/Script.cpp +++ b/cpp/Script.cpp @@ -17,12 +17,13 @@ #include <malloc.h> #include "RenderScript.h" +#include "rsCppInternal.h" using namespace android; using namespace RSC; void Script::invoke(uint32_t slot, const void *v, size_t len) const { - RS::dispatch->ScriptInvokeV(mRS->getContext(), getID(), slot, v, len); + tryDispatch(mRS, RS::dispatch->ScriptInvokeV(mRS->getContext(), getID(), slot, v, len)); } void Script::forEach(uint32_t slot, sp<const Allocation> ain, sp<const Allocation> aout, @@ -32,7 +33,7 @@ void Script::forEach(uint32_t slot, sp<const Allocation> ain, sp<const Allocatio } void *in_id = BaseObj::getObjID(ain); void *out_id = BaseObj::getObjID(aout); - RS::dispatch->ScriptForEach(mRS->getContext(), getID(), slot, in_id, out_id, usr, usrLen, NULL, 0); + tryDispatch(mRS, RS::dispatch->ScriptForEach(mRS->getContext(), getID(), slot, in_id, out_id, usr, usrLen, NULL, 0)); } @@ -41,16 +42,16 @@ Script::Script(void *id, sp<RS> rs) : BaseObj(id, rs) { void Script::bindAllocation(sp<Allocation> va, uint32_t slot) const { - RS::dispatch->ScriptBindAllocation(mRS->getContext(), getID(), BaseObj::getObjID(va), slot); + tryDispatch(mRS, RS::dispatch->ScriptBindAllocation(mRS->getContext(), getID(), BaseObj::getObjID(va), slot)); } void Script::setVar(uint32_t index, sp<const BaseObj> o) const { - RS::dispatch->ScriptSetVarObj(mRS->getContext(), getID(), index, (o == NULL) ? 0 : o->getID()); + tryDispatch(mRS, RS::dispatch->ScriptSetVarObj(mRS->getContext(), getID(), index, (o == NULL) ? 0 : o->getID())); } void Script::setVar(uint32_t index, const void *v, size_t len) const { - RS::dispatch->ScriptSetVarV(mRS->getContext(), getID(), index, v, len); + tryDispatch(mRS, RS::dispatch->ScriptSetVarV(mRS->getContext(), getID(), index, v, len)); } void Script::FieldBase::init(sp<RS> rs, uint32_t dimx, uint32_t usages) { diff --git a/cpp/ScriptIntrinsics.cpp b/cpp/ScriptIntrinsics.cpp index ab24952a..e4bf9076 100644 --- a/cpp/ScriptIntrinsics.cpp +++ b/cpp/ScriptIntrinsics.cpp @@ -24,6 +24,7 @@ using namespace RSC; ScriptIntrinsic::ScriptIntrinsic(sp<RS> rs, int id, sp<const Element> e) : Script(NULL, rs) { mID = RS::dispatch->ScriptIntrinsicCreate(rs->getContext(), id, e->getID()); + mElement = e; } ScriptIntrinsic::~ScriptIntrinsic() { @@ -31,6 +32,10 @@ ScriptIntrinsic::~ScriptIntrinsic() { } sp<ScriptIntrinsic3DLUT> ScriptIntrinsic3DLUT::create(sp<RS> rs, sp<const Element> e) { + if (e->isCompatible(Element::U8_4(rs)) == false) { + rs->throwError(RS_ERROR_INVALID_ELEMENT, "Element not supported for intrinsic"); + return NULL; + } return new ScriptIntrinsic3DLUT(rs, e); } @@ -39,13 +44,32 @@ ScriptIntrinsic3DLUT::ScriptIntrinsic3DLUT(sp<RS> rs, sp<const Element> e) } void ScriptIntrinsic3DLUT::forEach(sp<Allocation> ain, sp<Allocation> aout) { + if (ain->getType()->getElement()->isCompatible(mElement) == false || + aout->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "3DLUT forEach element mismatch"); + return; + } Script::forEach(0, ain, aout, NULL, 0); } void ScriptIntrinsic3DLUT::setLUT(sp<Allocation> lut) { + sp<const Type> t = lut->getType(); + if (!t->getElement()->isCompatible(mElement)) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "setLUT element does not match"); + return; + } + if (t->getZ() == 0) { + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "setLUT Allocation must be 3D"); + return; + } + Script::setVar(0, lut); } sp<ScriptIntrinsicBlend> ScriptIntrinsicBlend::create(sp<RS> rs, sp<const Element> e) { + if (e->isCompatible(Element::U8_4(rs)) == false) { + rs->throwError(RS_ERROR_INVALID_ELEMENT, "Element not supported for intrinsic"); + return NULL; + } return new ScriptIntrinsicBlend(rs, e); } @@ -54,64 +78,124 @@ ScriptIntrinsicBlend::ScriptIntrinsicBlend(sp<RS> rs, sp<const Element> e) } void ScriptIntrinsicBlend::blendClear(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(0, in, out, NULL, 0); } void ScriptIntrinsicBlend::blendSrc(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(1, in, out, NULL, 0); } void ScriptIntrinsicBlend::blendDst(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(2, in, out, NULL, 0); } void ScriptIntrinsicBlend::blendSrcOver(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(3, in, out, NULL, 0); } void ScriptIntrinsicBlend::blendDstOver(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(4, in, out, NULL, 0); } void ScriptIntrinsicBlend::blendSrcIn(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(5, in, out, NULL, 0); } void ScriptIntrinsicBlend::blendDstIn(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(6, in, out, NULL, 0); } void ScriptIntrinsicBlend::blendSrcOut(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(7, in, out, NULL, 0); } void ScriptIntrinsicBlend::blendDstOut(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(8, in, out, NULL, 0); } void ScriptIntrinsicBlend::blendSrcAtop(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(9, in, out, NULL, 0); } void ScriptIntrinsicBlend::blendDstAtop(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(10, in, out, NULL, 0); } void ScriptIntrinsicBlend::blendXor(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(11, in, out, NULL, 0); } // Numbering jumps here void ScriptIntrinsicBlend::blendMultiply(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(14, in, out, NULL, 0); } // Numbering jumps here void ScriptIntrinsicBlend::blendAdd(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(34, in, out, NULL, 0); } void ScriptIntrinsicBlend::blendSubtract(sp<Allocation> in, sp<Allocation> out) { + if (in->getType()->getElement()->isCompatible(mElement) == false || + out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blend"); + } Script::forEach(35, in, out, NULL, 0); } @@ -119,6 +203,11 @@ void ScriptIntrinsicBlend::blendSubtract(sp<Allocation> in, sp<Allocation> out) sp<ScriptIntrinsicBlur> ScriptIntrinsicBlur::create(sp<RS> rs, sp<const Element> e) { + if ((e->isCompatible(Element::U8_4(rs)) == false) && + (e->isCompatible(Element::U8(rs)) == false)) { + rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blur"); + return NULL; + } return new ScriptIntrinsicBlur(rs, e); } @@ -128,15 +217,27 @@ ScriptIntrinsicBlur::ScriptIntrinsicBlur(sp<RS> rs, sp<const Element> e) } void ScriptIntrinsicBlur::setInput(sp<Allocation> in) { + if (in->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blur input"); + return; + } Script::setVar(1, in); } void ScriptIntrinsicBlur::forEach(sp<Allocation> out) { + if (out->getType()->getElement()->isCompatible(mElement) == false) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element in blur output"); + return; + } Script::forEach(0, NULL, out, NULL, 0); } void ScriptIntrinsicBlur::setRadius(float radius) { - Script::setVar(0, &radius, sizeof(float)); + if (radius > 0.f && radius <= 25.f) { + Script::setVar(0, &radius, sizeof(float)); + } else { + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Blur radius out of 0-25 pixel bound"); + } } @@ -151,9 +252,36 @@ ScriptIntrinsicColorMatrix::ScriptIntrinsicColorMatrix(sp<RS> rs, sp<const Eleme } void ScriptIntrinsicColorMatrix::forEach(sp<Allocation> in, sp<Allocation> out) { + if (!(in->getType()->getElement()->isCompatible(Element::U8(mRS))) && + !(in->getType()->getElement()->isCompatible(Element::U8_2(mRS))) && + !(in->getType()->getElement()->isCompatible(Element::U8_3(mRS))) && + !(in->getType()->getElement()->isCompatible(Element::U8_4(mRS))) && + !(in->getType()->getElement()->isCompatible(Element::F32(mRS))) && + !(in->getType()->getElement()->isCompatible(Element::F32_2(mRS))) && + !(in->getType()->getElement()->isCompatible(Element::F32_3(mRS))) && + !(in->getType()->getElement()->isCompatible(Element::F32_4(mRS)))) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for ColorMatrix"); + return; + } + + if (!(out->getType()->getElement()->isCompatible(Element::U8(mRS))) && + !(out->getType()->getElement()->isCompatible(Element::U8_2(mRS))) && + !(out->getType()->getElement()->isCompatible(Element::U8_3(mRS))) && + !(out->getType()->getElement()->isCompatible(Element::U8_4(mRS))) && + !(out->getType()->getElement()->isCompatible(Element::F32(mRS))) && + !(out->getType()->getElement()->isCompatible(Element::F32_2(mRS))) && + !(out->getType()->getElement()->isCompatible(Element::F32_3(mRS))) && + !(out->getType()->getElement()->isCompatible(Element::F32_4(mRS)))) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for ColorMatrix"); + return; + } + Script::forEach(0, in, out, NULL, 0); } +void ScriptIntrinsicColorMatrix::setAdd(float* add) { + Script::setVar(1, (void*)add, sizeof(float) * 4); +} void ScriptIntrinsicColorMatrix::setColorMatrix3(float* m) { Script::setVar(0, (void*)m, sizeof(float) * 9); @@ -185,6 +313,18 @@ void ScriptIntrinsicColorMatrix::setYUVtoRGB() { sp<ScriptIntrinsicConvolve3x3> ScriptIntrinsicConvolve3x3::create(sp<RS> rs, sp<const Element> e) { + if (!(e->isCompatible(Element::U8(rs))) && + !(e->isCompatible(Element::U8_2(rs))) && + !(e->isCompatible(Element::U8_3(rs))) && + !(e->isCompatible(Element::U8_4(rs))) && + !(e->isCompatible(Element::F32(rs))) && + !(e->isCompatible(Element::F32_2(rs))) && + !(e->isCompatible(Element::F32_3(rs))) && + !(e->isCompatible(Element::F32_4(rs)))) { + rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Convolve3x3"); + return NULL; + } + return new ScriptIntrinsicConvolve3x3(rs, e); } @@ -194,10 +334,18 @@ ScriptIntrinsicConvolve3x3::ScriptIntrinsicConvolve3x3(sp<RS> rs, sp<const Eleme } void ScriptIntrinsicConvolve3x3::setInput(sp<Allocation> in) { + if (!(in->getType()->getElement()->isCompatible(mElement))) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve3x3"); + return; + } Script::setVar(1, in); } void ScriptIntrinsicConvolve3x3::forEach(sp<Allocation> out) { + if (!(out->getType()->getElement()->isCompatible(mElement))) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve3x3"); + return; + } Script::forEach(0, NULL, out, NULL, 0); } @@ -206,6 +354,18 @@ void ScriptIntrinsicConvolve3x3::setCoefficients(float* v) { } sp<ScriptIntrinsicConvolve5x5> ScriptIntrinsicConvolve5x5::create(sp<RS> rs, sp<const Element> e) { + if (!(e->isCompatible(Element::U8(rs))) && + !(e->isCompatible(Element::U8_2(rs))) && + !(e->isCompatible(Element::U8_3(rs))) && + !(e->isCompatible(Element::U8_4(rs))) && + !(e->isCompatible(Element::F32(rs))) && + !(e->isCompatible(Element::F32_2(rs))) && + !(e->isCompatible(Element::F32_3(rs))) && + !(e->isCompatible(Element::F32_4(rs)))) { + rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Convolve5x5"); + return NULL; + } + return new ScriptIntrinsicConvolve5x5(rs, e); } @@ -215,10 +375,19 @@ ScriptIntrinsicConvolve5x5::ScriptIntrinsicConvolve5x5(sp<RS> rs, sp<const Eleme } void ScriptIntrinsicConvolve5x5::setInput(sp<Allocation> in) { + if (!(in->getType()->getElement()->isCompatible(mElement))) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve5x5 input"); + return; + } Script::setVar(1, in); } void ScriptIntrinsicConvolve5x5::forEach(sp<Allocation> out) { + if (!(out->getType()->getElement()->isCompatible(mElement))) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Element mismatch in Convolve5x5 output"); + return; + } + Script::forEach(0, NULL, out, NULL, 0); } @@ -226,8 +395,8 @@ void ScriptIntrinsicConvolve5x5::setCoefficients(float* v) { Script::setVar(0, (void*)v, sizeof(float) * 25); } -sp<ScriptIntrinsicHistogram> ScriptIntrinsicHistogram::create(sp<RS> rs, sp<const Element> e) { - return new ScriptIntrinsicHistogram(rs, e); +sp<ScriptIntrinsicHistogram> ScriptIntrinsicHistogram::create(sp<RS> rs) { + return new ScriptIntrinsicHistogram(rs, NULL); } ScriptIntrinsicHistogram::ScriptIntrinsicHistogram(sp<RS> rs, sp<const Element> e) @@ -235,8 +404,27 @@ ScriptIntrinsicHistogram::ScriptIntrinsicHistogram(sp<RS> rs, sp<const Element> } -void ScriptIntrinsicHistogram::setOutput(sp<Allocation> aout) { - Script::setVar(1, aout); +void ScriptIntrinsicHistogram::setOutput(sp<Allocation> out) { + if (!(out->getType()->getElement()->isCompatible(Element::U32(mRS))) && + !(out->getType()->getElement()->isCompatible(Element::U32_2(mRS))) && + !(out->getType()->getElement()->isCompatible(Element::U32_3(mRS))) && + !(out->getType()->getElement()->isCompatible(Element::U32_4(mRS))) && + !(out->getType()->getElement()->isCompatible(Element::I32(mRS))) && + !(out->getType()->getElement()->isCompatible(Element::I32_2(mRS))) && + !(out->getType()->getElement()->isCompatible(Element::I32_3(mRS))) && + !(out->getType()->getElement()->isCompatible(Element::I32_4(mRS)))) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Histogram output"); + return; + } + + if (out->getType()->getX() != 256 || + out->getType()->getY() != 0 || + out->getType()->hasMipmaps()) { + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid Allocation type for Histogram output"); + return; + } + mOut = out; + Script::setVar(1, out); } void ScriptIntrinsicHistogram::setDotCoefficients(float r, float g, float b, float a) { @@ -257,15 +445,46 @@ void ScriptIntrinsicHistogram::setDotCoefficients(float r, float g, float b, flo } void ScriptIntrinsicHistogram::forEach(sp<Allocation> ain) { + if (ain->getType()->getElement()->getVectorSize() < + mOut->getType()->getElement()->getVectorSize()) { + mRS->throwError(RS_ERROR_INVALID_PARAMETER, + "Input vector size must be >= output vector size"); + return; + } + + if (!(ain->getType()->getElement()->isCompatible(Element::U8(mRS))) || + !(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, + "Input allocation to Histogram must be U8 or U8_4"); + return; + } + Script::forEach(0, ain, NULL, NULL, 0); } void ScriptIntrinsicHistogram::forEach_dot(sp<Allocation> ain) { + if (mOut->getType()->getElement()->getVectorSize() != 1) { + mRS->throwError(RS_ERROR_INVALID_PARAMETER, + "Output Histogram allocation must have vector size of 1 " \ + "when used with forEach_dot"); + return; + } + if (!(ain->getType()->getElement()->isCompatible(Element::U8(mRS))) || + !(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, + "Input allocation to Histogram must be U8 or U8_4"); + return; + } + Script::forEach(1, ain, NULL, NULL, 0); } sp<ScriptIntrinsicLUT> ScriptIntrinsicLUT::create(sp<RS> rs, sp<const Element> e) { + if (!(e->isCompatible(Element::U8_4(rs)))) { + rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for LUT"); + return NULL; + } return new ScriptIntrinsicLUT(rs, e); } @@ -285,6 +504,11 @@ void ScriptIntrinsicLUT::forEach(sp<Allocation> ain, sp<Allocation> aout) { LUT->copy1DFrom((void*)mCache); mDirty = false; } + if (!(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS))) || + !(aout->getType()->getElement()->isCompatible(Element::U8_4(mRS)))) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for LUT"); + return; + } Script::forEach(0, ain, aout, NULL, 0); } @@ -300,18 +524,34 @@ void ScriptIntrinsicLUT::setTable(unsigned int offset, unsigned char base, unsig } void ScriptIntrinsicLUT::setRed(unsigned char base, unsigned char length, unsigned char* lutValues) { + if (base + length >= 256) { + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "LUT out of range"); + return; + } setTable(0, base, length, lutValues); } void ScriptIntrinsicLUT::setGreen(unsigned char base, unsigned char length, unsigned char* lutValues) { + if (base + length >= 256) { + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "LUT out of range"); + return; + } setTable(256, base, length, lutValues); } void ScriptIntrinsicLUT::setBlue(unsigned char base, unsigned char length, unsigned char* lutValues) { + if (base + length >= 256) { + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "LUT out of range"); + return; + } setTable(512, base, length, lutValues); } void ScriptIntrinsicLUT::setAlpha(unsigned char base, unsigned char length, unsigned char* lutValues) { + if (base + length >= 256) { + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "LUT out of range"); + return; + } setTable(768, base, length, lutValues); } @@ -320,6 +560,10 @@ ScriptIntrinsicLUT::~ScriptIntrinsicLUT() { } sp<ScriptIntrinsicYuvToRGB> ScriptIntrinsicYuvToRGB::create(sp<RS> rs, sp<const Element> e) { + if (!(e->isCompatible(Element::U8_4(rs)))) { + rs->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for YuvToRGB"); + return NULL; + } return new ScriptIntrinsicYuvToRGB(rs, e); } @@ -329,9 +573,18 @@ ScriptIntrinsicYuvToRGB::ScriptIntrinsicYuvToRGB(sp<RS> rs, sp<const Element> e) } void ScriptIntrinsicYuvToRGB::setInput(sp<Allocation> in) { + if (!(in->getType()->getElement()->isCompatible(mElement))) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for input in YuvToRGB"); + return; + } Script::setVar(0, in); } void ScriptIntrinsicYuvToRGB::forEach(sp<Allocation> out) { + if (!(out->getType()->getElement()->isCompatible(mElement))) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for output in YuvToRGB"); + return; + } + Script::forEach(0, NULL, out, NULL, 0); } diff --git a/cpp/rsCppInternal.h b/cpp/rsCppInternal.h new file mode 100644 index 00000000..56ed5a31 --- /dev/null +++ b/cpp/rsCppInternal.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_RS_CPP_INTERNAL_H +#define ANDROID_RS_CPP_INTERNAL_H + +#define tryDispatch(rs, dispatch) \ + if (rs->getError() == RS_SUCCESS) { \ + dispatch; \ + } + +#endif diff --git a/cpp/rsCppStructs.h b/cpp/rsCppStructs.h index f6cb1dd8..ef354f80 100644 --- a/cpp/rsCppStructs.h +++ b/cpp/rsCppStructs.h @@ -48,6 +48,7 @@ class Sampler; RS_SUCCESS = 0, RS_ERROR_INVALID_PARAMETER = 1, RS_ERROR_RUNTIME_ERROR = 2, + RS_ERROR_INVALID_ELEMENT = 3, RS_ERROR_MAX = 9999 }; @@ -67,6 +68,7 @@ class Sampler; MessageHandlerFunc_t getMessageHandler() { return mMessageFunc; } void throwError(RSError error, const char *errMsg); + RSError getError(); RsContext getContext() { return mContext; } @@ -322,6 +324,10 @@ public: return mSizeBytes; } + uint32_t getVectorSize() const { + return mVectorSize; + } + static sp<const Element> BOOLEAN(sp<RS> rs); static sp<const Element> U8(sp<RS> rs); static sp<const Element> I8(sp<RS> rs); @@ -389,7 +395,7 @@ public: static sp<const Element> createUser(sp<RS> rs, RsDataType dt); static sp<const Element> createVector(sp<RS> rs, RsDataType dt, uint32_t size); static sp<const Element> createPixel(sp<RS> rs, RsDataType dt, RsDataKind dk); - bool isCompatible(sp<const Element>e); + bool isCompatible(sp<const Element>e) const; Element(void *id, sp<RS> rs, std::vector<sp<Element> > &elements, @@ -669,6 +675,7 @@ protected: class ScriptIntrinsic : public Script { protected: + sp<const Element> mElement; ScriptIntrinsic(sp<RS> rs, int id, sp<const Element> e); virtual ~ScriptIntrinsic(); }; @@ -720,6 +727,7 @@ class ScriptIntrinsicColorMatrix : public ScriptIntrinsic { public: static sp<ScriptIntrinsicColorMatrix> create(sp<RS> rs, sp<const Element> e); void forEach(sp<Allocation> in, sp<Allocation> out); + void setAdd(float* add); void setColorMatrix3(float* m); void setColorMatrix4(float* m); void setGreyscale(); @@ -750,8 +758,9 @@ class ScriptIntrinsicConvolve5x5 : public ScriptIntrinsic { class ScriptIntrinsicHistogram : public ScriptIntrinsic { private: ScriptIntrinsicHistogram(sp<RS> rs, sp<const Element> e); + sp<Allocation> mOut; public: - static sp<ScriptIntrinsicHistogram> create(sp<RS> rs, sp<const Element> e); + static sp<ScriptIntrinsicHistogram> create(sp<RS> rs); void setOutput(sp<Allocation> aout); void setDotCoefficients(float r, float g, float b, float a); void forEach(sp<Allocation> ain); |
