summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorAlex Sakhartchouk <alexst@google.com>2010-11-18 15:22:43 -0800
committerAlex Sakhartchouk <alexst@google.com>2010-11-18 15:27:28 -0800
commit67f2e442a31b8395e3c1951f8e91139ec7f2be99 (patch)
tree9e3001eb5181faec98ac13fa85c7915fb8c96c1a /libs
parent3d019afcdb167a04d9c879285b448f9be1de3c67 (diff)
downloadframeworks_base-67f2e442a31b8395e3c1951f8e91139ec7f2be99.zip
frameworks_base-67f2e442a31b8395e3c1951f8e91139ec7f2be99.tar.gz
frameworks_base-67f2e442a31b8395e3c1951f8e91139ec7f2be99.tar.bz2
Support for cubemaps.
Change-Id: Iaf6087f614451a8e233b3e5bc49c834ab0ad08ee
Diffstat (limited to 'libs')
-rw-r--r--libs/rs/RenderScript.h8
-rw-r--r--libs/rs/java/Samples/res/drawable/cubemap_test.pngbin0 -> 2898 bytes
-rw-r--r--libs/rs/java/Samples/res/raw/shadercubef.glsl8
-rw-r--r--libs/rs/java/Samples/res/raw/shadercubev.glsl10
-rw-r--r--libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java29
-rw-r--r--libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs44
-rw-r--r--libs/rs/rsAdapter.cpp11
-rw-r--r--libs/rs/rsAllocation.cpp143
-rw-r--r--libs/rs/rsAllocation.h5
-rw-r--r--libs/rs/rsFont.cpp4
-rw-r--r--libs/rs/rsProgram.cpp17
-rw-r--r--libs/rs/rsProgram.h2
-rw-r--r--libs/rs/rsProgramFragment.cpp27
-rw-r--r--libs/rs/rsProgramVertex.cpp6
-rw-r--r--libs/rs/rsSampler.cpp25
15 files changed, 290 insertions, 49 deletions
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index 20e289d..0ed129f 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -160,6 +160,11 @@ enum RsSamplerValue {
RS_SAMPLER_CLAMP
};
+enum RsTextureTarget {
+ RS_TEXTURE_2D,
+ RS_TEXTURE_CUBE
+};
+
enum RsDimension {
RS_DIMENSION_X,
RS_DIMENSION_Y,
@@ -218,7 +223,7 @@ enum RsProgramParam {
RS_PROGRAM_PARAM_INPUT,
RS_PROGRAM_PARAM_OUTPUT,
RS_PROGRAM_PARAM_CONSTANT,
- RS_PROGRAM_PARAM_TEXTURE_COUNT,
+ RS_PROGRAM_PARAM_TEXTURE_TYPE,
};
enum RsPrimitive {
@@ -322,6 +327,7 @@ RsType rsaTypeCreate(RsContext, RsElement, uint32_t dimCount,
const RsDimension *dims, const uint32_t *vals);
RsAllocation rsaAllocationCreateTyped(RsContext rsc, RsType vtype);
RsAllocation rsaAllocationCreateFromBitmap(RsContext con, uint32_t w, uint32_t h, RsElement _dst, RsElement _src, bool genMips, const void *data);
+RsAllocation rsaAllocationCubeCreateFromBitmap(RsContext con, uint32_t w, uint32_t h, RsElement _dst, RsElement _src, bool genMips, const void *data);
#ifndef NO_RS_FUNCS
#include "rsgApiFuncDecl.h"
diff --git a/libs/rs/java/Samples/res/drawable/cubemap_test.png b/libs/rs/java/Samples/res/drawable/cubemap_test.png
new file mode 100644
index 0000000..75ad0a4
--- /dev/null
+++ b/libs/rs/java/Samples/res/drawable/cubemap_test.png
Binary files differ
diff --git a/libs/rs/java/Samples/res/raw/shadercubef.glsl b/libs/rs/java/Samples/res/raw/shadercubef.glsl
new file mode 100644
index 0000000..15696a4
--- /dev/null
+++ b/libs/rs/java/Samples/res/raw/shadercubef.glsl
@@ -0,0 +1,8 @@
+
+varying vec3 worldNormal;
+
+void main() {
+ lowp vec4 col = textureCube(UNI_Tex0, worldNormal);
+ gl_FragColor = col;
+}
+
diff --git a/libs/rs/java/Samples/res/raw/shadercubev.glsl b/libs/rs/java/Samples/res/raw/shadercubev.glsl
new file mode 100644
index 0000000..70f5cd6
--- /dev/null
+++ b/libs/rs/java/Samples/res/raw/shadercubev.glsl
@@ -0,0 +1,10 @@
+varying vec3 worldNormal;
+
+// This is where actual shader code begins
+void main() {
+ vec4 worldPos = UNI_model * ATTRIB_position;
+ gl_Position = UNI_proj * worldPos;
+
+ mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz);
+ worldNormal = model3 * ATTRIB_normal;
+}
diff --git a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
index f0b69d1..766601b 100644
--- a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
+++ b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
@@ -22,6 +22,8 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.renderscript.*;
+import android.renderscript.Allocation.CubemapLayout;
+import android.renderscript.Program.TextureType;
import android.renderscript.ProgramStore.DepthFunc;
import android.renderscript.Sampler.Value;
import android.util.Log;
@@ -80,6 +82,9 @@ public class RsRenderStatesRS {
private ProgramVertex mProgVertexCustom2;
private ProgramFragment mProgFragmentCustom2;
+ private ProgramVertex mProgVertexCube;
+ private ProgramFragment mProgFragmentCube;
+
private ProgramRaster mCullBack;
private ProgramRaster mCullFront;
private ProgramRaster mCullNone;
@@ -88,6 +93,7 @@ public class RsRenderStatesRS {
private Allocation mTexOpaque;
private Allocation mTexTransparent;
private Allocation mTexChecker;
+ private Allocation mTexCube;
private Mesh mMbyNMesh;
private Mesh mTorus;
@@ -240,6 +246,19 @@ public class RsRenderStatesRS {
mProgFragmentCustom2 = pfbCustom.create();
mProgFragmentCustom2.bindConstants(mFSConst2.getAllocation(), 0);
+ // Cubemap test shaders
+ pvbCustom = new ProgramVertex.ShaderBuilder(mRS);
+ pvbCustom.setShader(mRes, R.raw.shadercubev);
+ pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
+ pvbCustom.addConstant(mVSConst.getAllocation().getType());
+ mProgVertexCube = pvbCustom.create();
+ mProgVertexCube.bindConstants(mVSConst.getAllocation(), 0);
+
+ pfbCustom = new ProgramFragment.ShaderBuilder(mRS);
+ pfbCustom.setShader(mRes, R.raw.shadercubef);
+ pfbCustom.addTexture(Program.TextureType.TEXTURE_CUBE);
+ mProgFragmentCube = pfbCustom.create();
+
pfbCustom = new ProgramFragment.ShaderBuilder(mRS);
pfbCustom.setShader(mRes, R.raw.multitexf);
pfbCustom.setTextureCount(3);
@@ -247,10 +266,11 @@ public class RsRenderStatesRS {
mScript.set_gProgVertexCustom(mProgVertexCustom);
mScript.set_gProgFragmentCustom(mProgFragmentCustom);
- mScript.set_gProgFragmentMultitex(mProgFragmentMultitex);
-
mScript.set_gProgVertexCustom2(mProgVertexCustom2);
mScript.set_gProgFragmentCustom2(mProgFragmentCustom2);
+ mScript.set_gProgVertexCube(mProgVertexCube);
+ mScript.set_gProgFragmentCube(mProgFragmentCube);
+ mScript.set_gProgFragmentMultitex(mProgFragmentMultitex);
}
private Allocation loadTextureRGB(int id) {
@@ -272,11 +292,16 @@ public class RsRenderStatesRS {
mTexOpaque = loadTextureRGB(R.drawable.data);
mTexTransparent = loadTextureARGB(R.drawable.leaf);
mTexChecker = loadTextureRGB(R.drawable.checker);
+ Bitmap b = BitmapFactory.decodeResource(mRes, R.drawable.cubemap_test);
+ mTexCube = Allocation.createCubemapFromBitmap(mRS, b, Element.RGB_565(mRS), false,
+ Allocation.CubemapLayout.VERTICAL_FACE_LIST);
+ mTexCube.uploadToTexture(0);
mScript.set_gTexTorus(mTexTorus);
mScript.set_gTexOpaque(mTexOpaque);
mScript.set_gTexTransparent(mTexTransparent);
mScript.set_gTexChecker(mTexChecker);
+ mScript.set_gTexCube(mTexCube);
}
private void initFonts() {
diff --git a/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs b/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs
index f26633d..39b0834 100644
--- a/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs
+++ b/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs
@@ -19,7 +19,7 @@
#include "rs_graphics.rsh"
#include "shader_def.rsh"
-const int gMaxModes = 10;
+const int gMaxModes = 11;
rs_program_vertex gProgVertex;
rs_program_fragment gProgFragmentColor;
@@ -34,6 +34,7 @@ rs_allocation gTexOpaque;
rs_allocation gTexTorus;
rs_allocation gTexTransparent;
rs_allocation gTexChecker;
+rs_allocation gTexCube;
rs_mesh gMbyNMesh;
rs_mesh gTorusMesh;
@@ -71,6 +72,8 @@ rs_program_vertex gProgVertexCustom;
rs_program_fragment gProgFragmentCustom;
rs_program_vertex gProgVertexCustom2;
rs_program_fragment gProgFragmentCustom2;
+rs_program_vertex gProgVertexCube;
+rs_program_fragment gProgFragmentCube;
rs_program_fragment gProgFragmentMultitex;
float gDt = 0;
@@ -506,6 +509,42 @@ void displayCustomShaderSamples2() {
rsgDrawText("Custom shader sample with array uniforms", 10, rsgGetHeight() - 10);
}
+void displayCubemapShaderSample() {
+ // Update vertex shader constants
+ // Load model matrix
+ // Aplly a rotation to our mesh
+ gTorusRotation += 50.0f * gDt;
+ if (gTorusRotation > 360.0f) {
+ gTorusRotation -= 360.0f;
+ }
+
+ // Position our model on the screen
+ // Position our model on the screen
+ rsMatrixLoadTranslate(&gVSConstants->model, 0.0f, 0.0f, -10.0f);
+ rsMatrixRotate(&gVSConstants->model, gTorusRotation, 1.0f, 0.0f, 0.0f);
+ rsMatrixRotate(&gVSConstants->model, gTorusRotation, 0.0f, 0.0f, 1.0f);
+ // Setup the projectioni matrix
+ float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+ rsMatrixLoadPerspective(&gVSConstants->proj, 30.0f, aspect, 0.1f, 100.0f);
+ rsAllocationMarkDirty(rsGetAllocation(gFSConstants));
+
+ rsgBindProgramVertex(gProgVertexCube);
+
+ // Fragment shader with texture
+ rsgBindProgramStore(gProgStoreBlendNoneDepth);
+ rsgBindProgramFragment(gProgFragmentCube);
+ rsgBindSampler(gProgFragmentCube, 0, gLinearClamp);
+ rsgBindTexture(gProgFragmentCube, 0, gTexCube);
+
+ // Use back face culling
+ rsgBindProgramRaster(gCullBack);
+ rsgDrawMesh(gTorusMesh);
+
+ rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+ rsgBindFont(gFontMono);
+ rsgDrawText("Cubemap shader sample", 10, rsgGetHeight() - 10);
+}
+
void displayMultitextureSample() {
bindProgramVertexOrtho();
rs_matrix4x4 matrix;
@@ -632,6 +671,9 @@ int root(int launchID) {
case 9:
displayCustomShaderSamples2();
break;
+ case 10:
+ displayCubemapShaderSample();
+ break;
}
return 10;
diff --git a/libs/rs/rsAdapter.cpp b/libs/rs/rsAdapter.cpp
index 2a705a1..8d363fd 100644
--- a/libs/rs/rsAdapter.cpp
+++ b/libs/rs/rsAdapter.cpp
@@ -143,8 +143,19 @@ void * Adapter2D::getElement(uint32_t x, uint32_t y) const {
rsAssert(mAllocation.get());
rsAssert(mAllocation->getPtr());
rsAssert(mAllocation->getType());
+ if (mFace != 0 && !mAllocation->getType()->getDimFaces()) {
+ LOGE("Adapter wants cubemap face, but allocation has none");
+ return NULL;
+ }
+
uint8_t * ptr = static_cast<uint8_t *>(mAllocation->getPtr());
ptr += mAllocation->getType()->getLODOffset(mLOD, x, y);
+
+ if (mFace != 0) {
+ uint32_t totalSizeBytes = mAllocation->getType()->getSizeBytes();
+ uint32_t faceOffset = totalSizeBytes / 6;
+ ptr += faceOffset * mFace;
+ }
return ptr;
}
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 23135e2..4ade714 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -123,8 +123,22 @@ void Allocation::deferedUploadToTexture(const Context *rsc, bool genMipmap, uint
mTextureGenMipmap = !mType->getDimLOD() && genMipmap;
}
+uint32_t Allocation::getGLTarget() const {
+ if (mIsTexture) {
+ if (mType->getDimFaces()) {
+ return GL_TEXTURE_CUBE_MAP;
+ } else {
+ return GL_TEXTURE_2D;
+ }
+ }
+ if (mIsVertexBuffer) {
+ return GL_ARRAY_BUFFER;
+ }
+ return 0;
+}
+
+
void Allocation::uploadToTexture(const Context *rsc) {
- //rsAssert(!mTextureId);
mIsTexture = true;
if (!rsc->checkDriver()) {
@@ -155,9 +169,30 @@ void Allocation::uploadToTexture(const Context *rsc) {
}
isFirstUpload = true;
}
- glBindTexture(GL_TEXTURE_2D, mTextureID);
+
+ GLenum target = (GLenum)getGLTarget();
+ glBindTexture(target, mTextureID);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ if (target == GL_TEXTURE_2D) {
+ upload2DTexture(isFirstUpload);
+ } else if (target == GL_TEXTURE_CUBE_MAP) {
+ uploadCubeTexture(isFirstUpload);
+ }
+
+ if (mTextureGenMipmap) {
+#ifndef ANDROID_RS_BUILD_FOR_HOST
+ glGenerateMipmap(target);
+#endif //ANDROID_RS_BUILD_FOR_HOST
+ }
+
+ rsc->checkError("Allocation::uploadToTexture");
+}
+
+void Allocation::upload2DTexture(bool isFirstUpload) {
+ GLenum type = mType->getElement()->getComponent().getGLType();
+ GLenum format = mType->getElement()->getComponent().getGLFormat();
+
Adapter2D adapt(getContext(), this);
for (uint32_t lod = 0; (lod + mTextureLOD) < mType->getLODCount(); lod++) {
adapt.setLOD(lod+mTextureLOD);
@@ -169,17 +204,45 @@ void Allocation::uploadToTexture(const Context *rsc) {
0, format, type, ptr);
} else {
glTexSubImage2D(GL_TEXTURE_2D, lod, 0, 0,
- adapt.getDimX(), adapt.getDimY(),
- format, type, ptr);
+ adapt.getDimX(), adapt.getDimY(),
+ format, type, ptr);
}
}
- if (mTextureGenMipmap) {
-#ifndef ANDROID_RS_BUILD_FOR_HOST
- glGenerateMipmap(GL_TEXTURE_2D);
-#endif //ANDROID_RS_BUILD_FOR_HOST
- }
+}
- rsc->checkError("Allocation::uploadToTexture");
+void Allocation::uploadCubeTexture(bool isFirstUpload) {
+ GLenum type = mType->getElement()->getComponent().getGLType();
+ GLenum format = mType->getElement()->getComponent().getGLFormat();
+
+ GLenum faceOrder[] = {
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+ };
+
+ Adapter2D adapt(getContext(), this);
+ for (uint32_t face = 0; face < 6; face ++) {
+ adapt.setFace(face);
+
+ for (uint32_t lod = 0; (lod + mTextureLOD) < mType->getLODCount(); lod++) {
+ adapt.setLOD(lod+mTextureLOD);
+
+ uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0));
+
+ if (isFirstUpload) {
+ glTexImage2D(faceOrder[face], lod, format,
+ adapt.getDimX(), adapt.getDimY(),
+ 0, format, type, ptr);
+ } else {
+ glTexSubImage2D(faceOrder[face], lod, 0, 0,
+ adapt.getDimX(), adapt.getDimY(),
+ format, type, ptr);
+ }
+ }
+ }
}
void Allocation::deferedUploadToBufferObject(const Context *rsc) {
@@ -205,10 +268,10 @@ void Allocation::uploadToBufferObject(const Context *rsc) {
mUploadDefered = true;
return;
}
-
- glBindBuffer(GL_ARRAY_BUFFER, mBufferID);
- glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
+ GLenum target = (GLenum)getGLTarget();
+ glBindBuffer(target, mBufferID);
+ glBufferData(target, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW);
+ glBindBuffer(target, 0);
rsc->checkError("Allocation::uploadToBufferObject");
}
@@ -816,3 +879,55 @@ RsAllocation rsaAllocationCreateFromBitmap(RsContext con, uint32_t w, uint32_t h
return texAlloc;
}
+
+RsAllocation rsaAllocationCubeCreateFromBitmap(RsContext con, uint32_t w, uint32_t h, RsElement _dst, RsElement _src, bool genMips, const void *data) {
+ Context *rsc = static_cast<Context *>(con);
+ const Element *src = static_cast<const Element *>(_src);
+ const Element *dst = static_cast<const Element *>(_dst);
+
+ // Cubemap allocation's faces should be Width by Width each.
+ // Source data should have 6 * Width by Width pixels
+ // Error checking is done in the java layer
+ RsDimension dims[] = {RS_DIMENSION_X, RS_DIMENSION_Y, RS_DIMENSION_LOD, RS_DIMENSION_FACE};
+ uint32_t dimValues[] = {w, w, genMips, true};
+ RsType type = rsaTypeCreate(rsc, _dst, 4, dims, dimValues);
+
+ RsAllocation vTexAlloc = rsaAllocationCreateTyped(rsc, type);
+ Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
+ if (texAlloc == NULL) {
+ LOGE("Memory allocation failure");
+ return NULL;
+ }
+
+ uint8_t *sourcePtr = (uint8_t*)data;
+ ElementConverter_t cvt = pickConverter(dst, src);
+ if (cvt) {
+ for (uint32_t face = 0; face < 6; face ++) {
+ Adapter2D faceAdapter(rsc, texAlloc);
+ faceAdapter.setFace(face);
+
+ cvt(faceAdapter.getElement(0, 0), sourcePtr, w * w);
+
+ // Move the data pointer to the next cube face
+ sourcePtr += w * w * src->getSizeBytes();
+
+ if (genMips) {
+ Adapter2D adapt(rsc, texAlloc);
+ Adapter2D adapt2(rsc, texAlloc);
+ adapt.setFace(face);
+ adapt2.setFace(face);
+ for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
+ adapt.setLOD(lod);
+ adapt2.setLOD(lod + 1);
+ mip(adapt2, adapt);
+ }
+ }
+ }
+ } else {
+ rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format");
+ delete texAlloc;
+ return NULL;
+ }
+
+ return texAlloc;
+}
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index f9a0fc9..5b432f2 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -48,6 +48,8 @@ public:
void uploadToTexture(const Context *rsc);
uint32_t getTextureID() const {return mTextureID;}
+ uint32_t getGLTarget() const;
+
void deferedUploadToBufferObject(const Context *rsc);
void uploadToBufferObject(const Context *rsc);
uint32_t getBufferObjectID() const {return mBufferID;}
@@ -134,7 +136,8 @@ protected:
private:
void init(Context *rsc, const Type *);
-
+ void upload2DTexture(bool isFirstUpload);
+ void uploadCubeTexture(bool isFirstUpload);
};
}
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index e4d77b2..107022d 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -498,8 +498,8 @@ void FontState::initRenderState() {
uint32_t tmp[4];
tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
tmp[1] = (uint32_t)inputType;
- tmp[2] = RS_PROGRAM_PARAM_TEXTURE_COUNT;
- tmp[3] = 1;
+ tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE;
+ tmp[3] = RS_TEXTURE_2D;
mFontShaderFConstant.set(new Allocation(mRSC, inputType));
ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(),
diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp
index 1c44e71..39b85e3 100644
--- a/libs/rs/rsProgram.cpp
+++ b/libs/rs/rsProgram.cpp
@@ -48,13 +48,14 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
mConstantCount++;
}
- if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_COUNT) {
- mTextureCount = params[ct+1];
+ if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) {
+ mTextureCount++;
}
}
mTextures = new ObjectBaseRef<Allocation>[mTextureCount];
mSamplers = new ObjectBaseRef<Sampler>[mTextureCount];
+ mTextureTargets = new RsTextureTarget[mTextureCount];
mInputElements = new ObjectBaseRef<Element>[mInputCount];
mOutputElements = new ObjectBaseRef<Element>[mOutputCount];
mConstantTypes = new ObjectBaseRef<Type>[mConstantCount];
@@ -63,6 +64,7 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
uint32_t input = 0;
uint32_t output = 0;
uint32_t constant = 0;
+ uint32_t texture = 0;
for (uint32_t ct=0; ct < paramLength; ct+=2) {
if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
mInputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
@@ -73,6 +75,9 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
}
+ if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) {
+ mTextureTargets[texture++] = (RsTextureTarget)params[ct+1];
+ }
}
mIsInternal = false;
uint32_t internalTokenLen = strlen(RS_SHADER_INTERNAL);
@@ -106,6 +111,7 @@ Program::~Program() {
}
delete[] mTextures;
delete[] mSamplers;
+ delete[] mTextureTargets;
delete[] mInputElements;
delete[] mOutputElements;
delete[] mConstantTypes;
@@ -127,6 +133,7 @@ void Program::initMemberVars() {
mTextures = NULL;
mSamplers = NULL;
+ mTextureTargets = NULL;
mInputElements = NULL;
mOutputElements = NULL;
mConstantTypes = NULL;
@@ -176,6 +183,12 @@ void Program::bindTexture(Context *rsc, uint32_t slot, Allocation *a) {
return;
}
+ if (a && a->getType()->getDimFaces() && mTextureTargets[slot] != RS_TEXTURE_CUBE) {
+ LOGE("Attempt to bind cubemap to slot %u but 2d texture needed", slot);
+ rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind cubemap to 2d texture slot");
+ return;
+ }
+
//LOGE("bindtex %i %p", slot, a);
mTextures[slot].set(a);
mDirty = true;
diff --git a/libs/rs/rsProgram.h b/libs/rs/rsProgram.h
index b682b97..c48464d 100644
--- a/libs/rs/rsProgram.h
+++ b/libs/rs/rsProgram.h
@@ -105,7 +105,7 @@ protected:
// Constants are strictly accessed by programetic loads.
ObjectBaseRef<Allocation> *mTextures;
ObjectBaseRef<Sampler> *mSamplers;
-
+ RsTextureTarget *mTextureTargets;
bool loadShader(Context *, uint32_t type);
};
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
index 407522b..ffa7d26 100644
--- a/libs/rs/rsProgramFragment.cpp
+++ b/libs/rs/rsProgramFragment.cpp
@@ -99,15 +99,20 @@ void ProgramFragment::setupGL2(Context *rsc, ProgramFragmentState *state, Shader
}
mTextures[ct]->uploadCheck(rsc);
- glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
+ GLenum target = (GLenum)mTextures[ct]->getGLTarget();
+ if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP) {
+ LOGE("Attempting to bind unknown texture to shader id %u, texture unit %u", (uint)this, ct);
+ rsc->setError(RS_ERROR_BAD_SHADER, "Non-texture allocation bound to a shader");
+ }
+ glBindTexture(target, mTextures[ct]->getTextureID());
rsc->checkError("ProgramFragment::setupGL2 tex bind");
if (mSamplers[ct].get()) {
mSamplers[ct]->setupGL(rsc, mTextures[ct].get());
} 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_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
rsc->checkError("ProgramFragment::setupGL2 tex env");
}
@@ -130,7 +135,11 @@ void ProgramFragment::createShader() {
appendUserConstants();
char buf[256];
for (uint32_t ct=0; ct < mTextureCount; ct++) {
- sprintf(buf, "uniform sampler2D UNI_Tex%i;\n", ct);
+ if (mTextureTargets[ct] == RS_TEXTURE_2D) {
+ sprintf(buf, "uniform sampler2D UNI_Tex%i;\n", ct);
+ } else {
+ sprintf(buf, "uniform samplerCube UNI_Tex%i;\n", ct);
+ }
mShader.append(buf);
}
mShader.append(mUserShader);
@@ -191,15 +200,13 @@ void ProgramFragmentState::init(Context *rsc) {
Type *inputType = Type::getType(rsc, constInput, 1, 0, 0, false, false);
- uint32_t tmp[4];
+ uint32_t tmp[2];
tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
tmp[1] = (uint32_t)inputType;
- tmp[2] = RS_PROGRAM_PARAM_TEXTURE_COUNT;
- tmp[3] = 0;
Allocation *constAlloc = new Allocation(rsc, inputType);
ProgramFragment *pf = new ProgramFragment(rsc, shaderString.string(),
- shaderString.length(), tmp, 4);
+ shaderString.length(), tmp, 2);
pf->bindAllocation(rsc, constAlloc, 0);
pf->setConstantColor(rsc, 1.0f, 1.0f, 1.0f, 1.0f);
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index e165967..3fd2981 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -253,16 +253,14 @@ void ProgramVertexState::init(Context *rsc) {
shaderString.append(" varTex0 = ATTRIB_texture0;\n");
shaderString.append("}\n");
- uint32_t tmp[6];
+ uint32_t tmp[4];
tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
tmp[1] = (uint32_t)inputType;
tmp[2] = RS_PROGRAM_PARAM_INPUT;
tmp[3] = (uint32_t)attrElem;
- tmp[4] = RS_PROGRAM_PARAM_TEXTURE_COUNT;
- tmp[5] = 0;
ProgramVertex *pv = new ProgramVertex(rsc, shaderString.string(),
- shaderString.length(), tmp, 6);
+ shaderString.length(), tmp, 4);
Allocation *alloc = new Allocation(rsc, inputType);
pv->bindAllocation(rsc, alloc, 0);
diff --git a/libs/rs/rsSampler.cpp b/libs/rs/rsSampler.cpp
index 1d0d270..54282a8 100644
--- a/libs/rs/rsSampler.cpp
+++ b/libs/rs/rsSampler.cpp
@@ -71,29 +71,32 @@ void Sampler::setupGL(const Context *rsc, const Allocation *tex) {
GL_CLAMP_TO_EDGE, //RS_SAMPLER_CLAMP
};
+ // This tells us the correct texture type
+ GLenum target = (GLenum)tex->getGLTarget();
+
if (!rsc->ext_OES_texture_npot() && tex->getType()->getIsNp2()) {
if (tex->getHasGraphicsMipmaps() && rsc->ext_GL_NV_texture_npot_2D_mipmap()) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
} else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, transNP[mMinFilter]);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, transNP[mMinFilter]);
}
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, transNP[mMagFilter]);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, transNP[mWrapS]);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, transNP[mWrapT]);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, transNP[mMagFilter]);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, transNP[mWrapS]);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, transNP[mWrapT]);
} else {
if (tex->getHasGraphicsMipmaps()) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
} else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, transNP[mMinFilter]);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, transNP[mMinFilter]);
}
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, trans[mMagFilter]);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, trans[mWrapS]);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, trans[mWrapT]);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, trans[mMagFilter]);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, trans[mWrapS]);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, trans[mWrapT]);
}
float anisoValue = rsMin(rsc->ext_texture_max_aniso(), mAniso);
if (rsc->ext_texture_max_aniso() > 1.0f) {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoValue);
+ glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoValue);
}
rsc->checkError("Sampler::setupGL2 tex env");