• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.glesv2debugger;
18 
19 import com.android.glesv2debugger.DebuggerMessage.Message;
20 import com.android.sdklib.util.SparseArray;
21 
22 import java.util.ArrayList;
23 
24 class GLShader implements Cloneable {
25     public final int name;
26     GLServerShader context; // the context this was created in
27     public final GLEnum type;
28     public boolean delete;
29     public ArrayList<Integer> programs = new ArrayList<Integer>();
30     public String source, originalSource;
31 
GLShader(final int name, final GLServerShader context, final GLEnum type)32     GLShader(final int name, final GLServerShader context, final GLEnum type) {
33         this.name = name;
34         this.context = context;
35         this.type = type;
36     }
37 
38     /** deep copy */
clone(final GLServerShader copyContext)39     public GLShader clone(final GLServerShader copyContext) {
40         try {
41             GLShader shader = (GLShader) super.clone();
42             shader.programs = (ArrayList<Integer>) programs.clone();
43             shader.context = copyContext;
44             return shader;
45         } catch (CloneNotSupportedException e) {
46             e.printStackTrace();
47             assert false;
48             return null;
49         }
50     }
51 }
52 
53 class GLProgram implements Cloneable {
54     public final int name;
55     GLServerShader context; // the context this was created in
56     public boolean delete;
57     public int vert, frag;
58 
GLProgram(final int name, final GLServerShader context)59     GLProgram(final int name, final GLServerShader context) {
60         this.name = name;
61         this.context = context;
62     }
63 
64     /** deep copy */
clone(final GLServerShader copyContext)65     public GLProgram clone(final GLServerShader copyContext) {
66         try {
67             GLProgram copy = (GLProgram) super.clone();
68             copy.context = copyContext;
69             return copy;
70         } catch (CloneNotSupportedException e) {
71             e.printStackTrace();
72             assert false;
73             return null;
74         }
75     }
76 }
77 
78 public class GLServerShader implements Cloneable {
79     Context context;
80     public SparseArray<GLShader> shaders = new SparseArray<GLShader>();
81     public SparseArray<GLProgram> programs = new SparseArray<GLProgram>();
82     public GLProgram current = null;
83     boolean uiUpdate = false;
84 
GLServerShader(Context context)85     GLServerShader(Context context) {
86         this.context = context;
87     }
88 
89     /** deep copy */
clone(final Context copyContext)90     public GLServerShader clone(final Context copyContext) {
91         try {
92             GLServerShader copy = (GLServerShader) super.clone();
93             copy.context = copyContext;
94 
95             copy.shaders = new SparseArray<GLShader>(shaders.size());
96             for (int i = 0; i < shaders.size(); i++)
97                 copy.shaders.append(shaders.keyAt(i), shaders.valueAt(i).clone(copy));
98 
99             copy.programs = new SparseArray<GLProgram>(programs.size());
100             for (int i = 0; i < programs.size(); i++)
101                 copy.programs.append(programs.keyAt(i), programs.valueAt(i).clone(copy));
102 
103             if (current != null)
104                 copy.current = copy.programs.get(current.name);
105             return copy;
106         } catch (CloneNotSupportedException e) {
107             e.printStackTrace();
108             assert false;
109             return null;
110         }
111     }
112 
113     /** returns true if processed */
processMessage(final Message msg)114     public boolean processMessage(final Message msg) {
115         boolean oldUiUpdate = uiUpdate;
116         uiUpdate = true;
117         switch (msg.getFunction()) {
118             case glAttachShader:
119                 glAttachShader(msg);
120                 return true;
121             case glCreateProgram:
122                 glCreateProgram(msg);
123                 return true;
124             case glCreateShader:
125                 glCreateShader(msg);
126                 return true;
127             case glDeleteProgram:
128                 glDeleteProgram(msg);
129                 return true;
130             case glDeleteShader:
131                 glDeleteShader(msg);
132                 return true;
133             case glDetachShader:
134                 glDetachShader(msg);
135                 return true;
136             case glShaderSource:
137                 glShaderSource(msg);
138                 return true;
139             case glUseProgram:
140                 glUseProgram(msg);
141                 return true;
142             default:
143                 uiUpdate = oldUiUpdate;
144                 return false;
145         }
146     }
147 
getShader(int name)148     GLShader getShader(int name) {
149         if (name == 0)
150             return null;
151         for (Context ctx : context.shares) {
152             GLShader shader = ctx.serverShader.shaders.get(name);
153             if (shader != null)
154                 return shader;
155         }
156         assert false;
157         return null;
158     }
159 
getProgram(int name)160     GLProgram getProgram(int name) {
161         if (name == 0)
162             return null;
163         for (Context ctx : context.shares) {
164             GLProgram program = ctx.serverShader.programs.get(name);
165             if (program != null)
166                 return program;
167         }
168         assert false;
169         return null;
170     }
171 
172     // void API_ENTRY(glAttachShader)(GLuint program, GLuint shader)
glAttachShader(final Message msg)173     void glAttachShader(final Message msg) {
174         GLProgram program = getProgram(msg.getArg0());
175         assert program != null;
176         GLShader shader = getShader(msg.getArg1());
177         assert program != null;
178         if (GLEnum.GL_VERTEX_SHADER == shader.type)
179             program.vert = shader.name;
180         else
181             program.frag = shader.name;
182         shader.programs.add(program.name);
183     }
184 
185     // GLuint API_ENTRY(glCreateProgram)(void)
glCreateProgram(final Message msg)186     void glCreateProgram(final Message msg) {
187         programs.put(msg.getRet(), new GLProgram(msg.getRet(), this));
188     }
189 
190     // GLuint API_ENTRY(glCreateShader)(GLenum type)
glCreateShader(final Message msg)191     void glCreateShader(final Message msg) {
192         shaders.put(msg.getRet(),
193                 new GLShader(msg.getRet(), this, GLEnum.valueOf(msg.getArg0())));
194     }
195 
196     // void API_ENTRY(glDeleteProgram)
glDeleteProgram(final Message msg)197     void glDeleteProgram(final Message msg) {
198         if (msg.getArg0() == 0)
199             return;
200         GLProgram program = getProgram(msg.getArg0());
201         program.delete = true;
202         for (Context ctx : context.shares)
203             if (ctx.serverShader.current == program)
204                 return;
205         glDetachShader(program, getShader(program.vert));
206         glDetachShader(program, getShader(program.frag));
207         programs.remove(program.name);
208     }
209 
210     // void API_ENTRY(glDeleteShader)(GLuint shader)
glDeleteShader(final Message msg)211     void glDeleteShader(final Message msg) {
212         if (msg.getArg0() == 0)
213             return;
214         GLShader shader = getShader(msg.getArg0());
215         shader.delete = true;
216         if (shader.programs.size() == 0)
217             shaders.remove(shader.name);
218     }
219 
220     // void API_ENTRY(glDetachShader)(GLuint program, GLuint shader)
glDetachShader(final Message msg)221     void glDetachShader(final Message msg) {
222         glDetachShader(getProgram(msg.getArg0()), getShader(msg.getArg1()));
223     }
224 
glDetachShader(final GLProgram program, final GLShader shader)225     void glDetachShader(final GLProgram program, final GLShader shader) {
226         if (program == null)
227             return;
228         if (program.vert == shader.name)
229             program.vert = 0;
230         else if (program.frag == shader.name)
231             program.frag = 0;
232         else
233             return;
234         shader.programs.remove(new Integer(program.name));
235         if (shader.delete && shader.programs.size() == 0)
236             shaders.remove(shader.name);
237     }
238 
239     // void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const
240     // GLchar** string, const GLint* length)
glShaderSource(final Message msg)241     void glShaderSource(final Message msg) {
242         if (!msg.hasData())
243             return; // TODO: distinguish between generated calls
244         GLShader shader = getShader(msg.getArg0());
245         shader.source = shader.originalSource = msg.getData().toStringUtf8();
246     }
247 
248     // void API_ENTRY(glUseProgram)(GLuint program)
glUseProgram(final Message msg)249     void glUseProgram(final Message msg) {
250         GLProgram oldCurrent = current;
251         current = getProgram(msg.getArg0());
252         if (null != oldCurrent && oldCurrent.delete && oldCurrent != current) {
253             for (Context ctx : context.shares)
254                 if (ctx.serverShader.current == oldCurrent)
255                     return;
256             oldCurrent.context.programs.remove(new Integer(oldCurrent.name));
257         }
258     }
259 }
260