blob: 784553bcc956afa0836c7811a03a646989a86561 [file] [log] [blame]
/*
* 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 namespace android;
using namespace RSC;
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(sp<RS> rs, 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;
}