blob: 27676ddd78e823a72e0fff9b19800c314c19f2af [file] [log] [blame]
/*
** Copyright 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.glesv2debugger;
import com.android.glesv2debugger.DebuggerMessage.Message;
import com.android.sdklib.util.SparseArray;
import java.nio.ByteBuffer;
import java.util.ArrayList;
class GLTexture implements Cloneable {
public final int name;
public final GLEnum target;
public ArrayList<Message> contentChanges = new ArrayList<Message>();
public GLEnum wrapS = GLEnum.GL_REPEAT, wrapT = GLEnum.GL_REPEAT;
public GLEnum min = GLEnum.GL_NEAREST_MIPMAP_LINEAR;
public GLEnum mag = GLEnum.GL_LINEAR;
public GLEnum format;
public int width, height;
GLTexture(final int name, final GLEnum target) {
this.name = name;
this.target = target;
}
@Override
public GLTexture clone() {
try {
GLTexture copy = (GLTexture) super.clone();
copy.contentChanges = (ArrayList<Message>) contentChanges.clone();
return copy;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
assert false;
return null;
}
}
boolean processMessage(final Message msg) {
switch (msg.getFunction()) {
case glCompressedTexImage2D:
case glCopyTexImage2D:
case glTexImage2D:
if (msg.getArg1() == 0) { // level 0
format = GLEnum.valueOf(msg.getArg2());
width = msg.getArg3();
height = msg.getArg4();
}
//$FALL-THROUGH$
case glCompressedTexSubImage2D:
case glCopyTexSubImage2D:
case glTexSubImage2D:
case glGenerateMipmap:
contentChanges.add(msg);
break;
default:
assert false;
}
return true;
}
@Override
public String toString() {
return String.format("%s %s %d*%d %d change(s)", target, format, width, height,
contentChanges.size());
}
}
public class GLServerTexture implements Cloneable {
Context context;
public GLEnum activeTexture = GLEnum.GL_TEXTURE0;
public int[] tmu2D;
public int[] tmuCube;
public SparseArray<GLTexture> textures = new SparseArray<GLTexture>();
public GLTexture tex2D = null, texCube = null;
GLServerTexture(final Context context, final int MAX_COMBINED_TEXTURE_IMAGE_UNITS) {
this.context = context;
textures.append(0, null);
tmu2D = new int[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
tmuCube = new int[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
}
public GLServerTexture clone(final Context copyContext) {
try {
GLServerTexture copy = (GLServerTexture) super.clone();
copy.context = copyContext;
copy.tmu2D = tmu2D.clone();
copy.tmuCube = tmuCube.clone();
copy.textures = new SparseArray<GLTexture>(textures.size());
for (int i = 0; i < textures.size(); i++)
if (textures.valueAt(i) != null)
copy.textures.append(textures.keyAt(i), textures.valueAt(i).clone());
else
copy.textures.append(textures.keyAt(i), null);
if (tex2D != null)
copy.tex2D = copy.textures.get(tex2D.name);
if (texCube != null)
copy.texCube = copy.textures.get(texCube.name);
return copy;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
assert false;
return null;
}
}
public boolean processMessage(final Message msg) {
switch (msg.getFunction()) {
case glActiveTexture:
activeTexture = GLEnum.valueOf(msg.getArg0());
return true;
case glBindTexture:
return bindTexture(msg.getArg0(), msg.getArg1());
case glCompressedTexImage2D:
case glCompressedTexSubImage2D:
case glCopyTexImage2D:
case glCopyTexSubImage2D:
case glTexImage2D:
case glTexSubImage2D:
switch (GLEnum.valueOf(msg.getArg0())) {
case GL_TEXTURE_2D:
if (tex2D != null)
return tex2D.processMessage(msg);
return true;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
if (texCube != null)
return texCube.processMessage(msg);
return true;
default:
return true;
}
case glDeleteTextures: {
final ByteBuffer names = msg.getData().asReadOnlyByteBuffer();
names.order(SampleView.targetByteOrder);
for (int i = 0; i < msg.getArg0(); i++) {
final int name = names.getInt();
if (tex2D != null && tex2D.name == name)
bindTexture(GLEnum.GL_TEXTURE_2D.value, 0);
if (texCube != null && texCube.name == name)
bindTexture(GLEnum.GL_TEXTURE_CUBE_MAP.value, 0);
if (name != 0)
textures.remove(name);
}
return true;
}
case glGenerateMipmap:
if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_TEXTURE_2D && tex2D != null)
return tex2D.processMessage(msg);
else if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_TEXTURE_CUBE_MAP
&& texCube != null)
return texCube.processMessage(msg);
return true;
case glTexParameteri:
return texParameter(msg.getArg0(), msg.getArg1(), msg.getArg2());
case glTexParameterf:
return texParameter(msg.getArg0(), msg.getArg1(),
(int) Float.intBitsToFloat(msg.getArg2()));
default:
return false;
}
}
boolean bindTexture(final int target, final int name) {
final int index = activeTexture.value - GLEnum.GL_TEXTURE0.value;
if (GLEnum.valueOf(target) == GLEnum.GL_TEXTURE_2D) {
tex2D = textures.get(name);
if (name != 0 && tex2D == null)
textures.put(name, tex2D = new GLTexture(name,
GLEnum.GL_TEXTURE_2D));
if (index >= 0 && index < tmu2D.length)
tmu2D[index] = name;
} else if (GLEnum.valueOf(target) == GLEnum.GL_TEXTURE_CUBE_MAP) {
texCube = textures.get(name);
if (name != 0 && texCube == null)
textures.put(name, texCube = new GLTexture(name,
GLEnum.GL_TEXTURE_CUBE_MAP));
if (index >= 0 && index < tmu2D.length)
tmu2D[index] = name;
} else
assert false;
return true;
}
boolean texParameter(final int target, final int pname, final int param) {
GLTexture tex = null;
if (GLEnum.valueOf(target) == GLEnum.GL_TEXTURE_2D)
tex = tex2D;
else if (GLEnum.valueOf(target) == GLEnum.GL_TEXTURE_CUBE_MAP)
tex = texCube;
if (tex == null)
return true;
final GLEnum p = GLEnum.valueOf(param);
switch (GLEnum.valueOf(pname)) {
case GL_TEXTURE_WRAP_S:
tex.wrapS = p;
return true;
case GL_TEXTURE_WRAP_T:
tex.wrapT = p;
return true;
case GL_TEXTURE_MIN_FILTER:
tex.min = p;
return true;
case GL_TEXTURE_MAG_FILTER:
tex.mag = p;
return true;
default:
return true;
}
}
}