| /* |
| ** 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.glesv2debugger.DebuggerMessage.Message.Function; |
| import com.android.sdklib.util.SparseArray; |
| import com.android.sdklib.util.SparseIntArray; |
| |
| class GLStencilState implements Cloneable { |
| public int ref, mask; |
| public GLEnum func; |
| public GLEnum sf, df, dp; // operation |
| |
| @Override |
| public Object clone() { |
| try { |
| return super.clone(); |
| } catch (CloneNotSupportedException e) { |
| e.printStackTrace(); |
| return null; |
| } |
| } |
| } |
| |
| public class GLServerState implements Cloneable { |
| final Context context; |
| public GLStencilState front = new GLStencilState(), back = new GLStencilState(); |
| public SparseIntArray enableDisables; |
| |
| /** integer states set via a GL function and GLEnum; keyed by GLEnum.value */ |
| public SparseArray<Message> integers; |
| |
| /** states set only via a GL function; keyed by Function.getNumber() */ |
| public SparseArray<Message> lastSetter; |
| |
| GLServerState(final Context context) { |
| this.context = context; |
| enableDisables = new SparseIntArray(9); |
| enableDisables.put(GLEnum.GL_BLEND.value, 0); |
| enableDisables.put(GLEnum.GL_DITHER.value, 1); |
| enableDisables.put(GLEnum.GL_DEPTH_TEST.value, 0); |
| enableDisables.put(GLEnum.GL_STENCIL_TEST.value, 0); |
| enableDisables.put(GLEnum.GL_SCISSOR_TEST.value, 0); |
| enableDisables.put(GLEnum.GL_SAMPLE_COVERAGE.value, 0); |
| enableDisables.put(GLEnum.GL_SAMPLE_ALPHA_TO_COVERAGE.value, 0); |
| enableDisables.put(GLEnum.GL_POLYGON_OFFSET_FILL.value, 0); |
| enableDisables.put(GLEnum.GL_CULL_FACE.value, 0); |
| |
| lastSetter = new SparseArray<Message>(); |
| lastSetter.put(Function.glBlendColor.getNumber(), null); |
| // glBlendEquation overwrites glBlendEquationSeparate |
| lastSetter.put(Function.glBlendEquationSeparate.getNumber(), null); |
| // glBlendFunc overwrites glBlendFuncSeparate |
| lastSetter.put(Function.glBlendFuncSeparate.getNumber(), null); |
| lastSetter.put(Function.glClearColor.getNumber(), null); |
| lastSetter.put(Function.glClearDepthf.getNumber(), null); |
| lastSetter.put(Function.glClearStencil.getNumber(), null); |
| lastSetter.put(Function.glColorMask.getNumber(), null); |
| lastSetter.put(Function.glCullFace.getNumber(), null); |
| lastSetter.put(Function.glDepthMask.getNumber(), null); |
| lastSetter.put(Function.glDepthFunc.getNumber(), null); |
| lastSetter.put(Function.glDepthRangef.getNumber(), null); |
| lastSetter.put(Function.glFrontFace.getNumber(), null); |
| lastSetter.put(Function.glLineWidth.getNumber(), null); |
| lastSetter.put(Function.glPolygonOffset.getNumber(), null); |
| lastSetter.put(Function.glSampleCoverage.getNumber(), null); |
| lastSetter.put(Function.glScissor.getNumber(), null); |
| lastSetter.put(Function.glStencilMaskSeparate.getNumber(), null); |
| lastSetter.put(Function.glViewport.getNumber(), null); |
| |
| integers = new SparseArray<Message>(); |
| integers.put(GLEnum.GL_PACK_ALIGNMENT.value, null); |
| integers.put(GLEnum.GL_UNPACK_ALIGNMENT.value, null); |
| } |
| |
| /** returns true if processed */ |
| public boolean ProcessMessage(final Message msg) { |
| switch (msg.getFunction()) { |
| case glBlendColor: |
| case glBlendEquation: |
| case glBlendEquationSeparate: |
| case glBlendFunc: |
| case glBlendFuncSeparate: |
| case glClearColor: |
| case glClearDepthf: |
| case glClearStencil: |
| case glColorMask: |
| case glCullFace: |
| case glDepthMask: |
| case glDepthFunc: |
| case glDepthRangef: |
| return Setter(msg); |
| case glDisable: |
| return EnableDisable(false, msg); |
| case glEnable: |
| return EnableDisable(true, msg); |
| case glFrontFace: |
| case glLineWidth: |
| return Setter(msg); |
| case glPixelStorei: |
| if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_PACK_ALIGNMENT) |
| integers.put(msg.getArg0(), msg); |
| else if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_UNPACK_ALIGNMENT) |
| integers.put(msg.getArg0(), msg); |
| else |
| assert false; |
| return true; |
| case glPolygonOffset: |
| case glSampleCoverage: |
| case glScissor: |
| return Setter(msg); |
| case glStencilFunc: { |
| Message.Builder builder = msg.toBuilder(); |
| builder.setArg2(msg.getArg1()); |
| builder.setArg1(msg.getArg0()); |
| builder.setArg0(GLEnum.GL_FRONT_AND_BACK.value); |
| return glStencilFuncSeparate(builder.build()); |
| } |
| case glStencilFuncSeparate: |
| return glStencilFuncSeparate(msg); |
| case glStencilMask: |
| case glStencilMaskSeparate: |
| return Setter(msg); |
| case glStencilOp: { |
| Message.Builder builder = msg.toBuilder(); |
| builder.setArg3(msg.getArg2()); |
| builder.setArg2(msg.getArg1()); |
| builder.setArg1(msg.getArg0()); |
| builder.setArg0(GLEnum.GL_FRONT_AND_BACK.value); |
| return glStencilOpSeparate(builder.build()); |
| } |
| case glStencilOpSeparate: |
| return glStencilOpSeparate(msg); |
| case glViewport: |
| return Setter(msg); |
| default: |
| return false; |
| } |
| } |
| |
| boolean Setter(final Message msg) { |
| switch (msg.getFunction()) { |
| case glBlendFunc: |
| lastSetter.put(Function.glBlendFuncSeparate.getNumber(), msg); |
| break; |
| case glBlendEquation: |
| lastSetter.put(Function.glBlendEquationSeparate.getNumber(), msg); |
| break; |
| case glStencilMask: |
| lastSetter.put(Function.glStencilMaskSeparate.getNumber(), msg); |
| break; |
| default: |
| lastSetter.put(msg.getFunction().getNumber(), msg); |
| break; |
| } |
| return true; |
| } |
| |
| boolean EnableDisable(boolean enable, final Message msg) { |
| int index = enableDisables.indexOfKey(msg.getArg0()); |
| assert index >= 0; |
| if ((enableDisables.valueAt(index) != 0) == enable) |
| return true; // TODO: redundant |
| enableDisables.put(msg.getArg0(), enable ? 1 : 0); |
| return true; |
| } |
| |
| // void StencilFuncSeparate( enum face, enum func, int ref, uint mask ) |
| boolean glStencilFuncSeparate(final Message msg) { |
| GLEnum ff = front.func, bf = back.func; |
| int fr = front.ref, br = back.ref; |
| int fm = front.mask, bm = back.mask; |
| final GLEnum face = GLEnum.valueOf(msg.getArg0()); |
| if (face == GLEnum.GL_FRONT || face == GLEnum.GL_FRONT_AND_BACK) { |
| ff = GLEnum.valueOf(msg.getArg1()); |
| fr = msg.getArg2(); |
| fm = msg.getArg3(); |
| } |
| if (face == GLEnum.GL_BACK || face == GLEnum.GL_FRONT_AND_BACK) { |
| bf = GLEnum.valueOf(msg.getArg1()); |
| br = msg.getArg2(); |
| bm = msg.getArg3(); |
| } |
| if (ff == front.func && fr == front.ref && fm == front.mask) |
| if (bf == back.func && br == back.ref && bm == back.mask) |
| return true; // TODO: redundant |
| front.func = ff; |
| front.ref = fr; |
| front.mask = fm; |
| back.func = bf; |
| back.ref = br; |
| back.mask = bm; |
| return true; |
| } |
| |
| // void StencilOpSeparate( enum face, enum sfail, enum dpfail, enum dppass ) |
| boolean glStencilOpSeparate(final Message msg) { |
| GLEnum fsf = front.sf, fdf = front.df, fdp = front.dp; |
| GLEnum bsf = back.sf, bdf = back.df, bdp = back.dp; |
| final GLEnum face = GLEnum.valueOf(msg.getArg0()); |
| if (face == GLEnum.GL_FRONT || face == GLEnum.GL_FRONT_AND_BACK) { |
| fsf = GLEnum.valueOf(msg.getArg1()); |
| fdf = GLEnum.valueOf(msg.getArg2()); |
| fdp = GLEnum.valueOf(msg.getArg3()); |
| } |
| if (face == GLEnum.GL_BACK || face == GLEnum.GL_FRONT_AND_BACK) { |
| bsf = GLEnum.valueOf(msg.getArg1()); |
| bdf = GLEnum.valueOf(msg.getArg2()); |
| bdp = GLEnum.valueOf(msg.getArg3()); |
| } |
| if (fsf == front.sf && fdf == front.df && fdp == front.dp) |
| if (bsf == back.sf && bdf == back.df && bdp == back.dp) |
| return true; // TODO: redundant |
| front.sf = fsf; |
| front.df = fdf; |
| front.dp = fdp; |
| back.sf = bsf; |
| back.df = bdf; |
| back.dp = bdp; |
| return true; |
| } |
| |
| /** deep copy */ |
| @Override |
| public GLServerState clone() { |
| try { |
| GLServerState newState = (GLServerState) super.clone(); |
| newState.front = (GLStencilState) front.clone(); |
| newState.back = (GLStencilState) back.clone(); |
| |
| newState.enableDisables = new SparseIntArray(enableDisables.size()); |
| for (int i = 0; i < enableDisables.size(); i++) |
| newState.enableDisables.append(enableDisables.keyAt(i), |
| enableDisables.valueAt(i)); |
| |
| newState.integers = new SparseArray<Message>(integers.size()); |
| for (int i = 0; i < integers.size(); i++) |
| newState.integers.append(integers.keyAt(i), integers.valueAt(i)); |
| |
| newState.lastSetter = new SparseArray<Message>(lastSetter.size()); |
| for (int i = 0; i < lastSetter.size(); i++) |
| newState.lastSetter.append(lastSetter.keyAt(i), lastSetter.valueAt(i)); |
| |
| return newState; |
| } catch (CloneNotSupportedException e) { |
| e.printStackTrace(); |
| assert false; |
| return null; |
| } |
| } |
| } |