android_frameworks_base/libs/rs/rsAllocation.cpp
Jason Sams 62f258f1e4 Clean up RS samples for SDK, bug 2943369
Fix bug 3403965 rsgSyncAll would not mark constants as changed
found by inspection.

Only rsAllocation.cpp affects on device bits.

Change-Id: I6b7ec0df87e42687b24384aaf54dc04976cb84f7

doc update

Change-Id: Id5841f08868557e086f185024470924ef202d19f
2011-01-28 16:18:01 -08:00

843 lines
25 KiB
C++

/*
* Copyright (C) 2009 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_BUILD_FOR_HOST
#include "rsContext.h"
#include <GLES/gl.h>
#include <GLES2/gl2.h>
#include <GLES/glext.h>
#else
#include "rsContextHostStub.h"
#include <OpenGL/gl.h>
#include <OpenGl/glext.h>
#endif
#include "utils/StopWatch.h"
static void rsaAllocationGenerateScriptMips(RsContext con, RsAllocation va);
using namespace android;
using namespace android::renderscript;
Allocation::Allocation(Context *rsc, const Type *type, uint32_t usages,
RsAllocationMipmapControl mc)
: ObjectBase(rsc) {
init(rsc, type);
mUsageFlags = usages;
mMipmapControl = mc;
allocScriptMemory();
if (mType->getElement()->getHasReferences()) {
memset(mPtr, 0, mType->getSizeBytes());
}
if (!mPtr) {
LOGE("Allocation::Allocation, alloc failure");
}
}
void Allocation::init(Context *rsc, const Type *type) {
mPtr = NULL;
mCpuWrite = false;
mCpuRead = false;
mGpuWrite = false;
mGpuRead = false;
mReadWriteRatio = 0;
mUpdateSize = 0;
mUsageFlags = 0;
mMipmapControl = RS_ALLOCATION_MIPMAP_NONE;
mTextureID = 0;
mBufferID = 0;
mUploadDefered = false;
mUserBitmapCallback = NULL;
mUserBitmapCallbackData = NULL;
mType.set(type);
rsAssert(type);
mPtr = NULL;
}
Allocation::~Allocation() {
if (mUserBitmapCallback != NULL) {
mUserBitmapCallback(mUserBitmapCallbackData);
mPtr = NULL;
}
freeScriptMemory();
if (mBufferID) {
// Causes a SW crash....
//LOGV(" mBufferID %i", mBufferID);
//glDeleteBuffers(1, &mBufferID);
//mBufferID = 0;
}
if (mTextureID) {
glDeleteTextures(1, &mTextureID);
mTextureID = 0;
}
}
void Allocation::setCpuWritable(bool) {
}
void Allocation::setGpuWritable(bool) {
}
void Allocation::setCpuReadable(bool) {
}
void Allocation::setGpuReadable(bool) {
}
bool Allocation::fixAllocation() {
return false;
}
void Allocation::deferedUploadToTexture(const Context *rsc) {
mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE;
mUploadDefered = true;
}
uint32_t Allocation::getGLTarget() const {
if (getIsTexture()) {
if (mType->getDimFaces()) {
return GL_TEXTURE_CUBE_MAP;
} else {
return GL_TEXTURE_2D;
}
}
if (getIsBufferObject()) {
return GL_ARRAY_BUFFER;
}
return 0;
}
void Allocation::allocScriptMemory() {
rsAssert(!mPtr);
mPtr = malloc(mType->getSizeBytes());
}
void Allocation::freeScriptMemory() {
if (mPtr) {
free(mPtr);
mPtr = NULL;
}
}
void Allocation::syncAll(Context *rsc, RsAllocationUsageType src) {
rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT);
if (getIsTexture()) {
uploadToTexture(rsc);
}
if (getIsBufferObject()) {
uploadToBufferObject(rsc);
}
mUploadDefered = false;
}
void Allocation::uploadToTexture(const Context *rsc) {
mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE;
GLenum type = mType->getElement()->getComponent().getGLType();
GLenum format = mType->getElement()->getComponent().getGLFormat();
if (!type || !format) {
return;
}
if (!mPtr) {
return;
}
bool isFirstUpload = false;
if (!mTextureID) {
glGenTextures(1, &mTextureID);
if (!mTextureID) {
// This should not happen, however, its likely the cause of the
// white sqare bug.
// Force a crash to 1: restart the app, 2: make sure we get a bugreport.
LOGE("Upload to texture failed to gen mTextureID");
rsc->dumpDebug();
mUploadDefered = true;
return;
}
isFirstUpload = true;
}
upload2DTexture(isFirstUpload);
if (!(mUsageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
freeScriptMemory();
}
rsc->checkError("Allocation::uploadToTexture");
}
const static GLenum gFaceOrder[] = {
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
};
void Allocation::update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff,
uint32_t lod, RsAllocationCubemapFace face,
uint32_t w, uint32_t h) {
GLenum type = mType->getElement()->getComponent().getGLType();
GLenum format = mType->getElement()->getComponent().getGLFormat();
GLenum target = (GLenum)getGLTarget();
rsAssert(mTextureID);
glBindTexture(target, mTextureID);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
GLenum t = GL_TEXTURE_2D;
if (mType->getDimFaces()) {
t = gFaceOrder[face];
}
glTexSubImage2D(t, lod, xoff, yoff, w, h, format, type, ptr);
}
void Allocation::upload2DTexture(bool isFirstUpload) {
GLenum type = mType->getElement()->getComponent().getGLType();
GLenum format = mType->getElement()->getComponent().getGLFormat();
GLenum target = (GLenum)getGLTarget();
glBindTexture(target, mTextureID);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
uint32_t faceCount = 1;
if (mType->getDimFaces()) {
faceCount = 6;
}
for (uint32_t face = 0; face < faceCount; face ++) {
for (uint32_t lod = 0; lod < mType->getLODCount(); lod++) {
const uint8_t *p = (const uint8_t *)mPtr;
p += mType->getLODFaceOffset(lod, (RsAllocationCubemapFace)face, 0, 0);
GLenum t = GL_TEXTURE_2D;
if (mType->getDimFaces()) {
t = gFaceOrder[face];
}
if (isFirstUpload) {
glTexImage2D(t, lod, format,
mType->getLODDimX(lod), mType->getLODDimY(lod),
0, format, type, p);
} else {
glTexSubImage2D(t, lod, 0, 0,
mType->getLODDimX(lod), mType->getLODDimY(lod),
format, type, p);
}
}
}
if (mMipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) {
#ifndef ANDROID_RS_BUILD_FOR_HOST
glGenerateMipmap(target);
#endif //ANDROID_RS_BUILD_FOR_HOST
}
}
void Allocation::deferedUploadToBufferObject(const Context *rsc) {
mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX;
mUploadDefered = true;
}
void Allocation::uploadToBufferObject(const Context *rsc) {
rsAssert(!mType->getDimY());
rsAssert(!mType->getDimZ());
mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX;
if (!mBufferID) {
glGenBuffers(1, &mBufferID);
}
if (!mBufferID) {
LOGE("Upload to buffer object failed");
mUploadDefered = true;
return;
}
GLenum target = (GLenum)getGLTarget();
glBindBuffer(target, mBufferID);
glBufferData(target, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW);
glBindBuffer(target, 0);
rsc->checkError("Allocation::uploadToBufferObject");
}
void Allocation::uploadCheck(Context *rsc) {
if (mUploadDefered) {
syncAll(rsc, RS_ALLOCATION_USAGE_SCRIPT);
}
}
void Allocation::read(void *data) {
memcpy(data, mPtr, mType->getSizeBytes());
}
void Allocation::data(Context *rsc, uint32_t xoff, uint32_t lod,
uint32_t count, const void *data, uint32_t sizeBytes) {
uint32_t eSize = mType->getElementSizeBytes();
uint8_t * ptr = static_cast<uint8_t *>(mPtr);
ptr += eSize * xoff;
uint32_t size = count * eSize;
if (size != sizeBytes) {
LOGE("Allocation::subData called with mismatched size expected %i, got %i", size, sizeBytes);
mType->dumpLOGV("type info");
return;
}
if (mType->getElement()->getHasReferences()) {
incRefs(data, count);
decRefs(ptr, count);
}
memcpy(ptr, data, size);
sendDirty();
mUploadDefered = true;
}
void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) {
uint32_t eSize = mType->getElementSizeBytes();
uint32_t lineSize = eSize * w;
uint32_t destW = mType->getDimX();
//LOGE("data2d %p, %i %i %i %i %i %i %p %i", this, xoff, yoff, lod, face, w, h, data, sizeBytes);
if ((lineSize * h) != sizeBytes) {
LOGE("Allocation size mismatch, expected %i, got %i", (lineSize * h), sizeBytes);
rsAssert(!"Allocation::subData called with mismatched size");
return;
}
if (mPtr) {
const uint8_t *src = static_cast<const uint8_t *>(data);
uint8_t *dst = static_cast<uint8_t *>(mPtr);
dst += mType->getLODFaceOffset(lod, face, xoff, yoff);
//LOGE(" %p %p %i ", dst, src, eSize);
for (uint32_t line=yoff; line < (yoff+h); line++) {
if (mType->getElement()->getHasReferences()) {
incRefs(src, w);
decRefs(dst, w);
}
memcpy(dst, src, lineSize);
src += lineSize;
dst += destW * eSize;
}
sendDirty();
mUploadDefered = true;
} else {
update2DTexture(data, xoff, yoff, lod, face, w, h);
}
}
void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
uint32_t lod, RsAllocationCubemapFace face,
uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) {
}
void Allocation::elementData(Context *rsc, uint32_t x, const void *data,
uint32_t cIdx, uint32_t sizeBytes) {
uint32_t eSize = mType->getElementSizeBytes();
uint8_t * ptr = static_cast<uint8_t *>(mPtr);
ptr += eSize * x;
if (cIdx >= mType->getElement()->getFieldCount()) {
LOGE("Error Allocation::subElementData component %i out of range.", cIdx);
rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
return;
}
if (x >= mType->getDimX()) {
LOGE("Error Allocation::subElementData X offset %i out of range.", x);
rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
return;
}
const Element * e = mType->getElement()->getField(cIdx);
ptr += mType->getElement()->getFieldOffsetBytes(cIdx);
if (sizeBytes != e->getSizeBytes()) {
LOGE("Error Allocation::subElementData data size %i does not match field size %i.", sizeBytes, e->getSizeBytes());
rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
return;
}
if (e->getHasReferences()) {
e->incRefs(data);
e->decRefs(ptr);
}
memcpy(ptr, data, sizeBytes);
sendDirty();
mUploadDefered = true;
}
void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y,
const void *data, uint32_t cIdx, uint32_t sizeBytes) {
uint32_t eSize = mType->getElementSizeBytes();
uint8_t * ptr = static_cast<uint8_t *>(mPtr);
ptr += eSize * (x + y * mType->getDimX());
if (x >= mType->getDimX()) {
LOGE("Error Allocation::subElementData X offset %i out of range.", x);
rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
return;
}
if (y >= mType->getDimY()) {
LOGE("Error Allocation::subElementData X offset %i out of range.", x);
rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
return;
}
if (cIdx >= mType->getElement()->getFieldCount()) {
LOGE("Error Allocation::subElementData component %i out of range.", cIdx);
rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
return;
}
const Element * e = mType->getElement()->getField(cIdx);
ptr += mType->getElement()->getFieldOffsetBytes(cIdx);
if (sizeBytes != e->getSizeBytes()) {
LOGE("Error Allocation::subElementData data size %i does not match field size %i.", sizeBytes, e->getSizeBytes());
rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
return;
}
if (e->getHasReferences()) {
e->incRefs(data);
e->decRefs(ptr);
}
memcpy(ptr, data, sizeBytes);
sendDirty();
mUploadDefered = true;
}
void Allocation::addProgramToDirty(const Program *p) {
mToDirtyList.push(p);
}
void Allocation::removeProgramToDirty(const Program *p) {
for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
if (mToDirtyList[ct] == p) {
mToDirtyList.removeAt(ct);
return;
}
}
rsAssert(0);
}
void Allocation::dumpLOGV(const char *prefix) const {
ObjectBase::dumpLOGV(prefix);
String8 s(prefix);
s.append(" type ");
if (mType.get()) {
mType->dumpLOGV(s.string());
}
LOGV("%s allocation ptr=%p mCpuWrite=%i, mCpuRead=%i, mGpuWrite=%i, mGpuRead=%i",
prefix, mPtr, mCpuWrite, mCpuRead, mGpuWrite, mGpuRead);
LOGV("%s allocation mUsageFlags=0x04%x, mMipmapControl=0x%04x, mTextureID=%i, mBufferID=%i",
prefix, mUsageFlags, mMipmapControl, mTextureID, mBufferID);
}
void Allocation::serialize(OStream *stream) const {
// Need to identify ourselves
stream->addU32((uint32_t)getClassId());
String8 name(getName());
stream->addString(&name);
// First thing we need to serialize is the type object since it will be needed
// to initialize the class
mType->serialize(stream);
uint32_t dataSize = mType->getSizeBytes();
// Write how much data we are storing
stream->addU32(dataSize);
// Now write the data
stream->addByteArray(mPtr, dataSize);
}
Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) {
// First make sure we are reading the correct object
RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
if (classID != RS_A3D_CLASS_ID_ALLOCATION) {
LOGE("allocation loading skipped due to invalid class id\n");
return NULL;
}
String8 name;
stream->loadString(&name);
Type *type = Type::createFromStream(rsc, stream);
if (!type) {
return NULL;
}
type->compute();
// Number of bytes we wrote out for this allocation
uint32_t dataSize = stream->loadU32();
if (dataSize != type->getSizeBytes()) {
LOGE("failed to read allocation because numbytes written is not the same loaded type wants\n");
ObjectBase::checkDelete(type);
return NULL;
}
Allocation *alloc = new Allocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT);
alloc->setName(name.string(), name.size());
uint32_t count = dataSize / type->getElementSizeBytes();
// Read in all of our allocation data
alloc->data(rsc, 0, 0, count, stream->getPtr() + stream->getPos(), dataSize);
stream->reset(stream->getPos() + dataSize);
return alloc;
}
void Allocation::sendDirty() const {
for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
mToDirtyList[ct]->forceDirty();
}
}
void Allocation::incRefs(const void *ptr, size_t ct, size_t startOff) const {
const uint8_t *p = static_cast<const uint8_t *>(ptr);
const Element *e = mType->getElement();
uint32_t stride = e->getSizeBytes();
p += stride * startOff;
while (ct > 0) {
e->incRefs(p);
ct --;
p += stride;
}
}
void Allocation::decRefs(const void *ptr, size_t ct, size_t startOff) const {
const uint8_t *p = static_cast<const uint8_t *>(ptr);
const Element *e = mType->getElement();
uint32_t stride = e->getSizeBytes();
p += stride * startOff;
while (ct > 0) {
e->decRefs(p);
ct --;
p += stride;
}
}
void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len) {
}
void Allocation::resize1D(Context *rsc, uint32_t dimX) {
Type *t = mType->cloneAndResize1D(rsc, dimX);
uint32_t oldDimX = mType->getDimX();
if (dimX == oldDimX) {
return;
}
if (dimX < oldDimX) {
decRefs(mPtr, oldDimX - dimX, dimX);
}
mPtr = realloc(mPtr, t->getSizeBytes());
if (dimX > oldDimX) {
const Element *e = mType->getElement();
uint32_t stride = e->getSizeBytes();
memset(((uint8_t *)mPtr) + stride * oldDimX, 0, stride * (dimX - oldDimX));
}
mType.set(t);
}
void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY) {
LOGE("not implemented");
}
/////////////////
//
namespace android {
namespace renderscript {
void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, bool genmip, uint32_t baseMipLevel) {
Allocation *alloc = static_cast<Allocation *>(va);
alloc->deferedUploadToTexture(rsc);
}
void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va) {
Allocation *alloc = static_cast<Allocation *>(va);
alloc->deferedUploadToBufferObject(rsc);
}
static void mip565(const Adapter2D &out, const Adapter2D &in) {
uint32_t w = out.getDimX();
uint32_t h = out.getDimY();
for (uint32_t y=0; y < h; y++) {
uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y));
const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2));
const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1));
for (uint32_t x=0; x < w; x++) {
*oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
oPtr ++;
i1 += 2;
i2 += 2;
}
}
}
static void mip8888(const Adapter2D &out, const Adapter2D &in) {
uint32_t w = out.getDimX();
uint32_t h = out.getDimY();
for (uint32_t y=0; y < h; y++) {
uint32_t *oPtr = static_cast<uint32_t *>(out.getElement(0, y));
const uint32_t *i1 = static_cast<uint32_t *>(in.getElement(0, y*2));
const uint32_t *i2 = static_cast<uint32_t *>(in.getElement(0, y*2+1));
for (uint32_t x=0; x < w; x++) {
*oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
oPtr ++;
i1 += 2;
i2 += 2;
}
}
}
static void mip8(const Adapter2D &out, const Adapter2D &in) {
uint32_t w = out.getDimX();
uint32_t h = out.getDimY();
for (uint32_t y=0; y < h; y++) {
uint8_t *oPtr = static_cast<uint8_t *>(out.getElement(0, y));
const uint8_t *i1 = static_cast<uint8_t *>(in.getElement(0, y*2));
const uint8_t *i2 = static_cast<uint8_t *>(in.getElement(0, y*2+1));
for (uint32_t x=0; x < w; x++) {
*oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
oPtr ++;
i1 += 2;
i2 += 2;
}
}
}
static void mip(const Adapter2D &out, const Adapter2D &in) {
switch (out.getBaseType()->getElement()->getSizeBits()) {
case 32:
mip8888(out, in);
break;
case 16:
mip565(out, in);
break;
case 8:
mip8(out, in);
break;
}
}
#ifndef ANDROID_RS_BUILD_FOR_HOST
void rsi_AllocationSyncAll(Context *rsc, RsAllocation va, RsAllocationUsageType src) {
Allocation *a = static_cast<Allocation *>(va);
a->syncAll(rsc, src);
a->sendDirty();
}
void rsi_AllocationGenerateMipmaps(Context *rsc, RsAllocation va) {
Allocation *texAlloc = static_cast<Allocation *>(va);
rsaAllocationGenerateScriptMips(rsc, texAlloc);
}
void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t dataLen) {
Allocation *texAlloc = static_cast<Allocation *>(va);
const Type * t = texAlloc->getType();
size_t s = t->getDimX() * t->getDimY() * t->getElementSizeBytes();
if (s != dataLen) {
rsc->setError(RS_ERROR_BAD_VALUE, "Bitmap size didn't match allocation size");
return;
}
memcpy(data, texAlloc->getPtr(), s);
}
void rsi_Allocation1DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t lod,
uint32_t count, const void *data, uint32_t sizeBytes) {
Allocation *a = static_cast<Allocation *>(va);
a->data(rsc, xoff, lod, count, data, sizeBytes);
}
void rsi_Allocation2DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, uint32_t lod, RsAllocationCubemapFace face,
const void *data, uint32_t eoff, uint32_t sizeBytes) {
Allocation *a = static_cast<Allocation *>(va);
a->elementData(rsc, x, y, data, eoff, sizeBytes);
}
void rsi_Allocation1DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t lod,
const void *data, uint32_t eoff, uint32_t sizeBytes) {
Allocation *a = static_cast<Allocation *>(va);
a->elementData(rsc, x, data, eoff, sizeBytes);
}
void rsi_Allocation2DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) {
Allocation *a = static_cast<Allocation *>(va);
a->data(rsc, xoff, yoff, lod, face, w, h, data, sizeBytes);
}
void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data) {
Allocation *a = static_cast<Allocation *>(va);
a->read(data);
}
void rsi_AllocationResize1D(Context *rsc, RsAllocation va, uint32_t dimX) {
Allocation *a = static_cast<Allocation *>(va);
a->resize1D(rsc, dimX);
}
void rsi_AllocationResize2D(Context *rsc, RsAllocation va, uint32_t dimX, uint32_t dimY) {
Allocation *a = static_cast<Allocation *>(va);
a->resize2D(rsc, dimX, dimY);
}
#endif //ANDROID_RS_BUILD_FOR_HOST
}
}
static void rsaAllocationGenerateScriptMips(RsContext con, RsAllocation va) {
Context *rsc = static_cast<Context *>(con);
Allocation *texAlloc = static_cast<Allocation *>(va);
uint32_t numFaces = texAlloc->getType()->getDimFaces() ? 6 : 1;
for (uint32_t face = 0; face < numFaces; face ++) {
Adapter2D adapt(rsc, texAlloc);
Adapter2D adapt2(rsc, texAlloc);
adapt.setFace(face);
adapt2.setFace(face);
for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
adapt.setLOD(lod);
adapt2.setLOD(lod + 1);
mip(adapt2, adapt);
}
}
}
const void * rsaAllocationGetType(RsContext con, RsAllocation va) {
Allocation *a = static_cast<Allocation *>(va);
a->getType()->incUserRef();
return a->getType();
}
RsAllocation rsaAllocationCreateTyped(RsContext con, RsType vtype,
RsAllocationMipmapControl mips,
uint32_t usages) {
Context *rsc = static_cast<Context *>(con);
Allocation * alloc = new Allocation(rsc, static_cast<Type *>(vtype), usages, mips);
alloc->incUserRef();
return alloc;
}
RsAllocation rsaAllocationCreateFromBitmap(RsContext con, RsType vtype,
RsAllocationMipmapControl mips,
const void *data, uint32_t usages) {
Context *rsc = static_cast<Context *>(con);
Type *t = static_cast<Type *>(vtype);
RsAllocation vTexAlloc = rsaAllocationCreateTyped(rsc, vtype, mips, usages);
Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
if (texAlloc == NULL) {
LOGE("Memory allocation failure");
return NULL;
}
memcpy(texAlloc->getPtr(), data, t->getDimX() * t->getDimY() * t->getElementSizeBytes());
if (mips == RS_ALLOCATION_MIPMAP_FULL) {
rsaAllocationGenerateScriptMips(rsc, texAlloc);
}
texAlloc->deferedUploadToTexture(rsc);
return texAlloc;
}
RsAllocation rsaAllocationCubeCreateFromBitmap(RsContext con, RsType vtype,
RsAllocationMipmapControl mips,
const void *data, uint32_t usages) {
Context *rsc = static_cast<Context *>(con);
Type *t = static_cast<Type *>(vtype);
// Cubemap allocation's faces should be Width by Width each.
// Source data should have 6 * Width by Width pixels
// Error checking is done in the java layer
RsAllocation vTexAlloc = rsaAllocationCreateTyped(rsc, t, mips, usages);
Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
if (texAlloc == NULL) {
LOGE("Memory allocation failure");
return NULL;
}
uint32_t faceSize = t->getDimX();
uint32_t strideBytes = faceSize * 6 * t->getElementSizeBytes();
uint32_t copySize = faceSize * t->getElementSizeBytes();
uint8_t *sourcePtr = (uint8_t*)data;
for (uint32_t face = 0; face < 6; face ++) {
Adapter2D faceAdapter(rsc, texAlloc);
faceAdapter.setFace(face);
for (uint32_t dI = 0; dI < faceSize; dI ++) {
memcpy(faceAdapter.getElement(0, dI), sourcePtr + strideBytes * dI, copySize);
}
// Move the data pointer to the next cube face
sourcePtr += copySize;
}
if (mips == RS_ALLOCATION_MIPMAP_FULL) {
rsaAllocationGenerateScriptMips(rsc, texAlloc);
}
texAlloc->deferedUploadToTexture(rsc);
return texAlloc;
}