First draft of fbo in renderscript.

Updating samples and benchmark

Change-Id: I469bf8b842fca72b59475c8fa024c12cf0e14954
This commit is contained in:
Alex Sakhartchouk
2011-04-01 14:19:01 -07:00
parent 397de169e5
commit 8e90f2bc1f
25 changed files with 1293 additions and 117 deletions

View File

@ -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;

View File

@ -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;

View File

@ -90,6 +90,7 @@ LOCAL_SRC_FILES:= \
rsContext.cpp \
rsDevice.cpp \
rsElement.cpp \
rsFBOCache.cpp \
rsFileA3D.cpp \
rsFont.cpp \
rsLocklessFifo.cpp \

View File

@ -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 {

View File

@ -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;
}

View File

@ -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 *);

View File

@ -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

View File

@ -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;
}

View File

@ -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 *);

209
libs/rs/rsFBOCache.cpp Normal file
View File

@ -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
}

57
libs/rs/rsFBOCache.h Normal file
View File

@ -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

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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 }
};

View File

@ -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.

View File

@ -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

View File

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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;
}
frameCount ++;
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();
}
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;
}