| /* |
| ** 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.SparseIntArray; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.jface.dialogs.ProgressMonitorDialog; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.swt.widgets.Shell; |
| |
| import java.io.FileOutputStream; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.lang.reflect.InvocationTargetException; |
| import java.nio.ByteBuffer; |
| |
| public class CodeGen implements IRunnableWithProgress { |
| private FileWriter codeFile, makeFile, namesHeaderFile, namesSourceFile; |
| private PrintWriter code, make, namesHeader, namesSource; |
| private FileOutputStream dataOut; |
| private SparseIntArray bufferNames, |
| framebufferNames, programNames, textureNames, shaderNames, renderbufferNames; |
| |
| /** return true if msg was a texture upload */ |
| private boolean codeGenTextureUpload(final Message msg, final boolean replaceCopy) { |
| String s = null; |
| switch (msg.getFunction()) { |
| case glCompressedTexImage2D: |
| s = MessageFormatter.format(msg, true).replace("arg7", "texData"); |
| break; |
| case glCompressedTexSubImage2D: |
| case glTexImage2D: |
| case glTexSubImage2D: |
| s = MessageFormatter.format(msg, true).replace("arg8", "texData"); |
| break; |
| case glCopyTexImage2D: |
| if (!replaceCopy) { |
| code.write(MessageFormatter.format(msg, true)); |
| code.write(";CHKERR;\n"); |
| return true; |
| } |
| assert msg.getArg2() == msg.getPixelFormat(); // TODO |
| s = "//" + MessageFormatter.format(msg, true) + "\n"; |
| s += String.format("glTexImage2D(%s, %d, %s, %d, %d, %d, %s, %s, texData);CHKERR;", |
| GLEnum.valueOf(msg.getArg0()), msg.getArg1(), |
| GLEnum.valueOf(msg.getArg2()), msg.getArg5(), msg.getArg6(), |
| msg.getArg7(), GLEnum.valueOf(msg.getPixelFormat()), |
| GLEnum.valueOf(msg.getPixelType())); |
| break; |
| case glCopyTexSubImage2D: |
| if (!replaceCopy) { |
| code.write(MessageFormatter.format(msg, true)); |
| code.write(";CHKERR;\n"); |
| return true; |
| } |
| // FIXME: check the texture format & type, and convert |
| s = "//" + MessageFormatter.format(msg, true) + "\n"; |
| s += String.format( |
| "glTexSubImage2D(%s, %d, %d, %d, %d, %d, %s, %s, texData);CHKERR;", |
| GLEnum.valueOf(msg.getArg0()), msg.getArg1(), msg.getArg2(), |
| msg.getArg3(), msg.getArg6(), msg.getArg7(), |
| GLEnum.valueOf(msg.getPixelFormat()), GLEnum.valueOf(msg.getPixelType())); |
| break; |
| default: |
| return false; |
| } |
| |
| if (msg.hasData()) { |
| final byte[] data = MessageProcessor.lzfDecompressChunks(msg.getData()); |
| try { |
| code.write("{\n"); |
| code.format(" void * texData = malloc(%d);CHKERR;\n", data.length); |
| code.format(" FILE * texFile = fopen(\"/sdcard/frame_data.bin\", \"rb\");CHKERR;\n"); |
| code.format(" assert(texFile);CHKERR;\n"); |
| code.format(" fseek(texFile, %d, SEEK_SET);CHKERR;\n", dataOut.getChannel() |
| .position()); |
| dataOut.write(data); |
| code.format(" fread(texData, %d, 1, texFile);CHKERR;\n", data.length); |
| code.format(" fclose(texFile);CHKERR;\n"); |
| code.format(" " + s + ";\n"); |
| code.format(" free(texData);CHKERR;\n"); |
| code.format("}\n"); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| assert false; |
| } |
| } else |
| code.write(s.replace("texData", "NULL") + ";\n"); |
| return true; |
| } |
| |
| private void codeGenServerState(final GLServerState serverState) { |
| code.write("// CodeGenServerState\n"); |
| for (int i = 0; i < serverState.enableDisables.size(); i++) { |
| final GLEnum key = GLEnum.valueOf(serverState.enableDisables.keyAt(i)); |
| if (serverState.enableDisables.valueAt(i) == 0) |
| code.format("glDisable(%s);CHKERR;\n", key); |
| else |
| code.format("glEnable(%s);CHKERR;\n", key); |
| } |
| for (int i = 0; i < serverState.lastSetter.size(); i++) { |
| final Function key = Function.valueOf(serverState.lastSetter.keyAt(i)); |
| final Message msg = serverState.lastSetter.valueAt(i); |
| if (msg == null) { |
| code.format("// %s is default\n", key); |
| continue; |
| } |
| final String s = MessageFormatter.format(msg, true); |
| code.write(s); |
| code.write(";\n"); |
| } |
| // TODO: stencil and integers |
| } |
| |
| private void codeGenServerShader(final GLServerShader serverShader) { |
| code.write("// CodeGenServerShader\n"); |
| for (int i = 0; i < serverShader.shaders.size(); i++) { |
| final int name = serverShader.shaders.keyAt(i); |
| final GLShader shader = serverShader.shaders.valueAt(i); |
| final String id = "shader_" + name; |
| if (shaderNames.indexOfKey(name) < 0) { |
| namesSource.format("GLuint %s = 0;\n", id); |
| namesHeader.format("extern GLuint %s;\n", id); |
| } |
| code.format("%s = glCreateShader(%s);CHKERR;\n", id, shader.type); |
| shaderNames.put(name, name); |
| |
| if (shader.source != null) { |
| final String src = shader.source.replace("\r", "").replace("\n", "\\n\\\n") |
| .replace("\"", "\\\""); |
| code.format("glShaderSource(%s, 1, (const GLchar *[]){\"%s\"}, NULL);CHKERR;\n", |
| id, src); |
| code.format("glCompileShader(%s);CHKERR;\n", id); |
| } |
| } |
| |
| for (int i = 0; i < serverShader.programs.size(); i++) { |
| final int name = serverShader.programs.keyAt(i); |
| final GLProgram program = serverShader.programs.valueAt(i); |
| final String id = "program_" + name; |
| if (programNames.indexOfKey(name) < 0) { |
| namesSource.format("GLuint %s = 0;\n", id); |
| namesHeader.format("extern GLuint %s;\n", id); |
| } |
| code.format("%s = glCreateProgram();CHKERR;\n", id); |
| programNames.put(name, name); |
| code.format("glAttachShader(%s, shader_%d);CHKERR;\n", id, |
| program.vert); |
| code.format("glAttachShader(%s, shader_%d);CHKERR;\n", id, |
| program.frag); |
| code.format("glLinkProgram(%s);CHKERR;\n", id); |
| if (serverShader.current == program) |
| code.format("glUseProgram(%s);CHKERR;\n", id); |
| } |
| } |
| |
| private void codeGenServerTexture(final GLServerTexture serverTexture, final boolean replaceCopy) { |
| code.write("// CodeGenServerTexture\n"); |
| for (int i = 0; i < serverTexture.textures.size(); i++) { |
| final int name = serverTexture.textures.keyAt(i); |
| final GLTexture tex = serverTexture.textures.valueAt(i); |
| final String id = "texture_" + name; |
| if (textureNames.indexOfKey(name) < 0) { |
| namesHeader.format("extern GLuint %s;\n", id); |
| namesSource.format("GLuint %s = 0;\n", id); |
| } |
| code.format("%s = 0;\n", id); |
| textureNames.put(name, name); |
| |
| if (name == 0) |
| continue; |
| code.format("glGenTextures(1, &%s);CHKERR;\n", id); |
| String s = String.format("glBindTexture(%s, texture_%d);CHKERR;\n", tex.target, |
| tex.name); |
| code.write(s); |
| for (final Message msg : tex.contentChanges) { |
| if (codeGenTextureUpload(msg, replaceCopy)) |
| continue; |
| switch (msg.getFunction()) { |
| case glGenerateMipmap: |
| s = MessageFormatter.format(msg, true); |
| break; |
| default: |
| assert false; |
| } |
| code.write(s + ";\n"); |
| } |
| code.format("glTexParameteriv(%s, GL_TEXTURE_WRAP_S, (GLint[]){%s});CHKERR;\n", |
| tex.target, tex.wrapS); |
| code.format("glTexParameteriv(%s, GL_TEXTURE_WRAP_T, (GLint[]){%s});CHKERR;\n", |
| tex.target, tex.wrapT); |
| code.format("glTexParameteriv(%s, GL_TEXTURE_MIN_FILTER, (GLint[]){%s});CHKERR;\n", |
| tex.target, tex.min); |
| code.format("glTexParameteriv(%s, GL_TEXTURE_MAG_FILTER, (GLint[]){%s});CHKERR;\n", |
| tex.target, tex.mag); |
| } |
| for (int i = 0; i < serverTexture.tmu2D.length; i++) { |
| code.format("glActiveTexture(%s);CHKERR;\n", |
| GLEnum.valueOf(GLEnum.GL_TEXTURE0.value + i)); |
| code.format("glBindTexture(GL_TEXTURE_2D, texture_%d);CHKERR;\n", |
| serverTexture.tmu2D[i]); |
| } |
| for (int i = 0; i < serverTexture.tmuCube.length; i++) { |
| code.format("glActiveTexture(%s);CHKERR;\n", |
| GLEnum.valueOf(GLEnum.GL_TEXTURE0.value + i)); |
| code.format("glBindTexture(GL_TEXTURE_CUBE_MAP, texture_%d);CHKERR;\n", |
| serverTexture.tmuCube[i]); |
| } |
| code.format("glActiveTexture(%s);CHKERR;\n", serverTexture.activeTexture); |
| if (serverTexture.tex2D == null) |
| code.format("glBindTexture(GL_TEXTURE_2D, 0);CHKERR;\n"); |
| else |
| code.format("glBindTexture(GL_TEXTURE_2D, texture_%d);CHKERR;\n", |
| serverTexture.tex2D.name); |
| if (serverTexture.texCube == null) |
| code.format("glBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHKERR;\n"); |
| else |
| code.format("glBindTexture(GL_TEXTURE_CUBE_MAP, texture_%d);CHKERR;\n", |
| serverTexture.texCube.name); |
| } |
| |
| private void codeGenBufferData(final ByteBuffer buffer, final String call) { |
| ByteBuffer bfr = buffer; |
| if (buffer.isReadOnly()) { |
| bfr = ByteBuffer.allocate(buffer.capacity()); |
| bfr.put(buffer); |
| } |
| final byte[] data = bfr.array(); |
| try { |
| code.write("{\n"); |
| code.format(" void * bufferData = malloc(%d);\n", data.length); |
| code.format(" FILE * bufferFile = fopen(\"/sdcard/frame_data.bin\", \"rb\");\n"); |
| code.format(" assert(bufferFile);\n"); |
| code.format(" fseek(bufferFile, %d, SEEK_SET);\n", dataOut.getChannel() |
| .position()); |
| dataOut.write(data); |
| code.format(" fread(bufferData, %d, 1, bufferFile);\n", data.length); |
| code.format(" fclose(bufferFile);\n"); |
| code.format(" " + call + ";CHKERR;\n"); |
| code.format(" free(bufferData);\n"); |
| code.format("}\n"); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| assert false; |
| } |
| } |
| |
| private void codeGenServerVertex(final GLServerVertex v) { |
| code.write("// CodeGenServerVertex\n"); |
| for (int i = 0; i < v.buffers.size(); i++) { |
| final int name = v.buffers.keyAt(i); |
| final String id = "buffer_" + name; |
| final GLBuffer buffer = v.buffers.valueAt(i); |
| if (bufferNames.indexOfKey(name) < 0) { |
| namesHeader.format("extern GLuint %s;\n", id); |
| namesSource.format("GLuint %s = 0;\n", id); |
| } |
| code.format("%s = 0;\n", id); |
| bufferNames.put(name, name); |
| if (name == 0) |
| continue; |
| code.format("glGenBuffers(1, &%s);CHKERR;\n", id); |
| if (buffer.target != null) { |
| code.format("glBindBuffer(%s, %s);CHKERR;\n", buffer.target, id); |
| if (buffer.data != null) { |
| String s = String.format("glBufferData(%s, %d, bufferData, %s)", buffer.target, |
| buffer.data.capacity(), buffer.usage); |
| codeGenBufferData(buffer.data, s); |
| } |
| } |
| } |
| // TODO: use MAX_VERTEX_ATTRIBS |
| for (int i = 0; i < v.defaultAttribs.length; i++) |
| code.format("glVertexAttrib4f(%d, %f, %f, %f, %f);CHKERR;\n", i, |
| v.defaultAttribs[i][0], |
| v.defaultAttribs[i][1], v.defaultAttribs[i][2], v.defaultAttribs[i][3]); |
| for (int i = 0; i < v.attribPointers.length; i++) { |
| final GLAttribPointer att = v.attribPointers[i]; |
| if (att.type == null) |
| continue; |
| if (att.buffer != null) |
| code.format("glBindBuffer(GL_ARRAY_BUFFER, buffer_%d);CHKERR;\n", att.buffer.name); |
| else |
| code.format("glBindBuffer(GL_ARRAY_BUFFER, 0);CHKERR;\n"); |
| code.format("glVertexAttribPointer(%d, %d, %s, %b, %d, (const GLvoid *)%d);CHKERR;\n", |
| i, att.size, att.type, att.normalized, att.stride, att.ptr); |
| } |
| if (v.attribBuffer != null) |
| code.format("glBindBuffer(GL_ARRAY_BUFFER, buffer_%d);CHKERR;\n", v.attribBuffer.name); |
| else |
| code.write("glBindBuffer(GL_ARRAY_BUFFER, 0);CHKERR;\n"); |
| if (v.indexBuffer != null) |
| code.format("glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_%d);CHKERR;\n", |
| v.indexBuffer.name); |
| else |
| code.write("glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);CHKERR;\n"); |
| } |
| |
| private void codeGenGenNames(final Message msg) { |
| final ByteBuffer names = msg.getData().asReadOnlyByteBuffer(); |
| names.order(SampleView.targetByteOrder); |
| SparseIntArray namesArray = null; |
| for (int i = 0; i < msg.getArg0(); i++) { |
| String id = ""; |
| final int name = names.getInt(); |
| switch (msg.getFunction()) { |
| case glGenBuffers: |
| id = "buffer"; |
| namesArray = bufferNames; |
| break; |
| case glGenFramebuffers: |
| id = "framebuffer"; |
| namesArray = framebufferNames; |
| break; |
| case glGenRenderbuffers: |
| id = "renderbuffer"; |
| namesArray = renderbufferNames; |
| break; |
| case glGenTextures: |
| id = "texture"; |
| namesArray = textureNames; |
| break; |
| default: |
| assert false; |
| } |
| id += "_" + name; |
| if (namesArray.indexOfKey(name) < 0) { |
| namesHeader.format("extern GLuint %s;\n", id); |
| namesSource.format("GLuint %s = 0;\n", id); |
| } |
| code.format("%s = 0;\n", id); |
| namesArray.put(name, name); |
| code.format("%s(1, &%s);CHKERR;\n", msg.getFunction(), id); |
| } |
| } |
| |
| private void codeGenDeleteNames(final Message msg) { |
| final ByteBuffer names = msg.getData().asReadOnlyByteBuffer(); |
| names.order(SampleView.targetByteOrder); |
| SparseIntArray namesArray = null; |
| for (int i = 0; i < msg.getArg0(); i++) { |
| String id = null; |
| final int name = names.getInt(); |
| switch (msg.getFunction()) { |
| case glDeleteBuffers: |
| id = "buffer"; |
| namesArray = bufferNames; |
| break; |
| case glDeleteFramebuffers: |
| id = "framebuffer"; |
| namesArray = framebufferNames; |
| break; |
| case glDeleteRenderbuffers: |
| id = "renderbuffer"; |
| namesArray = renderbufferNames; |
| break; |
| case glDeleteTextures: |
| id = "texture"; |
| namesArray = textureNames; |
| break; |
| default: |
| assert false; |
| } |
| id += "_" + name; |
| code.format("%s = 0;\n", id); |
| namesArray.put(name, 0); |
| code.format("%s(1, &%s);CHKERR;\n", msg.getFunction(), id); |
| } |
| } |
| |
| private void codeGenBindNames(final Message msg) { |
| String id = null; |
| SparseIntArray namesArray = null; |
| final int name = msg.getArg1(); |
| switch (msg.getFunction()) { |
| case glBindBuffer: |
| id = "buffer"; |
| namesArray = bufferNames; |
| break; |
| case glBindFramebuffer: |
| id = "framebuffer"; |
| namesArray = framebufferNames; |
| break; |
| case glBindRenderbuffer: |
| id = "renderbuffer"; |
| namesArray = renderbufferNames; |
| break; |
| case glBindTexture: |
| id = "texture"; |
| namesArray = textureNames; |
| break; |
| default: |
| assert false; |
| } |
| id += "_" + name; |
| if (namesArray.indexOfKey(name) < 0) { |
| namesHeader.format("extern GLuint %s;\n", id); |
| namesSource.format("GLuint %s = 0;\n", id); |
| } else if (namesArray.get(name) != name) |
| code.format("%s = %d;\n", id, name); // name was deleted |
| namesArray.put(name, name); |
| code.write(MessageFormatter.format(msg, true)); |
| code.write(";CHKERR;\n"); |
| } |
| |
| private void codeGenDrawArrays(final GLServerVertex v, final MessageData msgData) |
| throws IOException { |
| final int maxAttrib = msgData.msg.getArg7(); |
| if (maxAttrib < 1) { |
| code.write("// no vertex data\n"); |
| return; |
| } |
| final byte[] data = msgData.msg.getData().toByteArray(); |
| final GLEnum mode = GLEnum.valueOf(msgData.msg.getArg0()); |
| final int first = msgData.msg.getArg1(), count = msgData.msg.getArg2(); |
| int attribDataStride = 0; |
| for (int i = 0; i < maxAttrib; i++) { |
| final GLAttribPointer att = v.attribPointers[i]; |
| if (!att.enabled) |
| continue; |
| if (att.buffer != null) |
| continue; |
| attribDataStride += att.elemSize; |
| } |
| assert attribDataStride * count == data.length; |
| code.write("{\n"); |
| if (attribDataStride > 0) { |
| code.format(" FILE * attribFile = fopen(\"/sdcard/frame_data.bin\", \"rb\");CHKERR;\n"); |
| code.format(" assert(attribFile);CHKERR;\n"); |
| code.format(" fseek(attribFile, %d, SEEK_SET);CHKERR;\n", dataOut.getChannel() |
| .position()); |
| dataOut.write(data); |
| code.format(" char * const attribData = (char *)malloc(%d);\n", first |
| * attribDataStride + data.length); |
| code.format(" assert(attribData);\n"); |
| code.format(" fread(attribData + %d, %d, 1, attribFile);\n", |
| first * attribDataStride, data.length); |
| code.format(" fclose(attribFile);\n"); |
| code.format(" glBindBuffer(GL_ARRAY_BUFFER, 0);CHKERR;\n"); |
| int attribDataOffset = 0; |
| for (int i = 0; i < maxAttrib; i++) { |
| final GLAttribPointer att = v.attribPointers[i]; |
| if (!att.enabled) |
| continue; |
| if (att.buffer != null) |
| continue; |
| code.format( |
| " glVertexAttribPointer(%d, %d, %s, %b, %d, attribData + %d);CHKERR;\n", |
| i, att.size, att.type, att.normalized, |
| attribDataStride, attribDataOffset); |
| attribDataOffset += att.elemSize; |
| } |
| if (v.attribBuffer != null) |
| code.format(" glBindBuffer(GL_ARRAY_BUFFER, %d);CHKERR;\n", |
| v.attribBuffer.name); |
| } |
| code.format(" glDrawArrays(%s, %d, %d);CHKERR;\n", mode, first, count); |
| if (attribDataStride > 0) |
| code.format(" free(attribData);CHKERR;\n"); |
| code.write("};\n"); |
| } |
| |
| private void codeGenDrawElements(final GLServerVertex v, final MessageData msgData) |
| throws IOException { |
| final int maxAttrib = msgData.msg.getArg7(); |
| if (maxAttrib < 1) { |
| code.write("// no vertex data\n"); |
| return; |
| } |
| final GLEnum mode = GLEnum.valueOf(msgData.msg.getArg0()); |
| final int count = msgData.msg.getArg1(); |
| final GLEnum type = GLEnum.valueOf(msgData.msg.getArg2()); |
| String typeName = "GLubyte"; |
| if (type == GLEnum.GL_UNSIGNED_SHORT) |
| typeName = "GLushort"; |
| int attribDataStride = 0; |
| for (int i = 0; i < maxAttrib; i++) { |
| final GLAttribPointer att = v.attribPointers[i]; |
| if (!att.enabled) |
| continue; |
| if (att.buffer != null) |
| continue; |
| attribDataStride += att.elemSize; |
| } |
| code.write("{\n"); |
| if (v.indexBuffer == null || attribDataStride > 0) { |
| // need to load user pointer indices and/or attributes |
| final byte[] element = new byte[attribDataStride]; |
| final ByteBuffer data = msgData.msg.getData().asReadOnlyByteBuffer(); |
| data.order(SampleView.targetByteOrder); |
| final ByteBuffer indexData = ByteBuffer.allocate(count * GLServerVertex.typeSize(type)); |
| indexData.order(SampleView.targetByteOrder); |
| final ByteBuffer attribData = ByteBuffer.allocate(count * attribDataStride); |
| attribData.order(SampleView.targetByteOrder); |
| int maxIndex = -1; |
| ByteBuffer indexSrc = data; |
| if (v.indexBuffer != null) { |
| indexSrc = v.indexBuffer.data; |
| indexSrc.position(msgData.msg.getArg3()); |
| } |
| indexSrc.order(SampleView.targetByteOrder); |
| for (int i = 0; i < count; i++) { |
| int index = -1; |
| if (type == GLEnum.GL_UNSIGNED_BYTE) { |
| byte idx = indexSrc.get(); |
| index = idx & 0xff; |
| indexData.put(idx); |
| } else if (type == GLEnum.GL_UNSIGNED_SHORT) { |
| short idx = indexSrc.getShort(); |
| index = idx & 0xffff; |
| indexData.putShort(idx); |
| } else |
| assert false; |
| data.get(element); |
| attribData.put(element); |
| if (index > maxIndex) |
| maxIndex = index; |
| } |
| code.format(" FILE * attribFile = fopen(\"/sdcard/frame_data.bin\", \"rb\");CHKERR;\n"); |
| code.format(" assert(attribFile);CHKERR;\n"); |
| code.format(" fseek(attribFile, 0x%X, SEEK_SET);CHKERR;\n", |
| dataOut.getChannel().position()); |
| dataOut.write(indexData.array()); |
| code.format(" %s * const indexData = (%s *)malloc(%d);\n", typeName, typeName, |
| indexData.capacity()); |
| code.format(" assert(indexData);\n"); |
| code.format(" fread(indexData, %d, 1, attribFile);\n", indexData.capacity()); |
| if (attribDataStride > 0) { |
| code.format(" glBindBuffer(GL_ARRAY_BUFFER, 0);CHKERR;\n"); |
| for (int i = 0; i < maxAttrib; i++) { |
| final GLAttribPointer att = v.attribPointers[i]; |
| if (!att.enabled) |
| continue; |
| if (att.buffer != null) |
| continue; |
| code.format(" char * const attrib%d = (char *)malloc(%d);\n", |
| i, att.elemSize * (maxIndex + 1)); |
| code.format(" assert(attrib%d);\n", i); |
| code.format( |
| " glVertexAttribPointer(%d, %d, %s, %b, %d, attrib%d);CHKERR;\n", |
| i, att.size, att.type, att.normalized, att.elemSize, i); |
| } |
| dataOut.write(attribData.array()); |
| code.format(" for (%s i = 0; i < %d; i++) {\n", typeName, count); |
| for (int i = 0; i < maxAttrib; i++) { |
| final GLAttribPointer att = v.attribPointers[i]; |
| if (!att.enabled) |
| continue; |
| if (att.buffer != null) |
| continue; |
| code.format( |
| " fread(attrib%d + indexData[i] * %d, %d, 1, attribFile);\n", |
| i, att.elemSize, att.elemSize); |
| } |
| code.format(" }\n"); |
| if (v.attribBuffer != null) |
| code.format(" glBindBuffer(GL_ARRAY_BUFFER, %d);CHKERR;\n", |
| v.attribBuffer.name); |
| } |
| code.format(" fclose(attribFile);\n"); |
| } |
| if (v.indexBuffer != null) |
| code.format(" glDrawElements(%s, %d, %s, (const void *)%d);CHKERR;\n", |
| mode, count, type, msgData.msg.getArg3()); |
| else { |
| code.format(" glDrawElements(%s, %d, %s, indexData);CHKERR;\n", |
| mode, count, type); |
| code.format(" free(indexData);\n"); |
| } |
| for (int i = 0; i < maxAttrib; i++) { |
| final GLAttribPointer att = v.attribPointers[i]; |
| if (!att.enabled) |
| continue; |
| if (att.buffer != null) |
| continue; |
| code.format(" free(attrib%d);\n", i); |
| } |
| code.write("};\n"); |
| } |
| |
| private void codeGenDraw(final GLServerVertex v, final MessageData msgData) |
| throws IOException { |
| final int maxAttrib = msgData.msg.getArg7(); |
| if (maxAttrib < 1) { |
| code.write("// no vertex data\n"); |
| return; |
| } |
| final int count = msgData.attribs[0].length / 4; |
| final GLEnum mode = GLEnum.valueOf(msgData.msg.getArg0()); |
| final ByteBuffer attribData = ByteBuffer.allocate(maxAttrib * count * 16); |
| attribData.order(SampleView.targetByteOrder); |
| for (int i = 0; i < count; i++) |
| for (int j = 0; j < maxAttrib; j++) |
| for (int k = 0; k < 4; k++) |
| attribData.putFloat(msgData.attribs[j][i * 4 + k]); |
| assert attribData.remaining() == 0; |
| code.write("{\n"); |
| code.format(" FILE * attribFile = fopen(\"/sdcard/frame_data.bin\", \"rb\");CHKERR;\n"); |
| code.format(" assert(attribFile);CHKERR;\n"); |
| code.format(" fseek(attribFile, 0x%X, SEEK_SET);CHKERR;\n", |
| dataOut.getChannel().position()); |
| dataOut.write(attribData.array()); |
| code.format(" char * const attribData = (char *)malloc(%d);\n", attribData.capacity()); |
| code.format(" assert(attribData);\n"); |
| code.format(" fread(attribData, %d, 1, attribFile);\n", attribData.capacity()); |
| code.format(" fclose(attribFile);\n"); |
| code.format(" glBindBuffer(GL_ARRAY_BUFFER, 0);CHKERR;\n"); |
| for (int i = 0; i < maxAttrib; i++) { |
| final GLAttribPointer att = v.attribPointers[i]; |
| assert msgData.attribs[i].length == count * 4; |
| code.format( |
| " glVertexAttribPointer(%d, %d, GL_FLOAT, GL_FALSE, %d, attribData + %d);CHKERR;\n", |
| i, att.size, maxAttrib * 16, i * 16); |
| } |
| code.format(" glDrawArrays(%s, 0, %d);CHKERR;\n", mode, count); |
| code.format(" free(attribData);\n"); |
| if (v.attribBuffer != null) |
| code.format(" glBindBuffer(GL_ARRAY_BUFFER, %d);CHKERR;\n", |
| v.attribBuffer.name); |
| code.write("};\n"); |
| } |
| |
| private void codeGenFunction(final Context ctx, final MessageData msgData) |
| throws IOException { |
| final Message msg = msgData.msg; |
| String call = MessageFormatter.format(msg, true); |
| switch (msg.getFunction()) { |
| case glActiveTexture: |
| case glAttachShader: |
| case glBindAttribLocation: |
| break; |
| case glBindBuffer: |
| case glBindFramebuffer: |
| case glBindRenderbuffer: |
| case glBindTexture: |
| codeGenBindNames(msg); |
| return; |
| case glBlendColor: |
| case glBlendEquation: |
| case glBlendEquationSeparate: |
| case glBlendFunc: |
| case glBlendFuncSeparate: |
| break; |
| case glBufferData: |
| call = MessageFormatter.format(msg, true).replace("arg2", "bufferData"); |
| codeGenBufferData(msg.getData().asReadOnlyByteBuffer(), call); |
| return; |
| case glBufferSubData: |
| call = MessageFormatter.format(msg, true).replace("arg3", "bufferData"); |
| codeGenBufferData(msg.getData().asReadOnlyByteBuffer(), call); |
| return; |
| case glCheckFramebufferStatus: |
| case glClear: |
| case glClearColor: |
| case glClearDepthf: |
| case glClearStencil: |
| case glColorMask: |
| case glCompileShader: |
| break; |
| case glCompressedTexImage2D: |
| case glCompressedTexSubImage2D: |
| case glCopyTexImage2D: |
| case glCopyTexSubImage2D: |
| codeGenTextureUpload(msg, false); |
| return; |
| case glCreateProgram: |
| namesHeader.format("extern GLuint program_%d;\n", msg.getRet()); |
| namesSource.format("GLuint program_%d = 0;\n", msg.getRet()); |
| code.format("program_%d = glCreateProgram();CHKERR;\n", msg.getRet()); |
| return; |
| case glCreateShader: |
| namesHeader.format("extern GLuint shader_%d;\n", msg.getRet()); |
| namesSource.format("GLuint shader_%d = 0;\n", msg.getRet()); |
| code.format("shader_%d = %s;\n", msg.getRet(), call); |
| return; |
| case glCullFace: |
| break; |
| case glDeleteBuffers: |
| case glDeleteFramebuffers: |
| case glDeleteProgram: |
| programNames.put(msg.getArg0(), 0); |
| break; |
| case glDeleteRenderbuffers: |
| codeGenDeleteNames(msg); |
| return; |
| case glDeleteShader: |
| shaderNames.put(msg.getArg0(), 0); |
| return; |
| case glDeleteTextures: |
| codeGenDeleteNames(msg); |
| return; |
| case glDepthFunc: |
| case glDepthMask: |
| case glDepthRangef: |
| case glDetachShader: |
| case glDisable: |
| case glDisableVertexAttribArray: |
| break; |
| case glDrawArrays: |
| // CodeGenDraw(ctx.serverVertex, msgData); |
| codeGenDrawArrays(ctx.serverVertex, msgData); |
| return; |
| case glDrawElements: |
| // CodeGenDraw(ctx.serverVertex, msgData); |
| codeGenDrawElements(ctx.serverVertex, msgData); |
| return; |
| case glEnable: |
| case glEnableVertexAttribArray: |
| case glFinish: |
| case glFlush: |
| case glFramebufferRenderbuffer: |
| case glFramebufferTexture2D: |
| case glFrontFace: |
| break; |
| case glGenBuffers: |
| codeGenGenNames(msg); |
| return; |
| case glGenerateMipmap: |
| break; |
| case glGenFramebuffers: |
| case glGenRenderbuffers: |
| case glGenTextures: |
| codeGenGenNames(msg); |
| return; |
| case glGetActiveAttrib: |
| case glGetActiveUniform: |
| case glGetAttachedShaders: |
| break; |
| case glGetAttribLocation: |
| call = String.format("assert(%d == %s)", msg.getRet(), call); |
| break; |
| case glGetBooleanv: |
| case glGetBufferParameteriv: |
| return; // TODO |
| case glGetError: |
| code.write("CHKERR;\n"); |
| return; |
| case glGetFloatv: |
| case glGetFramebufferAttachmentParameteriv: |
| case glGetIntegerv: |
| case glGetProgramiv: |
| case glGetProgramInfoLog: |
| case glGetRenderbufferParameteriv: |
| case glGetShaderiv: |
| case glGetShaderInfoLog: |
| case glGetShaderPrecisionFormat: |
| case glGetShaderSource: |
| case glGetString: |
| case glGetTexParameterfv: |
| case glGetTexParameteriv: |
| case glGetUniformfv: |
| case glGetUniformiv: |
| return; |
| case glGetUniformLocation: |
| call = String.format("assert(%d == %s)", msg.getRet(), call); |
| break; |
| case glGetVertexAttribfv: |
| case glGetVertexAttribiv: |
| case glGetVertexAttribPointerv: |
| return; // TODO |
| case glHint: |
| case glIsBuffer: |
| case glIsEnabled: |
| case glIsFramebuffer: |
| case glIsProgram: |
| case glIsRenderbuffer: |
| case glIsShader: |
| case glIsTexture: |
| case glLineWidth: |
| case glLinkProgram: |
| case glPixelStorei: |
| case glPolygonOffset: |
| break; |
| case glReadPixels: |
| return; // TODO |
| case glReleaseShaderCompiler: |
| case glRenderbufferStorage: |
| case glSampleCoverage: |
| case glScissor: |
| break; |
| case glShaderBinary: |
| return; // TODO |
| case glShaderSource: |
| call = String.format( |
| "glShaderSource(shader_%d, 1, (const char * []){\"%s\"}, NULL)", |
| msg.getArg0(), |
| msg.getData().toStringUtf8().replace("\r", "").replace("\n", "\\n\\\n") |
| .replace("\"", "\\\"") |
| ); |
| break; |
| case glStencilFunc: |
| case glStencilFuncSeparate: |
| case glStencilMask: |
| case glStencilMaskSeparate: |
| case glStencilOp: |
| case glStencilOpSeparate: |
| break; |
| case glTexImage2D: |
| codeGenTextureUpload(msg, false); |
| return; |
| case glTexParameterf: |
| break; |
| case glTexParameterfv: |
| return; // TODO |
| case glTexParameteri: |
| break; |
| case glTexParameteriv: |
| return; // TODO |
| case glTexSubImage2D: |
| codeGenTextureUpload(msg, false); |
| return; |
| case glUniform1f: |
| case glUniform1fv: |
| case glUniform1i: |
| case glUniform1iv: |
| case glUniform2f: |
| case glUniform2fv: |
| case glUniform2i: |
| case glUniform2iv: |
| case glUniform3f: |
| case glUniform3fv: |
| case glUniform3i: |
| case glUniform3iv: |
| case glUniform4f: |
| case glUniform4fv: |
| case glUniform4i: |
| case glUniform4iv: |
| case glUniformMatrix2fv: |
| case glUniformMatrix3fv: |
| case glUniformMatrix4fv: |
| case glUseProgram: |
| case glValidateProgram: |
| case glVertexAttrib1f: |
| case glVertexAttrib1fv: |
| case glVertexAttrib2f: |
| case glVertexAttrib2fv: |
| case glVertexAttrib3f: |
| case glVertexAttrib3fv: |
| case glVertexAttrib4f: |
| case glVertexAttrib4fv: |
| break; |
| case glVertexAttribPointer: |
| // if it's user pointer, then CodeGenDrawArrays/Elements will |
| // replace it with loaded data just before the draw |
| call = call.replace("arg5", "(const void *)0x" + |
| Integer.toHexString(msg.getArg5())); |
| break; |
| case glViewport: |
| break; |
| case eglSwapBuffers: |
| return; |
| default: |
| assert false; |
| return; |
| } |
| if (call.indexOf("glEnable(/*cap*/ GL_TEXTURE_2D)") >= 0) |
| return; |
| else if (call.indexOf("glDisable(/*cap*/ GL_TEXTURE_2D)") >= 0) |
| return; |
| else if (call.indexOf("glActiveTexture(/*texture*/ GL_TEXTURE_2D)") >= 0) |
| return; |
| code.write(call + ";CHKERR;\n"); |
| } |
| |
| private void codeGenSetup(final Context ctx) { |
| try { |
| codeFile = new FileWriter("frame_setup.cpp", false); |
| code = new PrintWriter(codeFile); |
| dataOut = new FileOutputStream("frame_data.bin", false); |
| namesHeaderFile = new FileWriter("frame_names.h", false); |
| namesHeader = new PrintWriter(namesHeaderFile); |
| namesSourceFile = new FileWriter("frame_names.cpp", false); |
| namesSource = new PrintWriter(namesSourceFile); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| assert false; |
| } |
| bufferNames = new SparseIntArray(); |
| framebufferNames = new SparseIntArray(); |
| programNames = new SparseIntArray(); |
| textureNames = new SparseIntArray(); |
| shaderNames = new SparseIntArray(); |
| renderbufferNames = new SparseIntArray(); |
| |
| namesHeader.write("#include <stdlib.h>\n"); |
| namesHeader.write("#include <stdio.h>\n"); |
| namesHeader.write("#include <assert.h>\n"); |
| namesHeader.write("#include <GLES2/gl2.h>\n"); |
| namesHeader.write("#include <GLES2/gl2ext.h>\n"); |
| namesHeader.write("#define CHKERR assert(GL_NO_ERROR == glGetError());/**/\n"); |
| namesHeader.write("void FrameSetup();\n"); |
| namesHeader.write("extern const unsigned int FrameCount;\n"); |
| namesHeader.write("extern const GLuint program_0;\n"); |
| |
| namesSource.write("/*\n" + |
| " * Copyright (C) 2011 The Android Open Source Project\n" + |
| " *\n" + |
| " * Licensed under the Apache License, Version 2.0 (the \"License\");\n" + |
| " * you may not use this file except in compliance with the License.\n" + |
| " * You may obtain a copy of the License at\n" + |
| " *\n" + |
| " * http://www.apache.org/licenses/LICENSE-2.0\n" + |
| " *\n" + |
| " * Unless required by applicable law or agreed to in writing, software\n" + |
| " * distributed under the License is distributed on an \"AS IS\" BASIS,\n" + |
| " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + |
| " * See the License for the specific language governing permissions and\n" + |
| " * limitations under the License.\n" + |
| " */\n" + |
| "\n" + |
| "#include <stdlib.h>\n" + |
| "#include <stdio.h>\n" + |
| "\n" + |
| "#include <EGL/egl.h>\n" + |
| "#include <GLES2/gl2.h>\n" + |
| "#include <GLES2/gl2ext.h>\n" + |
| "\n" + |
| "#include <ui/FramebufferNativeWindow.h>\n" + |
| "#include <ui/EGLUtils.h>\n" + |
| "\n" + |
| "#include <private/ui/android_natives_priv.h>\n" + |
| "\n" + |
| "#include <surfaceflinger/Surface.h>\n" + |
| "#include <surfaceflinger/ISurface.h>\n" + |
| "#include <surfaceflinger/SurfaceComposerClient.h>\n" + |
| "\n" + |
| "using namespace android;\n" + |
| "\n" + |
| "static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE)\n" + |
| "{\n" + |
| " if (returnVal != EGL_TRUE) {\n" + |
| " fprintf(stderr, \"%s() returned %d\\n\", op, returnVal);\n" + |
| " }\n" + |
| "\n" + |
| " for (EGLint error = eglGetError(); error != EGL_SUCCESS; error\n" + |
| " = eglGetError()) {\n" + |
| " fprintf(stderr, \"after %s() eglError %s (0x%x)\\n\", op, EGLUtils::strerror(error),\n" + |
| " error);\n" + |
| " }\n" + |
| "}\n" + |
| "\n" + |
| "static EGLDisplay dpy;\n" + |
| "static EGLSurface surface;\n" + |
| "\n" + |
| "#include \"frame_names.h\"\n" + |
| "const GLuint program_0 = 0;\n" + |
| "int main(int argc, char** argv)\n" + |
| "{\n" + |
| " EGLBoolean returnValue;\n" + |
| " EGLConfig myConfig = {0};\n" + |
| "\n" + |
| " EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };\n" + |
| " EGLint majorVersion;\n" + |
| " EGLint minorVersion;\n" + |
| " EGLContext context;\n" + |
| " EGLint w, h;\n" + |
| "\n" + |
| "\n" + |
| " checkEglError(\"<init>\");\n" + |
| " dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);\n" + |
| " checkEglError(\"eglGetDisplay\");\n" + |
| " if (dpy == EGL_NO_DISPLAY) {\n" + |
| " printf(\"eglGetDisplay returned EGL_NO_DISPLAY.\\n\");\n" + |
| " return 0;\n" + |
| " }\n" + |
| "\n" + |
| " returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);\n" + |
| " checkEglError(\"eglInitialize\", returnValue);\n" + |
| " if (returnValue != EGL_TRUE) {\n" + |
| " printf(\"eglInitialize failed\\n\");\n" + |
| " return 0;\n" + |
| " }\n" + |
| "\n" + |
| " sp<SurfaceComposerClient> spClient;\n" + |
| " sp<SurfaceControl> spControl;\n" + |
| " sp<Surface> spSurface;\n" + |
| "\n" + |
| " // create a client to surfaceflinger\n" + |
| " spClient = new SurfaceComposerClient();\n" + |
| "\n" + |
| " spControl = spClient->createSurface(getpid(), 0, 1280, 752, PIXEL_FORMAT_RGBX_8888);\n" + |
| " spClient->openTransaction();\n" + |
| " spControl->setLayer(350000);\n" + |
| " spControl->show();\n" + |
| " spClient->closeTransaction();\n" + |
| "\n" + |
| " spSurface = spControl->getSurface();\n" + |
| " EGLNativeWindowType window = spSurface.get();\n" + |
| "\n" + |
| " printf(\"window=%p\\n\", window);\n" + |
| " EGLint attrib_list[] = {\n" + |
| " EGL_SURFACE_TYPE, EGL_WINDOW_BIT,\n" + |
| " EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,\n" + |
| " EGL_BUFFER_SIZE, 32,\n" + |
| " EGL_RED_SIZE, 8,\n" + |
| " EGL_GREEN_SIZE, 8,\n" + |
| " EGL_BLUE_SIZE, 8,\n" + |
| " EGL_NONE\n" + |
| " };\n" + |
| "\n" + |
| " EGLConfig configs[12] = {0};\n" + |
| " int num_config = -1;\n" + |
| " eglChooseConfig(dpy, attrib_list, configs, sizeof(configs) / sizeof(*configs), &num_config);\n" + |
| " printf(\"eglChooseConfig %d \\n\", num_config);\n" + |
| "\n" + |
| " surface = eglCreateWindowSurface(dpy, configs[0], window, NULL);\n" + |
| " checkEglError(\"eglCreateWindowSurface\");\n" + |
| " if (surface == EGL_NO_SURFACE) {\n" + |
| " printf(\"gelCreateWindowSurface failed.\\n\");\n" + |
| " return 0;\n" + |
| " }\n" + |
| "\n" + |
| " context = eglCreateContext(dpy, configs[0], EGL_NO_CONTEXT, context_attribs);\n" + |
| " checkEglError(\"eglCreateContext\");\n" + |
| " if (context == EGL_NO_CONTEXT) {\n" + |
| " printf(\"eglCreateContext failed\\n\");\n" + |
| " return 0;\n" + |
| " }\n" + |
| " printf(\"context=%p \\n\", context);\n" + |
| "\n" + |
| " returnValue = eglMakeCurrent(dpy, surface, surface, context);\n" + |
| " checkEglError(\"eglMakeCurrent\", returnValue);\n" + |
| " if (returnValue != EGL_TRUE) {\n" + |
| " return 0;\n" + |
| " }\n" + |
| "\n" + |
| " glClearColor(1,1,1,1);\n" + |
| " glClear(GL_COLOR_BUFFER_BIT);\n" + |
| "\n" + |
| " FrameSetup();\n" + |
| " while (true)\n" + |
| " for (unsigned int i = 0; i < FrameCount; i++) {\n" + |
| " Frames[i]();\n" + |
| " eglSwapBuffers(dpy, surface);\n" + |
| " printf(\"press ENTER after Frame%d \\n\", i);\n" + |
| " getchar();\n" + |
| " }\n" + |
| "\n" + |
| " return 0;\n" + |
| "}"); |
| |
| code.write("#include \"frame_names.h\"\n"); |
| code.write("void FrameSetup(){\n"); |
| |
| codeGenServerState(ctx.serverState); |
| codeGenServerShader(ctx.serverShader); |
| codeGenServerTexture(ctx.serverTexture, true); |
| codeGenServerVertex(ctx.serverVertex); |
| |
| code.write("}\n"); |
| |
| try { |
| codeFile.close(); |
| makeFile = new FileWriter("Android.mk", false); |
| make = new PrintWriter(makeFile); |
| make.write("LOCAL_PATH:= $(call my-dir)\n" + |
| "include $(CLEAR_VARS)\n" + |
| "LOCAL_SRC_FILES := \\\n"); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| assert false; |
| } |
| } |
| |
| private void codeGenCleanup() { |
| make.write(" frame_setup.cpp \\\n"); |
| make.write(" frame_names.cpp \\\n"); |
| make.write("#\n"); |
| make.write( |
| "LOCAL_SHARED_LIBRARIES := \\\n" + |
| " libcutils \\\n" + |
| " libutils \\\n" + |
| " libEGL \\\n" + |
| " libGLESv2 \\\n" + |
| " libui \\\n" + |
| " libhardware \\\n" + |
| " libgui\n" + |
| "\n" + |
| "LOCAL_MODULE:= gles2dbg\n" + |
| "\n" + |
| "LOCAL_MODULE_TAGS := optional\n" + |
| "\n" + |
| "LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -O0 -g -DDEBUG -UNDEBUG\n" + |
| "\n" + |
| "include $(BUILD_EXECUTABLE)"); |
| try { |
| dataOut.flush(); |
| dataOut.close(); |
| codeFile.close(); |
| makeFile.close(); |
| namesHeaderFile.close(); |
| namesSourceFile.close(); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| assert false; |
| } |
| dataOut = null; |
| code = null; |
| codeFile = null; |
| make = null; |
| makeFile = null; |
| |
| bufferNames = null; |
| framebufferNames = null; |
| programNames = null; |
| textureNames = null; |
| shaderNames = null; |
| renderbufferNames = null; |
| } |
| |
| private DebugContext dbgCtx; |
| private int count; |
| private IProgressMonitor progress; |
| |
| @Override |
| public void run(IProgressMonitor monitor) { |
| progress.beginTask("CodeGenFrames", count + 2); |
| Context ctx = dbgCtx.getFrame(0).startContext.clone(); |
| codeGenSetup(ctx); |
| progress.worked(1); |
| for (int i = 0; i < count; i++) { |
| try { |
| codeFile = new FileWriter("frame" + i + ".cpp", false); |
| code = new PrintWriter(codeFile); |
| } catch (IOException e1) { |
| e1.printStackTrace(); |
| assert false; |
| } |
| make.format(" frame%d.cpp \\\n", i); |
| |
| code.write("#include \"frame_names.h\"\n"); |
| code.format("void Frame%d(){\n", i); |
| final Frame frame = dbgCtx.getFrame(i); |
| for (int j = 0; j < frame.size(); j++) { |
| final MessageData msgData = frame.get(j); |
| code.format("/* frame function %d: %s %s*/\n", j, msgData.msg.getFunction(), |
| MessageFormatter.format(msgData.msg, false)); |
| ctx.processMessage(msgData.msg); |
| try { |
| codeGenFunction(ctx, msgData); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| assert false; |
| } |
| } |
| code.write("}\n"); |
| try { |
| codeFile.close(); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| assert false; |
| } |
| progress.worked(1); |
| } |
| for (int i = 0; i < count; i++) |
| namesHeader.format("void Frame%d();\n", i); |
| namesHeader.format("extern void (* Frames[%d])();\n", count); |
| namesSource.format("void (* Frames[%d])() = {\n", count); |
| for (int i = 0; i < count; i++) { |
| namesSource.format(" Frame%d,\n", i); |
| } |
| namesSource.write("};\n"); |
| namesSource.format("const unsigned int FrameCount = %d;\n", count); |
| codeGenCleanup(); |
| progress.worked(1); |
| } |
| |
| void codeGenFrames(final DebugContext dbgCtx, int count, final Shell shell) { |
| this.dbgCtx = dbgCtx; |
| this.count = count; |
| ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell); |
| this.progress = dialog.getProgressMonitor(); |
| try { |
| dialog.run(false, true, this); |
| } catch (InvocationTargetException e) { |
| e.printStackTrace(); |
| assert false; |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| this.dbgCtx = null; |
| this.count = 0; |
| progress = null; |
| } |
| |
| void codeGenFrame(final Frame frame) { |
| Context ctx = frame.startContext.clone(); |
| codeGenSetup(ctx); |
| try { |
| codeFile = new FileWriter("frame0.cpp", false); |
| code = new PrintWriter(codeFile); |
| } catch (IOException e1) { |
| e1.printStackTrace(); |
| assert false; |
| } |
| make.format(" frame0.cpp \\\n"); |
| code.write("#include \"frame_names.h\"\n"); |
| code.format("void Frame0(){\n"); |
| for (int i = 0; i < frame.size(); i++) { |
| final MessageData msgData = frame.get(i); |
| code.format("/* frame function %d: %s %s*/\n", i, msgData.msg.getFunction(), |
| MessageFormatter.format(msgData.msg, false)); |
| ctx.processMessage(msgData.msg); |
| try { |
| codeGenFunction(ctx, msgData); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| assert false; |
| } |
| } |
| code.write("}\n"); |
| namesHeader.write("void Frame0();\n"); |
| namesHeader.write("extern void (* Frames[1])();\n"); |
| namesSource.write("void (* Frames[1])() = {Frame0};\n"); |
| namesSource.write("const unsigned int FrameCount = 1;\n"); |
| codeGenCleanup(); |
| } |
| } |