/*
|
* Copyright (C) 2012 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.
|
*/
|
|
#include <malloc.h>
|
#include <string.h>
|
|
#include "RenderScript.h"
|
#include "rsCppInternal.h"
|
|
// From system/graphics.h
|
enum {
|
HAL_PIXEL_FORMAT_YV12 = 0x32315659, // YCrCb 4:2:0 Planar
|
HAL_PIXEL_FORMAT_YCrCb_420_SP = 0x11, // NV21
|
};
|
|
using android::RSC::Element;
|
using android::RSC::RS;
|
using android::RSC::Type;
|
using android::RSC::sp;
|
|
void Type::calcElementCount() {
|
bool hasLod = hasMipmaps();
|
uint32_t x = getX();
|
uint32_t y = getY();
|
uint32_t z = getZ();
|
uint32_t faces = 1;
|
if (hasFaces()) {
|
faces = 6;
|
}
|
if (x == 0) {
|
x = 1;
|
}
|
if (y == 0) {
|
y = 1;
|
}
|
if (z == 0) {
|
z = 1;
|
}
|
|
uint32_t count = x * y * z * faces;
|
while (hasLod && ((x > 1) || (y > 1) || (z > 1))) {
|
if(x > 1) {
|
x >>= 1;
|
}
|
if(y > 1) {
|
y >>= 1;
|
}
|
if(z > 1) {
|
z >>= 1;
|
}
|
|
count += x * y * z * faces;
|
}
|
mElementCount = count;
|
}
|
|
|
Type::Type(void *id, sp<RS> rs) : BaseObj(id, rs) {
|
mDimX = 0;
|
mDimY = 0;
|
mDimZ = 0;
|
mDimMipmaps = false;
|
mDimFaces = false;
|
mElement = nullptr;
|
mYuvFormat = RS_YUV_NONE;
|
}
|
|
void Type::updateFromNative() {
|
BaseObj::updateFromNative();
|
|
/*
|
* We have 6 integers / pointers (uintptr_t) to obtain from the return buffer:
|
* mDimX (buffer[0]);
|
* mDimY (buffer[1]);
|
* mDimZ (buffer[2]);
|
* mDimLOD (buffer[3]);
|
* mDimFaces (buffer[4]);
|
* mElement (buffer[5]);
|
*/
|
uintptr_t dataBuffer[6];
|
RS::dispatch->TypeGetNativeData(mRS->getContext(), getID(), dataBuffer, 6);
|
|
mDimX = (uint32_t)dataBuffer[0];
|
mDimY = (uint32_t)dataBuffer[1];
|
mDimZ = (uint32_t)dataBuffer[2];
|
mDimMipmaps = dataBuffer[3] == 1 ? true : false;
|
mDimFaces = dataBuffer[4] == 1 ? true : false;
|
|
uintptr_t elementID = dataBuffer[5];
|
if(elementID != 0) {
|
// Just create a new Element and update it from native.
|
sp<Element> e = new Element((void *)elementID, mRS);
|
e->updateFromNative();
|
mElement = e;
|
}
|
calcElementCount();
|
}
|
|
sp<const Type> Type::create(const sp<RS>& rs, const sp<const Element>& e, uint32_t dimX, uint32_t dimY, uint32_t dimZ) {
|
void * id = RS::dispatch->TypeCreate(rs->getContext(), e->getID(), dimX, dimY, dimZ, false, false, 0);
|
Type *t = new Type(id, rs);
|
|
t->mElement = e;
|
t->mDimX = dimX;
|
t->mDimY = dimY;
|
t->mDimZ = dimZ;
|
t->mDimMipmaps = false;
|
t->mDimFaces = false;
|
t->mYuvFormat = RS_YUV_NONE;
|
|
t->calcElementCount();
|
|
return t;
|
}
|
|
Type::Builder::Builder(sp<RS> rs, sp<const Element> e) {
|
mRS = rs.get();
|
mElement = e;
|
mDimX = 0;
|
mDimY = 0;
|
mDimZ = 0;
|
mDimMipmaps = false;
|
mDimFaces = false;
|
mYuvFormat = RS_YUV_NONE;
|
}
|
|
void Type::Builder::setX(uint32_t value) {
|
if(value < 1) {
|
ALOGE("Values of less than 1 for Dimension X are not valid.");
|
}
|
mDimX = value;
|
}
|
|
void Type::Builder::setY(uint32_t value) {
|
if(value < 1) {
|
ALOGE("Values of less than 1 for Dimension Y are not valid.");
|
}
|
mDimY = value;
|
}
|
|
void Type::Builder::setZ(uint32_t value) {
|
if(value < 1) {
|
ALOGE("Values of less than 1 for Dimension Z are not valid.");
|
}
|
mDimZ = value;
|
}
|
|
void Type::Builder::setYuvFormat(RsYuvFormat format) {
|
if (format != RS_YUV_NONE && !(mElement->isCompatible(Element::YUV(mRS)))) {
|
ALOGE("Invalid element for use with YUV.");
|
return;
|
}
|
|
if (format != RS_YUV_NONE &&
|
format != RS_YUV_YV12 &&
|
format != RS_YUV_NV21 &&
|
format != RS_YUV_420_888) {
|
ALOGE("Invalid YUV format.");
|
return;
|
}
|
mYuvFormat = format;
|
}
|
|
|
void Type::Builder::setMipmaps(bool value) {
|
mDimMipmaps = value;
|
}
|
|
void Type::Builder::setFaces(bool value) {
|
mDimFaces = value;
|
}
|
|
sp<const Type> Type::Builder::create() {
|
if (mDimZ > 0) {
|
if ((mDimX < 1) || (mDimY < 1)) {
|
ALOGE("Both X and Y dimension required when Z is present.");
|
return nullptr;
|
}
|
if (mDimFaces) {
|
ALOGE("Cube maps not supported with 3D types.");
|
return nullptr;
|
}
|
}
|
if (mDimY > 0) {
|
if (mDimX < 1) {
|
ALOGE("X dimension required when Y is present.");
|
return nullptr;
|
}
|
}
|
if (mDimFaces) {
|
if (mDimY < 1) {
|
ALOGE("Cube maps require 2D Types.");
|
return nullptr;
|
}
|
}
|
|
if (mYuvFormat != RS_YUV_NONE) {
|
if (mDimZ || mDimFaces || mDimMipmaps) {
|
ALOGE("YUV only supports basic 2D.");
|
return nullptr;
|
}
|
}
|
|
if (mYuvFormat == RS_YUV_420_888) {
|
ALOGE("YUV_420_888 not supported.");
|
return nullptr;
|
}
|
|
void * id = RS::dispatch->TypeCreate(mRS->getContext(), mElement->getID(), mDimX, mDimY, mDimZ,
|
mDimMipmaps, mDimFaces, mYuvFormat);
|
Type *t = new Type(id, mRS);
|
t->mElement = mElement;
|
t->mDimX = mDimX;
|
t->mDimY = mDimY;
|
t->mDimZ = mDimZ;
|
t->mDimMipmaps = mDimMipmaps;
|
t->mDimFaces = mDimFaces;
|
t->mYuvFormat = mYuvFormat;
|
|
t->calcElementCount();
|
return t;
|
}
|