普通文本  |  240行  |  9.37 KB

# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging
import os
import re
from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros.graphics import graphics_utils


class graphics_GLAPICheck(test.test):
    """
    Verify correctness of OpenGL/GLES and X11 versions/extensions.
    """
    version = 1
    preserve_srcdir = True
    error_message = ''
    GSC = None

    def setup(self):
        os.chdir(self.srcdir)
        utils.make('clean')
        utils.make('all')

    def __check_extensions(self, info, ext_entries):
        info_split = info.split()
        comply = True
        for extension in ext_entries:
            match = extension in info_split
            if not match:
                self.error_message += ' ' + extension
                comply = False
        return comply

    def __check_gl_extensions_1x(self, info):
        extensions = [
            'GL_ARB_vertex_buffer_object',
            'GL_ARB_shader_objects',
            'GL_ARB_texture_non_power_of_two',
            'GL_ARB_point_sprite',
            'GL_EXT_framebuffer_object',
            'GLX_EXT_texture_from_pixmap'
        ]
        return self.__check_extensions(info, extensions)

    def __check_gl_extensions_2x(self, info):
        extensions = [
            'GL_EXT_framebuffer_object',
            'GLX_EXT_texture_from_pixmap'
        ]
        return self.__check_extensions(info, extensions)

    def __check_gles_extensions(self, info):
        extensions = [
            'GL_OES_EGL_image',
            'EGL_KHR_image'
        ]
        extensions2 = [
            'GL_OES_EGL_image',
            'EGL_KHR_image_base',
            'EGL_KHR_image_pixmap'
        ]
        return (self.__check_extensions(info, extensions) or
                self.__check_extensions(info, extensions2))

    def __check_gl(self, result):
        version = re.findall(r'GL_VERSION = ([0-9]+).([0-9]+)', result)
        if version:
            version_major = int(version[0][0])
            version_minor = int(version[0][1])
            version_info = (' GL_VERSION = %d.%d' %
                            (version_major, version_minor))
            if version_major == 1:
                if version_minor < 4:
                    self.error_message = version_info
                    return False
                return self.__check_gl_extensions_1x(result)
            elif version_major >= 2:
                return self.__check_gl_extensions_2x(result)
            else:
                self.error_message = version_info
                return False
        # No GL version info found.
        self.error_message = ' missing GL version info'
        return False

    def __check_gles(self, result):
        version = re.findall(r'GLES_VERSION = OpenGL ES.* ([0-9]+).([0-9]+)',
                             result)
        if version:
            # GLES version has to be 2.0 or above.
            version_major = int(version[0][0])
            version_minor = int(version[0][1])
            version_info = (' GLES_VERSION = %d.%d' %
                            (version_major, version_minor))
            if version_major < 2:
                self.error_message = version_info
                return False
            # EGL version has to be 1.3 or above.
            version = re.findall(r'EGL_VERSION = ([0-9]+).([0-9]+)', result)
            if version:
                version_major = int(version[0][0])
                version_minor = int(version[0][1])
                version_info = ('EGL_VERSION = %d.%d' %
                                (version_major, version_minor))
                if (version_major == 1 and version_minor >= 3 or
                    version_major > 1):
                    return self.__check_gles_extensions(result)
                else:
                    self.error_message = version_info
                    return False
            # No EGL version info found.
            self.error_message = ' missing EGL version info'
            return False
        # No GLES version info found.
        self.error_message = ' missing GLES version info'
        return False

    def __check_x_extensions(self, result):
        extensions = [
            'DAMAGE',
            'Composite'
        ]
        return self.__check_extensions(result, extensions)

    def __run_x_cmd(self, cmd):
        cmd = graphics_utils.xcommand(cmd)
        result = utils.system_output(cmd, retain_output=True,
                                     ignore_status=True)
        return result

    def __check_wflinfo(self):
        # TODO(ihf): Extend this function once gl(es)_APICheck code has
        # been upstreamed to waffle.
        cmd = graphics_utils.wflinfo_cmd()
        logging.info('Running %s', cmd)
        wflinfo = utils.system_output(cmd, retain_output=True,
                                      ignore_status=False)
        # OpenGL version string: OpenGL ES 3.0 Mesa 10.5.0-devel
        version = re.findall(r'OpenGL version string: '
                             r'OpenGL ES ([0-9]+).([0-9]+)', wflinfo)
        if version:
            # GLES version has to be 2.0 or above.
            version_major = int(version[0][0])
            version_minor = int(version[0][1])
            version_info = ('GLES_VERSION = %d.%d' %
                            (version_major, version_minor))
            logging.info(version_info)
            if version_major < 2:
                self.error_message = ' %s' % version_info
                return False
            cmd = 'eglinfo'
            eglinfo = utils.system_output(cmd, retain_output=True,
                                          ignore_status=False)
            # EGL version string: 1.4 (DRI2)
            version = re.findall(r'EGL version string: ([0-9]+).([0-9]+)',
                                 eglinfo)
            # EGL version has to be 1.3 or above.
            if version:
                version_major = int(version[0][0])
                version_minor = int(version[0][1])
                version_info = ('EGL_VERSION = %d.%d' %
                                (version_major, version_minor))
                logging.info(version_info)
                if (version_major == 1 and version_minor >= 3 or
                    version_major > 1):
                    logging.warning('Please add missing extension check. '
                                    'Details crbug.com/413079')
                    # return self.__check_gles_extensions(wflinfo + eglinfo)
                    return True
                else:
                    self.error_message = version_info
                    return False
            # No EGL version info found.
            self.error_message = ' missing EGL version info'
            return False
        # No GLES version info found.
        self.error_message = ' missing GLES version info'
        return False

    def initialize(self):
        self.GSC = graphics_utils.GraphicsStateChecker()

    def cleanup(self):
        if self.GSC:
            self.GSC.finalize()

    def run_once(self):
        if utils.is_freon():
            if not self.__check_wflinfo():
                raise error.TestFail('GLES API insufficient:' +
                                     self.error_message)
            return

        # TODO(ihf): Remove this once all boards are switched to freon.
        cmd_gl = os.path.join(self.bindir, 'gl_APICheck')
        cmd_gles = os.path.join(self.bindir, 'gles_APICheck')
        exist_gl = os.path.isfile(cmd_gl)
        exist_gles = os.path.isfile(cmd_gles)
        if not exist_gl and not exist_gles:
            raise error.TestFail('Found neither gl_APICheck nor gles_APICheck. '
                                 'Test setup error.')
        elif exist_gl and exist_gles:
            raise error.TestFail('Found both gl_APICheck and gles_APICheck. '
                                 'Test setup error.')
        elif exist_gl:
            self.error_message = ''
            result = self.__run_x_cmd(cmd_gl)
            errors = re.findall(r'ERROR: ', result)
            run_through = re.findall(r'SUCCEED: run to the end', result)
            if not errors and run_through:
                check_result = self.__check_gl(result)
                if not check_result:
                    raise error.TestFail('GL API insufficient:' +
                                         self.error_message)
            else:
                raise error.TestFail('gl_APICheck error: ' + result)
        else:
            self.error_message = ''
            # TODO(zmo@): smarter mechanism with GLES & EGL library names.
            result = self.__run_x_cmd(cmd_gles + ' libGLESv2.so libEGL.so')
            errors = re.findall(r'ERROR: ', result)
            run_through = re.findall(r'SUCCEED: run to the end', result)
            if not errors and run_through:
                check_result = self.__check_gles(result)
                if not check_result:
                    raise error.TestFail('GLES API insufficient:' +
                                         self.error_message)
            else:
                raise error.TestFail('gles_APICheck error: ' + result)

        # Check X11 extensions.
        self.error_message = ''
        check_result = self.__check_x_extensions(result)
        if not check_result:
            raise error.TestFail('X extensions insufficient:' +
                                 self.error_message)