summaryrefslogtreecommitdiff
path: root/libs/rs/rsProgramFragment.cpp
diff options
context:
space:
mode:
author Jason Sams <rjsams@android.com> 2010-02-12 11:27:01 -0800
committer Android Git Automerger <android-git-automerger@android.com> 2010-02-12 11:27:01 -0800
commit79b646ffe51c532f00b69dc4967ee51ca28986cf (patch)
tree64dc779a8ee4d21f322499bbefa11e5972741be3 /libs/rs/rsProgramFragment.cpp
parent1e90ab542d675616e9370ab7e5add99d7af12587 (diff)
parent0b9bbb6dc5d7dabecf23e8c6bb4a267ba8c34fe8 (diff)
am 0b9bbb6d: DO NOT MERGE. Merge Froyo renderscript to Eclair to support live wallpapers on droid. This gives the necessary CPU reduction to allow the wallpapers to work on the slower CPU.
Merge commit '0b9bbb6dc5d7dabecf23e8c6bb4a267ba8c34fe8' into eclair-plus-aosp * commit '0b9bbb6dc5d7dabecf23e8c6bb4a267ba8c34fe8': DO NOT MERGE. Merge Froyo renderscript to Eclair to support live wallpapers on droid. This gives the necessary CPU reduction to allow the wallpapers to work on the slower CPU.
Diffstat (limited to 'libs/rs/rsProgramFragment.cpp')
-rw-r--r--libs/rs/rsProgramFragment.cpp292
1 files changed, 186 insertions, 106 deletions
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
index 5f2dfae6b2c9..15f3269a6add 100644
--- a/libs/rs/rsProgramFragment.cpp
+++ b/libs/rs/rsProgramFragment.cpp
@@ -19,25 +19,50 @@
#include <GLES/gl.h>
#include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
using namespace android;
using namespace android::renderscript;
-ProgramFragment::ProgramFragment(Context *rsc, Element *in, Element *out, bool pointSpriteEnable) :
- Program(rsc, in, out)
+ProgramFragment::ProgramFragment(Context *rsc, const uint32_t * params,
+ uint32_t paramLength) :
+ Program(rsc)
{
mAllocFile = __FILE__;
mAllocLine = __LINE__;
- for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
- mEnvModes[ct] = RS_TEX_ENV_MODE_REPLACE;
- mTextureDimensions[ct] = 2;
- }
+ rsAssert(paramLength = 5);
+
+ mEnvModes[0] = (RsTexEnvMode)params[0];
+ mTextureFormats[0] = params[1];
+ mEnvModes[1] = (RsTexEnvMode)params[2];
+ mTextureFormats[1] = params[3];
+ mPointSpriteEnable = params[4] != 0;
+
mTextureEnableMask = 0;
- mPointSpriteEnable = pointSpriteEnable;
- mEnvModes[1] = RS_TEX_ENV_MODE_DECAL;
+ if (mEnvModes[0]) {
+ mTextureEnableMask |= 1;
+ }
+ if (mEnvModes[1]) {
+ mTextureEnableMask |= 2;
+ }
+ init(rsc);
}
+ProgramFragment::ProgramFragment(Context *rsc, const char * shaderText,
+ uint32_t shaderLength, const uint32_t * params,
+ uint32_t paramLength) :
+ Program(rsc, shaderText, shaderLength, params, paramLength)
+{
+ mAllocFile = __FILE__;
+ mAllocLine = __LINE__;
+
+ init(rsc);
+ mTextureEnableMask = (1 << mTextureCount) -1;
+}
+
+
ProgramFragment::~ProgramFragment()
{
}
@@ -65,23 +90,13 @@ void ProgramFragment::setupGL(const Context *rsc, ProgramFragmentState *state)
}
glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, mPointSpriteEnable);
}
-
- rsAssert(mTextures[ct]->getTextureID() != 0);
- if (mTextures[ct]->getTextureID() == 0) {
- // This is a hack for eclair to try to fix the white squares bug.
- Allocation *a = (Allocation *)mTextures[ct].get();
- a->uploadToTexture((Context *)rsc, 0);
- if (mTextures[ct]->getTextureID() == 0) {
- // At this point we are screwed. Crash to restart the app.
- rsc->dumpDebug();
- LOGE("Multiple failures during texture upload. Driver appears wedged.");
- ((char *)0)[0] = 0;
- }
-
- }
+ mTextures[ct]->uploadCheck(rsc);
glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
switch(mEnvModes[ct]) {
+ case RS_TEX_ENV_MODE_NONE:
+ rsAssert(0);
+ break;
case RS_TEX_ENV_MODE_REPLACE:
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
break;
@@ -94,7 +109,7 @@ void ProgramFragment::setupGL(const Context *rsc, ProgramFragmentState *state)
}
if (mSamplers[ct].get()) {
- mSamplers[ct]->setupGL();
+ mSamplers[ct]->setupGL(rsc);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -121,73 +136,158 @@ void ProgramFragment::setupGL(const Context *rsc, ProgramFragmentState *state)
}
glActiveTexture(GL_TEXTURE0);
mDirty = false;
+ rsc->checkError("ProgramFragment::setupGL");
}
-
-void ProgramFragment::bindTexture(uint32_t slot, Allocation *a)
+void ProgramFragment::setupGL2(const Context *rsc, ProgramFragmentState *state, ShaderCache *sc)
{
- if (slot >= MAX_TEXTURE) {
- LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE");
- return;
+
+ //LOGE("sgl2 frag1 %x", glGetError());
+ if ((state->mLast.get() == this) && !mDirty) {
+ //return;
}
+ state->mLast.set(this);
- //LOGE("bindtex %i %p", slot, a);
- mTextures[slot].set(a);
- mDirty = true;
-}
+ rsc->checkError("ProgramFragment::setupGL2 start");
+ for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
+ glActiveTexture(GL_TEXTURE0 + ct);
+ if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) {
+ continue;
+ }
-void ProgramFragment::bindSampler(uint32_t slot, Sampler *s)
-{
- if (slot >= MAX_TEXTURE) {
- LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE");
- return;
+ mTextures[ct]->uploadCheck(rsc);
+ glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
+ rsc->checkError("ProgramFragment::setupGL2 tex bind");
+ if (mSamplers[ct].get()) {
+ mSamplers[ct]->setupGL(rsc);
+ } else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ rsc->checkError("ProgramFragment::setupGL2 tex env");
+ }
+
+ glUniform1i(sc->fragUniformSlot(ct), ct);
+ rsc->checkError("ProgramFragment::setupGL2 uniforms");
}
- mSamplers[slot].set(s);
- mDirty = true;
+ glActiveTexture(GL_TEXTURE0);
+ mDirty = false;
+ rsc->checkError("ProgramFragment::setupGL2");
+}
+
+void ProgramFragment::loadShader(Context *rsc) {
+ Program::loadShader(rsc, GL_FRAGMENT_SHADER);
}
-void ProgramFragment::setType(uint32_t slot, const Element *e, uint32_t dim)
+void ProgramFragment::createShader()
{
- if (slot >= MAX_TEXTURE) {
- LOGE("Attempt to setType to a slot > MAX_TEXTURE");
- return;
- }
+ mShader.setTo("precision mediump float;\n");
+ mShader.append("varying vec4 varColor;\n");
+ mShader.append("varying vec4 varTex0;\n");
+
+ if (mUserShader.length() > 1) {
+ for (uint32_t ct=0; ct < mTextureCount; ct++) {
+ char buf[256];
+ sprintf(buf, "uniform sampler2D uni_Tex%i;\n", ct);
+ mShader.append(buf);
+ }
- if (dim >= 4) {
- LOGE("Attempt to setType to a dimension > 3");
- return;
- }
+ mShader.append(mUserShader);
+ } else {
+ uint32_t mask = mTextureEnableMask;
+ uint32_t texNum = 0;
+ while (mask) {
+ if (mask & 1) {
+ char buf[64];
+ mShader.append("uniform sampler2D uni_Tex");
+ sprintf(buf, "%i", texNum);
+ mShader.append(buf);
+ mShader.append(";\n");
+ }
+ mask >>= 1;
+ texNum++;
+ }
- mTextureFormats[slot].set(e);
- mTextureDimensions[slot] = dim;
-}
-void ProgramFragment::setEnvMode(uint32_t slot, RsTexEnvMode env)
-{
- if (slot >= MAX_TEXTURE) {
- LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE");
- return;
- }
+ mShader.append("void main() {\n");
+ mShader.append(" vec4 col = varColor;\n");
- mEnvModes[slot] = env;
-}
+ if (mTextureEnableMask) {
+ if (mPointSpriteEnable) {
+ mShader.append(" vec2 t0 = gl_PointCoord;\n");
+ } else {
+ mShader.append(" vec2 t0 = varTex0.xy;\n");
+ }
+ }
-void ProgramFragment::setTexEnable(uint32_t slot, bool enable)
-{
- if (slot >= MAX_TEXTURE) {
- LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE");
- return;
- }
+ mask = mTextureEnableMask;
+ texNum = 0;
+ while (mask) {
+ if (mask & 1) {
+ switch(mEnvModes[texNum]) {
+ case RS_TEX_ENV_MODE_NONE:
+ rsAssert(0);
+ break;
+ case RS_TEX_ENV_MODE_REPLACE:
+ switch(mTextureFormats[texNum]) {
+ case 1:
+ mShader.append(" col.a = texture2D(uni_Tex0, t0).a;\n");
+ break;
+ case 2:
+ mShader.append(" col.rgba = texture2D(uni_Tex0, t0).rgba;\n");
+ break;
+ case 3:
+ mShader.append(" col.rgb = texture2D(uni_Tex0, t0).rgb;\n");
+ break;
+ case 4:
+ mShader.append(" col.rgba = texture2D(uni_Tex0, t0).rgba;\n");
+ break;
+ }
+ break;
+ case RS_TEX_ENV_MODE_MODULATE:
+ switch(mTextureFormats[texNum]) {
+ case 1:
+ mShader.append(" col.a *= texture2D(uni_Tex0, t0).a;\n");
+ break;
+ case 2:
+ mShader.append(" col.rgba *= texture2D(uni_Tex0, t0).rgba;\n");
+ break;
+ case 3:
+ mShader.append(" col.rgb *= texture2D(uni_Tex0, t0).rgb;\n");
+ break;
+ case 4:
+ mShader.append(" col.rgba *= texture2D(uni_Tex0, t0).rgba;\n");
+ break;
+ }
+ break;
+ case RS_TEX_ENV_MODE_DECAL:
+ mShader.append(" col = texture2D(uni_Tex0, t0);\n");
+ break;
+ }
- uint32_t bit = 1 << slot;
- mTextureEnableMask &= ~bit;
- if (enable) {
- mTextureEnableMask |= bit;
+ }
+ mask >>= 1;
+ texNum++;
+ }
+
+ //mShader.append(" col.a = 1.0;\n");
+ //mShader.append(" col.r = 0.5;\n");
+
+ mShader.append(" gl_FragColor = col;\n");
+ mShader.append("}\n");
}
}
+void ProgramFragment::init(Context *rsc)
+{
+ mUniformCount = 2;
+ mUniformNames[0].setTo("uni_Tex0");
+ mUniformNames[1].setTo("uni_Tex1");
+ createShader();
+}
ProgramFragmentState::ProgramFragmentState()
{
@@ -202,8 +302,14 @@ ProgramFragmentState::~ProgramFragmentState()
void ProgramFragmentState::init(Context *rsc, int32_t w, int32_t h)
{
- ProgramFragment *pf = new ProgramFragment(rsc, NULL, NULL, false);
+ uint32_t tmp[5] = {
+ RS_TEX_ENV_MODE_NONE, 0,
+ RS_TEX_ENV_MODE_NONE, 0,
+ 0
+ };
+ ProgramFragment *pf = new ProgramFragment(rsc, tmp, 5);
mDefault.set(pf);
+ pf->init(rsc);
}
void ProgramFragmentState::deinit(Context *rsc)
@@ -216,50 +322,24 @@ void ProgramFragmentState::deinit(Context *rsc)
namespace android {
namespace renderscript {
-void rsi_ProgramFragmentBegin(Context * rsc, RsElement in, RsElement out, bool pointSpriteEnable)
+RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc,
+ const uint32_t * params,
+ uint32_t paramLength)
{
- delete rsc->mStateFragment.mPF;
- rsc->mStateFragment.mPF = new ProgramFragment(rsc, (Element *)in, (Element *)out, pointSpriteEnable);
-}
-
-void rsi_ProgramFragmentBindTexture(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsAllocation a)
-{
- ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
- pf->bindTexture(slot, static_cast<Allocation *>(a));
-}
-
-void rsi_ProgramFragmentBindSampler(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsSampler s)
-{
- ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
- pf->bindSampler(slot, static_cast<Sampler *>(s));
-}
-
-void rsi_ProgramFragmentSetSlot(Context *rsc, uint32_t slot, bool enable, RsTexEnvMode env, RsType vt)
-{
- const Type *t = static_cast<const Type *>(vt);
- if (t) {
- uint32_t dim = 1;
- if (t->getDimY()) {
- dim ++;
- if (t->getDimZ()) {
- dim ++;
- }
- }
- rsc->mStateFragment.mPF->setType(slot, t->getElement(), dim);
- }
- rsc->mStateFragment.mPF->setEnvMode(slot, env);
- rsc->mStateFragment.mPF->setTexEnable(slot, enable);
+ ProgramFragment *pf = new ProgramFragment(rsc, params, paramLength);
+ pf->incUserRef();
+ return pf;
}
-RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc)
+RsProgramFragment rsi_ProgramFragmentCreate2(Context *rsc, const char * shaderText,
+ uint32_t shaderLength, const uint32_t * params,
+ uint32_t paramLength)
{
- ProgramFragment *pf = rsc->mStateFragment.mPF;
+ ProgramFragment *pf = new ProgramFragment(rsc, shaderText, shaderLength, params, paramLength);
pf->incUserRef();
- rsc->mStateFragment.mPF = 0;
return pf;
}
-
}
}