Merge "Support for cubemaps."

This commit is contained in:
Alex Sakhartchouk
2010-11-18 15:58:17 -08:00
committed by Android (Google) Code Review
21 changed files with 444 additions and 72 deletions

View File

@@ -34,6 +34,18 @@ public class Allocation extends BaseObj {
Type mType;
Bitmap mBitmap;
public enum CubemapLayout {
VERTICAL_FACE_LIST (0),
HORIZONTAL_FACE_LIST (1),
VERTICAL_CROSS (2),
HORIZONTAL_CROSS (3);
int mID;
CubemapLayout(int id) {
mID = id;
}
}
Allocation(int id, RenderScript rs, Type t) {
super(id, rs);
mType = t;
@@ -355,18 +367,21 @@ public class Allocation extends BaseObj {
throw new RSInvalidStateException("Bad bitmap type: " + bc);
}
static private Type typeFromBitmap(RenderScript rs, Bitmap b) {
static private Type typeFromBitmap(RenderScript rs, Bitmap b, boolean mip) {
Element e = elementFromBitmap(rs, b);
Type.Builder tb = new Type.Builder(rs, e);
tb.add(Dimension.X, b.getWidth());
tb.add(Dimension.Y, b.getHeight());
if (mip) {
tb.add(Dimension.LOD, 1);
}
return tb.create();
}
static public Allocation createFromBitmap(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips) {
static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
Element dstFmt, boolean genMips) {
rs.validate();
Type t = typeFromBitmap(rs, b);
Type t = typeFromBitmap(rs, b, genMips);
int id = rs.nAllocationCreateFromBitmap(dstFmt.getID(), genMips, b);
if(id == 0) {
@@ -375,10 +390,49 @@ public class Allocation extends BaseObj {
return new Allocation(id, rs, t);
}
static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
Element dstFmt,
boolean genMips,
CubemapLayout layout) {
rs.validate();
int height = b.getHeight();
int width = b.getWidth();
if (layout != CubemapLayout.VERTICAL_FACE_LIST) {
throw new RSIllegalArgumentException("Only vertical face list supported");
}
if (height % 6 != 0) {
throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
}
if (height / 6 != width) {
throw new RSIllegalArgumentException("Only square cobe map faces supported");
}
boolean isPow2 = (width & (width - 1)) == 0;
if (!isPow2) {
throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
}
Element e = elementFromBitmap(rs, b);
Type.Builder tb = new Type.Builder(rs, e);
tb.add(Dimension.X, width);
tb.add(Dimension.Y, width);
tb.add(Dimension.FACE, 1);
if (genMips) {
tb.add(Dimension.LOD, 1);
}
Type t = tb.create();
int id = rs.nAllocationCubeCreateFromBitmap(dstFmt.getID(), genMips, b);
if(id == 0) {
throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
}
return new Allocation(id, rs, t);
}
static public Allocation createBitmapRef(RenderScript rs, Bitmap b) {
rs.validate();
Type t = typeFromBitmap(rs, b);
Type t = typeFromBitmap(rs, b, false);
int id = rs.nAllocationCreateBitmapRef(t.getID(), b);
if(id == 0) {
@@ -404,7 +458,9 @@ public class Allocation extends BaseObj {
if (aId == 0) {
throw new RSRuntimeException("Load failed.");
}
return new Allocation(aId, rs, null);
Allocation alloc = new Allocation(aId, rs, null);
alloc.updateFromNative();
return alloc;
} finally {
if (is != null) {
try {

View File

@@ -36,9 +36,32 @@ public class Program extends BaseObj {
public static final int MAX_CONSTANT = 8;
public static final int MAX_TEXTURE = 8;
public enum TextureType {
TEXTURE_2D (0),
TEXTURE_CUBE (1);
int mID;
TextureType(int id) {
mID = id;
}
}
enum ProgramParam {
INPUT (0),
OUTPUT (1),
CONSTANT (2),
TEXTURE_TYPE (3);
int mID;
ProgramParam(int id) {
mID = id;
}
};
Element mInputs[];
Element mOutputs[];
Type mConstants[];
TextureType mTextures[];
int mTextureCount;
String mShader;
@@ -54,27 +77,34 @@ public class Program extends BaseObj {
a.getType().getID() != mConstants[slot].getID()) {
throw new IllegalArgumentException("Allocation type does not match slot type.");
}
mRS.nProgramBindConstants(getID(), slot, a.getID());
int id = a != null ? a.getID() : 0;
mRS.nProgramBindConstants(getID(), slot, id);
}
public void bindTexture(Allocation va, int slot)
throws IllegalArgumentException {
mRS.validate();
if((slot < 0) || (slot >= mTextureCount)) {
if ((slot < 0) || (slot >= mTextureCount)) {
throw new IllegalArgumentException("Slot ID out of range.");
}
if (va != null && va.getType().getFaces() &&
mTextures[slot] != TextureType.TEXTURE_CUBE) {
throw new IllegalArgumentException("Cannot bind cubemap to 2d texture slot");
}
mRS.nProgramBindTexture(getID(), slot, va.getID());
int id = va != null ? va.getID() : 0;
mRS.nProgramBindTexture(getID(), slot, id);
}
public void bindSampler(Sampler vs, int slot)
throws IllegalArgumentException {
mRS.validate();
if((slot < 0) || (slot >= mTextureCount)) {
if ((slot < 0) || (slot >= mTextureCount)) {
throw new IllegalArgumentException("Slot ID out of range.");
}
mRS.nProgramBindSampler(getID(), slot, vs.getID());
int id = vs != null ? vs.getID() : 0;
mRS.nProgramBindSampler(getID(), slot, id);
}
@@ -84,6 +114,7 @@ public class Program extends BaseObj {
Element mOutputs[];
Type mConstants[];
Type mTextures[];
TextureType mTextureTypes[];
int mInputCount;
int mOutputCount;
int mConstantCount;
@@ -100,6 +131,7 @@ public class Program extends BaseObj {
mOutputCount = 0;
mConstantCount = 0;
mTextureCount = 0;
mTextureTypes = new TextureType[MAX_TEXTURE];
}
public BaseProgramBuilder setShader(String s) {
@@ -192,6 +224,17 @@ public class Program extends BaseObj {
throw new IllegalArgumentException("Max texture count exceeded.");
}
mTextureCount = count;
for (int i = 0; i < mTextureCount; i ++) {
mTextureTypes[i] = TextureType.TEXTURE_2D;
}
return this;
}
public BaseProgramBuilder addTexture(TextureType texType) throws IllegalArgumentException {
if(mTextureCount >= MAX_TEXTURE) {
throw new IllegalArgumentException("Max texture count exceeded.");
}
mTextureTypes[mTextureCount ++] = texType;
return this;
}
@@ -203,6 +246,8 @@ public class Program extends BaseObj {
p.mConstants = new Type[mConstantCount];
System.arraycopy(mConstants, 0, p.mConstants, 0, mConstantCount);
p.mTextureCount = mTextureCount;
p.mTextures = new TextureType[mTextureCount];
System.arraycopy(mTextureTypes, 0, p.mTextures, 0, mTextureCount);
}
}

View File

@@ -37,23 +37,25 @@ public class ProgramFragment extends Program {
public ProgramFragment create() {
mRS.validate();
int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + 1) * 2];
int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
int idx = 0;
for (int i=0; i < mInputCount; i++) {
tmp[idx++] = 0;
tmp[idx++] = ProgramParam.INPUT.mID;
tmp[idx++] = mInputs[i].getID();
}
for (int i=0; i < mOutputCount; i++) {
tmp[idx++] = 1;
tmp[idx++] = ProgramParam.OUTPUT.mID;
tmp[idx++] = mOutputs[i].getID();
}
for (int i=0; i < mConstantCount; i++) {
tmp[idx++] = 2;
tmp[idx++] = ProgramParam.CONSTANT.mID;
tmp[idx++] = mConstants[i].getID();
}
tmp[idx++] = 3;
tmp[idx++] = mTextureCount;
for (int i=0; i < mTextureCount; i++) {
tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
tmp[idx++] = mTextureTypes[i].mID;
}
int id = mRS.nProgramFragmentCreate(mShader, tmp);
ProgramFragment pf = new ProgramFragment(id, mRS);

View File

@@ -46,23 +46,25 @@ public class ProgramVertex extends Program {
public ProgramVertex create() {
mRS.validate();
int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount +1) * 2];
int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
int idx = 0;
for (int i=0; i < mInputCount; i++) {
tmp[idx++] = 0;
tmp[idx++] = ProgramParam.INPUT.mID;
tmp[idx++] = mInputs[i].getID();
}
for (int i=0; i < mOutputCount; i++) {
tmp[idx++] = 1;
tmp[idx++] = ProgramParam.OUTPUT.mID;
tmp[idx++] = mOutputs[i].getID();
}
for (int i=0; i < mConstantCount; i++) {
tmp[idx++] = 2;
tmp[idx++] = ProgramParam.CONSTANT.mID;
tmp[idx++] = mConstants[i].getID();
}
tmp[idx++] = 3;
tmp[idx++] = mTextureCount;
for (int i=0; i < mTextureCount; i++) {
tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
tmp[idx++] = mTextureTypes[i].mID;
}
int id = mRS.nProgramVertexCreate(mShader, tmp);
ProgramVertex pv = new ProgramVertex(id, mRS);

View File

@@ -204,6 +204,10 @@ public class RenderScript {
synchronized int nAllocationCreateFromBitmap(int dstFmt, boolean genMips, Bitmap bmp) {
return rsnAllocationCreateFromBitmap(mContext, dstFmt, genMips, bmp);
}
native int rsnAllocationCubeCreateFromBitmap(int con, int dstFmt, boolean genMips, Bitmap bmp);
synchronized int nAllocationCubeCreateFromBitmap(int dstFmt, boolean genMips, Bitmap bmp) {
return rsnAllocationCubeCreateFromBitmap(mContext, dstFmt, genMips, bmp);
}
native int rsnAllocationCreateBitmapRef(int con, int type, Bitmap bmp);
synchronized int nAllocationCreateBitmapRef(int type, Bitmap bmp) {
return rsnAllocationCreateBitmapRef(mContext, type, bmp);

View File

@@ -455,6 +455,27 @@ nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint dst
return 0;
}
static int
nAllocationCubeCreateFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint dstFmt, jboolean genMips, jobject jbitmap)
{
SkBitmap const * nativeBitmap =
(SkBitmap const *)_env->GetIntField(jbitmap, gNativeBitmapID);
const SkBitmap& bitmap(*nativeBitmap);
SkBitmap::Config config = bitmap.getConfig();
RsElement e = SkBitmapToPredefined(config);
if (e) {
bitmap.lockPixels();
const int w = bitmap.width();
const int h = bitmap.height();
const void* ptr = bitmap.getPixels();
jint id = (jint)rsaAllocationCubeCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
bitmap.unlockPixels();
return id;
}
return 0;
}
static void
nAllocationUpdateFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jobject jbitmap)
{
@@ -1301,6 +1322,7 @@ static JNINativeMethod methods[] = {
{"rsnAllocationCreateTyped", "(II)I", (void*)nAllocationCreateTyped },
{"rsnAllocationUpdateFromBitmap", "(IILandroid/graphics/Bitmap;)V", (void*)nAllocationUpdateFromBitmap },
{"rsnAllocationCreateFromBitmap", "(IIZLandroid/graphics/Bitmap;)I", (void*)nAllocationCreateFromBitmap },
{"rsnAllocationCubeCreateFromBitmap","(IIZLandroid/graphics/Bitmap;)I", (void*)nAllocationCubeCreateFromBitmap },
{"rsnAllocationCreateBitmapRef", "(IILandroid/graphics/Bitmap;)I", (void*)nAllocationCreateBitmapRef },
{"rsnAllocationCreateFromAssetStream","(IIZI)I", (void*)nAllocationCreateFromAssetStream },
{"rsnAllocationUploadToTexture", "(IIZI)V", (void*)nAllocationUploadToTexture },

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -0,0 +1,8 @@
varying vec3 worldNormal;
void main() {
lowp vec4 col = textureCube(UNI_Tex0, worldNormal);
gl_FragColor = col;
}

View File

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

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.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() {

View File

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

View File

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

View File

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

View File

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

View File

@@ -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(),

View File

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

View File

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

View File

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

View File

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

View File

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