| /* |
| * Copyright (C) 2012 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.ide.eclipse.gltrace.state.transforms; |
| |
| import com.android.ide.eclipse.gltrace.FileUtils; |
| import com.android.ide.eclipse.gltrace.GLEnum; |
| import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage; |
| import com.android.ide.eclipse.gltrace.state.GLState; |
| import com.android.ide.eclipse.gltrace.state.GLStateType; |
| import com.android.ide.eclipse.gltrace.state.IGLProperty; |
| import com.google.common.io.Files; |
| import com.google.protobuf.ByteString; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.EnumSet; |
| import java.util.List; |
| |
| public class StateTransformFactory { |
| private static final String TEXTURE_DATA_FILE_PREFIX = "tex"; //$NON-NLS-1$ |
| private static final String TEXTURE_DATA_FILE_SUFFIX = ".dat"; //$NON-NLS-1$ |
| private static EnumSet<GLEnum> sTexParameterPnameValues; |
| |
| /** Construct a list of transformations to be applied for the provided OpenGL call. */ |
| public static List<IStateTransform> getTransformsFor(GLMessage msg) { |
| switch (msg.getFunction()) { |
| case eglCreateContext: |
| return transformsForEglCreateContext(msg); |
| case glBindFramebuffer: |
| return transformsForGlBindFramebuffer(msg); |
| |
| // vertex data |
| case glVertexAttribPointer: |
| return transformsForGlVertexAttribPointer(msg); |
| case glVertexAttrib1f: |
| case glVertexAttrib2f: |
| case glVertexAttrib3f: |
| case glVertexAttrib4f: |
| return transformsForGlVertexAttribxf(msg); |
| case glVertexAttrib1fv: |
| case glVertexAttrib2fv: |
| case glVertexAttrib3fv: |
| case glVertexAttrib4fv: |
| return transformsForGlVertexAttribxfv(msg); |
| case glEnableVertexAttribArray: |
| return transformsForGlEnableVertexAttribArray(msg); |
| case glDisableVertexAttribArray: |
| return transformsForGlDisableVertexAttribArray(msg); |
| |
| // VBO's |
| case glBindBuffer: |
| return transformsForGlBindBuffer(msg); |
| case glGenBuffers: |
| return transformsForGlGenBuffers(msg); |
| case glDeleteBuffers: |
| return transformsForGlDeleteBuffers(msg); |
| case glBufferData: |
| return transformsForGlBufferData(msg); |
| case glBufferSubData: |
| return transformsForGlBufferSubData(msg); |
| |
| // transformation state |
| case glViewport: |
| return transformsForGlViewport(msg); |
| case glDepthRangef: |
| return transformsForGlDepthRangef(msg); |
| |
| // rasterization |
| case glLineWidth: |
| return transformsForGlLineWidth(msg); |
| case glCullFace: |
| return transformsForGlCullFace(msg); |
| case glFrontFace: |
| return transformsForGlFrontFace(msg); |
| case glPolygonOffset: |
| return transformsForGlPolygonOffset(msg); |
| |
| // pixel operations |
| case glScissor: |
| return transformsForGlScissor(msg); |
| case glStencilFunc: |
| return transformsForGlStencilFunc(msg); |
| case glStencilFuncSeparate: |
| return transformsForGlStencilFuncSeparate(msg); |
| case glStencilOp: |
| return transformsForGlStencilOp(msg); |
| case glStencilOpSeparate: |
| return transformsForGlStencilOpSeparate(msg); |
| case glDepthFunc: |
| return transformsForGlDepthFunc(msg); |
| case glBlendEquation: |
| return transformsForGlBlendEquation(msg); |
| case glBlendEquationSeparate: |
| return transformsForGlBlendEquationSeparate(msg); |
| case glBlendFunc: |
| return transformsForGlBlendFunc(msg); |
| case glBlendFuncSeparate: |
| return transformsForGlBlendFuncSeparate(msg); |
| case glPixelStorei: |
| return transformsForGlPixelStorei(msg); |
| |
| // Texture State Transformations |
| case glGenTextures: |
| return transformsForGlGenTextures(msg); |
| case glDeleteTextures: |
| return transformsForGlDeleteTextures(msg); |
| case glActiveTexture: |
| return transformsForGlActiveTexture(msg); |
| case glBindTexture: |
| return transformsForGlBindTexture(msg); |
| case glTexImage2D: |
| return transformsForGlTexImage2D(msg); |
| case glTexSubImage2D: |
| return transformsForGlTexSubImage2D(msg); |
| case glTexParameteri: |
| return transformsForGlTexParameter(msg); |
| |
| // Program State Transformations |
| case glCreateProgram: |
| return transformsForGlCreateProgram(msg); |
| case glUseProgram: |
| return transformsForGlUseProgram(msg); |
| case glAttachShader: |
| return transformsForGlAttachShader(msg); |
| case glDetachShader: |
| return transformsForGlDetachShader(msg); |
| case glGetActiveAttrib: |
| return transformsForGlGetActiveAttrib(msg); |
| case glGetActiveUniform: |
| return transformsForGlGetActiveUniform(msg); |
| case glUniform1i: |
| case glUniform2i: |
| case glUniform3i: |
| case glUniform4i: |
| return transformsForGlUniform(msg, false); |
| case glUniform1f: |
| case glUniform2f: |
| case glUniform3f: |
| case glUniform4f: |
| return transformsForGlUniform(msg, true); |
| case glUniform1iv: |
| case glUniform2iv: |
| case glUniform3iv: |
| case glUniform4iv: |
| return transformsForGlUniformv(msg, false); |
| case glUniform1fv: |
| case glUniform2fv: |
| case glUniform3fv: |
| case glUniform4fv: |
| return transformsForGlUniformv(msg, true); |
| case glUniformMatrix2fv: |
| case glUniformMatrix3fv: |
| case glUniformMatrix4fv: |
| return transformsForGlUniformMatrix(msg); |
| |
| // Shader State Transformations |
| case glCreateShader: |
| return transformsForGlCreateShader(msg); |
| case glDeleteShader: |
| return transformsForGlDeleteShader(msg); |
| case glShaderSource: |
| return transformsForGlShaderSource(msg); |
| default: |
| return Collections.emptyList(); |
| } |
| } |
| |
| private static List<IStateTransform> transformsForGlVertexAttribPointer(GLMessage msg) { |
| int index = msg.getArgs(0).getIntValue(0); |
| |
| int size = msg.getArgs(1).getIntValue(0); |
| int type = msg.getArgs(2).getIntValue(0); |
| boolean normalized = msg.getArgs(3).getBoolValue(0); |
| int stride = msg.getArgs(4).getIntValue(0); |
| |
| long pointer; |
| if (msg.getArgs(5).getIntValueCount() > 0) { |
| pointer = msg.getArgs(5).getIntValue(0); |
| } else { |
| pointer = msg.getArgs(5).getInt64Value(0); |
| } |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.VERTEX_ARRAY_DATA, |
| GLStateType.VERTEX_ATTRIB_ARRAY, |
| Integer.valueOf(index), |
| GLStateType.VERTEX_ATTRIB_ARRAY_SIZE), |
| Integer.valueOf(size))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.VERTEX_ARRAY_DATA, |
| GLStateType.VERTEX_ATTRIB_ARRAY, |
| Integer.valueOf(index), |
| GLStateType.VERTEX_ATTRIB_ARRAY_TYPE), |
| GLEnum.valueOf(type))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.VERTEX_ARRAY_DATA, |
| GLStateType.VERTEX_ATTRIB_ARRAY, |
| Integer.valueOf(index), |
| GLStateType.VERTEX_ATTRIB_ARRAY_NORMALIZED), |
| Boolean.valueOf(normalized))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.VERTEX_ARRAY_DATA, |
| GLStateType.VERTEX_ATTRIB_ARRAY, |
| Integer.valueOf(index), |
| GLStateType.VERTEX_ATTRIB_ARRAY_STRIDE), |
| Integer.valueOf(stride))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.VERTEX_ARRAY_DATA, |
| GLStateType.VERTEX_ATTRIB_ARRAY, |
| Integer.valueOf(index), |
| GLStateType.VERTEX_ATTRIB_ARRAY_POINTER), |
| Long.valueOf(pointer))); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlVertexAttrib(int context, |
| int index, float v0, float v1, float v2, float v3) { |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(4); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(context, |
| GLStateType.VERTEX_ARRAY_DATA, |
| GLStateType.GENERIC_VERTEX_ATTRIBUTES, |
| Integer.valueOf(index), |
| GLStateType.GENERIC_VERTEX_ATTRIB_V0), |
| Float.valueOf(v0))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(context, |
| GLStateType.VERTEX_ARRAY_DATA, |
| GLStateType.GENERIC_VERTEX_ATTRIBUTES, |
| Integer.valueOf(index), |
| GLStateType.GENERIC_VERTEX_ATTRIB_V1), |
| Float.valueOf(v1))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(context, |
| GLStateType.VERTEX_ARRAY_DATA, |
| GLStateType.GENERIC_VERTEX_ATTRIBUTES, |
| Integer.valueOf(index), |
| GLStateType.GENERIC_VERTEX_ATTRIB_V2), |
| Float.valueOf(v2))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(context, |
| GLStateType.VERTEX_ARRAY_DATA, |
| GLStateType.GENERIC_VERTEX_ATTRIBUTES, |
| Integer.valueOf(index), |
| GLStateType.GENERIC_VERTEX_ATTRIB_V3), |
| Float.valueOf(v3))); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlVertexAttribxf(GLMessage msg) { |
| // void glVertexAttrib1f(GLuint index, GLfloat v0); |
| // void glVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1); |
| // void glVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2); |
| // void glVertexAttrib4f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); |
| |
| int index = msg.getArgs(0).getIntValue(0); |
| float v0 = msg.getArgs(1).getFloatValue(0); |
| float v1 = msg.getArgsCount() > 2 ? msg.getArgs(2).getFloatValue(0) : 0; |
| float v2 = msg.getArgsCount() > 3 ? msg.getArgs(3).getFloatValue(0) : 0; |
| float v3 = msg.getArgsCount() > 4 ? msg.getArgs(4).getFloatValue(0) : 0; |
| |
| return transformsForGlVertexAttrib(msg.getContextId(), index, v0, v1, v2, v3); |
| } |
| |
| private static List<IStateTransform> transformsForGlVertexAttribxfv(GLMessage msg) { |
| // void glVertexAttrib1fv(GLuint index, const GLfloat *v); |
| // void glVertexAttrib2fv(GLuint index, const GLfloat *v); |
| // void glVertexAttrib3fv(GLuint index, const GLfloat *v); |
| // void glVertexAttrib4fv(GLuint index, const GLfloat *v); |
| |
| int index = msg.getArgs(0).getIntValue(0); |
| float v[] = new float[4]; |
| |
| for (int i = 0; i < msg.getArgs(1).getFloatValueList().size(); i++) { |
| v[i] = msg.getArgs(1).getFloatValue(i); |
| } |
| |
| return transformsForGlVertexAttrib(msg.getContextId(), index, v[0], v[1], v[2], v[3]); |
| } |
| |
| private static List<IStateTransform> transformsForGlEnableVertexAttribArray(GLMessage msg) { |
| // void glEnableVertexAttribArray(GLuint index); |
| // void glDisableVertexAttribArray(GLuint index); |
| |
| int index = msg.getArgs(0).getIntValue(0); |
| IStateTransform transform = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.VERTEX_ARRAY_DATA, |
| GLStateType.VERTEX_ATTRIB_ARRAY, |
| Integer.valueOf(index), |
| GLStateType.VERTEX_ATTRIB_ARRAY_ENABLED), |
| Boolean.TRUE); |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlDisableVertexAttribArray(GLMessage msg) { |
| // void glEnableVertexAttribArray(GLuint index); |
| // void glDisableVertexAttribArray(GLuint index); |
| |
| int index = msg.getArgs(0).getIntValue(0); |
| IStateTransform transform = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.VERTEX_ARRAY_DATA, |
| GLStateType.VERTEX_ATTRIB_ARRAY, |
| Integer.valueOf(index), |
| GLStateType.VERTEX_ATTRIB_ARRAY_ENABLED), |
| Boolean.FALSE); |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlBindBuffer(GLMessage msg) { |
| // void glBindBuffer(GLenum target, GLuint buffer); |
| // target is one of GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER. |
| |
| GLEnum target = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| int buffer = msg.getArgs(1).getIntValue(0); |
| GLStateType bufferType; |
| |
| if (target == GLEnum.GL_ARRAY_BUFFER) { |
| bufferType = GLStateType.ARRAY_BUFFER_BINDING; |
| } else { |
| bufferType = GLStateType.ELEMENT_ARRAY_BUFFER_BINDING; |
| } |
| |
| IStateTransform transform = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.VERTEX_ARRAY_DATA, |
| GLStateType.BUFFER_BINDINGS, |
| bufferType), |
| Integer.valueOf(buffer)); |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlGenBuffers(GLMessage msg) { |
| // void glGenBuffers(GLsizei n, GLuint * buffers); |
| int n = msg.getArgs(0).getIntValue(0); |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| |
| for (int i = 0; i < n; i++) { |
| transforms.add(new SparseArrayElementAddTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.VERTEX_ARRAY_DATA, |
| GLStateType.VBO), |
| msg.getArgs(1).getIntValue(i))); |
| } |
| |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlDeleteBuffers(GLMessage msg) { |
| // void glDeleteBuffers(GLsizei n, const GLuint * buffers); |
| int n = msg.getArgs(0).getIntValue(0); |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| |
| for (int i = 0; i < n; i++) { |
| transforms.add(new SparseArrayElementRemoveTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.VERTEX_ARRAY_DATA, |
| GLStateType.VBO), |
| msg.getArgs(1).getIntValue(i))); |
| } |
| |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlBufferData(GLMessage msg) { |
| // void glBufferData(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); |
| GLEnum target = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| int size = msg.getArgs(1).getIntValue(0); |
| byte[] data = null; |
| GLEnum usage = GLEnum.valueOf(msg.getArgs(3).getIntValue(0)); |
| |
| if (msg.getArgs(2).getRawBytesList().size() > 0) { |
| data = msg.getArgs(2).getRawBytesList().get(0).toByteArray(); |
| } else { |
| data = new byte[size]; |
| } |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| |
| transforms.add(new PropertyChangeTransform( |
| new CurrentVboPropertyAccessor(msg.getContextId(), |
| target, |
| GLStateType.BUFFER_SIZE), |
| Integer.valueOf(size))); |
| transforms.add(new PropertyChangeTransform( |
| new CurrentVboPropertyAccessor(msg.getContextId(), |
| target, |
| GLStateType.BUFFER_DATA), |
| data)); |
| transforms.add(new PropertyChangeTransform( |
| new CurrentVboPropertyAccessor(msg.getContextId(), |
| target, |
| GLStateType.BUFFER_USAGE), |
| usage)); |
| transforms.add(new PropertyChangeTransform( |
| new CurrentVboPropertyAccessor(msg.getContextId(), |
| target, |
| GLStateType.BUFFER_TYPE), |
| target)); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlBufferSubData(GLMessage msg) { |
| // void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data); |
| GLEnum target = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| int offset = msg.getArgs(1).getIntValue(0); |
| byte[] data = msg.getArgs(3).getRawBytesList().get(0).toByteArray(); |
| |
| IStateTransform transform = new BufferSubDataTransform( |
| new CurrentVboPropertyAccessor(msg.getContextId(), |
| target, |
| GLStateType.BUFFER_DATA), |
| offset, data); |
| |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlBindFramebuffer(GLMessage msg) { |
| // void glBindFramebuffer(GLenum target, GLuint framebuffer); |
| int fb = msg.getArgs(1).getIntValue(0); |
| IStateTransform transform = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.FRAMEBUFFER_STATE, |
| GLStateType.FRAMEBUFFER_BINDING), |
| fb); |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlLineWidth(GLMessage msg) { |
| // void glLineWidth(GLfloat width); |
| float width = msg.getArgs(0).getFloatValue(0); |
| IStateTransform transform = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.RASTERIZATION_STATE, |
| GLStateType.LINE_WIDTH), |
| width); |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlCullFace(GLMessage msg) { |
| // void glCullFace(GLenum mode); |
| int mode = msg.getArgs(0).getIntValue(0); |
| IStateTransform transform = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.RASTERIZATION_STATE, |
| GLStateType.CULL_FACE_MODE), |
| GLEnum.valueOf(mode)); |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlFrontFace(GLMessage msg) { |
| // void glFrontFace(GLenum mode); |
| int mode = msg.getArgs(0).getIntValue(0); |
| IStateTransform transform = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.RASTERIZATION_STATE, |
| GLStateType.FRONT_FACE), |
| GLEnum.valueOf(mode)); |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlPolygonOffset(GLMessage msg) { |
| // void glPolygonOffset(GLfloat factor, GLfloat units) |
| float factor = msg.getArgs(0).getFloatValue(0); |
| float units = msg.getArgs(1).getFloatValue(0); |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.RASTERIZATION_STATE, |
| GLStateType.POLYGON_OFFSET_FACTOR), |
| Float.valueOf(factor))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.RASTERIZATION_STATE, |
| GLStateType.POLYGON_OFFSET_UNITS), |
| Float.valueOf(units))); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlScissor(GLMessage msg) { |
| // void glScissor(GLint x, GLint y, GLsizei width, GLsizei height); |
| int x = msg.getArgs(0).getIntValue(0); |
| int y = msg.getArgs(1).getIntValue(0); |
| int w = msg.getArgs(2).getIntValue(0); |
| int h = msg.getArgs(3).getIntValue(0); |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.SCISSOR_BOX, |
| GLStateType.SCISSOR_BOX_X), |
| Integer.valueOf(x))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.SCISSOR_BOX, |
| GLStateType.SCISSOR_BOX_Y), |
| Integer.valueOf(y))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.SCISSOR_BOX, |
| GLStateType.SCISSOR_BOX_WIDTH), |
| Integer.valueOf(w))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.SCISSOR_BOX, |
| GLStateType.SCISSOR_BOX_HEIGHT), |
| Integer.valueOf(h))); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlStencilFuncFront(int contextId, |
| GLEnum func, int ref, int mask) { |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.STENCIL, |
| GLStateType.STENCIL_FUNC), |
| func)); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.STENCIL, |
| GLStateType.STENCIL_REF), |
| Integer.valueOf(ref))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.STENCIL, |
| GLStateType.STENCIL_VALUE_MASK), |
| Integer.valueOf(mask))); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlStencilFuncBack(int contextId, |
| GLEnum func, int ref, int mask) { |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.STENCIL, |
| GLStateType.STENCIL_BACK_FUNC), |
| func)); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.STENCIL, |
| GLStateType.STENCIL_BACK_REF), |
| Integer.valueOf(ref))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.STENCIL, |
| GLStateType.STENCIL_BACK_VALUE_MASK), |
| Integer.valueOf(mask))); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlStencilFunc(GLMessage msg) { |
| // void glStencilFunc(GLenum func, GLint ref, GLuint mask); |
| GLEnum func = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| int ref = msg.getArgs(1).getIntValue(0); |
| int mask = msg.getArgs(2).getIntValue(0); |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.addAll(transformsForGlStencilFuncFront(msg.getContextId(), func, ref, mask)); |
| transforms.addAll(transformsForGlStencilFuncBack(msg.getContextId(), func, ref, mask)); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlStencilFuncSeparate(GLMessage msg) { |
| // void glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); |
| GLEnum face = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| GLEnum func = GLEnum.valueOf(msg.getArgs(1).getIntValue(0)); |
| int ref = msg.getArgs(2).getIntValue(0); |
| int mask = msg.getArgs(3).getIntValue(0); |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| if (face == GLEnum.GL_FRONT || face == GLEnum.GL_FRONT_AND_BACK) { |
| transforms.addAll( |
| transformsForGlStencilFuncFront(msg.getContextId(), func, ref, mask)); |
| } |
| if (face == GLEnum.GL_BACK || face == GLEnum.GL_FRONT_AND_BACK) { |
| transforms.addAll( |
| transformsForGlStencilFuncBack(msg.getContextId(), func, ref, mask)); |
| } |
| |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlStencilOpFront(int contextId, |
| GLEnum sfail, GLEnum dpfail, GLEnum dppass) { |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.STENCIL, |
| GLStateType.STENCIL_FAIL), |
| sfail)); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.STENCIL, |
| GLStateType.STENCIL_PASS_DEPTH_FAIL), |
| dpfail)); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.STENCIL, |
| GLStateType.STENCIL_PASS_DEPTH_PASS), |
| dppass)); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlStencilOpBack(int contextId, |
| GLEnum sfail, GLEnum dpfail, GLEnum dppass) { |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.STENCIL, |
| GLStateType.STENCIL_BACK_FAIL), |
| sfail)); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.STENCIL, |
| GLStateType.STENCIL_BACK_PASS_DEPTH_FAIL), |
| dpfail)); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.STENCIL, |
| GLStateType.STENCIL_BACK_PASS_DEPTH_PASS), |
| dppass)); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlStencilOp(GLMessage msg) { |
| // void glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass); |
| GLEnum sfail = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| GLEnum dpfail = GLEnum.valueOf(msg.getArgs(1).getIntValue(0)); |
| GLEnum dppass = GLEnum.valueOf(msg.getArgs(2).getIntValue(0)); |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.addAll( |
| transformsForGlStencilOpFront(msg.getContextId(), sfail, dpfail, dppass)); |
| transforms.addAll( |
| transformsForGlStencilOpBack(msg.getContextId(), sfail, dpfail, dppass)); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlStencilOpSeparate(GLMessage msg) { |
| // void glStencilOp(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); |
| GLEnum face = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| GLEnum sfail = GLEnum.valueOf(msg.getArgs(1).getIntValue(0)); |
| GLEnum dpfail = GLEnum.valueOf(msg.getArgs(2).getIntValue(0)); |
| GLEnum dppass = GLEnum.valueOf(msg.getArgs(3).getIntValue(0)); |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| |
| if (face == GLEnum.GL_FRONT || face == GLEnum.GL_FRONT_AND_BACK) { |
| transforms.addAll( |
| transformsForGlStencilOpFront(msg.getContextId(), sfail, dpfail, dppass)); |
| } |
| |
| if (face == GLEnum.GL_BACK || face == GLEnum.GL_FRONT_AND_BACK) { |
| transforms.addAll( |
| transformsForGlStencilOpBack(msg.getContextId(), sfail, dpfail, dppass)); |
| } |
| |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlDepthFunc(GLMessage msg) { |
| // void glDepthFunc(GLenum func); |
| GLEnum func = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| |
| IStateTransform transform = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.DEPTH_FUNC), |
| func); |
| return Collections.singletonList(transform); |
| } |
| |
| private static IStateTransform transformForGlEquationRGB(int contextId, GLEnum mode) { |
| return new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.BLEND, |
| GLStateType.BLEND_EQUATION_RGB), |
| mode); |
| } |
| |
| private static IStateTransform transformForGlEquationAlpha(int contextId, GLEnum mode) { |
| return new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.BLEND, |
| GLStateType.BLEND_EQUATION_ALPHA), |
| mode); |
| } |
| |
| private static List<IStateTransform> transformsForGlBlendEquationSeparate(GLMessage msg) { |
| // void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); |
| GLEnum rgb = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| GLEnum alpha = GLEnum.valueOf(msg.getArgs(1).getIntValue(0)); |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.add(transformForGlEquationRGB(msg.getContextId(), rgb)); |
| transforms.add(transformForGlEquationAlpha(msg.getContextId(), alpha)); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlBlendEquation(GLMessage msg) { |
| // void glBlendEquation(GLenum mode); |
| GLEnum mode = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.add(transformForGlEquationRGB(msg.getContextId(), mode)); |
| transforms.add(transformForGlEquationAlpha(msg.getContextId(), mode)); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlBlendFuncSrcDst(boolean src, |
| int contextId, GLEnum rgb, GLEnum alpha) { |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| |
| GLStateType rgbAccessor = GLStateType.BLEND_DST_RGB; |
| GLStateType alphaAccessor = GLStateType.BLEND_DST_ALPHA; |
| if (src) { |
| rgbAccessor = GLStateType.BLEND_SRC_RGB; |
| alphaAccessor = GLStateType.BLEND_SRC_ALPHA; |
| } |
| |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.BLEND, |
| rgbAccessor), |
| rgb)); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.PIXEL_OPERATIONS, |
| GLStateType.BLEND, |
| alphaAccessor), |
| alpha)); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlBlendFuncSeparate(GLMessage msg) { |
| // void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) |
| GLEnum srcRgb = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| GLEnum dstRgb = GLEnum.valueOf(msg.getArgs(1).getIntValue(0)); |
| GLEnum srcAlpha = GLEnum.valueOf(msg.getArgs(2).getIntValue(0)); |
| GLEnum dstAlpha = GLEnum.valueOf(msg.getArgs(3).getIntValue(0)); |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.addAll(transformsForGlBlendFuncSrcDst(true, |
| msg.getContextId(), srcRgb, srcAlpha)); |
| transforms.addAll(transformsForGlBlendFuncSrcDst(false, |
| msg.getContextId(), dstRgb, dstAlpha)); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlBlendFunc(GLMessage msg) { |
| // void glBlendFunc(GLenum sfactor, GLenum dfactor); |
| GLEnum sfactor = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| GLEnum dfactor = GLEnum.valueOf(msg.getArgs(1).getIntValue(0)); |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.addAll(transformsForGlBlendFuncSrcDst(true, |
| msg.getContextId(), sfactor, sfactor)); |
| transforms.addAll(transformsForGlBlendFuncSrcDst(false, |
| msg.getContextId(), dfactor, dfactor)); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlPixelStorei(GLMessage msg) { |
| // void glPixelStorei(GLenum pname, GLint param); |
| GLEnum pname = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| Integer param = Integer.valueOf(msg.getArgs(1).getIntValue(0)); |
| |
| IStateTransform transform; |
| if (pname == GLEnum.GL_PACK_ALIGNMENT) { |
| transform = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PIXEL_PACKING, |
| GLStateType.PACK_ALIGNMENT), |
| param); |
| } else { |
| transform = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PIXEL_PACKING, |
| GLStateType.UNPACK_ALIGNMENT), |
| param); |
| } |
| |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlViewport(GLMessage msg) { |
| // void glViewport( GLint x, GLint y, GLsizei width, GLsizei height); |
| int x = msg.getArgs(0).getIntValue(0); |
| int y = msg.getArgs(1).getIntValue(0); |
| int w = msg.getArgs(2).getIntValue(0); |
| int h = msg.getArgs(3).getIntValue(0); |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.TRANSFORMATION_STATE, |
| GLStateType.VIEWPORT, |
| GLStateType.VIEWPORT_X), |
| Integer.valueOf(x))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.TRANSFORMATION_STATE, |
| GLStateType.VIEWPORT, |
| GLStateType.VIEWPORT_Y), |
| Integer.valueOf(y))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.TRANSFORMATION_STATE, |
| GLStateType.VIEWPORT, |
| GLStateType.VIEWPORT_WIDTH), |
| Integer.valueOf(w))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.TRANSFORMATION_STATE, |
| GLStateType.VIEWPORT, |
| GLStateType.VIEWPORT_HEIGHT), |
| Integer.valueOf(h))); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlDepthRangef(GLMessage msg) { |
| // void glDepthRangef(GLclampf nearVal, GLclampf farVal); |
| float near = msg.getArgs(0).getFloatValue(0); |
| float far = msg.getArgs(1).getFloatValue(0); |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.TRANSFORMATION_STATE, |
| GLStateType.DEPTH_RANGE, |
| GLStateType.DEPTH_RANGE_NEAR), |
| Float.valueOf(near))); |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.TRANSFORMATION_STATE, |
| GLStateType.DEPTH_RANGE, |
| GLStateType.DEPTH_RANGE_FAR), |
| Float.valueOf(far))); |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlGenTextures(GLMessage msg) { |
| // void glGenTextures(GLsizei n, GLuint *textures); |
| int n = msg.getArgs(0).getIntValue(0); |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| for (int i = 0; i < n; i++) { |
| int texture = msg.getArgs(1).getIntValue(i); |
| transforms.add(new SparseArrayElementAddTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.TEXTURE_STATE, |
| GLStateType.TEXTURES), |
| texture)); |
| } |
| |
| return transforms; |
| } |
| |
| /** |
| * Obtain a list of transforms that will reset any existing texture units |
| * that are bound to provided texture. |
| * @param contextId context to operate on |
| * @param texture texture that should be unbound |
| */ |
| private static List<IStateTransform> transformsToResetBoundTextureUnits(int contextId, |
| int texture) { |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>( |
| GLState.TEXTURE_UNIT_COUNT); |
| |
| for (int i = 0; i < GLState.TEXTURE_UNIT_COUNT; i++) { |
| transforms.add(new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(contextId, |
| GLStateType.TEXTURE_STATE, |
| GLStateType.TEXTURE_UNITS, |
| Integer.valueOf(i), |
| GLStateType.TEXTURE_BINDING_2D), |
| Integer.valueOf(0), /* reset binding to texture 0 */ |
| Predicates.matchesInteger(texture) /* only if currently bound to @texture */ )); |
| } |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlDeleteTextures(GLMessage msg) { |
| // void glDeleteTextures(GLsizei n, const GLuint * textures); |
| int n = msg.getArgs(0).getIntValue(0); |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(n); |
| for (int i = 0; i < n; i++) { |
| int texture = msg.getArgs(1).getIntValue(i); |
| transforms.add(new SparseArrayElementRemoveTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.TEXTURE_STATE, |
| GLStateType.TEXTURES), |
| texture)); |
| transforms.addAll(transformsToResetBoundTextureUnits(msg.getContextId(), texture)); |
| } |
| |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlActiveTexture(GLMessage msg) { |
| // void glActiveTexture(GLenum texture); |
| GLEnum texture = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| Integer textureIndex = Integer.valueOf((int)(texture.value - GLEnum.GL_TEXTURE0.value)); |
| IStateTransform transform = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.TEXTURE_STATE, |
| GLStateType.ACTIVE_TEXTURE_UNIT), |
| textureIndex); |
| return Collections.singletonList(transform); |
| } |
| |
| private static GLStateType getTextureUnitTargetName(GLEnum target) { |
| if (target == GLEnum.GL_TEXTURE_CUBE_MAP) { |
| return GLStateType.TEXTURE_BINDING_CUBE_MAP; |
| } else if (target == GLEnum.GL_TEXTURE_EXTERNAL) { |
| // added by OES_EGL_image_external |
| return GLStateType.TEXTURE_BINDING_EXTERNAL; |
| } else { |
| return GLStateType.TEXTURE_BINDING_2D; |
| } |
| } |
| |
| private static GLStateType getTextureTargetName(GLEnum pname) { |
| switch (pname) { |
| case GL_TEXTURE_MIN_FILTER: |
| return GLStateType.TEXTURE_MIN_FILTER; |
| case GL_TEXTURE_MAG_FILTER: |
| return GLStateType.TEXTURE_MAG_FILTER; |
| case GL_TEXTURE_WRAP_S: |
| return GLStateType.TEXTURE_WRAP_S; |
| case GL_TEXTURE_WRAP_T: |
| return GLStateType.TEXTURE_WRAP_T; |
| } |
| |
| assert false : "glTexParameter's pname argument does not support provided value."; |
| return GLStateType.TEXTURE_MIN_FILTER; |
| } |
| |
| private static List<IStateTransform> transformsForGlBindTexture(GLMessage msg) { |
| // void glBindTexture(GLenum target, GLuint texture); |
| GLEnum target = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| Integer texture = Integer.valueOf(msg.getArgs(1).getIntValue(0)); |
| |
| IStateTransform transform = new PropertyChangeTransform( |
| new TextureUnitPropertyAccessor(msg.getContextId(), |
| getTextureUnitTargetName(target)), |
| texture); |
| return Collections.singletonList(transform); |
| } |
| |
| /** |
| * Utility function used by both {@link #transformsForGlTexImage2D(GLMessage) and |
| * {@link #transformsForGlTexSubImage2D(GLMessage)}. |
| */ |
| private static List<IStateTransform> transformsForGlTexImage(GLMessage msg, int widthArgIndex, |
| int heightArgIndex, int xOffsetIndex, int yOffsetIndex) { |
| GLEnum target = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| int level = msg.getArgs(1).getIntValue(0); |
| Integer width = Integer.valueOf(msg.getArgs(widthArgIndex).getIntValue(0)); |
| Integer height = Integer.valueOf(msg.getArgs(heightArgIndex).getIntValue(0)); |
| GLEnum format = GLEnum.valueOf(msg.getArgs(6).getIntValue(0)); |
| GLEnum type = GLEnum.valueOf(msg.getArgs(7).getIntValue(0)); |
| |
| List<IStateTransform> transforms = new ArrayList<IStateTransform>(); |
| transforms.add(new PropertyChangeTransform( |
| new TexturePropertyAccessor(msg.getContextId(), |
| getTextureUnitTargetName(target), |
| level, |
| GLStateType.TEXTURE_WIDTH), |
| width)); |
| transforms.add(new PropertyChangeTransform( |
| new TexturePropertyAccessor(msg.getContextId(), |
| getTextureUnitTargetName(target), |
| level, |
| GLStateType.TEXTURE_HEIGHT), |
| height)); |
| transforms.add(new PropertyChangeTransform( |
| new TexturePropertyAccessor(msg.getContextId(), |
| getTextureUnitTargetName(target), |
| level, |
| GLStateType.TEXTURE_FORMAT), |
| format)); |
| transforms.add(new PropertyChangeTransform( |
| new TexturePropertyAccessor(msg.getContextId(), |
| getTextureUnitTargetName(target), |
| level, |
| GLStateType.TEXTURE_IMAGE_TYPE), |
| type)); |
| |
| // if texture data is available, extract and store it in the cache folder |
| File f = null; |
| if (msg.getArgs(8).getIsArray()) { |
| ByteString data = msg.getArgs(8).getRawBytes(0); |
| f = FileUtils.createTempFile(TEXTURE_DATA_FILE_PREFIX, TEXTURE_DATA_FILE_SUFFIX); |
| try { |
| Files.write(data.toByteArray(), f); |
| } catch (IOException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| int xOffset = 0; |
| int yOffset = 0; |
| |
| if (xOffsetIndex >= 0) { |
| xOffset = msg.getArgs(xOffsetIndex).getIntValue(0); |
| } |
| |
| if (yOffsetIndex >= 0) { |
| yOffset = msg.getArgs(yOffsetIndex).getIntValue(0); |
| } |
| |
| transforms.add(new TexImageTransform( |
| new TexturePropertyAccessor(msg.getContextId(), |
| getTextureUnitTargetName(target), |
| level, |
| GLStateType.TEXTURE_IMAGE), |
| f, format, type, xOffset, yOffset, width, height)); |
| |
| return transforms; |
| } |
| |
| private static List<IStateTransform> transformsForGlTexImage2D(GLMessage msg) { |
| // void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, |
| // GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *data); |
| return transformsForGlTexImage(msg, 3, 4, -1, -1); |
| } |
| |
| private static List<IStateTransform> transformsForGlTexSubImage2D(GLMessage msg) { |
| // void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, |
| // GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *data); |
| return transformsForGlTexImage(msg, 4, 5, 2, 3); |
| } |
| |
| private static List<IStateTransform> transformsForGlTexParameter(GLMessage msg) { |
| // void glTexParameteri(GLenum target, GLenum pname, GLint param); |
| GLEnum target = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| GLEnum pname = GLEnum.valueOf(msg.getArgs(1).getIntValue(0)); |
| GLEnum pvalue = GLEnum.valueOf(msg.getArgs(2).getIntValue(0)); |
| |
| if (sTexParameterPnameValues == null) { |
| GLEnum[] pnameValues = new GLEnum[] { |
| GLEnum.GL_TEXTURE_BASE_LEVEL, |
| GLEnum.GL_TEXTURE_COMPARE_FUNC, |
| GLEnum.GL_TEXTURE_COMPARE_MODE, |
| GLEnum.GL_TEXTURE_MIN_FILTER, |
| GLEnum.GL_TEXTURE_MAG_FILTER, |
| GLEnum.GL_TEXTURE_MIN_LOD, |
| GLEnum.GL_TEXTURE_MAX_LOD, |
| GLEnum.GL_TEXTURE_MAX_LEVEL, |
| GLEnum.GL_TEXTURE_SWIZZLE_R, |
| GLEnum.GL_TEXTURE_SWIZZLE_G, |
| GLEnum.GL_TEXTURE_SWIZZLE_B, |
| GLEnum.GL_TEXTURE_SWIZZLE_A, |
| GLEnum.GL_TEXTURE_WRAP_S, |
| GLEnum.GL_TEXTURE_WRAP_T, |
| GLEnum.GL_TEXTURE_WRAP_R |
| }; |
| sTexParameterPnameValues = EnumSet.copyOf(Arrays.asList(pnameValues)); |
| } |
| |
| if (!sTexParameterPnameValues.contains(pname)) { |
| throw new IllegalArgumentException( |
| String.format("Unsupported parameter (%s) for glTexParameter()", pname)); |
| } |
| |
| IStateTransform transform = new PropertyChangeTransform( |
| new TexturePropertyAccessor(msg.getContextId(), |
| getTextureUnitTargetName(target), |
| getTextureTargetName(pname)), |
| pvalue); |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlCreateProgram(GLMessage msg) { |
| // GLuint glCreateProgram(void); |
| int program = msg.getReturnValue().getIntValue(0); |
| |
| IStateTransform transform = new SparseArrayElementAddTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PROGRAM_STATE, |
| GLStateType.PROGRAMS), |
| program); |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlUseProgram(GLMessage msg) { |
| // void glUseProgram(GLuint program); |
| Integer program = Integer.valueOf(msg.getArgs(0).getIntValue(0)); |
| |
| IStateTransform transform = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PROGRAM_STATE, |
| GLStateType.CURRENT_PROGRAM), |
| program); |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlAttachShader(GLMessage msg) { |
| // void glAttachShader(GLuint program, GLuint shader); |
| int program = msg.getArgs(0).getIntValue(0); |
| int shader = msg.getArgs(1).getIntValue(0); |
| |
| IStateTransform transform = new SparseArrayElementAddTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PROGRAM_STATE, |
| GLStateType.PROGRAMS, |
| Integer.valueOf(program), |
| GLStateType.ATTACHED_SHADERS), |
| Integer.valueOf(shader)); |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlDetachShader(GLMessage msg) { |
| // void glDetachShader(GLuint program, GLuint shader); |
| int program = msg.getArgs(0).getIntValue(0); |
| int shader = msg.getArgs(1).getIntValue(0); |
| |
| IStateTransform transform = new SparseArrayElementRemoveTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PROGRAM_STATE, |
| GLStateType.PROGRAMS, |
| Integer.valueOf(program), |
| GLStateType.ATTACHED_SHADERS), |
| Integer.valueOf(shader)); |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlGetActiveAttribOrUniform( |
| GLMessage msg, boolean isAttrib) { |
| // void glGetActive[Attrib|Uniform](GLuint program, GLuint index, GLsizei bufsize, |
| // GLsizei* length, GLint* size, GLenum* type, GLchar* name); |
| int program = msg.getArgs(0).getIntValue(0); |
| int size = msg.getArgs(4).getIntValue(0); |
| GLEnum type = GLEnum.valueOf(msg.getArgs(5).getIntValue(0)); |
| String name = msg.getArgs(6).getCharValue(0).toStringUtf8(); |
| |
| // The 2nd argument (index) does not give the correct location of the |
| // attribute/uniform in device. The actual location is obtained from |
| // the getAttribLocation or getUniformLocation calls. The trace library |
| // appends this value as an additional last argument to this call. |
| int location = msg.getArgs(7).getIntValue(0); |
| |
| GLStateType activeInput; |
| GLStateType inputName; |
| GLStateType inputType; |
| GLStateType inputSize; |
| |
| if (isAttrib) { |
| activeInput = GLStateType.ACTIVE_ATTRIBUTES; |
| inputName = GLStateType.ATTRIBUTE_NAME; |
| inputType = GLStateType.ATTRIBUTE_TYPE; |
| inputSize = GLStateType.ATTRIBUTE_SIZE; |
| } else { |
| activeInput = GLStateType.ACTIVE_UNIFORMS; |
| inputName = GLStateType.UNIFORM_NAME; |
| inputType = GLStateType.UNIFORM_TYPE; |
| inputSize = GLStateType.UNIFORM_SIZE; |
| } |
| |
| IStateTransform addAttribute = new SparseArrayElementAddTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PROGRAM_STATE, |
| GLStateType.PROGRAMS, |
| Integer.valueOf(program), |
| activeInput), |
| Integer.valueOf(location)); |
| IStateTransform setAttributeName = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PROGRAM_STATE, |
| GLStateType.PROGRAMS, |
| Integer.valueOf(program), |
| activeInput, |
| Integer.valueOf(location), |
| inputName), |
| name); |
| IStateTransform setAttributeType = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PROGRAM_STATE, |
| GLStateType.PROGRAMS, |
| Integer.valueOf(program), |
| activeInput, |
| Integer.valueOf(location), |
| inputType), |
| type); |
| IStateTransform setAttributeSize = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.PROGRAM_STATE, |
| GLStateType.PROGRAMS, |
| Integer.valueOf(program), |
| activeInput, |
| Integer.valueOf(location), |
| inputSize), |
| Integer.valueOf(size)); |
| return Arrays.asList(addAttribute, setAttributeName, setAttributeType, setAttributeSize); |
| } |
| |
| private static List<IStateTransform> transformsForGlGetActiveAttrib(GLMessage msg) { |
| return transformsForGlGetActiveAttribOrUniform(msg, true); |
| } |
| |
| private static List<IStateTransform> transformsForGlGetActiveUniform(GLMessage msg) { |
| return transformsForGlGetActiveAttribOrUniform(msg, false); |
| } |
| |
| private static List<IStateTransform> transformsForGlUniformMatrix(GLMessage msg) { |
| // void glUniformMatrix[2|3|4]fv(GLint location, GLsizei count, GLboolean transpose, |
| // const GLfloat *value); |
| int location = msg.getArgs(0).getIntValue(0); |
| List<Float> uniforms = msg.getArgs(3).getFloatValueList(); |
| |
| IStateTransform setValues = new PropertyChangeTransform( |
| new CurrentProgramPropertyAccessor(msg.getContextId(), |
| GLStateType.ACTIVE_UNIFORMS, |
| location, |
| GLStateType.UNIFORM_VALUE), |
| uniforms); |
| |
| return Collections.singletonList(setValues); |
| } |
| |
| private static List<IStateTransform> transformsForGlUniformv(GLMessage msg, boolean isFloats) { |
| // void glUniform1fv(GLint location, GLsizei count, const GLfloat *value); |
| int location = msg.getArgs(0).getIntValue(0); |
| List<?> uniforms; |
| if (isFloats) { |
| uniforms = msg.getArgs(2).getFloatValueList(); |
| } else { |
| uniforms = msg.getArgs(2).getIntValueList(); |
| } |
| |
| IStateTransform setValues = new PropertyChangeTransform( |
| new CurrentProgramPropertyAccessor(msg.getContextId(), |
| GLStateType.ACTIVE_UNIFORMS, |
| location, |
| GLStateType.UNIFORM_VALUE), |
| uniforms); |
| |
| return Collections.singletonList(setValues); |
| } |
| |
| private static List<IStateTransform> transformsForGlUniform(GLMessage msg, boolean isFloats) { |
| // void glUniform1f(GLint location, GLfloat v0); |
| // void glUniform2f(GLint location, GLfloat v0, GLfloat v1); |
| // .. 3f |
| // .. 4f |
| // void glUniform1i(GLint location, GLfloat v0); |
| // void glUniform2i(GLint location, GLfloat v0, GLfloat v1); |
| // .. 3i |
| // .. 4i |
| |
| int location = msg.getArgs(0).getIntValue(0); |
| if (location < 0) { |
| throw new IllegalArgumentException("Argument location cannot be less than 0."); |
| } |
| List<?> uniforms; |
| if (isFloats) { |
| List<Float> args = new ArrayList<Float>(msg.getArgsCount() - 1); |
| for (int i = 1; i < msg.getArgsCount(); i++) { |
| args.add(Float.valueOf(msg.getArgs(1).getFloatValue(0))); |
| } |
| uniforms = args; |
| } else { |
| List<Integer> args = new ArrayList<Integer>(msg.getArgsCount() - 1); |
| for (int i = 1; i < msg.getArgsCount(); i++) { |
| args.add(Integer.valueOf(msg.getArgs(1).getIntValue(0))); |
| } |
| uniforms = args; |
| } |
| |
| IStateTransform setValues = new PropertyChangeTransform( |
| new CurrentProgramPropertyAccessor(msg.getContextId(), |
| GLStateType.ACTIVE_UNIFORMS, |
| location, |
| GLStateType.UNIFORM_VALUE), |
| uniforms); |
| |
| return Collections.singletonList(setValues); |
| } |
| |
| private static List<IStateTransform> transformsForGlCreateShader(GLMessage msg) { |
| // GLuint glCreateShader(GLenum shaderType); |
| GLEnum shaderType = GLEnum.valueOf(msg.getArgs(0).getIntValue(0)); |
| int shader = msg.getReturnValue().getIntValue(0); |
| |
| IStateTransform addShader = new SparseArrayElementAddTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.SHADERS), |
| shader); |
| IStateTransform setShaderType = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.SHADERS, |
| Integer.valueOf(shader), |
| GLStateType.SHADER_TYPE), |
| shaderType); |
| return Arrays.asList(addShader, setShaderType); |
| } |
| |
| private static List<IStateTransform> transformsForGlDeleteShader(GLMessage msg) { |
| // void glDeleteShader(GLuint shader); |
| int shader = msg.getArgs(0).getIntValue(0); |
| |
| IStateTransform transform = new SparseArrayElementRemoveTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.SHADERS), |
| shader); |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForGlShaderSource(GLMessage msg) { |
| // void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, |
| // const GLint *length); |
| // This message is patched up on the device to return a single string as opposed to a |
| // list of strings |
| int shader = msg.getArgs(0).getIntValue(0); |
| String src = msg.getArgs(2).getCharValue(0).toStringUtf8(); |
| |
| IStateTransform transform = new PropertyChangeTransform( |
| GLPropertyAccessor.makeAccessor(msg.getContextId(), |
| GLStateType.SHADERS, |
| Integer.valueOf(shader), |
| GLStateType.SHADER_SOURCE), |
| src); |
| return Collections.singletonList(transform); |
| } |
| |
| private static List<IStateTransform> transformsForEglCreateContext(GLMessage msg) { |
| // void eglCreateContext(int version, int context); |
| int version = msg.getArgs(0).getIntValue(0); |
| IGLProperty glState = null; |
| if (version == 0) { |
| glState = GLState.createDefaultES1State(); |
| } else { |
| glState = GLState.createDefaultES2State(); |
| } |
| IStateTransform transform = new ListElementAddTransform(null, glState); |
| return Collections.singletonList(transform); |
| } |
| } |