# -*- mode: python; coding: utf-8 -*-
#
# Pigment Python binding timing example
#
# Copyright © 2006, 2007, 2008 Fluendo Embedded S.L.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
# Author: Benjamin Kampmann <benjamin@fluendo.com>

import sys, gobject, math, os

class BenchmarkResult(object):
    """
    The BenchmarkResult contains the data that was found out during the
    process of benchmarking.
    @ivar hardware_acceleration:    whether hardware acceleration is enabled
    @type hardware_acceleration:    bool
    @ivar shaders:                  whether shaders are found
    @type shaders:                  bool
    @ivar size:                     the size of the screen in pixels
    @type size:                     tuple of two int
    @ivar frame_rates:              the frame rates that got captures
    @type frame_rates:              list
    @ivar max_rate:                 the maximum frame rate, that has happened
    @type max_rate:                 int
    @ivar min_rate:                 the minimum frame rate, that has happened
    @type min_rate:                 int
    @ivar average:                  the average frame rate
    @type average:                  int
    @ivar median:                   the median frame rate
    @type median:                   int
    @ivar upper_median:             the upper median
    @type upper_median:             int
    @ivar lower_median:             the lower median
    @type lower_median:             int
    """
    def __init__(self):
        self.hardware_acceleration = False
        self.shaders = False
        self.size = (0,0)
        self.max_rate = 0
        self.min_rate = 0
        self.average = 0
        self.lower_median = 0
        self.median = 0
        self.upper_median = 0
        self.frame_rates = []

OPACITY_CHANGE = 12

try:
    import pgm
except ImportError:
    print "You need to install pigment"
    print "or run this script from the pigment-uninstalled-shell"
    sys.exit(0)

class Benchmark(object):
    """
    Do a simple Benchmark. You can set some parameters to influence the
    behaviour of the benchmark. After the values got set, you should run
    L{start} to start the benchmark. After the benchmarking is done the
    L{callback} gets called.

    B{Attention}: At runtime of this class certain enviroment-variables get
    set to get a certain behaviour of pigment. Please wait until the
    callback-call was done to run your own pigment application in the original
    enviroment.

    @ivar picture_path: the path to the image to load and let it rotate
    @type picture_path: str
    @ivar frames:       the number of frames to catch (default: 100)
    @type frames:       int
    @ivar callback:     to call after the benchmark is done. the first argument
                        will be the BenchmarkResult containing the values
    @type callback:     callable
    @ivar transformation: the transformation matrix to do to the image
    @ivar text:         the pgm-text. If you want to display another text, you could
                        do::
                            benchmark.text.label = "My new Text!"
    @ivar opacity_change: the step the opacity of the text should be changed
                          at any iteration
    """

    TEST_PLUGIN = 'opengl'
    """
    The plugin to test. Needs to be set BEFORE creating the Object
    """

    def __init__(self):
        self._vblank = os.environ.get('PGM_GL_VBLANK', '1')
        # don't sync to vblank for this test!
        os.environ['PGM_GL_VBLANK'] = '0'
        self.result = BenchmarkResult()

        self._fps = 0
        # remove any frame per second guessing
        if os.environ.has_key('PGM_GL_FPS'):
            self._fps = os.environ['PGM_GL_FPS']
            del os.environ['PGM_GL_FPS']

        # OpenGL viewport creation
        self.gl = pgm.viewport_factory_make(self.TEST_PLUGIN)

        # pgm was found!
        self.result.has_pgm = True

        self.gl.title = 'Benchmark'
        self.gl.fullscreen = True
        self.gl.decorated = True
        self.gl.cursor = pgm.VIEWPORT_NONE

        # check for hardware accelartion
        for cap in self.gl.caps_mask:
            if 'PGM_VIEWPORT_HARDWARE_ACCELERATION' in cap.value_names:
                self.result.hardware_acceleration = True
                break

        # check for shaders
        for format in self.gl.pixel_formats:
            if 'PGM_IMAGE_I420' in format.value_names:
                self.result.shaders = True
                break

        cvs = pgm.Canvas()
        self.gl.set_canvas(cvs)

        self.callback = None

    def _clean_up(self):
        os.environ['PGM_GL_VBLANK'] = self._vblank

        if self._fps:
            os.environ['PGM_GL_FPS'] = self._fps
        self.gl.set_canvas(None)
        self.gl.visible = False
        self.gl.hide()
        del self.gl
        if self.callback:
            self.callback(self.result)


    def start(self):
#        self.gl.show()
        gobject.timeout_add(100, self._clean_up)

    def _resulting(self):
        # calculate average
        total = 0
        result_num = len(self.result.frame_rates)
        for fps in self.result.frame_rates:
            total += fps

        average = total / result_num

        self.result.frame_rates.sort()
        # max
        max_rate = self.result.frame_rates[-1]
        # min
        min_rate = self.result.frame_rates[0]

        # middle
        middle_pos = result_num / 2
        quarter_pos = middle_pos / 2

        median = self.result.frame_rates[middle_pos]
        lower_median = self.result.frame_rates[quarter_pos]
        upper_median = self.result.frame_rates[middle_pos+quarter_pos]

        self.result.size = self.gl.size
        self.result.max_rate = max_rate
        self.result.min_rate = min_rate
        self.result.average = average
        self.result.lower_median = lower_median
        self.result.median = median
        self.result.upper_median = upper_median
        self._clean_up()

def main(args):

    try:
        frames = int(args[0])
    except:
        frames = 100

    b = Benchmark()

    def print_result(data):
        print "HW ac found:", data.hardware_acceleration
        pgm.stop()


    b.frames = frames
    b.start()
    b.callback = print_result
    pgm.main()

if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
