Add "boxed" bitmap uploads which simply place a non-pow2 bitmap into the smallest larger pow texture. The added space is filled black.

This commit is contained in:
Jason Sams
2009-07-28 12:02:16 -07:00
parent 8af858e9b6
commit b0ec1b46d6
17 changed files with 647 additions and 205 deletions

View File

@ -96,6 +96,7 @@ public class RenderScript {
native private int nAllocationCreatePredefSized(int predef, int count);
native private int nAllocationCreateSized(int elem, int count);
native private int nAllocationCreateFromBitmap(int dstFmt, boolean genMips, Bitmap bmp);
native private int nAllocationCreateFromBitmapBoxed(int dstFmt, boolean genMips, Bitmap bmp);
native private void nAllocationUploadToTexture(int alloc, int baseMioLevel);
native private void nAllocationDestroy(int alloc);
@ -529,7 +530,12 @@ public class RenderScript {
}
public Allocation allocationCreateFromBitmap(Bitmap b, ElementPredefined dstFmt, boolean genMips) {
int id = nAllocationCreateFromBitmap(dstFmt.mID, genMips, b);
int id = nAllocationCreateFromBitmap(dstFmt.mID, genMips, b);
return new Allocation(id);
}
public Allocation allocationCreateFromBitmapBoxed(Bitmap b, ElementPredefined dstFmt, boolean genMips) {
int id = nAllocationCreateFromBitmapBoxed(dstFmt.mID, genMips, b);
return new Allocation(id);
}

View File

@ -291,6 +291,29 @@ nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, jint dstFmt, jboolean g
return 0;
}
static int
nAllocationCreateFromBitmapBoxed(JNIEnv *_env, jobject _this, jint dstFmt, jboolean genMips, jobject jbitmap)
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
SkBitmap const * nativeBitmap =
(SkBitmap const *)_env->GetIntField(jbitmap, gNativeBitmapID);
const SkBitmap& bitmap(*nativeBitmap);
SkBitmap::Config config = bitmap.getConfig();
RsElementPredefined e = SkBitmapToPredefined(config);
if (e != RS_ELEMENT_USER_U8) {
bitmap.lockPixels();
const int w = bitmap.width();
const int h = bitmap.height();
const void* ptr = bitmap.getPixels();
jint id = (jint)rsAllocationCreateFromBitmapBoxed(w, h, (RsElementPredefined)dstFmt, e, genMips, ptr);
bitmap.unlockPixels();
return id;
}
return 0;
}
static void
nAllocationDestroy(JNIEnv *_env, jobject _this, jint a)
@ -994,6 +1017,7 @@ static JNINativeMethod methods[] = {
{"nAllocationCreatePredefSized", "(II)I", (void*)nAllocationCreatePredefSized },
{"nAllocationCreateSized", "(II)I", (void*)nAllocationCreateSized },
{"nAllocationCreateFromBitmap", "(IZLandroid/graphics/Bitmap;)I", (void*)nAllocationCreateFromBitmap },
{"nAllocationCreateFromBitmapBoxed","(IZLandroid/graphics/Bitmap;)I", (void*)nAllocationCreateFromBitmapBoxed },
{"nAllocationUploadToTexture", "(II)V", (void*)nAllocationUploadToTexture },
{"nAllocationDestroy", "(I)V", (void*)nAllocationDestroy },
{"nAllocationData", "(I[I)V", (void*)nAllocationData_i },

View File

@ -146,26 +146,26 @@ enum RsDepthFunc {
};
enum RsBlendSrcFunc {
RS_BLEND_SRC_ZERO,
RS_BLEND_SRC_ONE,
RS_BLEND_SRC_DST_COLOR,
RS_BLEND_SRC_ONE_MINUS_DST_COLOR,
RS_BLEND_SRC_SRC_ALPHA,
RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA,
RS_BLEND_SRC_DST_ALPHA,
RS_BLEND_SRC_ONE_MINUS_DST_ALPHA,
RS_BLEND_SRC_SRC_ALPHA_SATURATE
RS_BLEND_SRC_ZERO, // 0
RS_BLEND_SRC_ONE, // 1
RS_BLEND_SRC_DST_COLOR, // 2
RS_BLEND_SRC_ONE_MINUS_DST_COLOR, // 3
RS_BLEND_SRC_SRC_ALPHA, // 4
RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA, // 5
RS_BLEND_SRC_DST_ALPHA, // 6
RS_BLEND_SRC_ONE_MINUS_DST_ALPHA, // 7
RS_BLEND_SRC_SRC_ALPHA_SATURATE // 8
};
enum RsBlendDstFunc {
RS_BLEND_DST_ZERO,
RS_BLEND_DST_ONE,
RS_BLEND_DST_SRC_COLOR,
RS_BLEND_DST_ONE_MINUS_SRC_COLOR,
RS_BLEND_DST_SRC_ALPHA,
RS_BLEND_DST_ONE_MINUS_SRC_ALPHA,
RS_BLEND_DST_DST_ALPHA,
RS_BLEND_DST_ONE_MINUS_DST_ALPHA
RS_BLEND_DST_ZERO, // 0
RS_BLEND_DST_ONE, // 1
RS_BLEND_DST_SRC_COLOR, // 2
RS_BLEND_DST_ONE_MINUS_SRC_COLOR, // 3
RS_BLEND_DST_SRC_ALPHA, // 4
RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, // 5
RS_BLEND_DST_DST_ALPHA, // 6
RS_BLEND_DST_ONE_MINUS_DST_ALPHA // 7
};
enum RsTexEnvMode {

View File

@ -30,11 +30,3 @@ typedef struct {
#define RS_PROGRAM_VERTEX_PROJECTION_OFFSET 16
#define RS_PROGRAM_VERTEX_TEXTURE_OFFSET 32
//typedef int (*rsc_RunScript)(uint32_t launchIndex, const rsc_FunctionTable *);
/* EnableCap */
#define GL_LIGHTING 0x0B50
/* LightName */
#define GL_LIGHT0 0x4000

View File

@ -11,29 +11,29 @@ typedef struct FilmScriptUserEnvRec {
int32_t triangleOffsets[64];
float triangleOffsetsTex[64];
int32_t triangleOffsetsCount;
} FilmScriptUserEnv;
*/
} FilmScriptUserEnv;
*/
#define POS_TRANSLATE 0
#define POS_ROTATE 1
#define POS_FOCUS 2
#define STATE_TRIANGLE_OFFSET_COUNT 0
#define STATE_LAST_FOCUS 1
// The script enviroment has 3 env allocations.
// bank0: (r) The enviroment structure
// bank1: (r) The position information
// bank2: (rw) The temporary texture state
int main(int index)
int main(int index)
{
int f1,f2,f3,f4, f5,f6,f7,f8, f9,f10,f11,f12, f13,f14,f15,f16;
int g1,g2,g3,g4, g5,g6,g7,g8, g9,g10,g11,g12, g13,g14,g15,g16;
float trans;
float rot;
int x;
float focusPos; // float
int focusID;
int lastFocusID;
int imgCount;
trans = loadF(1, 0);
rot = loadF(1, 1);
float trans = loadF(1, POS_TRANSLATE);
float rot = loadF(1, POS_ROTATE);
matrixLoadScale(&f16, 2.f, 2.f, 2.f);
matrixTranslate(&f16, 0.f, 0.f, trans);
matrixRotate(&f16, 90.f, 0.f, 0.f, 1.f);
@ -46,24 +46,18 @@ int main(int index)
drawTriangleMesh(NAMED_mesh);
//int imgId = 0;
// Start of images.
bindProgramFragmentStore(NAMED_PFImages);
bindProgramFragment(NAMED_PFSImages);
bindProgramVertex(NAMED_PVImages);
//focusPos = loadF(1, 2);
//focusID = 0;
//lastFocusID = loadI32(2, 0);
//imgCount = 13;
float focusPos = loadF(1, POS_FOCUS);
int focusID = 0;
int lastFocusID = loadI32(2, STATE_LAST_FOCUS);
int imgCount = 13;
/*
disable(GL_LIGHTING);
if (trans > (-.3)) {
focusID = -1.0 - focusPos;
if (trans > (-.3f)) {
focusID = -1.0f - focusPos;
if (focusID >= imgCount) {
focusID = -1;
}
@ -71,6 +65,7 @@ int main(int index)
focusID = -1;
}
/*
if (focusID != lastFocusID) {
if (lastFocusID >= 0) {
uploadToTexture(con, env->tex[lastFocusID], 1);
@ -79,36 +74,38 @@ int main(int index)
uploadToTexture(con, env->tex[focusID], 0);
}
}
storeEnvI32(con, 2, 0, focusID);
*/
storeI32(2, STATE_LAST_FOCUS, focusID);
int triangleOffsetsCount = loadI32(2, STATE_TRIANGLE_OFFSET_COUNT);
int imgId = 0;
for (imgId=1; imgId <= imgCount; imgId++) {
float pos = focusPos + imgId + .4f;
int offset = (int)floor(pos*2);
pos -= 0.75;
offset += env->triangleOffsetsCount / 2;
if ((offset < 0) || (offset >= env->triangleOffsetsCount)) {
continue;
float pos = focusPos + imgId + 0.4f;
int offset = (int)floorf(pos * 2.f);
pos = pos - 0.75f;
offset = offset + triangleOffsetsCount / 2;
if (!((offset < 0) || (offset >= triangleOffsetsCount))) {
int start = offset -2;
int end = offset + 2;
if (start < 0) {
start = 0;
}
if (end > triangleOffsetsCount) {
end = triangleOffsetsCount;
}
bindTexture(NAMED_PFImages, 0, loadI32(0, imgId - 1));
/*
matrixLoadTranslate(con, &m, -pos - env->triangleOffsetsTex[env->triangleOffsetsCount / 2], 0, 0);
storeEnvMatrix(con, 3, RS_PROGRAM_VERTEX_TEXTURE_OFFSET, &m);
renderTriangleMeshRange(con, env->mesh, env->triangleOffsets[start], env->triangleOffsets[end] - env->triangleOffsets[start]);
*/
}
int start = offset -2;
int end = offset + 2;
if (start < 0) {
start = 0;
}
if (end > env->triangleOffsetsCount) {
end = env->triangleOffsetsCount;
}
programFragmentBindTexture(con, env->fpImages, 0, env->tex[imgId - 1]);
matrixLoadTranslate(con, &m, -pos - env->triangleOffsetsTex[env->triangleOffsetsCount / 2], 0, 0);
storeEnvMatrix(con, 3, RS_PROGRAM_VERTEX_TEXTURE_OFFSET, &m);
renderTriangleMeshRange(con, env->mesh, env->triangleOffsets[start], env->triangleOffsets[end] - env->triangleOffsets[start]);
}
*/
}
return 0;
}

View File

@ -25,6 +25,7 @@ import android.renderscript.Matrix;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
@ -38,6 +39,12 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
public class FilmRS {
private final int POS_TRANSLATE = 0;
private final int POS_ROTATE = 1;
private final int POS_FOCUS = 2;
private final int STATE_TRIANGLE_OFFSET_COUNT = 0;
private final int STATE_LAST_FOCUS = 1;
public FilmRS() {
}
@ -56,11 +63,11 @@ public class FilmRS {
if (x > 270) {
x = 270;
}
float anim = ((float)x-50) / 270.f;
mBufferPos[0] = 2f * anim + 0.5f; // translation
mBufferPos[1] = (anim * 40); // rotation
mBufferPos[2] = ((float)y) / 16.f - 8; // focusPos
mBufferPos[POS_TRANSLATE] = 2f * anim + 0.5f; // translation
mBufferPos[POS_ROTATE] = (anim * 40); // rotation
mBufferPos[POS_FOCUS] = ((float)y) / 16.f - 8; // focusPos
mAllocPos.data(mBufferPos);
}
@ -80,15 +87,19 @@ public class FilmRS {
private RenderScript.ProgramVertex mPVImages;
private ProgramVertexAlloc mPVA;
private RenderScript.Allocation mAllocEnv;
private RenderScript.Allocation mImages[];
private RenderScript.Allocation mAllocIDs;
private RenderScript.Allocation mAllocPos;
private RenderScript.Allocation mAllocState;
private RenderScript.Allocation mAllocPV;
private RenderScript.TriangleMesh mMesh;
private RenderScript.Light mLight;
private float[] mBufferPos;
private float[] mBufferPV;
private FilmStripMesh mFSM;
private int[] mBufferIDs;
private float[] mBufferPos = new float[3];
private int[] mBufferState;
private void initSamplers() {
mRS.samplerBegin();
@ -112,7 +123,7 @@ public class FilmRS {
mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.EQUAL);
mRS.programFragmentStoreDitherEnable(false);
mRS.programFragmentStoreDepthMask(false);
mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.ONE,
mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.ONE,
RenderScript.BlendDstFunc.ONE);
mPFSImages = mRS.programFragmentStoreCreate();
mPFSImages.setName("PFSImages");
@ -148,7 +159,75 @@ public class FilmRS {
}
int mParams[] = new int[10];
private void loadImages() {
mBufferIDs = new int[13];
mImages = new RenderScript.Allocation[13];
mAllocIDs = mRS.allocationCreatePredefSized(
RenderScript.ElementPredefined.USER_FLOAT,
mBufferIDs.length);
Bitmap b;
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inScaled = false;
b = BitmapFactory.decodeResource(mRes, R.drawable.p01, opts);
mImages[0] = mRS.allocationCreateFromBitmapBoxed(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.drawable.p02, opts);
mImages[1] = mRS.allocationCreateFromBitmapBoxed(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.drawable.p03, opts);
mImages[2] = mRS.allocationCreateFromBitmapBoxed(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.drawable.p04, opts);
mImages[3] = mRS.allocationCreateFromBitmapBoxed(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.drawable.p05, opts);
mImages[4] = mRS.allocationCreateFromBitmapBoxed(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.drawable.p06, opts);
mImages[5] = mRS.allocationCreateFromBitmapBoxed(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.drawable.p07, opts);
mImages[6] = mRS.allocationCreateFromBitmapBoxed(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.drawable.p08, opts);
mImages[7] = mRS.allocationCreateFromBitmapBoxed(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.drawable.p09, opts);
mImages[8] = mRS.allocationCreateFromBitmapBoxed(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.drawable.p10, opts);
mImages[9] = mRS.allocationCreateFromBitmapBoxed(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.drawable.p11, opts);
mImages[10] = mRS.allocationCreateFromBitmapBoxed(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.drawable.p12, opts);
mImages[11] = mRS.allocationCreateFromBitmapBoxed(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.drawable.p13, opts);
mImages[12] = mRS.allocationCreateFromBitmapBoxed(b, RenderScript.ElementPredefined.RGB_565, true);
for(int ct=0; ct < mImages.length; ct++) {
mImages[ct].uploadToTexture(1);
mBufferIDs[ct] = mImages[ct].getID();
}
mAllocIDs.data(mBufferIDs);
}
private void initState()
{
mBufferState = new int[10];
mAllocState = mRS.allocationCreatePredefSized(
RenderScript.ElementPredefined.USER_FLOAT,
mBufferState.length);
mBufferState[STATE_TRIANGLE_OFFSET_COUNT] = mFSM.mTriangleOffsetsCount;
mBufferState[STATE_LAST_FOCUS] = -1;
mAllocState.data(mBufferState);
}
private void initRS() {
mElementVertex = mRS.elementGetPredefined(
@ -157,8 +236,8 @@ public class FilmRS {
RenderScript.ElementPredefined.INDEX_16);
mRS.triangleMeshBegin(mElementVertex, mElementIndex);
FilmStripMesh fsm = new FilmStripMesh();
fsm.init(mRS);
mFSM = new FilmStripMesh();
mFSM.init(mRS);
mMesh = mRS.triangleMeshCreate();
mMesh.setName("mesh");
@ -176,19 +255,22 @@ public class FilmRS {
mRS.scriptCSetRoot(true);
mScriptStrip = mRS.scriptCCreate();
mBufferPos = new float[3];
mAllocPos = mRS.allocationCreatePredefSized(
RenderScript.ElementPredefined.USER_FLOAT,
RenderScript.ElementPredefined.USER_FLOAT,
mBufferPos.length);
loadImages();
initState();
mPVA = new ProgramVertexAlloc(mRS);
mPVBackground.bindAllocation(0, mPVA.mAlloc);
mPVImages.bindAllocation(0, mPVA.mAlloc);
mPVA.setupProjectionNormalized(320, 480);
mScriptStrip.bindAllocation(mAllocIDs, 0);
mScriptStrip.bindAllocation(mAllocPos, 1);
//mScriptStrip.bindAllocation(gStateAlloc, 2);
mScriptStrip.bindAllocation(mAllocState, 2);
mScriptStrip.bindAllocation(mPVA.mAlloc, 3);

View File

@ -51,7 +51,7 @@ int main(void* con, int ft, int launchID)
float touchCut = 1.f;
if (loadI32(0, STATE_TOUCH)) {
touchCut = 5.f;
touchCut = 4.f;
}
@ -60,14 +60,17 @@ int main(void* con, int ft, int launchID)
storeF(2, SCRATCH_ZOOM, zoom);
float targetRot = loadI32(0, STATE_FIRST_VISIBLE) / 180.0f * 3.14f;
float rot = filter(loadF(2, SCRATCH_ROT), targetRot, 0.1f * touchCut);
storeF(2, SCRATCH_ROT, rot);
float drawRot = filter(loadF(2, SCRATCH_ROT), targetRot, 0.1f * touchCut);
storeF(2, SCRATCH_ROT, drawRot);
float diam = 8.f;// + curve * 2.f;
float diam = 10.f;
float scale = 1.0f / zoom;
rot = rot * scale;
float rotStep = 20.0f / 180.0f * 3.14f * scale;
// Bug makes 1.0f alpha fail.
color(1.0f, 1.0f, 1.0f, 0.99f);
float rot = drawRot * scale;
float rotStep = 16.0f / 180.0f * 3.14f * scale;
rowCount = 4;
int index = 0;
int iconCount = loadI32(0, STATE_COUNT);
@ -82,24 +85,55 @@ int main(void* con, int ft, int launchID)
int y;
for (y = rowCount -1; (y >= 0) && iconCount; y--) {
float ty1 = ((y * 3.0f) - 4.5f) * scale;
float ty1 = ((y * 3.5f) - 6.f) * scale;
float ty2 = ty1 + scale * 2.f;
bindTexture(NAMED_PF, 0, loadI32(1, y));
color(1.0f, 1.0f, 1.0f, 1.0f);
if (done && (index != selectedID)) {
color(0.4f, 0.4f, 0.4f, 1.0f);
}
bindTexture(NAMED_PF, 0, loadI32(1, index));
//if (done && (index != selectedID)) {
//color(0.4f, 0.4f, 0.4f, 1.0f);
//}
drawQuad(tx1, ty1, tz1,
tx2, ty1, tz2,
tx2, ty2, tz2,
tx1, ty2, tz1);
iconCount--;
index++;
}
rot = rot + rotStep;
}
return 0;
// Draw the selected icon
color(1.0f, 1.0f, 1.0f, 0.9f);
rot = drawRot * scale;
index = 0;
iconCount = loadI32(0, STATE_COUNT);
while (iconCount) {
int y;
for (y = rowCount -1; (y >= 0) && iconCount; y--) {
if (index == selectedID) {
float tmpSin = sinf(rot) * scale;
float tmpCos = cosf(rot) * scale;
float tx1 = tmpSin * diam * 0.9f - tmpCos * 2.f;
float tx2 = tx1 + (tmpCos * 4.f);
float tz1 = tmpCos * diam * 0.9f + tmpSin * 2.f;
float tz2 = tz1 - (tmpSin * 4.f);
float ty1 = ((y * 3.5f) - 5.f) * scale;
float ty2 = ty1 + scale * 4.f;
bindTexture(NAMED_PF, 0, loadI32(1, index));
drawQuad(tx1, ty1, tz1,
tx2, ty1, tz2,
tx2, ty2, tz2,
tx1, ty2, tz1);
}
iconCount--;
index++;
}
rot = rot + rotStep;
}
return 1;
}

View File

@ -3,65 +3,153 @@
#pragma stateFragment(PF)
#pragma stateFragmentStore(PFS)
void drawLoop(int x, int y, int z, int rot)
// Scratch buffer layout
#define SCRATCH_FADE 0
#define SCRATCH_ZOOM 1
#define SCRATCH_ROT 2
//#define STATE_POS_X 0
#define STATE_DONE 1
//#define STATE_PRESSURE 2
#define STATE_ZOOM 3
//#define STATE_WARP 4
#define STATE_ORIENTATION 5
#define STATE_SELECTION 6
#define STATE_FIRST_VISIBLE 7
#define STATE_COUNT 8
#define STATE_TOUCH 9
float filter(float val, float target, float str)
{
int ct;
int tx;
int ty;
int tmpSin;
int tmpCos;
int sz;
for (ct = 0; ct < 10; ct ++) {
tmpSin = sinx((ct * 36 + rot) * 0x10000);
tmpCos = cosx((ct * 36 + rot) * 0x10000);
ty = y + tmpCos * 4;
tx = x + tmpSin * 4;
pfBindTexture(NAMED_PF, 0, loadI32(1, ct & 3));
sz = 0xc000;
drawQuad(tx - sz, ty - sz, z,
tx + sz, ty - sz, z,
tx + sz, ty + sz, z,
tx - sz, ty + sz, z);
}
float delta = (target - val);
return val + delta * str;
}
int main(void* con, int ft, int launchID)
{
int rowCount;
int x;
int y;
int row;
int col;
int imageID;
int tx1;
int ty1;
int tz1;
int tx2;
int ty2;
int tz2;
int tmpSin;
int tmpCos;
int iconCount;
int pressure;
int done = loadI32(0, STATE_DONE);
int selectedID = loadI32(0, STATE_SELECTION);
int iconCount = loadI32(0, STATE_COUNT);
int ringCount;
float f = loadF(2, 0);
float iconSize = 1.f;
float iconSpacing = 0.2f;
float z = 4.f;
rotStep = 16 * 0x10000;
pressure = loadI32(0, 2);
rowCount = 4;
iconCount = loadI32(0, 1);
rot = (-20 + loadI32(0, 0)) * 0x10000;
for (ringCount = 0; ringCount < 5; ringCount++) {
drawLoop(0, 0, 0x90000 + (ringCount * 0x80000));
pfClearColor(0.0f, 0.0f, 0.0f, f);
if (done) {
} else {
if (f < 0.8f) {
f = f + 0.02f;
storeF(2, 0, f);
}
}
return 0;
float touchCut = 1.f;
if (loadI32(0, STATE_TOUCH)) {
touchCut = 5.f;
}
float targetZoom = ((float)loadI32(0, STATE_ZOOM)) / 1000.f;
float zoom = filter(loadF(2, SCRATCH_ZOOM), targetZoom, 0.15 * touchCut);
storeF(2, SCRATCH_ZOOM, zoom);
float targetPos = loadI32(0, STATE_FIRST_VISIBLE) / (-20.0f);
float pos = filter(loadF(2, SCRATCH_ROT), targetPos, 0.1f * touchCut);
storeF(2, SCRATCH_ROT, pos);
pos = pos - 1.f;
color(1.0f, 1.0f, 1.0f, 1.0f);
// Draw flat icons first
int index = ((int)pos) * 4;
int row;
int col;
float xoffset = -0.3f;
float gridSize = iconSize * 4.f + iconSpacing * 3.f;
float yoffset = (pos - ((int)pos));
for (row = 0; row < 4; row ++) {
float ty1 = (gridSize / 2.f) - ((float)row - yoffset) * (iconSize + iconSpacing) - iconSize;
float ty2 = ty1 + iconSize;
for (col = 0; (col < 4) && (index < iconCount); col ++) {
if (index >= 0) {
bindTexture(NAMED_PF, 0, loadI32(1, index));
float fcol = col;
float tx1 = xoffset + (-gridSize / 2.f) + (fcol * (iconSize + iconSpacing));
float tx2 = tx1 + iconSize;
drawQuad(tx1, ty1, z,
tx2, ty1, z,
tx2, ty2, z,
tx1, ty2, z);
}
index++;
}
}
// bottom roller
{
float roll = (1.f - yoffset) * 0.5f * 3.14f;
float tmpSin = sinf(roll);
float tmpCos = cosf(roll);
for (col = 0; (col < 4) && (index < iconCount) && (index >= 0); col ++) {
float ty2 = (gridSize / 2.f) - ((float)row - yoffset) * (iconSize + iconSpacing);
float ty1 = ty2 - tmpCos * iconSize;
float tz1 = z + tmpSin * iconSize;
float tz2 = z;
float tx1 = xoffset + (-gridSize / 2.f) + ((float)col * (iconSize + iconSpacing));
float tx2 = tx1 + iconSize;
bindTexture(NAMED_PF, 0, loadI32(1, index));
drawQuad(tx1, ty1, tz1,
tx2, ty1, tz1,
tx2, ty2, tz2,
tx1, ty2, tz2);
index++;
}
}
// Top roller
{
index = (((int)pos) * 4) - 4;
float roll = yoffset * 0.5f * 3.14f;
float tmpSin = sinf(roll);
float tmpCos = cosf(roll);
for (col = 0; (col < 4) && (index < iconCount) && (index >= 0); col ++) {
float ty1 = (gridSize / 2.f) - ((float)-1.f - yoffset) * (iconSize + iconSpacing) - iconSize;
float ty2 = ty1 + tmpCos * iconSize;
float tz1 = z;
float tz2 = z + tmpSin * iconSize;
float tx1 = xoffset + (-gridSize / 2.f) + ((float)col * (iconSize + iconSpacing));
float tx2 = tx1 + iconSize;
bindTexture(NAMED_PF, 0, loadI32(1, index));
drawQuad(tx1, ty1, tz1,
tx2, ty1, tz1,
tx2, ty2, tz2,
tx1, ty2, tz2);
index++;
}
}
return 1;
}

View File

@ -18,6 +18,7 @@ package com.android.rollo;
import java.io.Writer;
import android.renderscript.RSSurfaceView;
import android.renderscript.RenderScript;
import android.renderscript.ProgramVertexAlloc;
@ -95,8 +96,11 @@ public class RolloRS {
private RenderScript.ProgramFragment mPFImages;
private RenderScript.ProgramVertex mPV;
private ProgramVertexAlloc mPVAlloc;
private RenderScript.ProgramVertex mPVOrtho;
private ProgramVertexAlloc mPVOrthoAlloc;
private RenderScript.Allocation[] mIcons;
private RenderScript.Allocation mIconPlate;
private RenderScript.Allocation mBackground;
private int[] mAllocStateBuf;
private RenderScript.Allocation mAllocState;
@ -130,23 +134,28 @@ public class RolloRS {
mRS.programFragmentStoreBegin(null, null);
mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.LESS);
mRS.programFragmentStoreDitherEnable(false);
mRS.programFragmentStoreDepthMask(false);
mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.ONE,
RenderScript.BlendDstFunc.ONE);
mRS.programFragmentStoreDepthMask(true);
mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.SRC_ALPHA,
RenderScript.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
mPFSBackground = mRS.programFragmentStoreCreate();
mPFSBackground.setName("PFS");
mPVAlloc = new ProgramVertexAlloc(mRS);
mRS.programVertexBegin(null, null);
mRS.programVertexSetTextureMatrixEnable(true);
mRS.programVertexSetTextureMatrixEnable(false);
mPV = mRS.programVertexCreate();
mPV.setName("PV");
mPV.bindAllocation(0, mPVAlloc.mAlloc);
mPVAlloc.setupProjectionNormalized(320, 480);
//mPVAlloc.setupOrthoNormalized(320, 480);
mPVOrthoAlloc = new ProgramVertexAlloc(mRS);
mRS.programVertexBegin(null, null);
mRS.programVertexSetTextureMatrixEnable(true);
mPVOrtho = mRS.programVertexCreate();
mPVOrtho.setName("PVOrtho");
mPVOrtho.bindAllocation(0, mPVOrthoAlloc.mAlloc);
mPVOrthoAlloc.setupOrthoWindow(320, 480);
mRS.contextBindProgramVertex(mPV);
mAllocScratchBuf = new int[32];
@ -162,16 +171,21 @@ public class RolloRS {
{
mIcons = new RenderScript.Allocation[4];
mIcons = new RenderScript.Allocation[29];
mAllocIconIDBuf = new int[mIcons.length];
mAllocIconID = mRS.allocationCreatePredefSized(
RenderScript.ElementPredefined.USER_I32, mAllocIconIDBuf.length);
Bitmap b;
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inScaled = false;
b = BitmapFactory.decodeResource(mRes, R.raw.cf_background, opts);
mBackground = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
mBackground.setName("TexBk");
b = BitmapFactory.decodeResource(mRes, R.raw.browser, opts);
mIcons[0] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
@ -184,6 +198,112 @@ public class RolloRS {
b = BitmapFactory.decodeResource(mRes, R.raw.settings, opts);
mIcons[3] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
/*
b = BitmapFactory.decodeResource(mRes, R.raw.assasins_creed, opts);
mIcons[4] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.bankofamerica, opts);
mIcons[5] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.chess, opts);
mIcons[6] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.dictionary, opts);
mIcons[7] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.facebook, opts);
mIcons[8] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.flashlight, opts);
mIcons[9] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.flight_control, opts);
mIcons[10] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.google_earth, opts);
mIcons[11] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.harry_potter, opts);
mIcons[12] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.movies, opts);
mIcons[13] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.nytimes, opts);
mIcons[14] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.pandora, opts);
mIcons[15] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.public_radio, opts);
mIcons[16] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.shazam, opts);
mIcons[17] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.skype, opts);
mIcons[18] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.solitaire, opts);
mIcons[19] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.sudoku, opts);
mIcons[20] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.taptaprevenge, opts);
mIcons[21] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.tetris, opts);
mIcons[22] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.tictactoe, opts);
mIcons[23] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.tweetie, opts);
mIcons[24] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.urbanspoon, opts);
mIcons[25] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.waterslide_extreme, opts);
mIcons[26] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.weather_channel, opts);
mIcons[27] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
b = BitmapFactory.decodeResource(mRes, R.raw.zippo, opts);
mIcons[28] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
*/
mIcons[4] = mIcons[3];
mIcons[5] = mIcons[2];
mIcons[6] = mIcons[1];
mIcons[7] = mIcons[0];
mIcons[8] = mIcons[1];
mIcons[9] = mIcons[2];
mIcons[10] = mIcons[3];
mIcons[11] = mIcons[2];
mIcons[12] = mIcons[1];
mIcons[13] = mIcons[0];
mIcons[14] = mIcons[1];
mIcons[15] = mIcons[2];
mIcons[16] = mIcons[3];
mIcons[17] = mIcons[2];
mIcons[18] = mIcons[1];
mIcons[19] = mIcons[0];
mIcons[20] = mIcons[1];
mIcons[21] = mIcons[2];
mIcons[22] = mIcons[3];
mIcons[23] = mIcons[2];
mIcons[24] = mIcons[1];
mIcons[25] = mIcons[0];
mIcons[26] = mIcons[1];
mIcons[27] = mIcons[2];
mIcons[28] = mIcons[3];
for(int ct=0; ct < mIcons.length; ct++) {
mIcons[ct].uploadToTexture(0);
mAllocIconIDBuf[ct] = mIcons[ct].getID();
@ -221,6 +341,11 @@ public class RolloRS {
}
private void makeTextBitmap() {
//Bitmap.createBitmap(width, height, Bitmap.Config);
//new Canvas(theBitmap);
//canvas.drawText();
}
private void initRS() {
@ -232,7 +357,7 @@ public class RolloRS {
//mRS.scriptCSetClearDepth(0);
mScript = mRS.scriptCCreate();
mAllocStateBuf = new int[] {0, 0, 0, 8, 0, 0, 0, 0, 38, 0, 0};
mAllocStateBuf = new int[] {0, 0, 0, 8, 0, 0, -1, 0, mAllocIconIDBuf.length, 0, 0};
mAllocState = mRS.allocationCreatePredefSized(
RenderScript.ElementPredefined.USER_I32, mAllocStateBuf.length);
mScript.bindAllocation(mAllocState, 0);
@ -248,4 +373,3 @@ public class RolloRS {
}

View File

@ -76,7 +76,7 @@ public class RolloView extends RSSurfaceView {
float mOldColumn;
float mZoom = 1;
int mIconCount = 38;
int mIconCount = 29;
int mRows = 4;
int mColumns = (mIconCount + mRows - 1) / mRows;
@ -101,7 +101,7 @@ public class RolloView extends RSSurfaceView {
void computeSelection(float x, float y)
{
float col = mColumn + (x - 0.5f) * 3;
float col = mColumn + (x - 0.5f) * 4 + 1;
int iCol = (int)(col + 0.25f);
float row = (y / 0.8f) * mRows;
@ -158,13 +158,14 @@ public class RolloView extends RSSurfaceView {
mZoom = zoom;
mFlingX = nx;
mRender.setZoom(zoom);
} else {
if(mControlMode && (mZoom < 1.01f)) {
if(mZoom < 1.01f) {
computeSelection(nx, ny);
}
} else {
mControlMode = false;
mColumn = mOldColumn;
mRender.setZoom(1.f);
mRender.setSelected(-1);
}
} else {
// Do something with corners here....

View File

@ -99,6 +99,16 @@ AllocationCreateFromBitmap {
ret RsAllocation
}
AllocationCreateFromBitmapBoxed {
param uint32_t width
param uint32_t height
param RsElementPredefined dstFmt
param RsElementPredefined srcFmt
param bool genMips
param const void * data
ret RsAllocation
}
AllocationUploadToTexture {
param RsAllocation alloc

View File

@ -301,14 +301,18 @@ static ElementConverter_t pickConverter(RsElementPredefined dstFmt, RsElementPre
return elementConverter_cpy_32;
}
LOGE("pickConverter, unsuported combo");
LOGE("pickConverter, unsuported combo, src %i, dst %i", srcFmt, dstFmt);
return 0;
}
RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElementPredefined dstFmt, RsElementPredefined srcFmt, bool genMips, const void *data)
{
rsi_TypeBegin(rsc, rsi_ElementGetPredefined(rsc, RS_ELEMENT_RGB_565));
rsAssert(!(w & (w-1)));
rsAssert(!(h & (h-1)));
//LOGE("rsi_AllocationCreateFromBitmap %i %i %i %i %i", w, h, dstFmt, srcFmt, genMips);
rsi_TypeBegin(rsc, rsi_ElementGetPredefined(rsc, dstFmt));
rsi_TypeAdd(rsc, RS_DIMENSION_X, w);
rsi_TypeAdd(rsc, RS_DIMENSION_Y, h);
if (genMips) {
@ -340,6 +344,42 @@ RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h
return texAlloc;
}
static uint32_t fmtToBits(RsElementPredefined fmt)
{
return 16;
}
RsAllocation rsi_AllocationCreateFromBitmapBoxed(Context *rsc, uint32_t w, uint32_t h, RsElementPredefined dstFmt, RsElementPredefined srcFmt, bool genMips, const void *data)
{
uint32_t w2 = rsHigherPow2(w);
uint32_t h2 = rsHigherPow2(h);
if ((w2 == w) && (h2 == h)) {
return rsi_AllocationCreateFromBitmap(rsc, w, h, dstFmt, srcFmt, genMips, data);
}
uint32_t bpp = fmtToBits(srcFmt) >> 3;
size_t size = w2 * h2 * bpp;
uint8_t *tmp = static_cast<uint8_t *>(malloc(size));
memset(tmp, 0, size);
const uint8_t * src = static_cast<const uint8_t *>(data);
for (uint32_t y = 0; y < h; y++) {
uint8_t * ydst = &tmp[y + ((h2 - h) >> 1)];
memcpy(&ydst[(w2 - w) >> 1], src, w * bpp);
src += h * bpp;
}
RsAllocation ret = rsi_AllocationCreateFromBitmap(rsc, w2, h2, dstFmt, srcFmt, genMips, tmp);
free(tmp);
return ret;
}
RsAllocation rsi_AllocationCreateFromFile(Context *rsc, const char *file, bool genMips)
{
bool use32bpp = false;

View File

@ -79,8 +79,7 @@ bool Context::runScript(Script *s, uint32_t launchID)
mFragment.set(frag);
mVertex.set(vtx);
mFragmentStore.set(store);
return true;
return ret;
}

View File

@ -83,6 +83,7 @@ public:
const ProgramFragment * getFragment() {return mFragment.get();}
const ProgramFragmentStore * getFragmentStore() {return mFragmentStore.get();}
const ProgramVertex * getVertex() {return mVertex.get();}
void setupCheck();

View File

@ -55,8 +55,6 @@ void ProgramVertex::setupGL()
glLoadIdentity();
}
LOGE("lights %i ", mLightCount);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if (mLightCount) {
@ -103,6 +101,25 @@ void ProgramVertex::addLight(const Light *l)
}
}
void ProgramVertex::setProjectionMatrix(const rsc_Matrix *m) const
{
float *f = static_cast<float *>(mConstants[0]->getPtr());
memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m, sizeof(rsc_Matrix));
}
void ProgramVertex::setModelviewMatrix(const rsc_Matrix *m) const
{
float *f = static_cast<float *>(mConstants[0]->getPtr());
memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m, sizeof(rsc_Matrix));
}
void ProgramVertex::setTextureMatrix(const rsc_Matrix *m) const
{
float *f = static_cast<float *>(mConstants[0]->getPtr());
memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m, sizeof(rsc_Matrix));
}
ProgramVertexState::ProgramVertexState()
{

View File

@ -41,6 +41,10 @@ public:
void setTextureMatrixEnable(bool e) {mTextureMatrixEnable = e;}
void addLight(const Light *);
void setProjectionMatrix(const rsc_Matrix *) const;
void setModelviewMatrix(const rsc_Matrix *) const;
void setTextureMatrix(const rsc_Matrix *) const;
protected:
bool mDirty;
uint32_t mLightCount;

View File

@ -135,7 +135,6 @@ static float SC_randf(float max)
//////////////////////////////////////////////////////////////////////////////
// Matrix routines
//////////////////////////////////////////////////////////////////////////////
@ -256,6 +255,24 @@ static void SC_bindProgramVertex(RsProgramVertex pv)
}
//////////////////////////////////////////////////////////////////////////////
// VP
//////////////////////////////////////////////////////////////////////////////
static void SC_vpLoadModelMatrix(const rsc_Matrix *m)
{
GET_TLS();
rsc->getVertex()->setModelviewMatrix(m);
}
static void SC_vpLoadTextureMatrix(const rsc_Matrix *m)
{
GET_TLS();
rsc->getVertex()->setTextureMatrix(m);
}
//////////////////////////////////////////////////////////////////////////////
// Drawing
//////////////////////////////////////////////////////////////////////////////
@ -343,20 +360,12 @@ static void SC_drawQuad(float x1, float y1, float z1,
//
//////////////////////////////////////////////////////////////////////////////
extern "C" const void * loadVp(uint32_t bank, uint32_t offset)
{
GET_TLS();
return &static_cast<const uint8_t *>(sc->mSlots[bank]->getPtr())[offset];
}
static void SC_color(float r, float g, float b, float a)
{
glColor4f(r, g, b, a);
}
/*
extern "C" void materialDiffuse(float r, float g, float b, float a)
{
float v[] = {r, g, b, a};
@ -369,35 +378,18 @@ extern "C" void materialSpecular(float r, float g, float b, float a)
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, v);
}
extern "C" void lightPosition(float x, float y, float z, float w)
{
float v[] = {x, y, z, w};
glLightfv(GL_LIGHT0, GL_POSITION, v);
}
extern "C" void materialShininess(float s)
{
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &s);
}
*/
extern "C" void uploadToTexture(RsAllocation va, uint32_t baseMipLevel)
static void SC_uploadToTexture(RsAllocation va, uint32_t baseMipLevel)
{
GET_TLS();
rsi_AllocationUploadToTexture(rsc, va, baseMipLevel);
}
extern "C" void enable(uint32_t p)
{
glEnable(p);
}
extern "C" void disable(uint32_t p)
{
glDisable(p);
}
static void SC_ClearColor(float r, float g, float b, float a)
{
//LOGE("c %f %f %f %f", r, g, b, a);
@ -408,6 +400,16 @@ static void SC_ClearColor(float r, float g, float b, float a)
sc->mEnviroment.mClearColor[3] = a;
}
static void SC_debugF(const char *s, float f)
{
LOGE("%s %f", s, f);
}
static void SC_debugI32(const char *s, int32_t i)
{
LOGE("%s %i", s, i);
}
//////////////////////////////////////////////////////////////////////////////
@ -444,6 +446,10 @@ ScriptCState::SymbolTable_t ScriptCState::gSyms[] = {
"float", "(float)" },
{ "randf", (void *)&SC_randf,
"float", "(float)" },
{ "floorf", (void *)&floorf,
"float", "(float)" },
{ "ceilf", (void *)&ceilf,
"float", "(float)" },
// matrix
{ "matrixLoadIdentity", (void *)&SC_matrixLoadIdentity,
@ -481,6 +487,14 @@ ScriptCState::SymbolTable_t ScriptCState::gSyms[] = {
{ "bindTexture", (void *)&SC_bindTexture,
"void", "(int, int, int)" },
// vp
{ "vpLoadModelMatrix", (void *)&SC_bindProgramFragment,
"void", "(void *)" },
{ "vpLoadTextureMatrix", (void *)&SC_bindProgramFragmentStore,
"void", "(void *)" },
// drawing
{ "drawQuad", (void *)&SC_drawQuad,
"void", "(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4)" },
@ -495,10 +509,19 @@ ScriptCState::SymbolTable_t ScriptCState::gSyms[] = {
// misc
{ "pfClearColor", (void *)&SC_ClearColor,
"void", "(float, float, float, float)" },
{ "color", (void *)&SC_color,
"void", "(float, float, float, float)" },
{ "uploadToTexture", (void *)&SC_uploadToTexture,
"void", "(int, int)" },
{ "debugF", (void *)&SC_debugF,
"void", "(void *, float)" },
{ "debugI32", (void *)&SC_debugI32,
"void", "(void *, int)" },
{ NULL, NULL, NULL, NULL }
};