summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--graphics/java/android/renderscript/Allocation.java11
-rw-r--r--graphics/java/android/renderscript/Element.java26
-rw-r--r--libs/rs/Android.mk1
-rw-r--r--libs/rs/RenderScriptDefines.h2
-rw-r--r--libs/rs/rsAllocation.cpp74
-rw-r--r--libs/rs/rsAllocation.h16
-rw-r--r--libs/rs/rsComponent.cpp2
-rw-r--r--libs/rs/rsContext.cpp1
-rw-r--r--libs/rs/rsContext.h2
-rw-r--r--libs/rs/rsFBOCache.cpp209
-rw-r--r--libs/rs/rsFBOCache.h57
-rw-r--r--libs/rs/rsFont.cpp2
-rw-r--r--libs/rs/rsMesh.cpp4
-rw-r--r--libs/rs/rsScriptC_LibGL.cpp40
-rw-r--r--libs/rs/scriptc/rs_graphics.rsh40
-rw-r--r--tests/RenderScriptTests/FBOTest/Android.mk30
-rw-r--r--tests/RenderScriptTests/FBOTest/AndroidManifest.xml13
-rw-r--r--tests/RenderScriptTests/FBOTest/res/drawable/robot.pngbin0 -> 292580 bytes
-rw-r--r--tests/RenderScriptTests/FBOTest/res/raw/robot.a3dbin0 -> 144528 bytes
-rw-r--r--tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOTest.java73
-rw-r--r--tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOTestRS.java205
-rw-r--r--tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOTestView.java144
-rw-r--r--tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs221
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java19
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs218
25 files changed, 1293 insertions, 117 deletions
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 4b8c58e..9ac1a00 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -99,6 +99,14 @@ public class Allocation extends BaseObj {
*/
public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008;
+ /**
+ * @hide
+ * USAGE_GRAPHICS_RENDER_TARGET The allcation will be used as a
+ * target for offscreen rendering
+ *
+ */
+ public static final int USAGE_GRAPHICS_RENDER_TARGET = 0x0010;
+
/**
* Controls mipmap behavior when using the bitmap creation and
@@ -137,7 +145,8 @@ public class Allocation extends BaseObj {
if ((usage & ~(USAGE_SCRIPT |
USAGE_GRAPHICS_TEXTURE |
USAGE_GRAPHICS_VERTEX |
- USAGE_GRAPHICS_CONSTANTS)) != 0) {
+ USAGE_GRAPHICS_CONSTANTS |
+ USAGE_GRAPHICS_RENDER_TARGET)) != 0) {
throw new RSIllegalArgumentException("Unknown usage specified.");
}
mType = t;
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index fae22f0..0c1ad2a 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -124,7 +124,8 @@ public class Element extends BaseObj {
PIXEL_A (8),
PIXEL_LA (9),
PIXEL_RGB (10),
- PIXEL_RGBA (11);
+ PIXEL_RGBA (11),
+ PIXEL_DEPTH (12);
int mID;
DataKind(int id) {
@@ -536,10 +537,12 @@ public class Element extends BaseObj {
dk == DataKind.PIXEL_A ||
dk == DataKind.PIXEL_LA ||
dk == DataKind.PIXEL_RGB ||
- dk == DataKind.PIXEL_RGBA)) {
+ dk == DataKind.PIXEL_RGBA ||
+ dk == DataKind.PIXEL_DEPTH)) {
throw new RSIllegalArgumentException("Unsupported DataKind");
}
if (!(dt == DataType.UNSIGNED_8 ||
+ dt == DataType.UNSIGNED_16 ||
dt == DataType.UNSIGNED_5_6_5 ||
dt == DataType.UNSIGNED_4_4_4_4 ||
dt == DataType.UNSIGNED_5_5_5_1)) {
@@ -554,16 +557,25 @@ public class Element extends BaseObj {
if (dt == DataType.UNSIGNED_4_4_4_4 && dk != DataKind.PIXEL_RGBA) {
throw new RSIllegalArgumentException("Bad kind and type combo");
}
+ if (dt == DataType.UNSIGNED_16 &&
+ dk != DataKind.PIXEL_DEPTH) {
+ throw new RSIllegalArgumentException("Bad kind and type combo");
+ }
int size = 1;
- if (dk == DataKind.PIXEL_LA) {
+ switch (dk) {
+ case PIXEL_LA:
size = 2;
- }
- if (dk == DataKind.PIXEL_RGB) {
+ break;
+ case PIXEL_RGB:
size = 3;
- }
- if (dk == DataKind.PIXEL_RGBA) {
+ break;
+ case PIXEL_RGBA:
size = 4;
+ break;
+ case PIXEL_DEPTH:
+ size = 2;
+ break;
}
boolean norm = true;
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 14152d8..9100693 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -90,6 +90,7 @@ LOCAL_SRC_FILES:= \
rsContext.cpp \
rsDevice.cpp \
rsElement.cpp \
+ rsFBOCache.cpp \
rsFileA3D.cpp \
rsFont.cpp \
rsLocklessFifo.cpp \
diff --git a/libs/rs/RenderScriptDefines.h b/libs/rs/RenderScriptDefines.h
index 4e1ac88..bb275b5 100644
--- a/libs/rs/RenderScriptDefines.h
+++ b/libs/rs/RenderScriptDefines.h
@@ -84,6 +84,7 @@ enum RsAllocationUsageType {
RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE = 0x0002,
RS_ALLOCATION_USAGE_GRAPHICS_VERTEX = 0x0004,
RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS = 0x0008,
+ RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET = 0x0010,
RS_ALLOCATION_USAGE_ALL = 0x000F
};
@@ -147,6 +148,7 @@ enum RsDataKind {
RS_KIND_PIXEL_LA,
RS_KIND_PIXEL_RGB,
RS_KIND_PIXEL_RGBA,
+ RS_KIND_PIXEL_DEPTH,
};
enum RsSamplerParam {
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index b8ddb0b..6b37e03 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -56,7 +56,8 @@ void Allocation::init(Context *rsc, const Type *type) {
mTextureID = 0;
mBufferID = 0;
- mUploadDefered = false;
+ mRenderTargetID = 0;
+ mUploadDeferred = false;
mUserBitmapCallback = NULL;
mUserBitmapCallbackData = NULL;
@@ -93,6 +94,10 @@ Allocation::~Allocation() {
glDeleteTextures(1, &mTextureID);
mTextureID = 0;
}
+ if (mRenderTargetID) {
+ glDeleteRenderbuffers(1, &mRenderTargetID);
+ mRenderTargetID = 0;
+ }
#endif //ANDROID_RS_SERIALIZE
}
@@ -112,9 +117,14 @@ bool Allocation::fixAllocation() {
return false;
}
-void Allocation::deferedUploadToTexture(const Context *rsc) {
+void Allocation::deferredUploadToTexture(const Context *rsc) {
mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE;
- mUploadDefered = true;
+ mUploadDeferred = true;
+}
+
+void Allocation::deferredAllocateRenderTarget(const Context *rsc) {
+ mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET;
+ mUploadDeferred = true;
}
uint32_t Allocation::getGLTarget() const {
@@ -155,8 +165,11 @@ void Allocation::syncAll(Context *rsc, RsAllocationUsageType src) {
if (getIsBufferObject()) {
uploadToBufferObject(rsc);
}
+ if (getIsRenderTarget() && !getIsTexture()) {
+ allocateRenderTarget(rsc);
+ }
- mUploadDefered = false;
+ mUploadDeferred = false;
}
void Allocation::uploadToTexture(const Context *rsc) {
@@ -184,7 +197,7 @@ void Allocation::uploadToTexture(const Context *rsc) {
// 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;
+ mUploadDeferred = true;
return;
}
isFirstUpload = true;
@@ -200,6 +213,32 @@ void Allocation::uploadToTexture(const Context *rsc) {
#endif //ANDROID_RS_SERIALIZE
}
+void Allocation::allocateRenderTarget(const Context *rsc) {
+#ifndef ANDROID_RS_SERIALIZE
+ mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET;
+
+ GLenum format = mHal.state.type->getElement()->getComponent().getGLFormat();
+ if (!format) {
+ return;
+ }
+
+ if (!mRenderTargetID) {
+ glGenRenderbuffers(1, &mRenderTargetID);
+
+ if (!mRenderTargetID) {
+ // This should generally not happen
+ LOGE("allocateRenderTarget failed to gen mRenderTargetID");
+ rsc->dumpDebug();
+ return;
+ }
+ glBindRenderbuffer(GL_RENDERBUFFER, mRenderTargetID);
+ glRenderbufferStorage(GL_RENDERBUFFER, format,
+ mHal.state.type->getDimX(),
+ mHal.state.type->getDimY());
+ }
+#endif //ANDROID_RS_SERIALIZE
+}
+
#ifndef ANDROID_RS_SERIALIZE
const static GLenum gFaceOrder[] = {
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
@@ -271,9 +310,9 @@ void Allocation::upload2DTexture(bool isFirstUpload) {
#endif //ANDROID_RS_SERIALIZE
}
-void Allocation::deferedUploadToBufferObject(const Context *rsc) {
+void Allocation::deferredUploadToBufferObject(const Context *rsc) {
mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX;
- mUploadDefered = true;
+ mUploadDeferred = true;
}
void Allocation::uploadToBufferObject(const Context *rsc) {
@@ -288,7 +327,7 @@ void Allocation::uploadToBufferObject(const Context *rsc) {
}
if (!mBufferID) {
LOGE("Upload to buffer object failed");
- mUploadDefered = true;
+ mUploadDeferred = true;
return;
}
GLenum target = (GLenum)getGLTarget();
@@ -300,7 +339,7 @@ void Allocation::uploadToBufferObject(const Context *rsc) {
}
void Allocation::uploadCheck(Context *rsc) {
- if (mUploadDefered) {
+ if (mUploadDeferred) {
syncAll(rsc, RS_ALLOCATION_USAGE_SCRIPT);
}
}
@@ -329,7 +368,7 @@ void Allocation::data(Context *rsc, uint32_t xoff, uint32_t lod,
memcpy(ptr, data, size);
sendDirty();
- mUploadDefered = true;
+ mUploadDeferred = true;
}
void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
@@ -362,7 +401,7 @@ void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod,
dst += destW * eSize;
}
sendDirty();
- mUploadDefered = true;
+ mUploadDeferred = true;
} else {
update2DTexture(data, xoff, yoff, lod, face, w, h);
}
@@ -407,7 +446,7 @@ void Allocation::elementData(Context *rsc, uint32_t x, const void *data,
memcpy(ptr, data, sizeBytes);
sendDirty();
- mUploadDefered = true;
+ mUploadDeferred = true;
}
void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y,
@@ -450,7 +489,7 @@ void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y,
memcpy(ptr, data, sizeBytes);
sendDirty();
- mUploadDefered = true;
+ mUploadDeferred = true;
}
void Allocation::addProgramToDirty(const Program *p) {
@@ -617,12 +656,12 @@ namespace renderscript {
void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, bool genmip, uint32_t baseMipLevel) {
Allocation *alloc = static_cast<Allocation *>(va);
- alloc->deferedUploadToTexture(rsc);
+ alloc->deferredUploadToTexture(rsc);
}
void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va) {
Allocation *alloc = static_cast<Allocation *>(va);
- alloc->deferedUploadToBufferObject(rsc);
+ alloc->deferredUploadToBufferObject(rsc);
}
static void mip565(const Adapter2D &out, const Adapter2D &in) {
@@ -792,7 +831,6 @@ RsAllocation rsaAllocationCreateTyped(RsContext con, RsType vtype,
return alloc;
}
-
RsAllocation rsaAllocationCreateFromBitmap(RsContext con, RsType vtype,
RsAllocationMipmapControl mips,
const void *data, uint32_t usages) {
@@ -811,7 +849,7 @@ RsAllocation rsaAllocationCreateFromBitmap(RsContext con, RsType vtype,
rsaAllocationGenerateScriptMips(rsc, texAlloc);
}
- texAlloc->deferedUploadToTexture(rsc);
+ texAlloc->deferredUploadToTexture(rsc);
return texAlloc;
}
@@ -852,7 +890,7 @@ RsAllocation rsaAllocationCubeCreateFromBitmap(RsContext con, RsType vtype,
rsaAllocationGenerateScriptMips(rsc, texAlloc);
}
- texAlloc->deferedUploadToTexture(rsc);
+ texAlloc->deferredUploadToTexture(rsc);
return texAlloc;
}
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index e63140c..d334841 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -71,13 +71,17 @@ public:
void syncAll(Context *rsc, RsAllocationUsageType src);
- void deferedUploadToTexture(const Context *rsc);
+ void deferredUploadToTexture(const Context *rsc);
void uploadToTexture(const Context *rsc);
uint32_t getTextureID() const {return mTextureID;}
+ void deferredAllocateRenderTarget(const Context *rsc);
+ void allocateRenderTarget(const Context *rsc);
+ uint32_t getRenderTargetID() const {return mRenderTargetID;}
+
uint32_t getGLTarget() const;
- void deferedUploadToBufferObject(const Context *rsc);
+ void deferredUploadToBufferObject(const Context *rsc);
void uploadToBufferObject(const Context *rsc);
uint32_t getBufferObjectID() const {return mBufferID;}
@@ -118,6 +122,9 @@ public:
bool getIsTexture() const {
return (mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) != 0;
}
+ bool getIsRenderTarget() const {
+ return (mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) != 0;
+ }
bool getIsBufferObject() const {
return (mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) != 0;
}
@@ -161,7 +168,10 @@ protected:
// is allowed.
uint32_t mBufferID;
- bool mUploadDefered;
+ // Is this a legal structure to be used as an FBO render target
+ uint32_t mRenderTargetID;
+
+ bool mUploadDeferred;
private:
void init(Context *rsc, const Type *);
diff --git a/libs/rs/rsComponent.cpp b/libs/rs/rsComponent.cpp
index 4c4987a..e2ae043 100644
--- a/libs/rs/rsComponent.cpp
+++ b/libs/rs/rsComponent.cpp
@@ -18,6 +18,7 @@
#ifndef ANDROID_RS_SERIALIZE
#include <GLES/gl.h>
+#include <GLES2/gl2.h>
#endif
using namespace android;
@@ -207,6 +208,7 @@ uint32_t Component::getGLFormat() const {
case RS_KIND_PIXEL_LA: return GL_LUMINANCE_ALPHA;
case RS_KIND_PIXEL_RGB: return GL_RGB;
case RS_KIND_PIXEL_RGBA: return GL_RGBA;
+ case RS_KIND_PIXEL_DEPTH: return GL_DEPTH_COMPONENT16;
default: break;
}
#endif //ANDROID_RS_SERIALIZE
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index c761c75..d727ba1 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -409,6 +409,7 @@ bool Context::setupCheck() {
mFragment->setupGL2(this, &mStateFragment, &mShaderCache);
mRaster->setupGL2(this, &mStateRaster);
mVertex->setupGL2(this, &mStateVertex, &mShaderCache);
+ mFBOCache.setupGL2(this);
return true;
}
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 72574a6..eacfdf7 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -38,6 +38,7 @@
#include "rsProgramRaster.h"
#include "rsProgramVertex.h"
#include "rsShaderCache.h"
+#include "rsFBOCache.h"
#include "rsVertexArray.h"
#include "rsgApiStructs.h"
@@ -119,6 +120,7 @@ public:
ScriptCState mScriptC;
ShaderCache mShaderCache;
+ FBOCache mFBOCache;
void swapBuffers();
void setRootScript(Script *);
diff --git a/libs/rs/rsFBOCache.cpp b/libs/rs/rsFBOCache.cpp
new file mode 100644
index 0000000..78aa8ce
--- /dev/null
+++ b/libs/rs/rsFBOCache.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2011 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 "rsFBOCache.h"
+
+#include "rsContext.h"
+#include "rsAllocation.h"
+
+#ifndef ANDROID_RS_SERIALIZE
+#include <GLES/gl.h>
+#include <GLES2/gl2.h>
+#endif //ANDROID_RS_SERIALIZE
+
+using namespace android;
+using namespace android::renderscript;
+
+
+FBOCache::FBOCache() {
+ mFBOId = 0;
+ mDirty = false;
+ mMaxTargets = 1;
+ mColorTargets = new ObjectBaseRef<Allocation>[mMaxTargets];
+}
+
+FBOCache::~FBOCache() {
+ delete[] mColorTargets;
+#ifndef ANDROID_RS_SERIALIZE
+ if(mFBOId != 0) {
+ glDeleteFramebuffers(1, &mFBOId);
+ }
+#endif //ANDROID_RS_SERIALIZE
+}
+
+void FBOCache::bindColorTarget(Context *rsc, Allocation *a, uint32_t slot) {
+ if (slot >= mMaxTargets) {
+ LOGE("Invalid render target index");
+ return;
+ }
+ if (a != NULL) {
+ if (!a->getIsTexture()) {
+ LOGE("Invalid Color Target");
+ return;
+ }
+ if (a->getIsTexture()) {
+ if (a->getTextureID() == 0) {
+ a->deferredUploadToTexture(rsc);
+ }
+ } else if (a->getRenderTargetID() == 0) {
+ a->deferredAllocateRenderTarget(rsc);
+ }
+ }
+ mColorTargets[slot].set(a);
+ mDirty = true;
+}
+
+void FBOCache::bindDepthTarget(Context *rsc, Allocation *a) {
+ if (a != NULL) {
+ if (!a->getIsRenderTarget()) {
+ LOGE("Invalid Depth Target");
+ return;
+ }
+ if (a->getIsTexture()) {
+ if (a->getTextureID() == 0) {
+ a->deferredUploadToTexture(rsc);
+ }
+ } else if (a->getRenderTargetID() == 0) {
+ a->deferredAllocateRenderTarget(rsc);
+ }
+ }
+ mDepthTarget.set(a);
+ mDirty = true;
+}
+
+void FBOCache::resetAll(Context *) {
+ for (uint32_t i = 0; i < mMaxTargets; i ++) {
+ mColorTargets[i].set(NULL);
+ }
+ mDepthTarget.set(NULL);
+ mDirty = true;
+}
+
+bool FBOCache::renderToFramebuffer() {
+ if (mDepthTarget.get() != NULL) {
+ return false;
+ }
+
+ for (uint32_t i = 0; i < mMaxTargets; i ++) {
+ if (mColorTargets[i].get() != NULL) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void FBOCache::checkError(Context *rsc) {
+ GLenum status;
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ switch (status) {
+ case GL_FRAMEBUFFER_COMPLETE:
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ rsc->setError(RS_ERROR_BAD_VALUE,
+ "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ rsc->setError(RS_ERROR_BAD_VALUE,
+ "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
+ rsc->setError(RS_ERROR_BAD_VALUE,
+ "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
+ break;
+ case GL_FRAMEBUFFER_UNSUPPORTED:
+ rsc->setError(RS_ERROR_BAD_VALUE,
+ "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED");
+ break;
+ }
+}
+
+void FBOCache::setDepthAttachment(Context *rsc) {
+#ifndef ANDROID_RS_SERIALIZE
+ if (mDepthTarget.get() != NULL) {
+ mDepthTarget->uploadCheck(rsc);
+ if (mDepthTarget->getIsTexture()) {
+ uint32_t texID = mDepthTarget->getTextureID();
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_TEXTURE_2D, texID, 0);
+ } else {
+ uint32_t texID = mDepthTarget->getRenderTargetID();
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, texID);
+ }
+ } else {
+ // Reset last attachment
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_TEXTURE_2D, 0, 0);
+ }
+#endif //ANDROID_RS_SERIALIZE
+}
+
+void FBOCache::setColorAttachment(Context *rsc) {
+#ifndef ANDROID_RS_SERIALIZE
+ // Now attach color targets
+ for (uint32_t i = 0; i < mMaxTargets; i ++) {
+ uint32_t texID = 0;
+ if (mColorTargets[i].get() != NULL) {
+ mColorTargets[i]->uploadCheck(rsc);
+ if (mColorTargets[i]->getIsTexture()) {
+ uint32_t texID = mColorTargets[i]->getTextureID();
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+ GL_TEXTURE_2D, texID, 0);
+ } else {
+ uint32_t texID = mDepthTarget->getRenderTargetID();
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+ GL_RENDERBUFFER, texID);
+ }
+ } else {
+ // Reset last attachment
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+ GL_RENDERBUFFER, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+ GL_TEXTURE_2D, 0, 0);
+ }
+ }
+#endif //ANDROID_RS_SERIALIZE
+}
+
+void FBOCache::setupGL2(Context *rsc) {
+#ifndef ANDROID_RS_SERIALIZE
+ if (!mDirty) {
+ return;
+ }
+
+ bool framebuffer = renderToFramebuffer();
+
+ if (!framebuffer) {
+ if(mFBOId == 0) {
+ glGenFramebuffers(1, &mFBOId);
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBOId);
+
+ setDepthAttachment(rsc);
+ setColorAttachment(rsc);
+
+ glViewport(0, 0, mColorTargets[0]->getType()->getDimX(),
+ mColorTargets[0]->getType()->getDimY());
+
+ checkError(rsc);
+ } else {
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glViewport(0, 0, rsc->getWidth(), rsc->getHeight());
+ }
+#endif //ANDROID_RS_SERIALIZE
+}
diff --git a/libs/rs/rsFBOCache.h b/libs/rs/rsFBOCache.h
new file mode 100644
index 0000000..9a0a3b6
--- /dev/null
+++ b/libs/rs/rsFBOCache.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 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_FRAME_BUFFER_OBJECT_CACHE_H
+#define ANDROID_FRAME_BUFFER_OBJECT_CACHE_H
+
+#include "rsObjectBase.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+class Allocation;
+
+class FBOCache {
+public:
+ FBOCache();
+ ~FBOCache();
+
+ void bindColorTarget(Context *rsc, Allocation *a, uint32_t slot);
+ void bindDepthTarget(Context *, Allocation *a);
+ void resetAll(Context *);
+
+ void setupGL2(Context *);
+
+protected:
+
+ bool mDirty;
+ uint32_t mMaxTargets;
+ void checkError(Context *);
+ void setColorAttachment(Context *rsc);
+ void setDepthAttachment(Context *rsc);
+ bool renderToFramebuffer();
+ ObjectBaseRef<Allocation> *mColorTargets;
+ ObjectBaseRef<Allocation> mDepthTarget;
+
+ uint32_t mFBOId;
+
+};
+
+} // renderscript
+} // android
+
+#endif //ANDROID_FRAME_BUFFER_OBJECT_CACHE_H
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index 01dbab8..595c89a 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -566,7 +566,7 @@ void FontState::initVertexArrayBuffers() {
indexPtr[i6 + 5] = i4 + 3;
}
- indexAlloc->deferedUploadToBufferObject(mRSC);
+ indexAlloc->deferredUploadToBufferObject(mRSC);
mIndexBuffer.set(indexAlloc);
const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3);
diff --git a/libs/rs/rsMesh.cpp b/libs/rs/rsMesh.cpp
index 76fe62d..e29c800 100644
--- a/libs/rs/rsMesh.cpp
+++ b/libs/rs/rsMesh.cpp
@@ -282,13 +282,13 @@ void Mesh::renderPrimitiveRange(Context *rsc, uint32_t primIndex, uint32_t start
void Mesh::uploadAll(Context *rsc) {
for (uint32_t ct = 0; ct < mVertexBufferCount; ct ++) {
if (mVertexBuffers[ct].get()) {
- mVertexBuffers[ct]->deferedUploadToBufferObject(rsc);
+ mVertexBuffers[ct]->deferredUploadToBufferObject(rsc);
}
}
for (uint32_t ct = 0; ct < mPrimitivesCount; ct ++) {
if (mPrimitives[ct]->mIndexBuffer.get()) {
- mPrimitives[ct]->mIndexBuffer->deferedUploadToBufferObject(rsc);
+ mPrimitives[ct]->mIndexBuffer->deferredUploadToBufferObject(rsc);
}
}
}
diff --git a/libs/rs/rsScriptC_LibGL.cpp b/libs/rs/rsScriptC_LibGL.cpp
index 4047049..1ed0f31 100644
--- a/libs/rs/rsScriptC_LibGL.cpp
+++ b/libs/rs/rsScriptC_LibGL.cpp
@@ -86,6 +86,33 @@ static void SC_bindProgramRaster(RsProgramRaster pv) {
rsi_ContextBindProgramRaster(rsc, pv);
}
+static void SC_bindFrameBufferObjectColorTarget(RsAllocation va, uint32_t slot) {
+ CHECK_OBJ(va);
+ GET_TLS();
+ rsc->mFBOCache.bindColorTarget(rsc, static_cast<Allocation *>(va), slot);
+}
+
+static void SC_bindFrameBufferObjectDepthTarget(RsAllocation va) {
+ CHECK_OBJ(va);
+ GET_TLS();
+ rsc->mFBOCache.bindDepthTarget(rsc, static_cast<Allocation *>(va));
+}
+
+static void SC_clearFrameBufferObjectColorTarget(uint32_t slot) {
+ GET_TLS();
+ rsc->mFBOCache.bindColorTarget(rsc, NULL, slot);
+}
+
+static void SC_clearFrameBufferObjectDepthTarget() {
+ GET_TLS();
+ rsc->mFBOCache.bindDepthTarget(rsc, NULL);
+}
+
+static void SC_clearFrameBufferObjectTargets() {
+ GET_TLS();
+ rsc->mFBOCache.resetAll(rsc);
+}
+
//////////////////////////////////////////////////////////////////////////////
// VP
//////////////////////////////////////////////////////////////////////////////
@@ -275,6 +302,10 @@ static void SC_color(float r, float g, float b, float a) {
pf->setConstantColor(rsc, r, g, b, a);
}
+static void SC_finish() {
+ glFinish();
+}
+
static void SC_allocationSyncAll(RsAllocation va) {
CHECK_OBJ(va);
GET_TLS();
@@ -291,6 +322,7 @@ static void SC_allocationSyncAll2(RsAllocation va, RsAllocationUsageType source)
static void SC_ClearColor(float r, float g, float b, float a) {
GET_TLS();
+ rsc->mFBOCache.setupGL2(rsc);
rsc->setupProgramStore();
glClearColor(r, g, b, a);
@@ -299,6 +331,7 @@ static void SC_ClearColor(float r, float g, float b, float a) {
static void SC_ClearDepth(float v) {
GET_TLS();
+ rsc->mFBOCache.setupGL2(rsc);
rsc->setupProgramStore();
glClearDepthf(v);
@@ -444,8 +477,15 @@ static ScriptCState::SymbolTable_t gSyms[] = {
{ "_Z11rsgBindFont7rs_font", (void *)&SC_BindFont, false },
{ "_Z12rsgFontColorffff", (void *)&SC_FontColor, false },
+ { "_Z18rsgBindColorTarget13rs_allocationj", (void *)&SC_bindFrameBufferObjectColorTarget, false },
+ { "_Z18rsgBindDepthTarget13rs_allocation", (void *)&SC_bindFrameBufferObjectDepthTarget, false },
+ { "_Z19rsgClearColorTargetj", (void *)&SC_clearFrameBufferObjectColorTarget, false },
+ { "_Z19rsgClearDepthTargetv", (void *)&SC_clearFrameBufferObjectDepthTarget, false },
+ { "_Z24rsgClearAllRenderTargetsv", (void *)&SC_clearFrameBufferObjectTargets, false },
+
// misc
{ "_Z5colorffff", (void *)&SC_color, false },
+ { "_Z9rsgFinishv", (void *)&SC_finish, false },
{ NULL, NULL, false }
};
diff --git a/libs/rs/scriptc/rs_graphics.rsh b/libs/rs/scriptc/rs_graphics.rsh
index 67ffc3d..d53bc95 100644
--- a/libs/rs/scriptc/rs_graphics.rsh
+++ b/libs/rs/scriptc/rs_graphics.rsh
@@ -1,6 +1,46 @@
#ifndef __RS_GRAPHICS_RSH__
#define __RS_GRAPHICS_RSH__
+/**
+ * Set the color target used for all subsequent rendering calls
+ * @param colorTarget
+ * @param slot
+ */
+extern void __attribute__((overloadable))
+ rsgBindColorTarget(rs_allocation colorTarget, uint slot);
+
+/**
+ * Clear the previously set color target
+ * @param slot
+ */
+extern void __attribute__((overloadable))
+ rsgClearColorTarget(uint slot);
+
+/**
+ * Set the depth target used for all subsequent rendering calls
+ * @param depthTarget
+ */
+extern void __attribute__((overloadable))
+ rsgBindDepthTarget(rs_allocation depthTarget);
+
+/**
+ * Clear the previously set depth target
+ */
+extern void __attribute__((overloadable))
+ rsgClearDepthTarget(void);
+
+/**
+ * Clear all color and depth targets and resume rendering into
+ * the framebuffer
+ */
+extern void __attribute__((overloadable))
+ rsgClearAllRenderTargets(void);
+
+/**
+ * Force RenderScript to finish all rendering commands
+ */
+extern uint __attribute__((overloadable))
+ rsgFinish(void);
/**
* Bind a new ProgramFragment to the rendering context.
diff --git a/tests/RenderScriptTests/FBOTest/Android.mk b/tests/RenderScriptTests/FBOTest/Android.mk
new file mode 100644
index 0000000..55525c4
--- /dev/null
+++ b/tests/RenderScriptTests/FBOTest/Android.mk
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2008 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.
+#
+
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := FBOTest
+
+include $(BUILD_PACKAGE)
+
+endif
diff --git a/tests/RenderScriptTests/FBOTest/AndroidManifest.xml b/tests/RenderScriptTests/FBOTest/AndroidManifest.xml
new file mode 100644
index 0000000..c2e0cc6
--- /dev/null
+++ b/tests/RenderScriptTests/FBOTest/AndroidManifest.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.fbotest">
+ <application android:label="_FBOTest">
+ <activity android:name="FBOTest"
+ android:theme="@android:style/Theme.Black.NoTitleBar">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/RenderScriptTests/FBOTest/res/drawable/robot.png b/tests/RenderScriptTests/FBOTest/res/drawable/robot.png
new file mode 100644
index 0000000..f7353fd
--- /dev/null
+++ b/tests/RenderScriptTests/FBOTest/res/drawable/robot.png
Binary files differ
diff --git a/tests/RenderScriptTests/FBOTest/res/raw/robot.a3d b/tests/RenderScriptTests/FBOTest/res/raw/robot.a3d
new file mode 100644
index 0000000..f48895c
--- /dev/null
+++ b/tests/RenderScriptTests/FBOTest/res/raw/robot.a3d
Binary files differ
diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOTest.java b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOTest.java
new file mode 100644
index 0000000..79d6012
--- /dev/null
+++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+package com.android.fbotest;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings.System;
+import android.util.Config;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.MenuInflater;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ListView;
+import android.net.Uri;
+
+import java.lang.Runtime;
+
+public class FBOTest extends Activity {
+
+ private FBOTestView mView;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ // Create our Preview view and set it as the content of our
+ // Activity
+ mView = new FBOTestView(this);
+ setContentView(mView);
+ }
+
+ @Override
+ protected void onResume() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mView.resume();
+ }
+
+ @Override
+ protected void onPause() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mView.pause();
+ }
+}
+
diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOTestRS.java b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOTestRS.java
new file mode 100644
index 0000000..9e30c4b5
--- /dev/null
+++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOTestRS.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.fbotest;
+
+import java.io.Writer;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.Element.DataType;
+import android.renderscript.Element.DataKind;
+import android.renderscript.ProgramStore.DepthFunc;
+import android.renderscript.Type.Builder;
+import android.util.Log;
+
+
+public class FBOTestRS {
+
+ public FBOTestRS() {
+ }
+
+ public void init(RenderScriptGL rs, Resources res) {
+ mRS = rs;
+ mRes = res;
+ initRS();
+ }
+
+ public void surfaceChanged() {
+ mRS.getWidth();
+ mRS.getHeight();
+ }
+
+ private Resources mRes;
+ private RenderScriptGL mRS;
+ private Sampler mSampler;
+ private ProgramStore mPSBackground;
+ private ProgramFragment mPFBackground;
+ private ProgramVertex mPVBackground;
+ private ProgramVertexFixedFunction.Constants mPVA;
+
+ private Allocation mGridImage;
+ private Allocation mOffscreen;
+ private Allocation mOffscreenDepth;
+ private Allocation mAllocPV;
+
+ private Font mItalic;
+ private Allocation mTextAlloc;
+
+ private ScriptField_MeshInfo mMeshes;
+ private ScriptC_fbotest mScript;
+
+
+ public void onActionDown(float x, float y) {
+ mScript.invoke_onActionDown(x, y);
+ }
+
+ public void onActionScale(float scale) {
+ mScript.invoke_onActionScale(scale);
+ }
+
+ public void onActionMove(float x, float y) {
+ mScript.invoke_onActionMove(x, y);
+ }
+
+ private void initPFS() {
+ ProgramStore.Builder b = new ProgramStore.Builder(mRS);
+
+ b.setDepthFunc(ProgramStore.DepthFunc.LESS);
+ b.setDitherEnabled(false);
+ b.setDepthMaskEnabled(true);
+ mPSBackground = b.create();
+
+ mScript.set_gPFSBackground(mPSBackground);
+ }
+
+ private void initPF() {
+ Sampler.Builder bs = new Sampler.Builder(mRS);
+ bs.setMinification(Sampler.Value.LINEAR);
+ bs.setMagnification(Sampler.Value.LINEAR);
+ bs.setWrapS(Sampler.Value.CLAMP);
+ bs.setWrapT(Sampler.Value.CLAMP);
+ mSampler = bs.create();
+
+ ProgramFragmentFixedFunction.Builder b = new ProgramFragmentFixedFunction.Builder(mRS);
+ b.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+ ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
+ mPFBackground = b.create();
+ mPFBackground.bindSampler(mSampler, 0);
+
+ mScript.set_gPFBackground(mPFBackground);
+ }
+
+ private void initPV() {
+ ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
+ mPVBackground = pvb.create();
+
+ mPVA = new ProgramVertexFixedFunction.Constants(mRS);
+ ((ProgramVertexFixedFunction)mPVBackground).bindConstants(mPVA);
+
+ mScript.set_gPVBackground(mPVBackground);
+ }
+
+ private void loadImage() {
+ mGridImage = Allocation.createFromBitmapResource(mRS, mRes, R.drawable.robot,
+ Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+ Allocation.USAGE_GRAPHICS_TEXTURE);
+ mScript.set_gTGrid(mGridImage);
+ }
+
+ private void initTextAllocation(String fileName) {
+ String allocString = "Displaying file: " + fileName;
+ mTextAlloc = Allocation.createFromString(mRS, allocString, Allocation.USAGE_SCRIPT);
+ mScript.set_gTextAlloc(mTextAlloc);
+ }
+
+ private void initMeshes(FileA3D model) {
+ int numEntries = model.getIndexEntryCount();
+ int numMeshes = 0;
+ for (int i = 0; i < numEntries; i ++) {
+ FileA3D.IndexEntry entry = model.getIndexEntry(i);
+ if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) {
+ numMeshes ++;
+ }
+ }
+
+ if (numMeshes > 0) {
+ mMeshes = new ScriptField_MeshInfo(mRS, numMeshes);
+
+ for (int i = 0; i < numEntries; i ++) {
+ FileA3D.IndexEntry entry = model.getIndexEntry(i);
+ if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) {
+ Mesh mesh = entry.getMesh();
+ mMeshes.set_mMesh(i, mesh, false);
+ mMeshes.set_mNumIndexSets(i, mesh.getPrimitiveCount(), false);
+ }
+ }
+ mMeshes.copyAll();
+ } else {
+ throw new RSRuntimeException("No valid meshes in file");
+ }
+
+ mScript.bind_gMeshes(mMeshes);
+ mScript.invoke_updateMeshInfo();
+ }
+
+ public void loadA3DFile(String path) {
+ FileA3D model = FileA3D.createFromFile(mRS, path);
+ initMeshes(model);
+ initTextAllocation(path);
+ }
+
+ private void initRS() {
+
+ mScript = new ScriptC_fbotest(mRS, mRes, R.raw.fbotest);
+
+ initPFS();
+ initPF();
+ initPV();
+
+ loadImage();
+
+ Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS));
+ b.setX(512).setY(512);
+ mOffscreen = Allocation.createTyped(mRS,
+ b.create(),
+ Allocation.USAGE_GRAPHICS_TEXTURE |
+ Allocation.USAGE_GRAPHICS_RENDER_TARGET);
+ mScript.set_gOffscreen(mOffscreen);
+
+ b = new Type.Builder(mRS,
+ Element.createPixel(mRS, DataType.UNSIGNED_16,
+ DataKind.PIXEL_DEPTH));
+ b.setX(512).setY(512);
+ mOffscreenDepth = Allocation.createTyped(mRS,
+ b.create(),
+ Allocation.USAGE_GRAPHICS_RENDER_TARGET);
+ mScript.set_gOffscreenDepth(mOffscreenDepth);
+
+ FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot);
+ initMeshes(model);
+
+ mItalic = Font.create(mRS, mRes, "serif", Font.Style.ITALIC, 8);
+ mScript.set_gItalic(mItalic);
+
+ initTextAllocation("R.raw.robot");
+
+ mRS.bindRootScript(mScript);
+ }
+}
+
+
+
diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOTestView.java b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOTestView.java
new file mode 100644
index 0000000..c9598ee
--- /dev/null
+++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOTestView.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.fbotest;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScriptGL;
+
+import android.content.Context;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.ScaleGestureDetector;
+import android.util.Log;
+
+public class FBOTestView extends RSSurfaceView {
+
+ private RenderScriptGL mRS;
+ private FBOTestRS mRender;
+
+ private ScaleGestureDetector mScaleDetector;
+
+ private static final int INVALID_POINTER_ID = -1;
+ private int mActivePointerId = INVALID_POINTER_ID;
+
+ public FBOTestView(Context context) {
+ super(context);
+ ensureRenderScript();
+ mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
+ }
+
+ private void ensureRenderScript() {
+ if (mRS == null) {
+ RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+ sc.setDepth(16, 24);
+ mRS = createRenderScriptGL(sc);
+ mRender = new FBOTestRS();
+ mRender.init(mRS, getResources());
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ ensureRenderScript();
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ super.surfaceChanged(holder, format, w, h);
+ mRender.surfaceChanged();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ mRender = null;
+ if (mRS != null) {
+ mRS = null;
+ destroyRenderScriptGL();
+ }
+ }
+
+ public void loadA3DFile(String path) {
+ mRender.loadA3DFile(path);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ mScaleDetector.onTouchEvent(ev);
+
+ boolean ret = false;
+ float x = ev.getX();
+ float y = ev.getY();
+
+ final int action = ev.getAction();
+
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN: {
+ mRender.onActionDown(x, y);
+ mActivePointerId = ev.getPointerId(0);
+ ret = true;
+ break;
+ }
+ case MotionEvent.ACTION_MOVE: {
+ if (!mScaleDetector.isInProgress()) {
+ mRender.onActionMove(x, y);
+ }
+ mRender.onActionDown(x, y);
+ ret = true;
+ break;
+ }
+
+ case MotionEvent.ACTION_UP: {
+ mActivePointerId = INVALID_POINTER_ID;
+ break;
+ }
+
+ case MotionEvent.ACTION_CANCEL: {
+ mActivePointerId = INVALID_POINTER_ID;
+ break;
+ }
+
+ case MotionEvent.ACTION_POINTER_UP: {
+ final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
+ >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ final int pointerId = ev.getPointerId(pointerIndex);
+ if (pointerId == mActivePointerId) {
+ // This was our active pointer going up. Choose a new
+ // active pointer and adjust accordingly.
+ final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
+ x = ev.getX(newPointerIndex);
+ y = ev.getY(newPointerIndex);
+ mRender.onActionDown(x, y);
+ mActivePointerId = ev.getPointerId(newPointerIndex);
+ }
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+ private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
+ @Override
+ public boolean onScale(ScaleGestureDetector detector) {
+ mRender.onActionScale(detector.getScaleFactor());
+ return true;
+ }
+ }
+}
+
+
diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs
new file mode 100644
index 0000000..31dd3e9
--- /dev/null
+++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs
@@ -0,0 +1,221 @@
+// Copyright (C) 2011 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.fbotest)
+
+#include "rs_graphics.rsh"
+
+rs_program_vertex gPVBackground;
+rs_program_fragment gPFBackground;
+
+rs_allocation gTGrid;
+
+rs_program_store gPFSBackground;
+
+rs_font gItalic;
+rs_allocation gTextAlloc;
+
+rs_allocation gOffscreen;
+rs_allocation gOffscreenDepth;
+
+typedef struct MeshInfo {
+ rs_mesh mMesh;
+ int mNumIndexSets;
+ float3 bBoxMin;
+ float3 bBoxMax;
+} MeshInfo_t;
+
+MeshInfo_t *gMeshes;
+
+static float3 gLookAt;
+
+static float gRotateX;
+static float gRotateY;
+static float gZoom;
+
+static float gLastX;
+static float gLastY;
+
+void onActionDown(float x, float y) {
+ gLastX = x;
+ gLastY = y;
+}
+
+void onActionScale(float scale) {
+
+ gZoom *= 1.0f / scale;
+ gZoom = max(0.1f, min(gZoom, 500.0f));
+}
+
+void onActionMove(float x, float y) {
+ float dx = gLastX - x;
+ float dy = gLastY - y;
+
+ if (fabs(dy) <= 2.0f) {
+ dy = 0.0f;
+ }
+ if (fabs(dx) <= 2.0f) {
+ dx = 0.0f;
+ }
+
+ gRotateY -= dx;
+ if (gRotateY > 360) {
+ gRotateY -= 360;
+ }
+ if (gRotateY < 0) {
+ gRotateY += 360;
+ }
+
+ gRotateX -= dy;
+ gRotateX = min(gRotateX, 80.0f);
+ gRotateX = max(gRotateX, -80.0f);
+
+ gLastX = x;
+ gLastY = y;
+}
+
+void init() {
+ gRotateX = 0.0f;
+ gRotateY = 0.0f;
+ gZoom = 50.0f;
+ gLookAt = 0.0f;
+}
+
+void updateMeshInfo() {
+ rs_allocation allMeshes = rsGetAllocation(gMeshes);
+ int size = rsAllocationGetDimX(allMeshes);
+ gLookAt = 0.0f;
+ float minX, minY, minZ, maxX, maxY, maxZ;
+ for (int i = 0; i < size; i++) {
+ MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i);
+ rsgMeshComputeBoundingBox(info->mMesh,
+ &minX, &minY, &minZ,
+ &maxX, &maxY, &maxZ);
+ info->bBoxMin = (minX, minY, minZ);
+ info->bBoxMax = (maxX, maxY, maxZ);
+ gLookAt += (info->bBoxMin + info->bBoxMax)*0.5f;
+ }
+ gLookAt = gLookAt / (float)size;
+}
+
+static void renderAllMeshes() {
+ rs_allocation allMeshes = rsGetAllocation(gMeshes);
+ int size = rsAllocationGetDimX(allMeshes);
+ gLookAt = 0.0f;
+ float minX, minY, minZ, maxX, maxY, maxZ;
+ for (int i = 0; i < size; i++) {
+ MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i);
+ rsgDrawMesh(info->mMesh);
+ }
+}
+
+static void drawDescription() {
+ uint width = rsgGetWidth();
+ uint height = rsgGetHeight();
+ int left = 0, right = 0, top = 0, bottom = 0;
+
+ rsgBindFont(gItalic);
+
+ rsgMeasureText(gTextAlloc, &left, &right, &top, &bottom);
+ rsgDrawText(gTextAlloc, 2 -left, height - 2 + bottom);
+}
+
+static void renderOffscreen(bool useDepth) {
+
+ rsgBindColorTarget(gOffscreen, 0);
+ if (useDepth) {
+ rsgBindDepthTarget(gOffscreenDepth);
+ rsgClearDepth(1.0f);
+ } else {
+ rsgClearDepthTarget();
+ }
+ rsgClearColor(0.8f, 0.8f, 0.8f, 1.0f);
+
+ rsgBindProgramVertex(gPVBackground);
+ rs_matrix4x4 proj;
+ float aspect = (float)rsAllocationGetDimX(gOffscreen) / (float)rsAllocationGetDimY(gOffscreen);
+ rsMatrixLoadPerspective(&proj, 30.0f, aspect, 1.0f, 100.0f);
+ rsgProgramVertexLoadProjectionMatrix(&proj);
+
+ rsgBindProgramFragment(gPFBackground);
+ rsgBindProgramStore(gPFSBackground);
+ rsgBindTexture(gPFBackground, 0, gTGrid);
+
+ rs_matrix4x4 matrix;
+ rsMatrixLoadIdentity(&matrix);
+ // Position our models on the screen
+ rsMatrixTranslate(&matrix, gLookAt.x, gLookAt.y, gLookAt.z - gZoom);
+ rsMatrixRotate(&matrix, gRotateX, 1.0f, 0.0f, 0.0f);
+ rsMatrixRotate(&matrix, gRotateY, 0.0f, 1.0f, 0.0f);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+
+ renderAllMeshes();
+
+ // Render into the frambuffer
+ rsgClearAllRenderTargets();
+}
+
+static void drawOffscreenResult(int posX, int posY) {
+ // display the result
+ rs_matrix4x4 proj, matrix;
+ rsMatrixLoadOrtho(&proj, 0, rsgGetWidth(), rsgGetHeight(), 0, -500, 500);
+ rsgProgramVertexLoadProjectionMatrix(&proj);
+ rsMatrixLoadIdentity(&matrix);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+ rsgBindTexture(gPFBackground, 0, gOffscreen);
+ float startX = posX, startY = posY;
+ float width = 256, height = 256;
+ rsgDrawQuadTexCoords(startX, startY, 0, 0, 1,
+ startX, startY + height, 0, 0, 0,
+ startX + width, startY + height, 0, 1, 0,
+ startX + width, startY, 0, 1, 1);
+}
+
+int root(int launchID) {
+
+ rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+ rsgClearDepth(1.0f);
+
+ renderOffscreen(true);
+ drawOffscreenResult(0, 0);
+
+ renderOffscreen(false);
+ drawOffscreenResult(0, 256);
+
+ rsgBindProgramVertex(gPVBackground);
+ rs_matrix4x4 proj;
+ float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+ rsMatrixLoadPerspective(&proj, 30.0f, aspect, 1.0f, 100.0f);
+ rsgProgramVertexLoadProjectionMatrix(&proj);
+
+ rsgBindProgramFragment(gPFBackground);
+ rsgBindProgramStore(gPFSBackground);
+ rsgBindTexture(gPFBackground, 0, gTGrid);
+
+ rs_matrix4x4 matrix;
+ rsMatrixLoadIdentity(&matrix);
+ // Position our models on the screen
+ rsMatrixTranslate(&matrix, gLookAt.x, gLookAt.y, gLookAt.z - gZoom);
+ rsMatrixRotate(&matrix, gRotateX, 1.0f, 0.0f, 0.0f);
+ rsMatrixRotate(&matrix, gRotateY, 0.0f, 1.0f, 0.0f);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+
+ renderAllMeshes();
+
+ drawDescription();
+
+ return 0;
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
index 9757ec6..5443ef8 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
@@ -22,6 +22,8 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.renderscript.*;
+import android.renderscript.Element.DataKind;
+import android.renderscript.Element.DataType;
import android.renderscript.Allocation.MipmapControl;
import android.renderscript.Program.TextureType;
import android.renderscript.ProgramStore.DepthFunc;
@@ -399,6 +401,23 @@ public class RsBenchRS {
initProgramRaster();
initCustomShaders();
+ Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS));
+ b.setX(1280).setY(720);
+ Allocation offscreen = Allocation.createTyped(mRS,
+ b.create(),
+ Allocation.USAGE_GRAPHICS_TEXTURE |
+ Allocation.USAGE_GRAPHICS_RENDER_TARGET);
+ mScript.set_gRenderBufferColor(offscreen);
+
+ b = new Type.Builder(mRS,
+ Element.createPixel(mRS, DataType.UNSIGNED_16,
+ DataKind.PIXEL_DEPTH));
+ b.setX(1280).setY(720);
+ offscreen = Allocation.createTyped(mRS,
+ b.create(),
+ Allocation.USAGE_GRAPHICS_RENDER_TARGET);
+ mScript.set_gRenderBufferDepth(offscreen);
+
mRS.bindRootScript(mScript);
}
}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
index 3c92725..fd0f16f 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
@@ -76,11 +76,17 @@ rs_program_vertex gProgVertexPixelLightMove;
rs_program_fragment gProgFragmentPixelLight;
rs_program_fragment gProgFragmentMultitex;
+rs_allocation gRenderBufferColor;
+rs_allocation gRenderBufferDepth;
+
float gDt = 0;
void init() {
}
+static int gRenderSurfaceW;
+static int gRenderSurfaceH;
+
static const char *sampleText = "This is a sample of small text for performace";
// Offsets for multiple layer of text
static int textOffsets[] = { 0, 0, -5, -5, 5, 5, -8, -8, 8, 8};
@@ -91,6 +97,11 @@ static float textColors[] = {1.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.6f, 0.7f, 1.0f,
};
+static void setupOffscreenTarget() {
+ rsgBindColorTarget(gRenderBufferColor, 0);
+ rsgBindDepthTarget(gRenderBufferDepth);
+}
+
static void displayFontSamples(int fillNum) {
rs_font fonts[5];
@@ -100,8 +111,8 @@ static void displayFontSamples(int fillNum) {
rsSetObject(&fonts[3], gFontSerifBoldItalic);
rsSetObject(&fonts[4], gFontSans);
- uint width = rsgGetWidth();
- uint height = rsgGetHeight();
+ uint width = gRenderSurfaceW;
+ uint height = gRenderSurfaceH;
int left = 0, right = 0, top = 0, bottom = 0;
rsgMeasureText(sampleText, &left, &right, &top, &bottom);
@@ -136,7 +147,7 @@ static void bindProgramVertexOrtho() {
rsgBindProgramVertex(gProgVertex);
// Setup the projection matrix
rs_matrix4x4 proj;
- rsMatrixLoadOrtho(&proj, 0, rsgGetWidth(), rsgGetHeight(), 0, -500, 500);
+ rsMatrixLoadOrtho(&proj, 0, gRenderSurfaceW, gRenderSurfaceH, 0, -500, 500);
rsgProgramVertexLoadProjectionMatrix(&proj);
}
@@ -158,7 +169,7 @@ static void displaySingletexFill(bool blend, int quadCount) {
for (int i = 0; i < quadCount; i ++) {
float startX = 10 * i, startY = 10 * i;
- float width = rsgGetWidth() - startX, height = rsgGetHeight() - startY;
+ float width = gRenderSurfaceW - startX, height = gRenderSurfaceH - startY;
rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
startX, startY + height, 0, 0, 1,
startX + width, startY + height, 0, 1, 1,
@@ -216,7 +227,7 @@ static void displayMeshSamples(int meshNum) {
bindProgramVertexOrtho();
rs_matrix4x4 matrix;
- rsMatrixLoadTranslate(&matrix, rsgGetWidth()/2, rsgGetHeight()/2, 0);
+ rsMatrixLoadTranslate(&matrix, gRenderSurfaceW/2, gRenderSurfaceH/2, 0);
rsgProgramVertexLoadModelMatrix(&matrix);
// Fragment shader with texture
@@ -344,7 +355,7 @@ static void displaySimpleGeoSamples(bool useTexture, int numMeshes) {
rsgBindProgramRaster(gCullBack);
// Setup the projection matrix with 30 degree field of view
rs_matrix4x4 proj;
- float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+ float aspect = (float)gRenderSurfaceW / (float)gRenderSurfaceH;
rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f);
rsgProgramVertexLoadProjectionMatrix(&proj);
@@ -445,7 +456,7 @@ static void displayCustomShaderSamples(int numMeshes) {
}
// Setup the projection matrix
- float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+ float aspect = (float)gRenderSurfaceW / (float)gRenderSurfaceH;
rsMatrixLoadPerspective(&gVSConstants->proj, 30.0f, aspect, 0.1f, 100.0f);
setupCustomShaderLights();
@@ -476,7 +487,7 @@ static void displayPixelLightSamples(int numMeshes, bool heavyVertex) {
gVSConstPixel->time = rsUptimeMillis()*0.005;
// Setup the projection matrix
- float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+ float aspect = (float)gRenderSurfaceW / (float)gRenderSurfaceH;
rsMatrixLoadPerspective(&gVSConstPixel->proj, 30.0f, aspect, 0.1f, 100.0f);
setupCustomShaderLights();
@@ -520,7 +531,7 @@ static void displayMultitextureSample(bool blend, int quadCount) {
for (int i = 0; i < quadCount; i ++) {
float startX = 10 * i, startY = 10 * i;
- float width = rsgGetWidth() - startX, height = rsgGetHeight() - startY;
+ float width = gRenderSurfaceW - startX, height = gRenderSurfaceH - startY;
rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
startX, startY + height, 0, 0, 1,
startX + width, startY + height, 0, 1, 1,
@@ -535,7 +546,7 @@ static void displayAnisoSample() {
gAnisoTime += gDt;
rsgBindProgramVertex(gProgVertex);
- float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+ float aspect = (float)gRenderSurfaceW / (float)gRenderSurfaceH;
rs_matrix4x4 proj;
rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f);
rsgProgramVertexLoadProjectionMatrix(&proj);
@@ -592,10 +603,6 @@ static bool checkInit() {
static int countdown = 5;
- if (countdown == 0) {
- gDt = 0;
- countdown --;
- }
// Perform all the uploads so we only measure rendered time
if(countdown > 1) {
displayFontSamples(5);
@@ -612,19 +619,13 @@ static bool checkInit() {
countdown --;
rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);
- // Now use text metrics to center the text
- uint width = rsgGetWidth();
- uint height = rsgGetHeight();
- int left = 0, right = 0, top = 0, bottom = 0;
-
rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
rsgBindFont(gFontSerifBoldItalic);
-
- const char* text = "Initializing";
- rsgMeasureText(text, &left, &right, &top, &bottom);
- int centeredPosX = width / 2 - (right - left) / 2;
- int centeredPosY = height / 2 - (top - bottom) / 2;
- rsgDrawText(text, centeredPosX, centeredPosY);
+ if (countdown == 1) {
+ rsgDrawText("Rendering", 50, 50);
+ } else {
+ rsgDrawText("Initializing", 50, 50);
+ }
return false;
}
@@ -632,70 +633,40 @@ static bool checkInit() {
return true;
}
-static int frameCount = 0;
-static int totalFramesRendered = 0;
static int benchMode = 0;
-#define testTime 5.0f
-static float curTestTime = testTime;
-
static const char *testNames[] = {
- "Finished text fill 1",
- "Finished text fill 2",
- "Finished text fill 3",
- "Finished text fill 4",
- "Finished text fill 5",
- "Finished 25.6k geo flat color",
- "Finished 51.2k geo flat color",
- "Finished 204.8k geo raster load flat color",
- "Finished 25.6k geo texture",
- "Finished 51.2k geo texture",
- "Finished 204.8k geo raster load texture",
- "Finished full screen mesh 10 by 10",
- "Finished full screen mesh 100 by 100",
- "Finished full screen mesh W / 4 by H / 4",
- "Finished 25.6k geo heavy vertex",
- "Finished 51.2k geo heavy vertex",
- "Finished 204.8k geo raster load heavy vertex",
- "Finished singletexture 5x fill",
- "Finished 3tex multitexture 5x fill",
- "Finished blend singletexture 5x fill",
- "Finished blend 3tex multitexture 5x fill",
- "Finished 25.6k geo heavy fragment",
- "Finished 51.2k geo heavy fragment",
- "Finished 204.8k geo raster load heavy fragment",
- "Finished 25.6k geo heavy fragment, heavy vertex",
- "Finished 51.2k geo heavy fragment, heavy vertex",
- "Finished 204.8k geo raster load heavy fragment, heavy vertex",
+ "Finished text fill 1,",
+ "Finished text fill 2,",
+ "Finished text fill 3,",
+ "Finished text fill 4,",
+ "Finished text fill 5,",
+ "Finished 25.6k geo flat color,",
+ "Finished 51.2k geo flat color,",
+ "Finished 204.8k geo raster load flat color,",
+ "Finished 25.6k geo texture,",
+ "Finished 51.2k geo texture,",
+ "Finished 204.8k geo raster load texture,",
+ "Finished full screen mesh 10 by 10,",
+ "Finished full screen mesh 100 by 100,",
+ "Finished full screen mesh W / 4 by H / 4,",
+ "Finished 25.6k geo heavy vertex,",
+ "Finished 51.2k geo heavy vertex,",
+ "Finished 204.8k geo raster load heavy vertex,",
+ "Finished singletexture 5x fill,",
+ "Finished 3tex multitexture 5x fill,",
+ "Finished blend singletexture 5x fill,",
+ "Finished blend 3tex multitexture 5x fill,",
+ "Finished 25.6k geo heavy fragment,",
+ "Finished 51.2k geo heavy fragment,",
+ "Finished 204.8k geo raster load heavy fragment,",
+ "Finished 25.6k geo heavy fragment heavy vertex,",
+ "Finished 51.2k geo heavy fragment heavy vertex,",
+ "Finished 204.8k geo raster load heavy fragment heavy vertex,",
};
-int root(int launchID) {
-
- gDt = rsGetDt();
-
- rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);
- rsgClearDepth(1.0f);
-
- if(!checkInit()) {
- return 1;
- }
-
- curTestTime -= gDt;
- if(curTestTime < 0.0f) {
- float fps = (float)(frameCount) / (testTime - curTestTime);
- rsDebug(testNames[benchMode], fps);
- benchMode ++;
- curTestTime = testTime;
- totalFramesRendered += frameCount;
- frameCount = 0;
- gTorusRotation = 0;
-
- if (benchMode > gMaxModes) {
- benchMode = 0;
- }
- }
-
- switch (benchMode) {
+static void runTest(int index) {
+ switch (index) {
case 0:
displayFontSamples(1);
break;
@@ -777,10 +748,87 @@ int root(int launchID) {
case 26:
displayPixelLightSamples(8, true);
break;
+ }
+}
+
+static void drawOffscreenResult(int posX, int posY, int width, int height) {
+ bindProgramVertexOrtho();
+ rs_matrix4x4 matrix;
+ rsMatrixLoadIdentity(&matrix);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+
+ rsgBindProgramFragment(gProgFragmentTexture);
+
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+ rsgBindTexture(gProgFragmentTexture, 0, gRenderBufferColor);
+
+ float startX = posX, startY = posY;
+ rsgDrawQuadTexCoords(startX, startY, 0, 0, 1,
+ startX, startY + height, 0, 0, 0,
+ startX + width, startY + height, 0, 1, 0,
+ startX + width, startY, 0, 1, 1);
+}
+
+int root(int launchID) {
+
+ gRenderSurfaceW = rsgGetWidth();
+ gRenderSurfaceH = rsgGetHeight();
+ rsgClearColor(0.2f, 0.2f, 0.2f, 1.0f);
+ rsgClearDepth(1.0f);
+ if(!checkInit()) {
+ return 1;
+ }
+
+ rsgFinish();
+ int64_t start = rsUptimeMillis();
+ rsGetDt();
+
+ int drawPos = 0;
+ int frameCount = 100;
+ for(int i = 0; i < frameCount; i ++) {
+ setupOffscreenTarget();
+ gRenderSurfaceW = rsAllocationGetDimX(gRenderBufferColor);
+ gRenderSurfaceH = rsAllocationGetDimY(gRenderBufferColor);
+ rsgClearColor(0.1f, 0.1f, 0.1f, 1.0f);
+ rsgClearDepth(1.0f);
+
+ runTest(benchMode);
+ rsgClearAllRenderTargets();
+ gRenderSurfaceW = rsgGetWidth();
+ gRenderSurfaceH = rsgGetHeight();
+ int size = 8;
+ drawOffscreenResult((drawPos+=size)%gRenderSurfaceW, (gRenderSurfaceH * 3) / 4, size, size);
+ gDt = rsGetDt();
}
- frameCount ++;
+ rsgFinish();
+
+ int64_t end = rsUptimeMillis();
+ float fps = (float)(frameCount) / ((float)(end - start)*0.001f);
+ rsDebug(testNames[benchMode], fps);
+
+ drawOffscreenResult(0, 0,
+ gRenderSurfaceW / 2,
+ gRenderSurfaceH / 2);
+
+ const char* text = testNames[benchMode];
+ int left = 0, right = 0, top = 0, bottom = 0;
+ uint width = rsgGetWidth();
+ uint height = rsgGetHeight();
+ rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
+ rsgBindFont(gFontSerifBoldItalic);
+ rsgMeasureText(text, &left, &right, &top, &bottom);
+ rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+ rsgDrawText(text, 2 -left, height - 2 + bottom);
+
+ benchMode ++;
+
+ gTorusRotation = 0;
+
+ if (benchMode > gMaxModes) {
+ benchMode = 0;
+ }
return 1;
}