blob: ab38ec3a39b9aa5748097d3b2ede0aa3eaca1da8 [file] [log] [blame]
#include "rs_core.rsh"
#include "rs_graphics.rsh"
/*****************************************************************************
* CAUTION
*
* The following structure layout provides a more efficient way to access
* internal members of the C++ class Allocation owned by librs. Unfortunately,
* since this class has virtual members, we can't simply use offsetof() or any
* other compiler trickery to dynamically get the appropriate values at
* build-time. This layout may need to be updated whenever
* frameworks/base/libs/rs/rsAllocation.h is modified.
*
* Having the layout information available in this file allows us to
* accelerate functionality like rsAllocationGetDimX(). Without this
* information, we would not be able to inline the bitcode, thus resulting in
* potential runtime performance penalties for tight loops operating on
* allocations.
*
*****************************************************************************/
typedef enum {
RS_ALLOCATION_MIPMAP_NONE = 0,
RS_ALLOCATION_MIPMAP_FULL = 1,
RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE = 2
} rs_allocation_mipmap_control;
typedef struct Allocation {
char __pad[28];
struct {
void * drv;
struct {
const void *type;
uint32_t usageFlags;
rs_allocation_mipmap_control mipmapControl;
uint32_t dimensionX;
uint32_t dimensionY;
uint32_t dimensionZ;
uint32_t elementSizeBytes;
bool hasMipmaps;
bool hasFaces;
bool hasReferences;
void * usrPtr;
int32_t surfaceTextureID;
void * wndSurface;
} state;
struct DrvState {
void * mallocPtr;
} drvState;
} mHal;
} Allocation_t;
/*****************************************************************************
* CAUTION
*
* The following structure layout provides a more efficient way to access
* internal members of the C++ class ProgramStore owned by librs. Unfortunately,
* since this class has virtual members, we can't simply use offsetof() or any
* other compiler trickery to dynamically get the appropriate values at
* build-time. This layout may need to be updated whenever
* frameworks/base/libs/rs/rsProgramStore.h is modified.
*
* Having the layout information available in this file allows us to
* accelerate functionality like rsgProgramStoreGetDepthFunc(). Without this
* information, we would not be able to inline the bitcode, thus resulting in
* potential runtime performance penalties for tight loops operating on
* program store.
*
*****************************************************************************/
typedef struct ProgramStore {
char __pad[36];
struct {
struct {
bool ditherEnable;
bool colorRWriteEnable;
bool colorGWriteEnable;
bool colorBWriteEnable;
bool colorAWriteEnable;
rs_blend_src_func blendSrc;
rs_blend_dst_func blendDst;
bool depthWriteEnable;
rs_depth_func depthFunc;
} state;
} mHal;
} ProgramStore_t;
/*****************************************************************************
* CAUTION
*
* The following structure layout provides a more efficient way to access
* internal members of the C++ class ProgramRaster owned by librs. Unfortunately,
* since this class has virtual members, we can't simply use offsetof() or any
* other compiler trickery to dynamically get the appropriate values at
* build-time. This layout may need to be updated whenever
* frameworks/base/libs/rs/rsProgramRaster.h is modified.
*
* Having the layout information available in this file allows us to
* accelerate functionality like rsgProgramRasterGetCullMode(). Without this
* information, we would not be able to inline the bitcode, thus resulting in
* potential runtime performance penalties for tight loops operating on
* program raster.
*
*****************************************************************************/
typedef struct ProgramRaster {
char __pad[36];
struct {
struct {
bool pointSprite;
rs_cull_mode cull;
} state;
} mHal;
} ProgramRaster_t;
/*****************************************************************************
* CAUTION
*
* The following structure layout provides a more efficient way to access
* internal members of the C++ class Sampler owned by librs. Unfortunately,
* since this class has virtual members, we can't simply use offsetof() or any
* other compiler trickery to dynamically get the appropriate values at
* build-time. This layout may need to be updated whenever
* frameworks/base/libs/rs/rsSampler.h is modified.
*
* Having the layout information available in this file allows us to
* accelerate functionality like rsgProgramRasterGetMagFilter(). Without this
* information, we would not be able to inline the bitcode, thus resulting in
* potential runtime performance penalties for tight loops operating on
* samplers.
*
*****************************************************************************/
typedef struct Sampler {
char __pad[32];
struct {
struct {
rs_sampler_value magFilter;
rs_sampler_value minFilter;
rs_sampler_value wrapS;
rs_sampler_value wrapT;
rs_sampler_value wrapR;
float aniso;
} state;
} mHal;
} Sampler_t;
/*****************************************************************************
* CAUTION
*
* The following structure layout provides a more efficient way to access
* internal members of the C++ class Element owned by librs. Unfortunately,
* since this class has virtual members, we can't simply use offsetof() or any
* other compiler trickery to dynamically get the appropriate values at
* build-time. This layout may need to be updated whenever
* frameworks/base/libs/rs/rsElement.h is modified.
*
* Having the layout information available in this file allows us to
* accelerate functionality like rsElementGetSubElementCount(). Without this
* information, we would not be able to inline the bitcode, thus resulting in
* potential runtime performance penalties for tight loops operating on
* elements.
*
*****************************************************************************/
typedef struct Element {
char __pad[28];
struct {
void *drv;
struct {
rs_data_type dataType;
rs_data_kind dataKind;
uint32_t vectorSize;
uint32_t elementSizeBytes;
// Subelements
const void **fields;
uint32_t *fieldArraySizes;
const char **fieldNames;
uint32_t *fieldNameLengths;
uint32_t *fieldOffsetBytes;
uint32_t fieldsCount;
} state;
} mHal;
} Element_t;
/*****************************************************************************
* CAUTION
*
* The following structure layout provides a more efficient way to access
* internal members of the C++ class Type owned by librs. Unfortunately,
* since this class has virtual members, we can't simply use offsetof() or any
* other compiler trickery to dynamically get the appropriate values at
* build-time. This layout may need to be updated whenever
* frameworks/base/libs/rs/rsType.h is modified.
*
* Having the layout information available in this file allows us to
* accelerate functionality like rsAllocationGetElement(). Without this
* information, we would not be able to inline the bitcode, thus resulting in
* potential runtime performance penalties for tight loops operating on
* types.
*
*****************************************************************************/
typedef struct Type {
char __pad[28];
struct {
void *drv;
struct {
const void * element;
uint32_t dimX;
uint32_t dimY;
uint32_t dimZ;
uint32_t *lodDimX;
uint32_t *lodDimY;
uint32_t *lodDimZ;
uint32_t *lodOffset;
uint32_t lodCount;
bool faces;
} state;
} mHal;
} Type_t;
/*****************************************************************************
* CAUTION
*
* The following structure layout provides a more efficient way to access
* internal members of the C++ class Mesh owned by librs. Unfortunately,
* since this class has virtual members, we can't simply use offsetof() or any
* other compiler trickery to dynamically get the appropriate values at
* build-time. This layout may need to be updated whenever
* frameworks/base/libs/rs/rsMesh.h is modified.
*
* Having the layout information available in this file allows us to
* accelerate functionality like rsMeshGetVertexAllocationCount(). Without this
* information, we would not be able to inline the bitcode, thus resulting in
* potential runtime performance penalties for tight loops operating on
* meshes.
*
*****************************************************************************/
typedef struct Mesh {
char __pad[28];
struct {
void *drv;
struct {
void **vertexBuffers;
uint32_t vertexBuffersCount;
// indexBuffers[i] could be NULL, in which case only primitives[i] is used
void **indexBuffers;
uint32_t indexBuffersCount;
rs_primitive *primitives;
uint32_t primitivesCount;
} state;
} mHal;
} Mesh_t;
/* Declaration of 4 basic functions in libRS */
extern void __attribute__((overloadable))
rsDebug(const char *, float, float);
extern void __attribute__((overloadable))
rsDebug(const char *, float, float, float);
extern void __attribute__((overloadable))
rsDebug(const char *, float, float, float, float);
extern float4 __attribute__((overloadable)) convert_float4(uchar4 c);
/* Implementation of Core Runtime */
extern void __attribute__((overloadable)) rsDebug(const char *s, float2 v) {
rsDebug(s, v.x, v.y);
}
extern void __attribute__((overloadable)) rsDebug(const char *s, float3 v) {
rsDebug(s, v.x, v.y, v.z);
}
extern void __attribute__((overloadable)) rsDebug(const char *s, float4 v) {
rsDebug(s, v.x, v.y, v.z, v.w);
}
/*
extern uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b)
{
uchar4 c;
c.x = (uchar)(r * 255.f + 0.5f);
c.y = (uchar)(g * 255.f + 0.5f);
c.z = (uchar)(b * 255.f + 0.5f);
c.w = 255;
return c;
}
extern uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b, float a)
{
uchar4 c;
c.x = (uchar)(r * 255.f + 0.5f);
c.y = (uchar)(g * 255.f + 0.5f);
c.z = (uchar)(b * 255.f + 0.5f);
c.w = (uchar)(a * 255.f + 0.5f);
return c;
}
extern uchar4 __attribute__((overloadable)) rsPackColorTo8888(float3 color)
{
color *= 255.f;
color += 0.5f;
uchar4 c = {color.x, color.y, color.z, 255};
return c;
}
extern uchar4 __attribute__((overloadable)) rsPackColorTo8888(float4 color)
{
color *= 255.f;
color += 0.5f;
uchar4 c = {color.x, color.y, color.z, color.w};
return c;
}
*/
extern float4 rsUnpackColor8888(uchar4 c)
{
float4 ret = (float4)0.003921569f;
ret *= convert_float4(c);
return ret;
}
/////////////////////////////////////////////////////
// Matrix ops
/////////////////////////////////////////////////////
extern void __attribute__((overloadable))
rsMatrixSet(rs_matrix4x4 *m, uint32_t row, uint32_t col, float v) {
m->m[row * 4 + col] = v;
}
extern float __attribute__((overloadable))
rsMatrixGet(const rs_matrix4x4 *m, uint32_t row, uint32_t col) {
return m->m[row * 4 + col];
}
extern void __attribute__((overloadable))
rsMatrixSet(rs_matrix3x3 *m, uint32_t row, uint32_t col, float v) {
m->m[row * 3 + col] = v;
}
extern float __attribute__((overloadable))
rsMatrixGet(const rs_matrix3x3 *m, uint32_t row, uint32_t col) {
return m->m[row * 3 + col];
}
extern void __attribute__((overloadable))
rsMatrixSet(rs_matrix2x2 *m, uint32_t row, uint32_t col, float v) {
m->m[row * 2 + col] = v;
}
extern float __attribute__((overloadable))
rsMatrixGet(const rs_matrix2x2 *m, uint32_t row, uint32_t col) {
return m->m[row * 2 + col];
}
/*
extern float4 __attribute__((overloadable))
rsMatrixMultiply(const rs_matrix4x4 *m, float4 in) {
float4 ret;
ret.x = (m->m[0] * in.x) + (m->m[4] * in.y) + (m->m[8] * in.z) + (m->m[12] * in.w);
ret.y = (m->m[1] * in.x) + (m->m[5] * in.y) + (m->m[9] * in.z) + (m->m[13] * in.w);
ret.z = (m->m[2] * in.x) + (m->m[6] * in.y) + (m->m[10] * in.z) + (m->m[14] * in.w);
ret.w = (m->m[3] * in.x) + (m->m[7] * in.y) + (m->m[11] * in.z) + (m->m[15] * in.w);
return ret;
}
extern float4 __attribute__((overloadable))
rsMatrixMultiply(rs_matrix4x4 *m, float4 in) {
return rsMatrixMultiply((const rs_matrix4x4 *)m, in);
}
extern float4 __attribute__((overloadable))
rsMatrixMultiply(const rs_matrix4x4 *m, float3 in) {
float4 ret;
ret.x = (m->m[0] * in.x) + (m->m[4] * in.y) + (m->m[8] * in.z) + m->m[12];
ret.y = (m->m[1] * in.x) + (m->m[5] * in.y) + (m->m[9] * in.z) + m->m[13];
ret.z = (m->m[2] * in.x) + (m->m[6] * in.y) + (m->m[10] * in.z) + m->m[14];
ret.w = (m->m[3] * in.x) + (m->m[7] * in.y) + (m->m[11] * in.z) + m->m[15];
return ret;
}
extern float4 __attribute__((overloadable))
rsMatrixMultiply(rs_matrix4x4 *m, float3 in) {
return rsMatrixMultiply((const rs_matrix4x4 *)m, in);
}
extern float4 __attribute__((overloadable))
rsMatrixMultiply(const rs_matrix4x4 *m, float2 in) {
float4 ret;
ret.x = (m->m[0] * in.x) + (m->m[4] * in.y) + m->m[12];
ret.y = (m->m[1] * in.x) + (m->m[5] * in.y) + m->m[13];
ret.z = (m->m[2] * in.x) + (m->m[6] * in.y) + m->m[14];
ret.w = (m->m[3] * in.x) + (m->m[7] * in.y) + m->m[15];
return ret;
}
extern float4 __attribute__((overloadable))
rsMatrixMultiply(rs_matrix4x4 *m, float2 in) {
return rsMatrixMultiply((const rs_matrix4x4 *)m, in);
}
extern float3 __attribute__((overloadable))
rsMatrixMultiply(const rs_matrix3x3 *m, float3 in) {
float3 ret;
ret.x = (m->m[0] * in.x) + (m->m[3] * in.y) + (m->m[6] * in.z);
ret.y = (m->m[1] * in.x) + (m->m[4] * in.y) + (m->m[7] * in.z);
ret.z = (m->m[2] * in.x) + (m->m[5] * in.y) + (m->m[8] * in.z);
return ret;
}
extern float3 __attribute__((overloadable))
rsMatrixMultiply(rs_matrix3x3 *m, float3 in) {
return rsMatrixMultiply((const rs_matrix3x3 *)m, in);
}
extern float3 __attribute__((overloadable))
rsMatrixMultiply(const rs_matrix3x3 *m, float2 in) {
float3 ret;
ret.x = (m->m[0] * in.x) + (m->m[3] * in.y);
ret.y = (m->m[1] * in.x) + (m->m[4] * in.y);
ret.z = (m->m[2] * in.x) + (m->m[5] * in.y);
return ret;
}
extern float3 __attribute__((overloadable))
rsMatrixMultiply(rs_matrix3x3 *m, float2 in) {
return rsMatrixMultiply((const rs_matrix3x3 *)m, in);
}
*/
extern float2 __attribute__((overloadable))
rsMatrixMultiply(const rs_matrix2x2 *m, float2 in) {
float2 ret;
ret.x = (m->m[0] * in.x) + (m->m[2] * in.y);
ret.y = (m->m[1] * in.x) + (m->m[3] * in.y);
return ret;
}
extern float2 __attribute__((overloadable))
rsMatrixMultiply(rs_matrix2x2 *m, float2 in) {
return rsMatrixMultiply((const rs_matrix2x2 *)m, in);
}
/////////////////////////////////////////////////////
// int ops
/////////////////////////////////////////////////////
/*extern uint __attribute__((overloadable, always_inline)) rsClamp(uint amount, uint low, uint high) {
return amount < low ? low : (amount > high ? high : amount);
}*/
extern int __attribute__((overloadable, always_inline)) rsClamp(int amount, int low, int high) {
return amount < low ? low : (amount > high ? high : amount);
}
extern ushort __attribute__((overloadable, always_inline)) rsClamp(ushort amount, ushort low, ushort high) {
return amount < low ? low : (amount > high ? high : amount);
}
extern short __attribute__((overloadable, always_inline)) rsClamp(short amount, short low, short high) {
return amount < low ? low : (amount > high ? high : amount);
}
extern uchar __attribute__((overloadable, always_inline)) rsClamp(uchar amount, uchar low, uchar high) {
return amount < low ? low : (amount > high ? high : amount);
}
extern char __attribute__((overloadable, always_inline)) rsClamp(char amount, char low, char high) {
return amount < low ? low : (amount > high ? high : amount);
}
// Opaque Allocation type operations
extern uint32_t __attribute__((overloadable))
rsAllocationGetDimX(rs_allocation a) {
Allocation_t *alloc = (Allocation_t *)a.p;
return alloc->mHal.state.dimensionX;
}
extern uint32_t __attribute__((overloadable))
rsAllocationGetDimY(rs_allocation a) {
Allocation_t *alloc = (Allocation_t *)a.p;
return alloc->mHal.state.dimensionY;
}
extern uint32_t __attribute__((overloadable))
rsAllocationGetDimZ(rs_allocation a) {
Allocation_t *alloc = (Allocation_t *)a.p;
return alloc->mHal.state.dimensionZ;
}
extern uint32_t __attribute__((overloadable))
rsAllocationGetDimLOD(rs_allocation a) {
Allocation_t *alloc = (Allocation_t *)a.p;
return alloc->mHal.state.hasMipmaps;
}
extern uint32_t __attribute__((overloadable))
rsAllocationGetDimFaces(rs_allocation a) {
Allocation_t *alloc = (Allocation_t *)a.p;
return alloc->mHal.state.hasFaces;
}
extern const void * __attribute__((overloadable))
rsGetElementAt(rs_allocation a, uint32_t x) {
Allocation_t *alloc = (Allocation_t *)a.p;
const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.mallocPtr;
const uint32_t eSize = alloc->mHal.state.elementSizeBytes;
return &p[eSize * x];
}
extern const void * __attribute__((overloadable))
rsGetElementAt(rs_allocation a, uint32_t x, uint32_t y) {
Allocation_t *alloc = (Allocation_t *)a.p;
const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.mallocPtr;
const uint32_t eSize = alloc->mHal.state.elementSizeBytes;
const uint32_t dimX = alloc->mHal.state.dimensionX;
return &p[eSize * (x + y * dimX)];
}
extern const void * __attribute__((overloadable))
rsGetElementAt(rs_allocation a, uint32_t x, uint32_t y, uint32_t z) {
Allocation_t *alloc = (Allocation_t *)a.p;
const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.mallocPtr;
const uint32_t eSize = alloc->mHal.state.elementSizeBytes;
const uint32_t dimX = alloc->mHal.state.dimensionX;
const uint32_t dimY = alloc->mHal.state.dimensionY;
return &p[eSize * (x + y * dimX + z * dimX * dimY)];
}
extern rs_element __attribute__((overloadable))
rsAllocationGetElement(rs_allocation a) {
Allocation_t *alloc = (Allocation_t *)a.p;
if (alloc == NULL) {
rs_element nullElem = {0};
return nullElem;
}
Type_t *type = (Type_t *)alloc->mHal.state.type;
rs_element returnElem = {type->mHal.state.element};
return returnElem;
}
/**
* Program Store
*/
extern rs_depth_func __attribute__((overloadable))
rsgProgramStoreGetDepthFunc(rs_program_store ps) {
ProgramStore_t *prog = (ProgramStore_t *)ps.p;
if (prog == NULL) {
return RS_DEPTH_FUNC_INVALID;
}
return prog->mHal.state.depthFunc;
}
extern bool __attribute__((overloadable))
rsgProgramStoreGetDepthMask(rs_program_store ps) {
ProgramStore_t *prog = (ProgramStore_t *)ps.p;
if (prog == NULL) {
return false;
}
return prog->mHal.state.depthWriteEnable;
}
extern bool __attribute__((overloadable))
rsgProgramStoreGetColorMaskR(rs_program_store ps) {
ProgramStore_t *prog = (ProgramStore_t *)ps.p;
if (prog == NULL) {
return false;
}
return prog->mHal.state.colorRWriteEnable;
}
extern bool __attribute__((overloadable))
rsgProgramStoreGetColorMaskG(rs_program_store ps) {
ProgramStore_t *prog = (ProgramStore_t *)ps.p;
if (prog == NULL) {
return false;
}
return prog->mHal.state.colorGWriteEnable;
}
extern bool __attribute__((overloadable))
rsgProgramStoreGetColorMaskB(rs_program_store ps) {
ProgramStore_t *prog = (ProgramStore_t *)ps.p;
if (prog == NULL) {
return false;
}
return prog->mHal.state.colorBWriteEnable;
}
extern bool __attribute__((overloadable))
rsgProgramStoreGetColorMaskA(rs_program_store ps) {
ProgramStore_t *prog = (ProgramStore_t *)ps.p;
if (prog == NULL) {
return false;
}
return prog->mHal.state.colorAWriteEnable;
}
extern rs_blend_src_func __attribute__((overloadable))
rsgProgramStoreGetBlendSrcFunc(rs_program_store ps) {
ProgramStore_t *prog = (ProgramStore_t *)ps.p;
if (prog == NULL) {
return RS_BLEND_SRC_INVALID;
}
return prog->mHal.state.blendSrc;
}
extern rs_blend_dst_func __attribute__((overloadable))
rsgProgramStoreGetBlendDstFunc(rs_program_store ps) {
ProgramStore_t *prog = (ProgramStore_t *)ps.p;
if (prog == NULL) {
return RS_BLEND_DST_INVALID;
}
return prog->mHal.state.blendDst;
}
extern bool __attribute__((overloadable))
rsgProgramStoreGetDitherEnabled(rs_program_store ps) {
ProgramStore_t *prog = (ProgramStore_t *)ps.p;
if (prog == NULL) {
return false;
}
return prog->mHal.state.ditherEnable;
}
/**
* Program Raster
*/
extern bool __attribute__((overloadable))
rsgProgramRasterGetPointSpriteEnabled(rs_program_raster pr) {
ProgramRaster_t *prog = (ProgramRaster_t *)pr.p;
if (prog == NULL) {
return false;
}
return prog->mHal.state.pointSprite;
}
extern rs_cull_mode __attribute__((overloadable))
rsgProgramRasterGetCullMode(rs_program_raster pr) {
ProgramRaster_t *prog = (ProgramRaster_t *)pr.p;
if (prog == NULL) {
return RS_CULL_INVALID;
}
return prog->mHal.state.cull;
}
/**
* Sampler
*/
extern rs_sampler_value __attribute__((overloadable))
rsgSamplerGetMinification(rs_sampler s) {
Sampler_t *prog = (Sampler_t *)s.p;
if (prog == NULL) {
return RS_SAMPLER_INVALID;
}
return prog->mHal.state.minFilter;
}
extern rs_sampler_value __attribute__((overloadable))
rsgSamplerGetMagnification(rs_sampler s) {
Sampler_t *prog = (Sampler_t *)s.p;
if (prog == NULL) {
return RS_SAMPLER_INVALID;
}
return prog->mHal.state.magFilter;
}
extern rs_sampler_value __attribute__((overloadable))
rsgSamplerGetWrapS(rs_sampler s) {
Sampler_t *prog = (Sampler_t *)s.p;
if (prog == NULL) {
return RS_SAMPLER_INVALID;
}
return prog->mHal.state.wrapS;
}
extern rs_sampler_value __attribute__((overloadable))
rsgSamplerGetWrapT(rs_sampler s) {
Sampler_t *prog = (Sampler_t *)s.p;
if (prog == NULL) {
return RS_SAMPLER_INVALID;
}
return prog->mHal.state.wrapT;
}
extern float __attribute__((overloadable))
rsgSamplerGetAnisotropy(rs_sampler s) {
Sampler_t *prog = (Sampler_t *)s.p;
if (prog == NULL) {
return 0.0f;
}
return prog->mHal.state.aniso;
}
/**
* Mesh
*/
extern uint32_t __attribute__((overloadable))
rsMeshGetVertexAllocationCount(rs_mesh m) {
Mesh_t *mesh = (Mesh_t *)m.p;
if (mesh == NULL) {
return 0;
}
return mesh->mHal.state.vertexBuffersCount;
}
extern uint32_t __attribute__((overloadable))
rsMeshGetPrimitiveCount(rs_mesh m) {
Mesh_t *mesh = (Mesh_t *)m.p;
if (mesh == NULL) {
return 0;
}
return mesh->mHal.state.primitivesCount;
}
extern rs_allocation __attribute__((overloadable))
rsMeshGetVertexAllocation(rs_mesh m, uint32_t index) {
Mesh_t *mesh = (Mesh_t *)m.p;
if (mesh == NULL || index >= mesh->mHal.state.vertexBuffersCount) {
rs_allocation nullAlloc = {0};
return nullAlloc;
}
rs_allocation returnAlloc = {mesh->mHal.state.vertexBuffers[index]};
return returnAlloc;
}
extern rs_allocation __attribute__((overloadable))
rsMeshGetIndexAllocation(rs_mesh m, uint32_t index) {
Mesh_t *mesh = (Mesh_t *)m.p;
if (mesh == NULL || index >= mesh->mHal.state.primitivesCount) {
rs_allocation nullAlloc = {0};
return nullAlloc;
}
rs_allocation returnAlloc = {mesh->mHal.state.indexBuffers[index]};
return returnAlloc;
}
extern rs_primitive __attribute__((overloadable))
rsMeshGetPrimitive(rs_mesh m, uint32_t index) {
Mesh_t *mesh = (Mesh_t *)m.p;
if (mesh == NULL || index >= mesh->mHal.state.primitivesCount) {
return RS_PRIMITIVE_INVALID;
}
return mesh->mHal.state.primitives[index];
}
/**
* Element
*/
extern uint32_t __attribute__((overloadable))
rsElementGetSubElementCount(rs_element e) {
Element_t *element = (Element_t *)e.p;
if (element == NULL) {
return 0;
}
return element->mHal.state.fieldsCount;
}
extern rs_element __attribute__((overloadable))
rsElementGetSubElement(rs_element e, uint32_t index) {
Element_t *element = (Element_t *)e.p;
if (element == NULL || index >= element->mHal.state.fieldsCount) {
rs_element nullElem = {0};
return nullElem;
}
rs_element returnElem = {element->mHal.state.fields[index]};
return returnElem;
}
extern uint32_t __attribute__((overloadable))
rsElementGetSubElementNameLength(rs_element e, uint32_t index) {
Element_t *element = (Element_t *)e.p;
if (element == NULL || index >= element->mHal.state.fieldsCount) {
return 0;
}
return element->mHal.state.fieldNameLengths[index];
}
extern uint32_t __attribute__((overloadable))
rsElementGetSubElementName(rs_element e, uint32_t index, char *name, uint32_t nameLength) {
Element_t *element = (Element_t *)e.p;
if (element == NULL || index >= element->mHal.state.fieldsCount ||
nameLength == 0 || name == 0) {
return 0;
}
uint32_t numToCopy = element->mHal.state.fieldNameLengths[index];
if (nameLength < numToCopy) {
numToCopy = nameLength;
}
// Place the null terminator manually, in case of partial string
numToCopy --;
name[numToCopy] = '\0';
const char *nameSource = element->mHal.state.fieldNames[index];
for (uint32_t i = 0; i < numToCopy; i ++) {
name[i] = nameSource[i];
}
return numToCopy;
}
extern uint32_t __attribute__((overloadable))
rsElementGetSubElementArraySize(rs_element e, uint32_t index) {
Element_t *element = (Element_t *)e.p;
if (element == NULL || index >= element->mHal.state.fieldsCount) {
return 0;
}
return element->mHal.state.fieldArraySizes[index];
}
extern uint32_t __attribute__((overloadable))
rsElementGetSubElementOffsetBytes(rs_element e, uint32_t index) {
Element_t *element = (Element_t *)e.p;
if (element == NULL || index >= element->mHal.state.fieldsCount) {
return 0;
}
return element->mHal.state.fieldOffsetBytes[index];
}
extern uint32_t __attribute__((overloadable))
rsElementGetSizeBytes(rs_element e) {
Element_t *element = (Element_t *)e.p;
if (element == NULL) {
return 0;
}
return element->mHal.state.elementSizeBytes;
}
extern rs_data_type __attribute__((overloadable))
rsElementGetDataType(rs_element e) {
Element_t *element = (Element_t *)e.p;
if (element == NULL) {
return RS_TYPE_INVALID;
}
return element->mHal.state.dataType;
}
extern rs_data_kind __attribute__((overloadable))
rsElementGetDataKind(rs_element e) {
Element_t *element = (Element_t *)e.p;
if (element == NULL) {
return RS_KIND_INVALID;
}
return element->mHal.state.dataKind;
}
extern uint32_t __attribute__((overloadable))
rsElementGetVectorSize(rs_element e) {
Element_t *element = (Element_t *)e.p;
if (element == NULL) {
return 0;
}
return element->mHal.state.vectorSize;
}
/**
* Allocation sampling
*/
static const void * __attribute__((overloadable))
getElementAt(rs_allocation a, uint32_t x, uint32_t lod) {
Allocation_t *alloc = (Allocation_t *)a.p;
const Type_t *type = (const Type_t*)alloc->mHal.state.type;
const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.mallocPtr;
const uint32_t offset = type->mHal.state.lodOffset[lod];
const uint32_t eSize = alloc->mHal.state.elementSizeBytes;
return &p[offset + eSize * x];
}
static const void * __attribute__((overloadable))
getElementAt(rs_allocation a, uint32_t x, uint32_t y, uint32_t lod) {
Allocation_t *alloc = (Allocation_t *)a.p;
const Type_t *type = (const Type_t*)alloc->mHal.state.type;
const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.mallocPtr;
const uint32_t eSize = alloc->mHal.state.elementSizeBytes;
const uint32_t offset = type->mHal.state.lodOffset[lod];
const uint32_t lodDimX = type->mHal.state.lodDimX[lod];
return &p[offset + eSize * (x + y * lodDimX)];
}
static int32_t wrapI(rs_sampler_value wrap, int32_t coord, int32_t size) {
if (wrap == RS_SAMPLER_WRAP) {
coord = coord % size;
if (coord < 0) {
coord += size;
}
}
return max(0, min(coord, size - 1));
}
#define convert_float(v) (float)v
#define SAMPLE_1D_FUNC(vecsize) \
static float##vecsize get1DSample##vecsize(rs_allocation a, float2 weights, \
int iPixel, int next, uint32_t lod) { \
uchar##vecsize *p0c = (uchar##vecsize*)getElementAt(a, iPixel, lod); \
uchar##vecsize *p1c = (uchar##vecsize*)getElementAt(a, next, lod); \
float##vecsize p0 = convert_float##vecsize(*p0c); \
float##vecsize p1 = convert_float##vecsize(*p1c); \
return p0 * weights.x + p1 * weights.y; \
}
#define SAMPLE_2D_FUNC(vecsize) \
static float##vecsize get2DSample##vecsize(rs_allocation a, float4 weights, \
int2 iPixel, int nextX, int nextY, \
uint32_t lod) { \
uchar##vecsize *p0c = (uchar##vecsize*)getElementAt(a, iPixel.x, iPixel.y, lod); \
uchar##vecsize *p1c = (uchar##vecsize*)getElementAt(a, nextX, iPixel.y, lod); \
uchar##vecsize *p2c = (uchar##vecsize*)getElementAt(a, iPixel.x, nextY, lod); \
uchar##vecsize *p3c = (uchar##vecsize*)getElementAt(a, nextX, nextY, lod); \
float##vecsize p0 = convert_float##vecsize(*p0c); \
float##vecsize p1 = convert_float##vecsize(*p1c); \
float##vecsize p2 = convert_float##vecsize(*p2c); \
float##vecsize p3 = convert_float##vecsize(*p3c); \
return p0 * weights.x + p1 * weights.y + p2 * weights.z + p3 * weights.w; \
}
SAMPLE_1D_FUNC()
SAMPLE_1D_FUNC(2)
SAMPLE_1D_FUNC(3)
SAMPLE_1D_FUNC(4)
SAMPLE_2D_FUNC()
SAMPLE_2D_FUNC(2)
SAMPLE_2D_FUNC(3)
SAMPLE_2D_FUNC(4)
// TODO: implement 565
static float4 getBilinearSample565(rs_allocation a, float4 weights,
int2 iPixel, int nextX, int nextY, uint32_t lod) {
float4 zero = {0.0f, 0.0f, 0.0f, 0.0f};
return zero;
}
static float4 getBilinearSample(rs_allocation a, float4 weights,
int2 iPixel, int nextX, int nextY,
uint32_t vecSize, rs_data_type dt, uint32_t lod) {
if (dt == RS_TYPE_UNSIGNED_5_6_5) {
return getBilinearSample565(a, weights, iPixel, nextX, nextY, lod);
}
float4 result;
switch(vecSize) {
case 1:
result.x = get2DSample(a, weights, iPixel, nextX, nextY, lod);
break;
case 2:
result.xy = get2DSample2(a, weights, iPixel, nextX, nextY, lod);
break;
case 3:
result.xyz = get2DSample3(a, weights, iPixel, nextX, nextY, lod);
break;
case 4:
result = get2DSample4(a, weights, iPixel, nextX, nextY, lod);
break;
}
return result;
}
static float4 getNearestSample(rs_allocation a, int2 iPixel, uint32_t vecSize,
rs_data_type dt, uint32_t lod) {
if (dt == RS_TYPE_UNSIGNED_5_6_5) {
float4 zero = {0.0f, 0.0f, 0.0f, 0.0f};
return zero;
}
float4 result;
switch(vecSize) {
case 1:
result.x = convert_float(*((uchar*)getElementAt(a, iPixel.x, iPixel.y, lod)));
break;
case 2:
result.xy = convert_float2(*((uchar2*)getElementAt(a, iPixel.x, iPixel.y, lod)));
break;
case 3:
result.xyz = convert_float3(*((uchar3*)getElementAt(a, iPixel.x, iPixel.y, lod)));
break;
case 4:
result = convert_float4(*((uchar4*)getElementAt(a, iPixel.x, iPixel.y, lod)));
break;
}
return result;
}
extern const float4 __attribute__((overloadable))
rsSample(rs_allocation a, rs_sampler s, float location) {
return rsSample(a, s, location, 0);
}
//TODO: implement 1D sampling
extern const float4 __attribute__((overloadable))
rsSample(rs_allocation a, rs_sampler s, float location, float lod) {
float4 result;
return result;
}
extern const float4 __attribute__((overloadable))
rsSample(rs_allocation a, rs_sampler s, float2 location) {
return rsSample(a, s, location, 0.0f);
}
static float4 sample_LOD_LinearPixel(rs_allocation a, const Type_t *type,
uint32_t vecSize, rs_data_type dt,
rs_sampler s,
float2 uv, uint32_t lod) {
rs_sampler_value wrapS = rsgSamplerGetWrapS(s);
rs_sampler_value wrapT = rsgSamplerGetWrapT(s);
int32_t sourceW = type->mHal.state.lodDimX[lod];
int32_t sourceH = type->mHal.state.lodDimY[lod];
float2 dimF;
dimF.x = (float)(sourceW);
dimF.y = (float)(sourceH);
float2 pixelUV = uv * dimF;
int2 iPixel = convert_int2(pixelUV);
float2 frac = pixelUV - convert_float2(iPixel);
if (frac.x < 0.5f) {
iPixel.x -= 1;
frac.x += 0.5f;
} else {
frac.x -= 0.5f;
}
if (frac.y < 0.5f) {
iPixel.y -= 1;
frac.y += 0.5f;
} else {
frac.y -= 0.5f;
}
float2 oneMinusFrac = 1.0f - frac;
float4 weights;
weights.x = oneMinusFrac.x * oneMinusFrac.y;
weights.y = frac.x * oneMinusFrac.y;
weights.z = oneMinusFrac.x * frac.y;
weights.w = frac.x * frac.y;
int32_t nextX = wrapI(wrapS, iPixel.x + 1, sourceW);
int32_t nextY = wrapI(wrapT, iPixel.y + 1, sourceH);
iPixel.x = wrapI(wrapS, iPixel.x, sourceW);
iPixel.y = wrapI(wrapT, iPixel.y, sourceH);
return getBilinearSample(a, weights, iPixel, nextX, nextY, vecSize, dt, lod);
}
static float4 sample_LOD_NearestPixel(rs_allocation a, const Type_t *type,
uint32_t vecSize, rs_data_type dt,
rs_sampler s,
float2 uv, uint32_t lod) {
rs_sampler_value wrapS = rsgSamplerGetWrapS(s);
rs_sampler_value wrapT = rsgSamplerGetWrapT(s);
int32_t sourceW = type->mHal.state.lodDimX[lod];
int32_t sourceH = type->mHal.state.lodDimY[lod];
float2 dimF;
dimF.x = (float)(sourceW);
dimF.y = (float)(sourceH);
int2 iPixel = convert_int2(uv * dimF);
iPixel.x = wrapI(wrapS, iPixel.x, sourceW);
iPixel.y = wrapI(wrapT, iPixel.y, sourceH);
return getNearestSample(a, iPixel, vecSize, dt, lod);
}
extern const float4 __attribute__((overloadable))
rsSample(rs_allocation a, rs_sampler s, float2 uv, float lod) {
// Find out what kind of input data we are sampling
rs_element elem = rsAllocationGetElement(a);
rs_data_kind dk = rsElementGetDataKind(elem);
rs_data_type dt = rsElementGetDataType(elem);
if (dk == RS_KIND_USER || (dt != RS_TYPE_UNSIGNED_8 && dt != RS_TYPE_UNSIGNED_5_6_5)) {
float4 zero = {0.0f, 0.0f, 0.0f, 0.0f};
return zero;
}
uint32_t vecSize = rsElementGetVectorSize(elem);
Allocation_t *alloc = (Allocation_t *)a.p;
const Type_t *type = (const Type_t*)alloc->mHal.state.type;
rs_sampler_value sampleMin = rsgSamplerGetMinification(s);
rs_sampler_value sampleMag = rsgSamplerGetMagnification(s);
if (sampleMin == RS_SAMPLER_NEAREST &&
sampleMag == RS_SAMPLER_NEAREST) {
return sample_LOD_NearestPixel(a, type, vecSize, dt, s, uv, 0);
}
if (sampleMin == RS_SAMPLER_LINEAR_MIP_NEAREST) {
// clamp the lod to between zero and the highest available
lod = clamp(lod, 0.0f, (float)(type->mHal.state.lodCount - 1));
uint32_t nearestLOD = (uint32_t)round(lod);
return sample_LOD_LinearPixel(a, type, vecSize, dt, s, uv, nearestLOD);
}
if (sampleMin == RS_SAMPLER_LINEAR_MIP_LINEAR) {
// clamp the lod to between zero and the highest available
lod = clamp(lod, 0.0f, (float)(type->mHal.state.lodCount - 1));
uint32_t lod0 = (uint32_t)floor(lod);
uint32_t lod1 = (uint32_t)ceil(lod);
float4 sample0 = sample_LOD_LinearPixel(a, type, vecSize, dt, s, uv, lod0);
float4 sample1 = sample_LOD_LinearPixel(a, type, vecSize, dt, s, uv, lod1);
float frac = lod - (float)lod0;
return sample0 * (1.0f - frac) + sample1 * frac;
}
return sample_LOD_LinearPixel(a, type, vecSize, dt, s, uv, 0);
}
// TODO: implement cubemap lookups
extern const float4 __attribute__((overloadable))
rsSample(rs_allocation a, rs_sampler s, float3 location) {
return rsSample(a, s, location, 0.0f);
}
// TODO: implement cubemap lookups
extern const float4 __attribute__((overloadable))
rsSample(rs_allocation a, rs_sampler s, float3 location, float lod) {
float4 result;
return result;
}
#undef convert_float