Home | History | Annotate | Download | only in gldebugger
      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