1 /* 2 ** Copyright 2011, The Android Open Source Project 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17 package com.android.ide.eclipse.gldebugger; 18 19 import com.android.ide.eclipse.gldebugger.DebuggerMessage.Message; 20 import com.android.ide.eclipse.gldebugger.DebuggerMessage.Message.Function; 21 import com.android.sdklib.util.SparseArray; 22 import com.android.sdklib.util.SparseIntArray; 23 24 class GLStencilState implements Cloneable { 25 public int ref, mask; 26 public GLEnum func; 27 public GLEnum sf, df, dp; // operation 28 29 @Override 30 public Object clone() { 31 try { 32 return super.clone(); 33 } catch (CloneNotSupportedException e) { 34 e.printStackTrace(); 35 return null; 36 } 37 } 38 } 39 40 public class GLServerState implements Cloneable { 41 final Context context; 42 public GLStencilState front = new GLStencilState(), back = new GLStencilState(); 43 public SparseIntArray enableDisables; 44 45 /** integer states set via a GL function and GLEnum; keyed by GLEnum.value */ 46 public SparseArray<Message> integers; 47 48 /** states set only via a GL function; keyed by Function.getNumber() */ 49 public SparseArray<Message> lastSetter; 50 51 GLServerState(final Context context) { 52 this.context = context; 53 enableDisables = new SparseIntArray(); 54 enableDisables.put(GLEnum.GL_BLEND.value, 0); 55 enableDisables.put(GLEnum.GL_DITHER.value, 1); 56 enableDisables.put(GLEnum.GL_DEPTH_TEST.value, 0); 57 enableDisables.put(GLEnum.GL_STENCIL_TEST.value, 0); 58 enableDisables.put(GLEnum.GL_SCISSOR_TEST.value, 0); 59 enableDisables.put(GLEnum.GL_SAMPLE_COVERAGE.value, 0); 60 enableDisables.put(GLEnum.GL_SAMPLE_ALPHA_TO_COVERAGE.value, 0); 61 enableDisables.put(GLEnum.GL_POLYGON_OFFSET_FILL.value, 0); 62 enableDisables.put(GLEnum.GL_CULL_FACE.value, 0); 63 // enableDisables.put(GLEnum.GL_TEXTURE_2D.value, 1); 64 65 lastSetter = new SparseArray<Message>(); 66 lastSetter.put(Function.glBlendColor.getNumber(), null); 67 // glBlendEquation overwrites glBlendEquationSeparate 68 lastSetter.put(Function.glBlendEquationSeparate.getNumber(), null); 69 // glBlendFunc overwrites glBlendFuncSeparate 70 lastSetter.put(Function.glBlendFuncSeparate.getNumber(), null); 71 lastSetter.put(Function.glClearColor.getNumber(), null); 72 lastSetter.put(Function.glClearDepthf.getNumber(), null); 73 lastSetter.put(Function.glClearStencil.getNumber(), null); 74 lastSetter.put(Function.glColorMask.getNumber(), null); 75 lastSetter.put(Function.glCullFace.getNumber(), null); 76 lastSetter.put(Function.glDepthMask.getNumber(), null); 77 lastSetter.put(Function.glDepthFunc.getNumber(), null); 78 lastSetter.put(Function.glDepthRangef.getNumber(), null); 79 lastSetter.put(Function.glFrontFace.getNumber(), null); 80 lastSetter.put(Function.glLineWidth.getNumber(), null); 81 lastSetter.put(Function.glPolygonOffset.getNumber(), null); 82 lastSetter.put(Function.glSampleCoverage.getNumber(), null); 83 lastSetter.put(Function.glScissor.getNumber(), null); 84 lastSetter.put(Function.glStencilMaskSeparate.getNumber(), null); 85 lastSetter.put(Function.glViewport.getNumber(), null); 86 87 integers = new SparseArray<Message>(); 88 integers.put(GLEnum.GL_PACK_ALIGNMENT.value, null); 89 integers.put(GLEnum.GL_UNPACK_ALIGNMENT.value, null); 90 } 91 92 /** returns true if processed */ 93 public boolean processMessage(final Message msg) { 94 switch (msg.getFunction()) { 95 case glBlendColor: 96 case glBlendEquation: 97 case glBlendEquationSeparate: 98 case glBlendFunc: 99 case glBlendFuncSeparate: 100 case glClearColor: 101 case glClearDepthf: 102 case glClearStencil: 103 case glColorMask: 104 case glCullFace: 105 case glDepthMask: 106 case glDepthFunc: 107 case glDepthRangef: 108 return setter(msg); 109 case glDisable: 110 return enableDisable(false, msg); 111 case glEnable: 112 return enableDisable(true, msg); 113 case glFrontFace: 114 case glLineWidth: 115 return setter(msg); 116 case glPixelStorei: 117 if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_PACK_ALIGNMENT) 118 integers.put(msg.getArg0(), msg); 119 else if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_UNPACK_ALIGNMENT) 120 integers.put(msg.getArg0(), msg); 121 else 122 assert false; 123 return true; 124 case glPolygonOffset: 125 case glSampleCoverage: 126 case glScissor: 127 return setter(msg); 128 case glStencilFunc: { 129 Message.Builder builder = msg.toBuilder(); 130 builder.setArg2(msg.getArg1()); 131 builder.setArg1(msg.getArg0()); 132 builder.setArg0(GLEnum.GL_FRONT_AND_BACK.value); 133 return glStencilFuncSeparate(builder.build()); 134 } 135 case glStencilFuncSeparate: 136 return glStencilFuncSeparate(msg); 137 case glStencilMask: 138 case glStencilMaskSeparate: 139 return setter(msg); 140 case glStencilOp: { 141 Message.Builder builder = msg.toBuilder(); 142 builder.setArg3(msg.getArg2()); 143 builder.setArg2(msg.getArg1()); 144 builder.setArg1(msg.getArg0()); 145 builder.setArg0(GLEnum.GL_FRONT_AND_BACK.value); 146 return glStencilOpSeparate(builder.build()); 147 } 148 case glStencilOpSeparate: 149 return glStencilOpSeparate(msg); 150 case glViewport: 151 return setter(msg); 152 default: 153 return false; 154 } 155 } 156 157 boolean setter(final Message msg) { 158 switch (msg.getFunction()) { 159 case glBlendFunc: 160 lastSetter.put(Function.glBlendFuncSeparate.getNumber(), msg); 161 break; 162 case glBlendEquation: 163 lastSetter.put(Function.glBlendEquationSeparate.getNumber(), msg); 164 break; 165 case glStencilMask: 166 lastSetter.put(Function.glStencilMaskSeparate.getNumber(), msg); 167 break; 168 default: 169 lastSetter.put(msg.getFunction().getNumber(), msg); 170 break; 171 } 172 return true; 173 } 174 175 boolean enableDisable(boolean enable, final Message msg) { 176 int index = enableDisables.indexOfKey(msg.getArg0()); 177 if (index < 0) { 178 System.out.print("invalid glDisable/Enable: "); 179 System.out.println(MessageFormatter.format(msg, false)); 180 return true; 181 } 182 if ((enableDisables.valueAt(index) != 0) == enable) 183 return true; // TODO: redundant 184 enableDisables.put(msg.getArg0(), enable ? 1 : 0); 185 return true; 186 } 187 188 // void StencilFuncSeparate( enum face, enum func, int ref, uint mask ) 189 boolean glStencilFuncSeparate(final Message msg) { 190 GLEnum ff = front.func, bf = back.func; 191 int fr = front.ref, br = back.ref; 192 int fm = front.mask, bm = back.mask; 193 final GLEnum face = GLEnum.valueOf(msg.getArg0()); 194 if (face == GLEnum.GL_FRONT || face == GLEnum.GL_FRONT_AND_BACK) { 195 ff = GLEnum.valueOf(msg.getArg1()); 196 fr = msg.getArg2(); 197 fm = msg.getArg3(); 198 } 199 if (face == GLEnum.GL_BACK || face == GLEnum.GL_FRONT_AND_BACK) { 200 bf = GLEnum.valueOf(msg.getArg1()); 201 br = msg.getArg2(); 202 bm = msg.getArg3(); 203 } 204 if (ff == front.func && fr == front.ref && fm == front.mask) 205 if (bf == back.func && br == back.ref && bm == back.mask) 206 return true; // TODO: redundant 207 front.func = ff; 208 front.ref = fr; 209 front.mask = fm; 210 back.func = bf; 211 back.ref = br; 212 back.mask = bm; 213 return true; 214 } 215 216 // void StencilOpSeparate( enum face, enum sfail, enum dpfail, enum dppass ) 217 boolean glStencilOpSeparate(final Message msg) { 218 GLEnum fsf = front.sf, fdf = front.df, fdp = front.dp; 219 GLEnum bsf = back.sf, bdf = back.df, bdp = back.dp; 220 final GLEnum face = GLEnum.valueOf(msg.getArg0()); 221 if (face == GLEnum.GL_FRONT || face == GLEnum.GL_FRONT_AND_BACK) { 222 fsf = GLEnum.valueOf(msg.getArg1()); 223 fdf = GLEnum.valueOf(msg.getArg2()); 224 fdp = GLEnum.valueOf(msg.getArg3()); 225 } 226 if (face == GLEnum.GL_BACK || face == GLEnum.GL_FRONT_AND_BACK) { 227 bsf = GLEnum.valueOf(msg.getArg1()); 228 bdf = GLEnum.valueOf(msg.getArg2()); 229 bdp = GLEnum.valueOf(msg.getArg3()); 230 } 231 if (fsf == front.sf && fdf == front.df && fdp == front.dp) 232 if (bsf == back.sf && bdf == back.df && bdp == back.dp) 233 return true; // TODO: redundant 234 front.sf = fsf; 235 front.df = fdf; 236 front.dp = fdp; 237 back.sf = bsf; 238 back.df = bdf; 239 back.dp = bdp; 240 return true; 241 } 242 243 /** deep copy */ 244 @Override 245 public GLServerState clone() { 246 try { 247 GLServerState newState = (GLServerState) super.clone(); 248 newState.front = (GLStencilState) front.clone(); 249 newState.back = (GLStencilState) back.clone(); 250 251 newState.enableDisables = new SparseIntArray(enableDisables.size()); 252 for (int i = 0; i < enableDisables.size(); i++) 253 newState.enableDisables.append(enableDisables.keyAt(i), 254 enableDisables.valueAt(i)); 255 256 newState.integers = new SparseArray<Message>(integers.size()); 257 for (int i = 0; i < integers.size(); i++) 258 newState.integers.append(integers.keyAt(i), integers.valueAt(i)); 259 260 newState.lastSetter = new SparseArray<Message>(lastSetter.size()); 261 for (int i = 0; i < lastSetter.size(); i++) 262 newState.lastSetter.append(lastSetter.keyAt(i), lastSetter.valueAt(i)); 263 264 return newState; 265 } catch (CloneNotSupportedException e) { 266 e.printStackTrace(); 267 assert false; 268 return null; 269 } 270 } 271 } 272