10469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#!/usr/bin/env python
20469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#
30469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy# Copyright (C) 2011 Google Inc.
40469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#
50469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy# Licensed under the Apache License, Version 2.0 (the "License");
60469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy# you may not use this file except in compliance with the License.
70469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy# You may obtain a copy of the License at
80469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#
90469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#      http://www.apache.org/licenses/LICENSE-2.0
100469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#
110469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy# Unless required by applicable law or agreed to in writing, software
120469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy# distributed under the License is distributed on an "AS IS" BASIS,
130469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
140469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy# See the License for the specific language governing permissions and
150469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy# limitations under the License.
160469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#
170469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy# ABOUT
180469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#   This script is used to generate the trace implementations of all
190469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#   OpenGL calls. When executed, it reads the specs for the OpenGL calls
200469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#   from the files GLES2/gl2_api.in, GLES2/gl2ext_api.in, GLES_CM/gl_api.in,
213703f7f014846b8bf83e08a8bf25450dd0dcd7afJesse Hall#   and GLES_CM/glext_api.in, and generates trace versions for all the
220469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#   defined functions.
230469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#
240469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy# PREREQUISITES
250469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#   To generate C++ files, this script uses the 'pyratemp' template
260469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#   module. The only reason to use pyratemp is that it is extremly
270469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#   simple to install:
2839177b4103f7c8f1f9903b3f52e83048fc066235Siva Velusamy#   $ wget http://www.simple-is-better.org/template/pyratemp-0.3.2.tgz
2939177b4103f7c8f1f9903b3f52e83048fc066235Siva Velusamy#   Extract and put the pyratemp.py file in the GLES_trace/tools folder,
3039177b4103f7c8f1f9903b3f52e83048fc066235Siva Velusamy#   or update PYTHONPATH to point to wherever it was downloaded.
310469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#
320469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy# USAGE
3331272606149d83437a097800074b21e9e6a205adMathias Agopian#   $ cd GLES_trace       - run the program from GLES2_trace folder
340469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#   $ ./tools/genapi.py   - generates a .cpp and .h file
350469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#   $ mv *.cpp *.h src/   - move the generated files into the src folder
360469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
370469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamyimport sys
380469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamyimport re
390469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamyimport pyratemp
400469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
410469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy# Constants corresponding to the protobuf DataType.Type
420469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamyclass DataType:
430469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    def __init__(self, name):
440469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        self.name = name
450469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
460469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    def __str__(self):
4739177b4103f7c8f1f9903b3f52e83048fc066235Siva Velusamy        if self.name == "pointer":  # pointers map to the INT64 DataType
4839177b4103f7c8f1f9903b3f52e83048fc066235Siva Velusamy            return "INT64"
490469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        return self.name.upper()
500469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
510469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    def getProtobufCall(self):
520469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        if self.name == "void":
530469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            raise ValueError("Attempt to set void value")
540469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        elif self.name == "char" or self.name == "byte" \
5539177b4103f7c8f1f9903b3f52e83048fc066235Siva Velusamy                or self.name == "enum":
560469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            return "add_intvalue((int)"
5739177b4103f7c8f1f9903b3f52e83048fc066235Siva Velusamy        elif self.name == "pointer":
5839177b4103f7c8f1f9903b3f52e83048fc066235Siva Velusamy            return "add_int64value((uintptr_t)"
590469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        elif self.name == "int":
600469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            return "add_intvalue("
610469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        elif self.name == "float":
620469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            return "add_floatvalue("
630469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        elif self.name == "bool":
640469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            return "add_boolvalue("
654774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall        elif self.name == "int64":
664774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall            return "add_int64value("
670469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        else:
680469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            raise ValueError("Unknown value type %s" % self.name)
690469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
700469dd6d55fa331bfd7de9431da98b6340d82271Siva VelusamyDataType.VOID = DataType("void")
710469dd6d55fa331bfd7de9431da98b6340d82271Siva VelusamyDataType.CHAR = DataType("char")
720469dd6d55fa331bfd7de9431da98b6340d82271Siva VelusamyDataType.BYTE = DataType("byte")
730469dd6d55fa331bfd7de9431da98b6340d82271Siva VelusamyDataType.ENUM = DataType("enum")
740469dd6d55fa331bfd7de9431da98b6340d82271Siva VelusamyDataType.BOOL = DataType("bool")
750469dd6d55fa331bfd7de9431da98b6340d82271Siva VelusamyDataType.INT = DataType("int")
760469dd6d55fa331bfd7de9431da98b6340d82271Siva VelusamyDataType.FLOAT = DataType("float")
770469dd6d55fa331bfd7de9431da98b6340d82271Siva VelusamyDataType.POINTER = DataType("pointer")
784774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse HallDataType.INT64 = DataType("int64")
790469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
800469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy# mapping of GL types to protobuf DataType
814774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse HallGLPROTOBUF_TYPE_MAP = {
820469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLvoid":DataType.VOID,
830469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "void":DataType.VOID,
840469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLchar":DataType.CHAR,
850469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLenum":DataType.ENUM,
860469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLboolean":DataType.BOOL,
870469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLbitfield":DataType.INT,
880469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLbyte":DataType.BYTE,
890469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLshort":DataType.INT,
900469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLint":DataType.INT,
910469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "int":DataType.INT,
920469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLsizei":DataType.INT,
930469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLubyte":DataType.BYTE,
940469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLushort":DataType.INT,
950469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLuint":DataType.INT,
960469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLfloat":DataType.FLOAT,
970469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLclampf":DataType.FLOAT,
980469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLfixed":DataType.INT,
990469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLclampx":DataType.INT,
1009801142afbe3d906259b634ef3bc8bebdafe0083Siva Velusamy    "GLsizeiptr":DataType.INT,
1019801142afbe3d906259b634ef3bc8bebdafe0083Siva Velusamy    "GLintptr":DataType.INT,
1020469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    "GLeglImageOES":DataType.POINTER,
1034774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall    "GLint64":DataType.INT64,
1044774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall    "GLuint64":DataType.INT64,
1054774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall    "GLsync":DataType.POINTER,
1063703f7f014846b8bf83e08a8bf25450dd0dcd7afJesse Hall    "GLDEBUGPROCKHR":DataType.POINTER,
1070469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
1080469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1090469dd6d55fa331bfd7de9431da98b6340d82271Siva VelusamyAPI_SPECS = [
1100469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    ('GL2','../GLES2/gl2_api.in'),
1110469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    ('GL2Ext','../GLES2/gl2ext_api.in'),
1120469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    ('GL1','../GLES_CM/gl_api.in'),
1130469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    ('GL1Ext','../GLES_CM/glext_api.in'),
1140469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy]
1150469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
11656ac6ff9bdc3c117e820c5a361ab45049c8b03f8Siva VelusamyHEADER_LICENSE = """/*
1170469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * Copyright 2011, The Android Open Source Project
1180469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy *
1190469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * Licensed under the Apache License, Version 2.0 (the "License");
1200469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * you may not use this file except in compliance with the License.
1210469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * You may obtain a copy of the License at
1220469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy *
1230469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy *     http://www.apache.org/licenses/LICENSE-2.0
1240469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy *
1250469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * Unless required by applicable law or agreed to in writing, software
1260469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * distributed under the License is distributed on an "AS IS" BASIS,
1270469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1280469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * See the License for the specific language governing permissions and
1290469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * limitations under the License.
1300469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy *
1310469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * THIS FILE WAS GENERATED BY A SCRIPT. DO NOT EDIT.
1320469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy */
13356ac6ff9bdc3c117e820c5a361ab45049c8b03f8Siva Velusamy"""
1340469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
13556ac6ff9bdc3c117e820c5a361ab45049c8b03f8Siva VelusamyHEADER_INCLUDES = """
1360469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include <cutils/log.h>
13756ac6ff9bdc3c117e820c5a361ab45049c8b03f8Siva Velusamy#include <utils/Timers.h>
1380469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1390469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include "gltrace.pb.h"
1400469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include "gltrace_context.h"
1410469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include "gltrace_fixup.h"
1420469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include "gltrace_transport.h"
14356ac6ff9bdc3c117e820c5a361ab45049c8b03f8Siva Velusamy"""
1440469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
14556ac6ff9bdc3c117e820c5a361ab45049c8b03f8Siva VelusamyHEADER_NAMESPACE_START = """
1460469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamynamespace android {
1470469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamynamespace gltrace {
1480469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy"""
1490469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1500469dd6d55fa331bfd7de9431da98b6340d82271Siva VelusamyFOOTER_TEXT = """
1510469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}; // namespace gltrace
1520469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}; // namespace android
1530469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy"""
1540469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1550469dd6d55fa331bfd7de9431da98b6340d82271Siva VelusamyTRACE_CALL_TEMPLATE = pyratemp.Template(
1560469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy"""$!retType!$ GLTrace_$!func!$($!inputArgList!$) {
1570469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    GLMessage glmsg;
1580469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    GLTraceContext *glContext = getGLTraceContext();
1590469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1600469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    glmsg.set_function(GLMessage::$!func!$);
1610469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy<!--(if len(parsedArgs) > 0)-->
1620469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    <!--(for argname, argtype in parsedArgs)-->
1630469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1640469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    // copy argument $!argname!$
1650469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    GLMessage_DataType *arg_$!argname!$ = glmsg.add_args();
1660469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    arg_$!argname!$->set_isarray(false);
1670469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    arg_$!argname!$->set_type(GLMessage::DataType::$!argtype!$);
1680469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    arg_$!argname!$->$!argtype.getProtobufCall()!$$!argname!$);
1690469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    <!--(end)-->
1700469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy<!--(end)-->
1710469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1720469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    // call function
17305df4504e57657994a89e424b6881ee26d0f313cSiva Velusamy    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
17405df4504e57657994a89e424b6881ee26d0f313cSiva Velusamy    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
1750469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy<!--(if retType != "void")-->
1760469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    $!retType!$ retValue = glContext->hooks->gl.$!callsite!$;
1770469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy<!--(else)-->
1780469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    glContext->hooks->gl.$!callsite!$;
1790469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy<!--(end)-->
18005df4504e57657994a89e424b6881ee26d0f313cSiva Velusamy    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
18105df4504e57657994a89e424b6881ee26d0f313cSiva Velusamy    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
1820469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy<!--(if retType != "void")-->
1830469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1840469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    // set return value
1850469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
1860469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    rt->set_isarray(false);
1870469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    rt->set_type(GLMessage::DataType::$!retDataType!$);
1880469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    rt->$!retDataType.getProtobufCall()!$retValue);
1890469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy<!--(end)-->
1900469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1919801142afbe3d906259b634ef3bc8bebdafe0083Siva Velusamy    void *pointerArgs[] = {
1929801142afbe3d906259b634ef3bc8bebdafe0083Siva Velusamy<!--(for argname, argtype in parsedArgs)-->
1939801142afbe3d906259b634ef3bc8bebdafe0083Siva Velusamy    <!--(if argtype == DataType.POINTER)-->
1949801142afbe3d906259b634ef3bc8bebdafe0083Siva Velusamy        (void *) $!argname!$,
1959801142afbe3d906259b634ef3bc8bebdafe0083Siva Velusamy    <!--(end)-->
1969801142afbe3d906259b634ef3bc8bebdafe0083Siva Velusamy<!--(end)-->
1979801142afbe3d906259b634ef3bc8bebdafe0083Siva Velusamy<!--(if retDataType == DataType.POINTER)-->
1989801142afbe3d906259b634ef3bc8bebdafe0083Siva Velusamy        (void *) retValue,
1999801142afbe3d906259b634ef3bc8bebdafe0083Siva Velusamy<!--(end)-->
2009801142afbe3d906259b634ef3bc8bebdafe0083Siva Velusamy    };
2019801142afbe3d906259b634ef3bc8bebdafe0083Siva Velusamy
20205df4504e57657994a89e424b6881ee26d0f313cSiva Velusamy    fixupGLMessage(glContext, wallStartTime, wallEndTime,
20305df4504e57657994a89e424b6881ee26d0f313cSiva Velusamy                              threadStartTime, threadEndTime,
2049801142afbe3d906259b634ef3bc8bebdafe0083Siva Velusamy                              &glmsg, pointerArgs);
20593a826f78f6313db791e6fc880439189897651b3Siva Velusamy    glContext->traceGLMessage(&glmsg);
2060469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy<!--(if retType != "void")-->
2070469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2080469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    return retValue;
2090469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy<!--(end)-->
2100469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
2110469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy""")
2120469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2130469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamydef getDataTypeFromKw(kw):
2140469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    """ Get the data type given declaration.
2150469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    All pointer declarations are of type DataType.POINTER
2160469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2170469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    e.g.: GLvoid -> DataType.VOID"""
2180469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2190469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    if kw.count('*') > 0:
2200469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        return DataType.POINTER
2214774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall    return GLPROTOBUF_TYPE_MAP.get(kw)
2220469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2230469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamydef getNameTypePair(decl):
2240469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    """ Split declaration of a variable to a tuple of (variable name, DataType).
2250469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    e.g. "const GLChar* varName" -> (varName, POINTER) """
2260469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    elements = decl.strip().split(' ')
2270469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    name = None
2280469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    if len(elements) > 1:
2290469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        name = " ".join(elements[-1:]).strip()      # last element is the name
2300469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        dataType = " ".join(elements[:-1]).strip()  # everything else is the data type
2310469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2320469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        # if name is a pointer (e.g. "*ptr"), then remove the "*" from the name
2330469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        # and add it to the data type
2343703f7f014846b8bf83e08a8bf25450dd0dcd7afJesse Hall        pointersInName = name.count("*")
2350469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        if pointersInName > 0:
2360469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            name = name.replace("*", "")
2370469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            dataType += "*" * pointersInName
2380469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2390469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        # if name is an array (e.g. "array[10]"), then remove the "[X]" from the name
2400469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        # and make the datatype to be a pointer
2410469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        arraysInName = name.count("[")
2420469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        if arraysInName > 0:
2430469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            name = name.split('[')[0]
2440469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            dataType += "*"
2450469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    else:
2460469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        dataType = elements[0]
2470469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    return (name, getDataTypeFromKw(dataType))
2480469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2490469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamydef parseArgs(arglist):
2500469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    """ Parse the argument list into a list of (var name, DataType) tuples """
2510469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    args = arglist.split(',')
2520469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    args = map(lambda x: x.strip(), args)    # remove unnecessary whitespaces
2530469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    argtypelist = map(getNameTypePair, args) # split arg into arg type and arg name
2540469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    if len(argtypelist) == 1:
2550469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        (name, argtype) = argtypelist[0]
2560469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        if argtype == DataType.VOID:
2570469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            return []
2580469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2590469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    return argtypelist
2600469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2610469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamyclass ApiCall(object):
2620469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    """An ApiCall models all information about a single OpenGL API"""
2630469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2640469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    # Regex to match API_ENTRY specification:
2650469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    #       e.g. void API_ENTRY(glActiveTexture)(GLenum texture) {
2660469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    # the regex uses a non greedy match (?) to match the first closing paren
2670469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    API_ENTRY_REGEX = "(.*)API_ENTRY\(.*?\)\((.*?)\)"
2680469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2690469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    # Regex to match CALL_GL_API specification:
2703703f7f014846b8bf83e08a8bf25450dd0dcd7afJesse Hall    #       e.g. CALL_GL_API(glCullFace, mode);
2710469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    #            CALL_GL_API_RETURN(glCreateProgram);
2720469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    CALL_GL_API_REGEX = "CALL_GL_API(_RETURN)?\((.*)\);"
2730469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2740469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    def __init__(self, prefix, apientry, callsite):
2750469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        """Construct an ApiCall from its specification.
2760469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2770469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        The specification is provided by the two arguments:
2780469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        prefix: prefix to use for function names
2790469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        defn: specification line containing API_ENTRY macro
2800469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy              e.g: void API_ENTRY(glActiveTexture)(GLenum texture) {
2810469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        callsite: specification line containing CALL_GL_API macro
2823703f7f014846b8bf83e08a8bf25450dd0dcd7afJesse Hall              e.g: CALL_GL_API(glActiveTexture, texture);
2830469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        """
2840469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        self.prefix = prefix
2850469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        self.ret = self.getReturnType(apientry)
2860469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        self.arglist = self.getArgList(apientry)
2870469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2880469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        # some functions (e.g. __glEGLImageTargetRenderbufferStorageOES), define their
2890469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        # names one way in the API_ENTRY and another way in the CALL_GL_API macros.
2900469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        # so self.func is reassigned based on what is there in the call site
2910469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        self.func = self.getFunc(callsite)
2920469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        self.callsite = self.getCallSite(callsite)
2930469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2940469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    def getReturnType(self, apientry):
2950469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        '''Extract the return type from the API_ENTRY specification'''
2960469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        m = re.search(self.API_ENTRY_REGEX, apientry)
2970469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        if not m:
2983703f7f014846b8bf83e08a8bf25450dd0dcd7afJesse Hall            raise ValueError("%s does not match API_ENTRY specification %s"
2990469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy                             % (apientry, self.API_ENTRY_REGEX))
3000469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3010469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        return m.group(1).strip()
3020469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3030469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    def getArgList(self, apientry):
3040469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        '''Extract the argument list from the API_ENTRY specification'''
3050469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        m = re.search(self.API_ENTRY_REGEX, apientry)
3060469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        if not m:
3073703f7f014846b8bf83e08a8bf25450dd0dcd7afJesse Hall            raise ValueError("%s does not match API_ENTRY specification %s"
3080469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy                             % (apientry, self.API_ENTRY_REGEX))
3090469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3100469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        return m.group(2).strip()
3110469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3120469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    def parseCallSite(self, callsite):
3130469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        m = re.search(self.CALL_GL_API_REGEX, callsite)
3140469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        if not m:
3150469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            raise ValueError("%s does not match CALL_GL_API specification (%s)"
3160469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy                             % (callsite, self.CALL_GL_API_REGEX))
3170469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3180469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        arglist = m.group(2)
3190469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        args = arglist.split(',')
3200469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        args = map(lambda x: x.strip(), args)
3210469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3220469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        return args
3230469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3240469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    def getCallSite(self, callsite):
3250469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        '''Extract the callsite from the CALL_GL_API specification'''
3260469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        args = self.parseCallSite(callsite)
3270469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        return "%s(%s)" % (args[0], ", ".join(args[1:]))
3280469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3290469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    def getFunc(self, callsite):
3300469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        '''Extract the function name from the CALL_GL_API specification'''
3310469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        args = self.parseCallSite(callsite)
3320469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        return args[0]
3330469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3340469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    def genDeclaration(self):
3350469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        return "%s GLTrace_%s(%s);" % (self.ret, self.func, self.arglist)
3360469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3370469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    def genCode(self):
3383703f7f014846b8bf83e08a8bf25450dd0dcd7afJesse Hall        return TRACE_CALL_TEMPLATE(func = self.func,
3390469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy                                   retType = self.ret,
3400469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy                                   retDataType = getDataTypeFromKw(self.ret),
3410469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy                                   inputArgList = self.arglist,
3420469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy                                   callsite = self.callsite,
3430469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy                                   parsedArgs = parseArgs(self.arglist),
3440469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy                                   DataType=DataType)
3450469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3460469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamydef getApis(apiEntryFile, prefix):
3470469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    '''Get a list of all ApiCalls in provided specification file'''
3480469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    lines = open(apiEntryFile).readlines()
3490469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3500469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    apis = []
3510469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    for i in range(0, len(lines)/3):
3520469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        apis.append(ApiCall(prefix, lines[i*3], lines[i*3+1]))
3530469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3540469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    return apis
3550469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3560469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamydef parseAllSpecs(specs):
3570469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    apis = []
3580469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    for name, specfile in specs:
3590469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        a = getApis(specfile, name)
3600469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        print 'Parsed %s APIs from %s, # of entries = %d' % (name, specfile, len(a))
3610469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        apis.extend(a)
3620469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    return apis
3630469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3640469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamydef removeDuplicates(apis):
3650469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    '''Remove all duplicate function entries.
3660469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3674774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall    The input list contains functions declared in GL1, GL2, and GL3 APIs.
3680469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    This will return a list that contains only the first function if there are
3690469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    multiple functions with the same name.'''
3700469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    uniqs = []
3710469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    funcs = set()
3720469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    for api in apis:
3730469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        if api.func not in funcs:
3740469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            uniqs.append(api)
3750469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            funcs.add(api.func)
3760469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3770469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    return uniqs
3780469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3790469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamydef genHeaders(apis, fname):
3800469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    lines = []
38156ac6ff9bdc3c117e820c5a361ab45049c8b03f8Siva Velusamy    lines.append(HEADER_LICENSE)
38256ac6ff9bdc3c117e820c5a361ab45049c8b03f8Siva Velusamy    lines.append(HEADER_NAMESPACE_START)
3830469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    prefix = ""
3840469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    for api in apis:
3850469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        if prefix != api.prefix:
3860469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            lines.append("\n// Declarations for %s APIs\n\n" % api.prefix)
3870469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            prefix = api.prefix
3880469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        lines.append(api.genDeclaration())
3890469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        lines.append("\n")
3900469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    lines.append(FOOTER_TEXT)
3910469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3920469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    with open(fname, "w") as f:
3930469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        f.writelines(lines)
3940469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3950469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamydef genSrcs(apis, fname):
3960469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    lines = []
39756ac6ff9bdc3c117e820c5a361ab45049c8b03f8Siva Velusamy    lines.append(HEADER_LICENSE)
39856ac6ff9bdc3c117e820c5a361ab45049c8b03f8Siva Velusamy    lines.append(HEADER_INCLUDES)
39956ac6ff9bdc3c117e820c5a361ab45049c8b03f8Siva Velusamy    lines.append(HEADER_NAMESPACE_START)
4000469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    prefix = ""
4010469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    for api in apis:
4020469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        if prefix != api.prefix:
4030469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            lines.append("\n// Definitions for %s APIs\n\n" % api.prefix)
4040469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy            prefix = api.prefix
4050469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        lines.append(api.genCode())
4060469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        lines.append("\n")
4070469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    lines.append(FOOTER_TEXT)
4080469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
4090469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    with open(fname, "w") as f:
4100469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy        f.writelines(lines)
4110469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
4120469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamyif __name__ == '__main__':
4134774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall    apis = parseAllSpecs(API_SPECS)    # read in all the specfiles
4144774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall    apis = removeDuplicates(apis)      # remove duplication of functions common to multiple versions
4150469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    genHeaders(apis, 'gltrace_api.h')  # generate header file
4160469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    genSrcs(apis, 'gltrace_api.cpp')   # generate source file
417