diff options
author | Miao Wang <miaowang@google.com> | 2015-03-10 15:29:40 -0700 |
---|---|---|
committer | Miao Wang <miaowang@google.com> | 2015-03-30 12:16:28 -0700 |
commit | e5428e661ce6f9d24f838cab0a8fb0fa8c76dbca (patch) | |
tree | 63202ff218aff023d7b0adb5e34cb28dff992287 | |
parent | c3851d58e6f0a97a3f5239d78515acd2be47b507 (diff) | |
download | rs-e5428e661ce6f9d24f838cab0a8fb0fa8c76dbca.tar.gz |
Update RenderScript C++ API
- Add Copy3DRangeTo API
- Add AutoPadding & unPadding for CopyTo and CopyFrom APIs
- Add IntrinsicResize
Change-Id: I1138225f8a7b738929a09636bf2669f5d68b0c7d
-rw-r--r-- | cpp/Allocation.cpp | 153 | ||||
-rw-r--r-- | cpp/RenderScript.cpp | 8 | ||||
-rw-r--r-- | cpp/Sampler.cpp | 23 | ||||
-rw-r--r-- | cpp/ScriptIntrinsics.cpp | 40 | ||||
-rw-r--r-- | cpp/rsCppStructs.h | 61 |
5 files changed, 254 insertions, 31 deletions
diff --git a/cpp/Allocation.cpp b/cpp/Allocation.cpp index c4d62b5f..85304404 100644 --- a/cpp/Allocation.cpp +++ b/cpp/Allocation.cpp @@ -63,7 +63,7 @@ Allocation::Allocation(void *id, sp<RS> rs, sp<const Type> t, uint32_t usage) : mType = t; mUsage = usage; - + mAutoPadding = false; if (t != nullptr) { updateCacheInfo(t); } @@ -71,6 +71,13 @@ Allocation::Allocation(void *id, sp<RS> rs, sp<const Type> t, uint32_t usage) : } +void Allocation::validateIsInt64() { + RsDataType dt = mType->getElement()->getDataType(); + if ((dt == RS_TYPE_SIGNED_64) || (dt == RS_TYPE_UNSIGNED_64)) { + return; + } + ALOGE("64 bit integer source does not match allocation type %i", dt); +} void Allocation::validateIsInt32() { RsDataType dt = mType->getElement()->getDataType(); @@ -104,6 +111,14 @@ void Allocation::validateIsFloat32() { ALOGE("32 bit float source does not match allocation type %i", dt); } +void Allocation::validateIsFloat64() { + RsDataType dt = mType->getElement()->getDataType(); + if (dt == RS_TYPE_FLOAT_64) { + return; + } + ALOGE("64 bit float source does not match allocation type %i", dt); +} + void Allocation::validateIsObject() { RsDataType dt = mType->getElement()->getDataType(); if ((dt == RS_TYPE_ELEMENT) || @@ -150,6 +165,7 @@ void Allocation::syncAll(RsAllocationUsageType srcLocation) { } void Allocation::ioSendOutput() { +//TODO: Also make it able to use for compatlib. #ifndef RS_COMPATIBILITY_LIB if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) { mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only send buffer if IO_OUTPUT usage specified."); @@ -162,7 +178,7 @@ void Allocation::ioSendOutput() { void Allocation::ioGetInput() { #ifndef RS_COMPATIBILITY_LIB if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) { - mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only send buffer if IO_OUTPUT usage specified."); + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only get buffer if IO_INPUT usage specified."); return; } tryDispatch(mRS, RS::dispatch->AllocationIoReceive(mRS->getContext(), getID())); @@ -191,6 +207,33 @@ void * Allocation::getPointer(size_t *stride) { return p; } +// --------------------------------------------------------------------------- +//Functions needed for autopadding & unpadding +static void copyWithPadding(void* ptr, const void* srcPtr, int mSize, int count) { + int sizeBytesPad = mSize * 4; + int sizeBytes = mSize * 3; + uint8_t *dst = static_cast<uint8_t *>(ptr); + const uint8_t *src = static_cast<const uint8_t *>(srcPtr); + for (int i = 0; i < count; i++) { + memcpy(dst, src, sizeBytes); + dst += sizeBytesPad; + src += sizeBytes; + } +} + +static void copyWithUnPadding(void* ptr, const void* srcPtr, int mSize, int count) { + int sizeBytesPad = mSize * 4; + int sizeBytes = mSize * 3; + uint8_t *dst = static_cast<uint8_t *>(ptr); + const uint8_t *src = static_cast<const uint8_t *>(srcPtr); + for (int i = 0; i < count; i++) { + memcpy(dst, src, sizeBytes); + dst += sizeBytes; + src += sizeBytesPad; + } +} +// --------------------------------------------------------------------------- + void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const void *data) { if(count < 1) { @@ -202,9 +245,17 @@ void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const void *data) { mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified"); return; } - - tryDispatch(mRS, RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD, - count, data, count * mType->getElement()->getSizeBytes())); + if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) { + size_t eSize = mType->getElement()->getSizeBytes(); + void *ptr = malloc(eSize * count); + copyWithPadding(ptr, data, eSize / 4, count); + tryDispatch(mRS, RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD, + count, ptr, count * mType->getElement()->getSizeBytes())); + free(ptr); + } else { + 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) { @@ -217,9 +268,17 @@ void Allocation::copy1DRangeTo(uint32_t off, size_t count, void *data) { mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified"); return; } - - tryDispatch(mRS, RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD, - count, data, count * mType->getElement()->getSizeBytes())); + if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) { + size_t eSize = mType->getElement()->getSizeBytes(); + void *ptr = malloc(eSize * count); + tryDispatch(mRS, RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD, + count, ptr, count * mType->getElement()->getSizeBytes())); + copyWithUnPadding(data, ptr, eSize / 4, count); + free(ptr); + } else { + 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, @@ -253,10 +312,21 @@ 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); - tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, - yoff, mSelectedLOD, mSelectedFace, - w, h, data, w * h * mType->getElement()->getSizeBytes(), - w * mType->getElement()->getSizeBytes())); + if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) { + size_t eSize = mType->getElement()->getSizeBytes(); + void *ptr = malloc(eSize * w * h); + copyWithPadding(ptr, data, eSize / 4, w * h); + tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, + yoff, mSelectedLOD, mSelectedFace, + w, h, ptr, w * h * mType->getElement()->getSizeBytes(), + w * mType->getElement()->getSizeBytes())); + free(ptr); + } else { + 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, @@ -271,10 +341,21 @@ void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint3 void Allocation::copy2DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, void* data) { validate2DRange(xoff, yoff, w, h); - tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, - mSelectedLOD, mSelectedFace, w, h, data, - w * h * mType->getElement()->getSizeBytes(), - w * mType->getElement()->getSizeBytes())); + if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) { + size_t eSize = mType->getElement()->getSizeBytes(); + void *ptr = malloc(eSize * w * h); + tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, + mSelectedLOD, mSelectedFace, w, h, ptr, + w * h * mType->getElement()->getSizeBytes(), + w * mType->getElement()->getSizeBytes())); + copyWithUnPadding(data, ptr, eSize / 4, w * h); + free(ptr); + } else { + 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, @@ -315,20 +396,50 @@ void Allocation::validate3DRange(uint32_t xoff, uint32_t yoff, uint32_t zoff, ui void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, uint32_t h, uint32_t d, const void* data) { validate3DRange(xoff, yoff, zoff, w, h, d); - tryDispatch(mRS, RS::dispatch->Allocation3DData(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, - mSelectedLOD, w, h, d, data, - w * h * d * mType->getElement()->getSizeBytes(), - w * mType->getElement()->getSizeBytes())); + if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) { + size_t eSize = mType->getElement()->getSizeBytes(); + void *ptr = malloc(eSize * w * h * d); + copyWithPadding(ptr, data, eSize / 4, w * h * d); + tryDispatch(mRS, RS::dispatch->Allocation3DData(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, + mSelectedLOD, w, h, d, ptr, + w * h * d * mType->getElement()->getSizeBytes(), + w * mType->getElement()->getSizeBytes())); + free(ptr); + } else { + tryDispatch(mRS, RS::dispatch->Allocation3DData(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, + mSelectedLOD, w, h, d, data, + w * h * d * mType->getElement()->getSizeBytes(), + w * mType->getElement()->getSizeBytes())); + } } void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, uint32_t h, uint32_t d, sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff, uint32_t dataZoff) { - validate3DRange(xoff, yoff, zoff, dataXoff, dataYoff, dataZoff); + validate3DRange(xoff, yoff, zoff, w, h, d); tryDispatch(mRS, RS::dispatch->AllocationCopy3DRange(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d, data->getIDSafe(), dataXoff, dataYoff, dataZoff, data->mSelectedLOD)); } +void Allocation::copy3DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, + uint32_t h, uint32_t d, void* data) { + validate3DRange(xoff, yoff, zoff, w, h, d); + if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) { + size_t eSize = mType->getElement()->getSizeBytes(); + void *ptr = malloc(eSize * w * h * d); + tryDispatch(mRS, RS::dispatch->Allocation3DRead(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, + mSelectedLOD, w, h, d, ptr, + w * h * d * mType->getElement()->getSizeBytes(), + w * mType->getElement()->getSizeBytes())); + copyWithUnPadding(data, ptr, eSize / 4, w * h * d); + free(ptr); + } else { + tryDispatch(mRS, RS::dispatch->Allocation3DRead(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, + mSelectedLOD, w, h, d, data, + w * h * d * mType->getElement()->getSizeBytes(), + w * mType->getElement()->getSizeBytes())); + } +} sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, RsAllocationMipmapControl mipmaps, uint32_t usage) { diff --git a/cpp/RenderScript.cpp b/cpp/RenderScript.cpp index de22dea6..2a041090 100644 --- a/cpp/RenderScript.cpp +++ b/cpp/RenderScript.cpp @@ -80,14 +80,14 @@ bool RS::init(std::string name, uint32_t flags) { // this will only open API 19+ libRS // because that's when we changed libRS to extern "C" entry points -static bool loadSO(const char* filename) { +static bool loadSO(const char* filename, int targetApi) { void* handle = dlopen(filename, RTLD_LAZY | RTLD_LOCAL); if (handle == nullptr) { ALOGV("couldn't dlopen %s, %s", filename, dlerror()); return false; } - if (loadSymbols(handle, *RS::dispatch) == false) { + if (loadSymbols(handle, *RS::dispatch, targetApi) == false) { ALOGV("%s init failed!", filename); return false; } @@ -119,10 +119,10 @@ bool RS::initDispatch(int targetApi) { // attempt to load libRS, load libRSSupport on failure // if property is set, proceed directly to libRSSupport if (getProp("debug.rs.forcecompat") == 0) { - usingNative = loadSO("libRS.so"); + usingNative = loadSO("libRS.so", targetApi); } if (usingNative == false) { - if (loadSO("libRSSupport.so") == false) { + if (loadSO("libRSSupport.so", targetApi) == false) { ALOGE("Failed to load libRS.so and libRSSupport.so"); goto error; } diff --git a/cpp/Sampler.cpp b/cpp/Sampler.cpp index 500651fe..62cea87c 100644 --- a/cpp/Sampler.cpp +++ b/cpp/Sampler.cpp @@ -25,11 +25,22 @@ Sampler::Sampler(sp<RS> rs, void* id): { RsSamplerValue mMin = RS_SAMPLER_INVALID; RsSamplerValue mMag = RS_SAMPLER_INVALID; - RsSamplerValue mWrapS = RS_SAMPLER_INVALID;; - RsSamplerValue mWrapT = RS_SAMPLER_INVALID;; + RsSamplerValue mWrapS = RS_SAMPLER_INVALID; + RsSamplerValue mWrapT = RS_SAMPLER_INVALID; float mAniso = 0.f; } +Sampler::Sampler(sp<RS> rs, void* id, RsSamplerValue min, RsSamplerValue mag, + RsSamplerValue wrapS, RsSamplerValue wrapT, float anisotropy): + BaseObj(id, rs) +{ + RsSamplerValue mMin = min; + RsSamplerValue mMag = mag; + RsSamplerValue mWrapS = wrapS; + RsSamplerValue mWrapT = wrapT; + float mAniso = anisotropy; +} + RsSamplerValue Sampler::getMinification() { return mMin; } @@ -50,10 +61,12 @@ float Sampler::getAnisotropy() { return mAniso; } -sp<Sampler> Sampler::create(sp<RS> rs, RsSamplerValue min, RsSamplerValue mag, RsSamplerValue wrapS, RsSamplerValue wrapT, float anisotropy) { +sp<Sampler> Sampler::create(sp<RS> rs, RsSamplerValue min, RsSamplerValue mag, + RsSamplerValue wrapS, RsSamplerValue wrapT, float anisotropy) { // we aren't supporting wrapR in C++ API atm, so always pass wrap for that - void* id = RS::dispatch->SamplerCreate(rs->getContext(), min, mag, wrapS, wrapT, RS_SAMPLER_WRAP, anisotropy); - return new Sampler(rs, id); + void* id = RS::dispatch->SamplerCreate(rs->getContext(), min, mag, wrapS, wrapT, + RS_SAMPLER_WRAP, anisotropy); + return new Sampler(rs, id, min, mag, wrapS, wrapT, anisotropy); } #define CREATE_SAMPLER(N, MIN, MAG, WRAPS, WRAPT) sp<const Sampler> Sampler::N(sp<RS> rs) { \ diff --git a/cpp/ScriptIntrinsics.cpp b/cpp/ScriptIntrinsics.cpp index e40d1a03..54ce4650 100644 --- a/cpp/ScriptIntrinsics.cpp +++ b/cpp/ScriptIntrinsics.cpp @@ -24,7 +24,8 @@ using namespace RSC; ScriptIntrinsic::ScriptIntrinsic(sp<RS> rs, int id, sp<const Element> e) : Script(nullptr, rs) { - mID = createDispatch(rs, RS::dispatch->ScriptIntrinsicCreate(rs->getContext(), id, e->getID())); + mID = createDispatch(rs, RS::dispatch->ScriptIntrinsicCreate(rs->getContext(), id, + e != nullptr ? e->getID() : 0)); mElement = e; } @@ -569,6 +570,43 @@ ScriptIntrinsicLUT::~ScriptIntrinsicLUT() { } +sp<ScriptIntrinsicResize> ScriptIntrinsicResize::create(sp<RS> rs) { + return new ScriptIntrinsicResize(rs, nullptr); +} + +ScriptIntrinsicResize::ScriptIntrinsicResize(sp<RS> rs, sp<const Element> e) + : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_RESIZE, e) { + +} +void ScriptIntrinsicResize::forEach_bicubic(sp<Allocation> aout) { + if (aout == mInput) { + mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Resize Input and Ouput cannot be the same"); + } + + if (!(mInput->getType()->getElement()->isCompatible(aout->getType()->getElement()))) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Resize forEach element mismatch"); + return; + } + Script::forEach(0, nullptr, aout, nullptr, 0); +} +void ScriptIntrinsicResize::setInput(sp<Allocation> ain) { + if (!(ain->getType()->getElement()->isCompatible(Element::U8(mRS))) && + !(ain->getType()->getElement()->isCompatible(Element::U8_2(mRS))) && + !(ain->getType()->getElement()->isCompatible(Element::U8_3(mRS))) && + !(ain->getType()->getElement()->isCompatible(Element::U8_4(mRS))) && + !(ain->getType()->getElement()->isCompatible(Element::F32(mRS))) && + !(ain->getType()->getElement()->isCompatible(Element::F32_2(mRS))) && + !(ain->getType()->getElement()->isCompatible(Element::F32_3(mRS))) && + !(ain->getType()->getElement()->isCompatible(Element::F32_4(mRS)))) { + mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for Resize Input"); + return; + } + + mInput = ain; + Script::setVar(0, ain); +} + + 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"); diff --git a/cpp/rsCppStructs.h b/cpp/rsCppStructs.h index cd8f39a1..14166f02 100644 --- a/cpp/rsCppStructs.h +++ b/cpp/rsCppStructs.h @@ -305,6 +305,7 @@ protected: bool mConstrainedZ; bool mReadAllowed; bool mWriteAllowed; + bool mAutoPadding; uint32_t mSelectedY; uint32_t mSelectedZ; uint32_t mSelectedLOD; @@ -320,10 +321,12 @@ protected: Allocation(void *id, sp<RS> rs, sp<const Type> t, uint32_t usage); + void validateIsInt64(); void validateIsInt32(); void validateIsInt16(); void validateIsInt8(); void validateIsFloat32(); + void validateIsFloat64(); void validateIsObject(); virtual void updateFromNative(); @@ -343,6 +346,16 @@ public: } /** + * Enable/Disable AutoPadding for Vec3 elements. + * + * @param useAutoPadding True: enable AutoPadding; flase: disable AutoPadding + * + */ + void setAutoPadding(bool useAutoPadding) { + mAutoPadding = useAutoPadding; + } + + /** * Propagate changes from one usage of the Allocation to other usages of the Allocation. * @param[in] srcLocation source location with changes to propagate elsewhere */ @@ -505,6 +518,20 @@ public: uint32_t dataXoff, uint32_t dataYoff, uint32_t dataZoff); /** + * Copy a 3D region in this Allocation into an array. The + * array is assumed to be tightly packed. + * @param[in] xoff X offset of region to update in this Allocation + * @param[in] yoff Y offset of region to update in this Allocation + * @param[in] zoff Z offset of region to update in this Allocation + * @param[in] w Width of region to update + * @param[in] h Height of region to update + * @param[in] d Depth of region to update + * @param[in] data Array from which to copy + */ + void copy3DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, + uint32_t h, uint32_t d, void* data); + + /** * Creates an Allocation for use by scripts with a given Type. * @param[in] rs Context to which the Allocation will belong * @param[in] type Type of the Allocation @@ -1836,6 +1863,38 @@ class ScriptIntrinsicLUT : public ScriptIntrinsic { }; /** + * Intrinsic for performing a resize of a 2D allocation. + */ +class ScriptIntrinsicResize : public ScriptIntrinsic { + private: + sp<Allocation> mInput; + ScriptIntrinsicResize(sp<RS> rs, sp<const Element> e); + public: + /** + * Supported Element types are U8_4. Default lookup table is identity. + * @param[in] rs RenderScript context + * @param[in] e Element + * @return new ScriptIntrinsic + */ + static sp<ScriptIntrinsicResize> create(sp<RS> rs); + + /** + * Resize copy the input allocation to the output specified. The + * Allocation is rescaled if necessary using bi-cubic + * interpolation. + * @param[in] ain input Allocation + * @param[in] aout output Allocation + */ + void forEach_bicubic(sp<Allocation> aout); + + /** + * Set the input of the resize. + * @param[in] lut new lookup table + */ + void setInput(sp<Allocation> ain); +}; + +/** * Intrinsic for converting an Android YUV buffer to RGB. * * The input allocation should be supplied in a supported YUV format @@ -1887,6 +1946,8 @@ class ScriptIntrinsicYuvToRGB : public ScriptIntrinsic { class Sampler : public BaseObj { private: Sampler(sp<RS> rs, void* id); + Sampler(sp<RS> rs, void* id, RsSamplerValue min, RsSamplerValue mag, + RsSamplerValue wrapS, RsSamplerValue wrapT, float anisotropy); RsSamplerValue mMin; RsSamplerValue mMag; RsSamplerValue mWrapS; |