/*
 * 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);
    }
}
