diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
commit | f8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch) | |
tree | 26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/Additions/common/crOpenGL | |
parent | Initial commit. (diff) | |
download | virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.zip |
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Additions/common/crOpenGL')
111 files changed, 27895 insertions, 0 deletions
diff --git a/src/VBox/Additions/common/crOpenGL/.scm-settings b/src/VBox/Additions/common/crOpenGL/.scm-settings new file mode 100644 index 00000000..e6362722 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/.scm-settings @@ -0,0 +1,62 @@ +# $Id: .scm-settings $ +## @file +# Source code massager settings for common/crOpenGL. +# + +# +# Copyright (C) 2010-2019 Oracle Corporation +# +# This file is part of VirtualBox Open Source Edition (OSE), as +# available from http://www.virtualbox.org. This file is free software; +# you can redistribute it and/or modify it under the terms of the GNU +# General Public License (GPL) as published by the Free Software +# Foundation, in version 2 as it comes in the "COPYING" file of the +# VirtualBox OSE distribution. VirtualBox OSE is distributed in the +# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. +# + +# Much of this is externally licensed, but not all, sigh. +--external-copyright --no-convert-tabs + +/array/arrayspu.rc: --no-external-copyright --convert-tabs + +/feedback/feedbackspu.rc: --no-external-copyright --convert-tabs +/feedback/feedback_context.c: --no-external-copyright --convert-tabs + +/pack/packspu.rc: --no-external-copyright --convert-tabs +/pack/packspu_framebuffer.c: --no-external-copyright --convert-tabs +/pack/packspu_getshaders.c: --no-external-copyright --convert-tabs +/pack/packspu_glsl.c: --no-external-copyright --convert-tabs +/pack/packspu_texture.c: --no-external-copyright --convert-tabs + +/passthrough/passthroughspu.rc: --no-external-copyright --convert-tabs + +/.scm-settings: --no-external-copyright --convert-tabs +/dri_drv.c: --no-external-copyright --convert-tabs +/dri_drv.h: --no-external-copyright --convert-tabs +/dri_glx.h: --no-external-copyright --convert-tabs +/egl.c: --no-external-copyright --convert-tabs +/fakedri_drv.c: --no-external-copyright --convert-tabs +/fakedri_drv.h: --no-external-copyright --convert-tabs +/fakedri_glfuncsList.h: --no-external-copyright --convert-tabs --no-fix-header-guards +/fakedri_glxfuncsList.h: --no-external-copyright --convert-tabs --no-fix-header-guards +/glx.c: --no-external-copyright --convert-tabs +/glx_c_exports.c: --no-external-copyright --convert-tabs +/glx_proto.h: --no-external-copyright --convert-tabs +/icd_drv.c: --no-external-copyright --convert-tabs +/icd_drv.h: --no-external-copyright --convert-tabs +/Linux_i386_glxapi_exports.py: --no-external-copyright --convert-tabs +/Makefile.kmk: --no-external-copyright --convert-tabs +/SunOS_i386_exports.py: --no-external-copyright --convert-tabs +/SunOS_i386_exports_dri.py: --no-external-copyright --convert-tabs +/SunOS_i386_glxapi_exports.py: --no-external-copyright --convert-tabs +/VBoxCROGL.rc: --no-external-copyright --convert-tabs +/VBoxICDList.h: --no-external-copyright --no-fix-header-guards + +*_special: --treat-as Makefile + +# Ignore some stuff. +--filter-out-files /COPYRIGHT.LLNL +--filter-out-files /COPYRIGHT.REDHAT +--filter-out-files /LICENSE + diff --git a/src/VBox/Additions/common/crOpenGL/AIX_exports.py b/src/VBox/Additions/common/crOpenGL/AIX_exports.py new file mode 100644 index 00000000..2f55db33 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/AIX_exports.py @@ -0,0 +1,11 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +import entrypoints + +hacks = ["TexImage3D", "MultiDrawElementsEXT" ] + +entrypoints.GenerateEntrypoints(hacks) + diff --git a/src/VBox/Additions/common/crOpenGL/COPYRIGHT.LLNL b/src/VBox/Additions/common/crOpenGL/COPYRIGHT.LLNL new file mode 100644 index 00000000..5fc1a271 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/COPYRIGHT.LLNL @@ -0,0 +1,61 @@ +This Chromium distribution contains information and code which is +covered under the following notice: + +Copyright (c) 2002, The Regents of the University of California. +Produced at the Lawrence Livermore National Laboratory +For details, contact: Randall Frank (rjfrank@llnl.gov). +UCRL-CODE-2002-058 +All rights reserved. + +This file is part of Chromium. For details, see accompanying +documentation. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this +list of conditions and the disclaimer below. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the disclaimer (as noted below) in the +documentation and/or other materials provided with the distribution. + +Neither the name of the UC/LLNL nor the names of its contributors may be +used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +Additional BSD Notice + +1. This notice is required to be provided under our contract with the U.S. + Department of Energy (DOE). This work was produced at the University of + California, Lawrence Livermore National Laboratory under Contract No. + W-7405-ENG-48 with the DOE. + +2. Neither the United States Government nor the University of California + nor any of their employees, makes any warranty, express or implied, or + assumes any liability or responsibility for the accuracy, completeness, + or usefulness of any information, apparatus, product, or process + disclosed, or represents that its use would not infringe privately-owned + rights. + +3. Also, reference herein to any specific commercial products, process, or + services by trade name, trademark, manufacturer or otherwise does not + necessarily constitute or imply its endorsement, recommendation, or + favoring by the United States Government or the University of + California. The views and opinions of authors expressed herein do not + necessarily state or reflect those of the United States Government or + the University of California, and shall not be used for advertising or + product endorsement purposes. diff --git a/src/VBox/Additions/common/crOpenGL/COPYRIGHT.REDHAT b/src/VBox/Additions/common/crOpenGL/COPYRIGHT.REDHAT new file mode 100644 index 00000000..7812243e --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/COPYRIGHT.REDHAT @@ -0,0 +1,29 @@ +This Chromium distribution contains information and code which is +covered under the following notice: + +/* + * Copyright 2001,2002 Red Hat Inc., Durham, North Carolina. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ diff --git a/src/VBox/Additions/common/crOpenGL/DD_glc.py b/src/VBox/Additions/common/crOpenGL/DD_glc.py new file mode 100755 index 00000000..33aee4da --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/DD_glc.py @@ -0,0 +1,139 @@ +from __future__ import print_function +print(""" +/** @file + * VBox OpenGL chromium functions header + */ + +/* + * Copyright (C) 2009-2016 """ """Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ +""") +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +import sys + +import apiutil + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - THIS FILE GENERATED BY THE DD_gl.py SCRIPT */ + +#include "chromium.h" +#include "cr_string.h" +#include "cr_version.h" +#include "stub.h" +#include "dri_drv.h" +#include "cr_gl.h" +""") + +commoncall_special = [ + "ArrayElement", + "Begin", + "CallList", + "CallLists", + "Color3f", + "Color3fv", + "Color4f", + "Color4fv", + "EdgeFlag", + "End", + "EvalCoord1f", + "EvalCoord1fv", + "EvalCoord2f", + "EvalCoord2fv", + "EvalPoint1", + "EvalPoint2", + "FogCoordfEXT", + "FogCoordfvEXT", + "Indexf", + "Indexfv", + "Materialfv", + "MultiTexCoord1fARB", + "MultiTexCoord1fvARB", + "MultiTexCoord2fARB", + "MultiTexCoord2fvARB", + "MultiTexCoord3fARB", + "MultiTexCoord3fvARB", + "MultiTexCoord4fARB", + "MultiTexCoord4fvARB", + "Normal3f", + "Normal3fv", + "SecondaryColor3fEXT", + "SecondaryColor3fvEXT", + "TexCoord1f", + "TexCoord1fv", + "TexCoord2f", + "TexCoord2fv", + "TexCoord3f", + "TexCoord3fv", + "TexCoord4f", + "TexCoord4fv", + "Vertex2f", + "Vertex2fv", + "Vertex3f", + "Vertex3fv", + "Vertex4f", + "Vertex4fv", + "VertexAttrib1fNV", + "VertexAttrib1fvNV", + "VertexAttrib2fNV", + "VertexAttrib2fvNV", + "VertexAttrib3fNV", + "VertexAttrib3fvNV", + "VertexAttrib4fNV", + "VertexAttrib4fvNV", + "VertexAttrib1fARB", + "VertexAttrib1fvARB", + "VertexAttrib2fARB", + "VertexAttrib2fvARB", + "VertexAttrib3fARB", + "VertexAttrib3fvARB", + "VertexAttrib4fARB", + "VertexAttrib4fvARB", + "EvalMesh1", + "EvalMesh2", + "Rectf", + "DrawArrays", + "DrawElements", + "DrawRangeElements" +] + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +for func_name in keys: + if "Chromium" == apiutil.Category(func_name): + continue + if func_name == "BoundsInfoCR": + continue + + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + + if func_name in commoncall_special: + print("%s vboxDD_gl%s(%s)" % (return_type, func_name, apiutil.MakeDeclarationString(params) )) + else: + if apiutil.MakeDeclarationString(params)=="void": + print("%s vboxDD_gl%s(GLcontext *ctx)" % (return_type, func_name )) + else: + print("%s vboxDD_gl%s(GLcontext *ctx, %s)" % (return_type, func_name, apiutil.MakeDeclarationString(params) )) + print("{") + + if return_type != "void": + print("\treturn ", end=' ') + + print("\tcr_gl%s(%s);" % (func_name, apiutil.MakeCallString(params))) + print("}") + print("") + diff --git a/src/VBox/Additions/common/crOpenGL/DD_glh.py b/src/VBox/Additions/common/crOpenGL/DD_glh.py new file mode 100755 index 00000000..38d9ba60 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/DD_glh.py @@ -0,0 +1,136 @@ +from __future__ import print_function +print(""" +/** @file + * VBox OpenGL chromium functions header + */ + +/* + * Copyright (C) 2009-2016 """ """Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ +""") +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +import sys + +import apiutil + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - THIS FILE GENERATED BY THE DD_gl.py SCRIPT */ +#ifndef __DD_GL_H__ +#define __DD_GL_H__ + +#include "chromium.h" +#include "cr_string.h" +#include "cr_version.h" +#include "stub.h" + +""") + +commoncall_special = [ + "ArrayElement", + "Begin", + "CallList", + "CallLists", + "Color3f", + "Color3fv", + "Color4f", + "Color4fv", + "EdgeFlag", + "End", + "EvalCoord1f", + "EvalCoord1fv", + "EvalCoord2f", + "EvalCoord2fv", + "EvalPoint1", + "EvalPoint2", + "FogCoordfEXT", + "FogCoordfvEXT", + "Indexf", + "Indexfv", + "Materialfv", + "MultiTexCoord1fARB", + "MultiTexCoord1fvARB", + "MultiTexCoord2fARB", + "MultiTexCoord2fvARB", + "MultiTexCoord3fARB", + "MultiTexCoord3fvARB", + "MultiTexCoord4fARB", + "MultiTexCoord4fvARB", + "Normal3f", + "Normal3fv", + "SecondaryColor3fEXT", + "SecondaryColor3fvEXT", + "TexCoord1f", + "TexCoord1fv", + "TexCoord2f", + "TexCoord2fv", + "TexCoord3f", + "TexCoord3fv", + "TexCoord4f", + "TexCoord4fv", + "Vertex2f", + "Vertex2fv", + "Vertex3f", + "Vertex3fv", + "Vertex4f", + "Vertex4fv", + "VertexAttrib1fNV", + "VertexAttrib1fvNV", + "VertexAttrib2fNV", + "VertexAttrib2fvNV", + "VertexAttrib3fNV", + "VertexAttrib3fvNV", + "VertexAttrib4fNV", + "VertexAttrib4fvNV", + "VertexAttrib1fARB", + "VertexAttrib1fvARB", + "VertexAttrib2fARB", + "VertexAttrib2fvARB", + "VertexAttrib3fARB", + "VertexAttrib3fvARB", + "VertexAttrib4fARB", + "VertexAttrib4fvARB", + "EvalMesh1", + "EvalMesh2", + "Rectf", + "DrawArrays", + "DrawElements", + "DrawRangeElements" +] + +# Extern-like declarations +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +for func_name in keys: + if "Chromium" == apiutil.Category(func_name): + continue + if func_name == "BoundsInfoCR": + continue + + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + + if func_name in commoncall_special: + print("extern %s vboxDD_gl%s(%s);" % (return_type, func_name, + apiutil.MakeDeclarationString( params ))) + else: + if apiutil.MakeDeclarationString(params)=="void": + print("extern %s vboxDD_gl%s(GLcontext *ctx);" % (return_type, func_name)) + else: + print("extern %s vboxDD_gl%s(GLcontext *ctx, %s);" % (return_type, func_name, + apiutil.MakeDeclarationString( params ))) + +print("#endif /* __DD_GL_H__ */") diff --git a/src/VBox/Additions/common/crOpenGL/Darwin_exports.py b/src/VBox/Additions/common/crOpenGL/Darwin_exports.py new file mode 100644 index 00000000..c3120e4d --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/Darwin_exports.py @@ -0,0 +1,12 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +import entrypoints + +hacks = ["TexImage3D", "TexImage2D", "TexImage1D", "MultiDrawArrays", + "BufferData", "BufferSubData", "GetBufferSubData" ] + +entrypoints.GenerateEntrypoints(hacks) + diff --git a/src/VBox/Additions/common/crOpenGL/FreeBSD_exports.py b/src/VBox/Additions/common/crOpenGL/FreeBSD_exports.py new file mode 100644 index 00000000..8f63e0a5 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/FreeBSD_exports.py @@ -0,0 +1,11 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +import entrypoints + +hacks = [] + +entrypoints.GenerateEntrypoints(hacks) + diff --git a/src/VBox/Additions/common/crOpenGL/IRIX64_exports.py b/src/VBox/Additions/common/crOpenGL/IRIX64_exports.py new file mode 100644 index 00000000..674efff1 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/IRIX64_exports.py @@ -0,0 +1,11 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +import entrypoints + +hacks = ["TexImage3D", "EdgeFlagPointer" ] + +entrypoints.GenerateEntrypoints(hacks) + diff --git a/src/VBox/Additions/common/crOpenGL/LICENSE b/src/VBox/Additions/common/crOpenGL/LICENSE new file mode 100644 index 00000000..d609a358 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/LICENSE @@ -0,0 +1,32 @@ +Copyright (c) 2002, Stanford University +All rights reserved. + +Some portions of Chromium are copyrighted by individual organizations. +Please see the files COPYRIGHT.LLNL and COPYRIGHT.REDHAT for more +information. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of Stanford University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/src/VBox/Additions/common/crOpenGL/Linux_exports.py b/src/VBox/Additions/common/crOpenGL/Linux_exports.py new file mode 100644 index 00000000..79dc8ddd --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/Linux_exports.py @@ -0,0 +1,10 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +import entrypoints + +hacks = [] + +entrypoints.GenerateEntrypoints(hacks) diff --git a/src/VBox/Additions/common/crOpenGL/Linux_i386_exports.py b/src/VBox/Additions/common/crOpenGL/Linux_i386_exports.py new file mode 100755 index 00000000..653b00a2 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/Linux_i386_exports.py @@ -0,0 +1,96 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + + +from __future__ import print_function +import sys + +import apiutil + + +def GenerateEntrypoints(): + + #apiutil.CopyrightC() + + # Get sorted list of dispatched functions. + # The order is very important - it must match cr_opcodes.h + # and spu_dispatch_table.h + print('%include "iprt/asmdefs.mac"') + print("") + print("%ifdef RT_ARCH_AMD64") + print("extern glim") + print("%else ; X86") + print("extern glim") + print("%endif") + print("") + + keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + + for index in range(len(keys)): + func_name = keys[index] + if apiutil.Category(func_name) == "Chromium": + continue + if apiutil.Category(func_name) == "VBox": + continue + + print("BEGINPROC_EXPORTED gl%s" % func_name) + print("%ifdef RT_ARCH_AMD64") + print("\tmov \trax, qword glim+%d" % (8*index)) + print("\tjmp \t[rax]") + print("%else ; X86") + print("\tmov \teax, dword glim+%d" % (4*index)) + print("\tjmp \t[eax]") + print("%endif") + print("ENDPROC gl%s" % func_name) + print("") + + + print(';') + print('; Aliases') + print(';') + + # Now loop over all the functions and take care of any aliases + allkeys = apiutil.GetAllFunctions(sys.argv[1]+"/APIspec.txt") + for func_name in allkeys: + if "omit" in apiutil.ChromiumProps(func_name): + continue + + if func_name in keys: + # we already processed this function earlier + continue + + # alias is the function we're aliasing + alias = apiutil.Alias(func_name) + if alias: + # this dict lookup should never fail (raise an exception)! + index = keys.index(alias) + print("BEGINPROC_EXPORTED gl%s" % func_name) + print("%ifdef RT_ARCH_AMD64") + print("\tmov \trax, qword glim+%d" % (8*index)) + print("\tjmp \t[rax]") + print("%else ; X86") + print("\tmov \teax, dword glim+%d" % (4*index)) + print("\tjmp \t[eax]") + print("%endif") + print("ENDPROC gl%s" % func_name) + print("") + + + print(';') + print('; No-op stubs') + print(';') + + # Now generate no-op stub functions + for func_name in allkeys: + if "stub" in apiutil.ChromiumProps(func_name): + print("BEGINPROC_EXPORTED gl%s" % func_name) + print("\tleave") + print("\tret") + print("ENDPROC gl%s" % func_name) + print("") + + +GenerateEntrypoints() + diff --git a/src/VBox/Additions/common/crOpenGL/Linux_i386_exports_dri.py b/src/VBox/Additions/common/crOpenGL/Linux_i386_exports_dri.py new file mode 100755 index 00000000..e212fb68 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/Linux_i386_exports_dri.py @@ -0,0 +1,96 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + + +from __future__ import print_function +import sys + +import apiutil + + +def GenerateEntrypoints(): + + #apiutil.CopyrightC() + + # Get sorted list of dispatched functions. + # The order is very important - it must match cr_opcodes.h + # and spu_dispatch_table.h + print('%include "iprt/asmdefs.mac"') + print("") + print("%ifdef RT_ARCH_AMD64") + print("extern glim") + print("%else ; X86") + print("extern glim") + print("%endif") + print("") + + keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + + for index in range(len(keys)): + func_name = keys[index] + if apiutil.Category(func_name) == "Chromium": + continue + if apiutil.Category(func_name) == "VBox": + continue + + print("BEGINPROC_EXPORTED cr_gl%s" % func_name) + print("%ifdef RT_ARCH_AMD64") + print("\tmov \trax, qword glim+%d" % (8*index)) + print("\tjmp \t[rax]") + print("%else ; X86") + print("\tmov \teax, dword glim+%d" % (4*index)) + print("\tjmp \t[eax]") + print("%endif") + print("ENDPROC cr_gl%s" % func_name) + print("") + + + print(';') + print('; Aliases') + print(';') + + # Now loop over all the functions and take care of any aliases + allkeys = apiutil.GetAllFunctions(sys.argv[1]+"/APIspec.txt") + for func_name in allkeys: + if "omit" in apiutil.ChromiumProps(func_name): + continue + + if func_name in keys: + # we already processed this function earlier + continue + + # alias is the function we're aliasing + alias = apiutil.Alias(func_name) + if alias: + # this dict lookup should never fail (raise an exception)! + index = keys.index(alias) + print("BEGINPROC_EXPORTED cr_gl%s" % func_name) + print("%ifdef RT_ARCH_AMD64") + print("\tmov \trax, qword glim+%d" % (8*index)) + print("\tjmp \t[rax]") + print("%else ; X86") + print("\tmov \teax, dword glim+%d" % (4*index)) + print("\tjmp \t[eax]") + print("%endif") + print("ENDPROC cr_gl%s" % func_name) + print("") + + + print(';') + print('; No-op stubs') + print(';') + + # Now generate no-op stub functions + for func_name in allkeys: + if "stub" in apiutil.ChromiumProps(func_name): + print("BEGINPROC_EXPORTED cr_gl%s" % func_name) + print("\tleave") + print("\tret") + print("ENDPROC cr_gl%s" % func_name) + print("") + + +GenerateEntrypoints() + diff --git a/src/VBox/Additions/common/crOpenGL/Linux_i386_glxapi_exports.py b/src/VBox/Additions/common/crOpenGL/Linux_i386_glxapi_exports.py new file mode 100755 index 00000000..f345e679 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/Linux_i386_glxapi_exports.py @@ -0,0 +1,109 @@ +from __future__ import print_function + +__copyright__ = \ +""" +Copyright (C) 2009-2019 Oracle Corporation + +This file is part of VirtualBox Open Source Edition (OSE), as +available from http://www.virtualbox.org. This file is free software; +you can redistribute it and/or modify it under the terms of the GNU +General Public License (GPL) as published by the Free Software +Foundation, in version 2 as it comes in the "COPYING" file of the +VirtualBox OSE distribution. VirtualBox OSE is distributed in the +hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. +""" + +import sys + +#Note, this should match the fakedri_glxfuncsList.h order +glx_functions = [ +"CopyContext", +"UseXFont", +#"GetDriverConfig", +"GetProcAddress", +"QueryExtension", +"IsDirect", +"DestroyGLXPbufferSGIX", +"QueryGLXPbufferSGIX", +"CreateGLXPixmap", +"CreateGLXPixmapWithConfigSGIX", +"QueryContext", +"CreateContextWithConfigSGIX", +"SwapBuffers", +"CreateNewContext", +"SelectEventSGIX", +"GetCurrentDrawable", +"ChooseFBConfig", +"WaitGL", +"GetFBConfigs", +"CreatePixmap", +"GetSelectedEventSGIX", +"GetCurrentReadDrawable", +"GetCurrentDisplay", +"QueryServerString", +"CreateWindow", +"SelectEvent", +"GetVisualFromFBConfigSGIX", +"GetFBConfigFromVisualSGIX", +"QueryDrawable", +"CreateContext", +"GetConfig", +"CreateGLXPbufferSGIX", +"CreatePbuffer", +"ChooseFBConfigSGIX", +"WaitX", +"GetVisualFromFBConfig", +#"GetScreenDriver", +"GetFBConfigAttrib", +"GetCurrentContext", +"GetClientString", +"DestroyPixmap", +"MakeCurrent", +"DestroyContext", +"GetProcAddressARB", +"GetSelectedEvent", +"DestroyPbuffer", +"DestroyWindow", +"DestroyGLXPixmap", +"QueryVersion", +"ChooseVisual", +"MakeContextCurrent", +"QueryExtensionsString", +"GetFBConfigAttribSGIX", +"FreeMemoryMESA", +"QueryContextInfoEXT", +"ImportContextEXT", +"GetContextIDEXT", +"MakeCurrentReadSGI", +"AllocateMemoryMESA", +"GetMemoryOffsetMESA", +"CreateGLXPixmapMESA", +"GetCurrentDisplayEXT", +"FreeContextEXT" +]; + +print('%include "iprt/asmdefs.mac"') +print("") +print("%ifdef RT_ARCH_AMD64") +print("extern glxim") +print("%else ; X86") +print("extern glxim") +print("%endif") +print("") + +## r=bird: This could all be done with macros in the assembler. + +for index in range(len(glx_functions)): + func_name = glx_functions[index] + + print("BEGINPROC_EXPORTED vbox_glX%s" % func_name) + print("%ifdef RT_ARCH_AMD64") + print("\tmov \trax, qword glxim+%d" % (8*index)) + print("\tjmp \t[rax]") + print("%else ; X86") + print("\tmov \teax, dword glxim+%d" % (4*index)) + print("\tjmp \t[eax]") + print("%endif") + print("ENDPROC vbox_glX%s" % func_name) + print("") + diff --git a/src/VBox/Additions/common/crOpenGL/Makefile.kmk b/src/VBox/Additions/common/crOpenGL/Makefile.kmk new file mode 100644 index 00000000..4d0011d8 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/Makefile.kmk @@ -0,0 +1,734 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-Makefile for the VirtualBox Guest OpenGL part +# + +# +# Copyright (C) 2008-2019 Oracle Corporation +# +# This file is part of VirtualBox Open Source Edition (OSE), as +# available from http://www.virtualbox.org. This file is free software; +# you can redistribute it and/or modify it under the terms of the GNU +# General Public License (GPL) as published by the Free Software +# Foundation, in version 2 as it comes in the "COPYING" file of the +# VirtualBox OSE distribution. VirtualBox OSE is distributed in the +# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. +# + +SUB_DEPTH = ../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +# +# Target lists. +# +BLDDIRS += \ + $(VBOX_PATH_CROGL_GENFILES)/ + +if1of ($(KBUILD_TARGET), win linux solaris freebsd) + DLLS += \ + VBoxOGL \ + VBoxOGLarrayspu \ + VBoxOGLpassthroughspu \ + VBoxOGLpackspu \ + VBoxOGLfeedbackspu +endif + +VBOX_OGL_X86_GUEST_DLLS = \ + VBoxOGL-x86 \ + VBoxOGLarrayspu-x86 \ + VBoxOGLpassthroughspu-x86 \ + VBoxOGLpackspu-x86 \ + VBoxOGLfeedbackspu-x86 + +ifdef VBOX_WITH_WDDM + DLLS.win.amd64 += $(VBOX_OGL_X86_GUEST_DLLS) +endif + +if1of ($(KBUILD_TARGET), linux solaris freebsd) + #VBoxOGL_DRI = 1 + DLLS += VBoxEGL + ifn1of ($(KBUILD_TARGET),linux solaris) # No DRI on Solaris yet + VBoxOGL_FAKEDRI = 1 + endif + + # Only Solaris right now needs C stubs because I can't figure out how to + # generate the GOT based relocation ASM yet. + ifdef VBoxOGL_FAKEDRI + if1of ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH),solaris.x86 solaris.amd64 linux.x86 linux.amd64 freebsd.x86 freebsd.amd64) + VBOX_OGL_GLX_USE_CSTUBS = 1 + endif + endif +endif + + +# +# VBoxOGL +# +VBoxOGL_TEMPLATE = VBOXCROGLR3GUESTDLL +VBoxOGL_INCS = . $(VBOX_GRAPHICS_INCS) +if1of ($(KBUILD_TARGET), linux solaris freebsd) + ifndef VBOX_USE_SYSTEM_GL_HEADERS + VBoxOGL_INCS += \ + $(VBOX_PATH_X11_ROOT)/libXdamage-1.1 \ + $(VBOX_PATH_X11_ROOT)/libXcomposite-0.4.0 \ + $(VBOX_PATH_X11_ROOT)/libXext-1.3.1 \ + $(VBOX_PATH_X11_ROOT)/libXfixes-4.0.3 \ + $(VBOX_PATH_X11_ROOT)/damageproto-1.1.0 \ + $(VBOX_PATH_X11_ROOT)/compositeproto-0.4 \ + $(VBOX_PATH_X11_ROOT)/fixesproto-4.0 \ + $(VBOX_PATH_X11_ROOT)/libx11-1.1.5-other \ + $(VBOX_PATH_X11_ROOT)/xextproto-7.1.1 \ + $(VBOX_PATH_X11_ROOT)/xproto-7.0.18 \ + $(VBOX_GL_INCS) + endif + VBoxOGL_DEFS += VBOX_NO_NATIVEGL +endif + +ifdef VBoxOGL_DRI + VBoxOGL_DEFS += VBOXOGL_DRI IN_DRI_DRIVER +else ifdef VBoxOGL_FAKEDRI + VBoxOGL_DEFS += VBOXOGL_FAKEDRI + ifdef VBOX_OGL_GLX_USE_CSTUBS + VBoxOGL_DEFS += VBOX_OGL_GLX_USE_CSTUBS + endif +endif + +ifdef VBOX_WITH_WDDM + VBoxOGL_DEFS.win += VBOX_WITH_WDDM + VBoxOGL_SDKS.win += $(VBOX_WINDDK_GST_WLH) +endif + +ifeq ($(KBUILD_TARGET),win) +#fixme?, INTERMEDIATES.win ain't working + VBoxOGL_INTERMEDIATES += $(VBOX_PATH_CROGL_GENFILES)/cr_gl.h + if defined(VBOX_SIGNING_MODE) && defined(VBOX_WITH_WDDM) + VBoxOGL_INSTTYPE.win = none + VBoxOGL_DEBUG_INSTTYPE.win = both + endif +endif +ifdef VBoxOGL_DRI + VBoxOGL_INTERMEDIATES += \ + $(VBOX_PATH_CROGL_GENFILES)/cr_gl.h \ + $(VBOX_PATH_CROGL_GENFILES)/DD_gl.h +else ifdef VBoxOGL_FAKEDRI + VBoxOGL_INTERMEDIATES += \ + $(VBOX_PATH_CROGL_GENFILES)/cr_gl.h +endif +VBoxOGL_SOURCES += \ + load.c \ + stub.c \ + context.c \ + $(VBOX_PATH_CROGL_GENFILES)/getprocaddress.c \ + $(VBOX_PATH_CROGL_GENFILES)/NULLfuncs.c \ + $(VBOX_PATH_CROGL_GENFILES)/tsfuncs.c + +if1of ($(KBUILD_TARGET), linux solaris freebsd) + VBoxOGL_SOURCES += \ + glx.c \ + xfont.c + ifdef VBOX_OGL_GLX_USE_CSTUBS + VBoxOGL_SOURCES += glx_c_exports.c + endif + + ifdef VBoxOGL_DRI + VBoxOGL_SOURCES += \ + $(VBOX_PATH_CROGL_GENFILES)/DD_gl.c \ + dri_drv.c + VBoxOGL_SOURCES.linux += \ + $(VBOX_PATH_CROGL_GENFILES)/linux_exports_dri.asm + VBoxOGL_SOURCES.solaris += \ + $(VBOX_PATH_CROGL_GENFILES)/solaris_exports_dri.asm + VBoxOGL_SOURCES.freebsd += \ + $(VBOX_PATH_CROGL_GENFILES)/freebsd_exports_dri.asm + else ifdef VBoxOGL_FAKEDRI + VBoxOGL_SOURCES += \ + fakedri_drv.c + ifndef VBOX_OGL_GLX_USE_CSTUBS + VBoxOGL_SOURCES.solaris += \ + $(VBOX_PATH_CROGL_GENFILES)/solaris_glxapi_exports.asm \ + $(VBOX_PATH_CROGL_GENFILES)/solaris_exports_dri.asm + VBoxOGL_SOURCES.linux += \ + $(VBOX_PATH_CROGL_GENFILES)/linux_glxapi_exports.asm \ + $(VBOX_PATH_CROGL_GENFILES)/linux_exports_dri.asm + VBoxOGL_SOURCES.freebsd += \ + $(VBOX_PATH_CROGL_GENFILES)/freebsd_glxapi_exports.asm \ + $(VBOX_PATH_CROGL_GENFILES)/freebsd_exports_dri.asm + else + VBoxOGL_SOURCES.solaris += \ + $(VBOX_PATH_CROGL_GENFILES)/solaris_exports.c + VBoxOGL_SOURCES.linux += \ + $(VBOX_PATH_CROGL_GENFILES)/linux_exports.c + VBoxOGL_SOURCES.freebsd += \ + $(VBOX_PATH_CROGL_GENFILES)/freebsd_exports.c + endif + else + VBoxOGL_SOURCES.linux += \ + $(VBOX_PATH_CROGL_GENFILES)/linux_exports.c + VBoxOGL_SOURCES.solaris += \ + $(VBOX_PATH_CROGL_GENFILES)/solaris_exports.c + VBoxOGL_SOURCES.freebsd += \ + $(VBOX_PATH_CROGL_GENFILES)/freebsd_exports.c + endif +endif + +VBoxOGL_SOURCES.win = \ + wgl.c \ + icd_drv.c \ + VBoxCROGL.rc \ + $(VBOX_PATH_CROGL_GENFILES)/windows_exports.asm \ + $(VBOX_PATH_CROGL_GENFILES)/cropengl.def +VBoxOGL_CLEAN = \ + $(VBOX_PATH_CROGL_GENFILES)/getprocaddress.c \ + $(VBOX_PATH_CROGL_GENFILES)/NULLfuncs.c \ + $(VBOX_PATH_CROGL_GENFILES)/tsfuncs.c +VBoxOGL_CLEAN.linux += \ + $(VBOX_PATH_CROGL_GENFILES)/linux_exports.c +VBoxOGL_CLEAN.solaris += \ + $(VBOX_PATH_CROGL_GENFILES)/solaris_exports.c +VBoxOGL_CLEAN.win = \ + $(VBOX_PATH_CROGL_GENFILES)/windows_exports.asm \ + $(VBOX_PATH_CROGL_GENFILES)/cropengl.def +if1of ($(KBUILD_TARGET), linux solaris) + ifdef VBoxOGL_DRI + VBoxOGL_CLEAN += \ + $(VBOX_PATH_CROGL_GENFILES)/cr_gl.h \ + $(VBOX_PATH_CROGL_GENFILES)/DD_gl.h \ + $(VBOX_PATH_CROGL_GENFILES)/DD_gl.c + else ifdef VBoxOGL_FAKEDRI + VBoxOGL_CLEAN += \ + $(VBOX_PATH_CROGL_GENFILES)/cr_gl.h + VBoxOGL_CLEAN.linux += \ + $(VBOX_PATH_CROGL_GENFILES)/linux_glxapi_exports.asm + VBoxOGL_CLEAN.solaris += \ + $(VBOX_PATH_CROGL_GENFILES)/solaris_glxapi_exports.asm + endif +endif +# VBoxOGL_LIBS = \ # VBOX_LIB_OGL_CRUTIL includes these and caused an interesting conflict. +# $(VBOX_LIB_IPRT_GUEST_R3_SHARED) \ +# $(VBOX_LIB_VBGL_R3_SHARED) \ + +VBoxOGL_LIBS = \ + $(VBOX_LIB_OGL_CRUTIL) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLspuload$(VBOX_SUFF_LIB) + +VBoxOGL_LIBS.win += \ + $(PATH_STAGE_LIB)/additions/VBoxDispMpLogger$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxWddmUmKmt$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxCrHgsmi$(VBOX_SUFF_LIB) + +if1of ($(KBUILD_TARGET), linux solaris freebsd) + ifdef VBOX_USE_SYSTEM_GL_HEADERS + VBoxOGL_LIBS += Xcomposite Xdamage Xfixes Xext + else + VBoxOGL_LIBS += \ + $(PATH_STAGE_LIB)/libXcomposite.so \ + $(PATH_STAGE_LIB)/libXdamage.so \ + $(PATH_STAGE_LIB)/libXfixes.so \ + $(PATH_STAGE_LIB)/libXext.so + endif + ifdef VBoxOGL_FAKEDRI + ifeq ($(KBUILD_TARGET), freebsd) + VBoxOGL_LIBS += \ + elf + else + VBoxOGL_LIBS += \ + dl + endif + else + VBoxOGL_SONAME.linux = libGL.so.1 + VBoxOGL_LDFLAGS.linux += -Wl,-e,LibMain + endif +endif +ifdef VBOX_WITH_CRHGSMI +VBoxOGL_DEFS.win += VBOX_WITH_CRHGSMI +endif +ifdef VBOX_WITH_WDDM +VBoxOGL_DEFS.win += VBOX_WITH_WDDM +endif +if1of ($(KBUILD_TARGET), linux) +VBoxOGL_LDFLAGS += -Wl,-z,nodelete +endif +ifdef VBOX_WITH_WDDM +# +# VBoxOGL-x86 - x86 VBoxOGL version built for amd64 build +# +VBoxOGL-x86_EXTENDS = VBoxOGL +VBoxOGL-x86_BLD_TRG_ARCH = x86 +VBoxOGL-x86_LIBS = $(VBOX_LIB_IPRT_GUEST_R3_SHARED_X86) \ + $(VBOX_LIB_VBGL_R3_SHARED_X86) \ + $(VBOX_LIB_OGL_CRUTIL_X86) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLspuload-x86$(VBOX_SUFF_LIB) + +VBoxOGL-x86_LIBS.win += \ + $(PATH_STAGE_LIB)/additions/VBoxDispMpLogger-x86$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxWddmUmKmt-x86$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxCrHgsmi-x86$(VBOX_SUFF_LIB) + + +VBoxOGL-x86_SOURCES.win = $(subst cropengl.def,cropengl-x86.def,$(VBoxOGL_SOURCES.win)) +VBoxOGL-x86_CLEAN.win = $(subst cropengl.def,cropengl-x86.def,$(VBoxOGL_CLEAN.win)) +VBoxOGL-x86_DEFS = $(VBoxOGL_DEFS) VBOX_WDDM_WOW64 +endif + +# +# Generate files for VBoxOGL. +# +$(VBOX_PATH_CROGL_GENFILES)/NULLfuncs.c: $(PATH_SUB_CURRENT)/NULLfuncs.py $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + +$(VBOX_PATH_CROGL_GENFILES)/tsfuncs.c: $(PATH_SUB_CURRENT)/tsfuncs.py $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + + +ifeq ($(KBUILD_TARGET),win) + # Windows +$(VBOX_PATH_CROGL_GENFILES)/getprocaddress.c: $(PATH_SUB_CURRENT)/windows_getprocaddress.py $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + + ifeq ($(KBUILD_TARGET_ARCH),amd64) +$(VBOX_PATH_CROGL_GENFILES)/cropengl.def: $(PATH_SUB_CURRENT)/defs64.py $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + else +$(VBOX_PATH_CROGL_GENFILES)/cropengl.def: $(PATH_SUB_CURRENT)/defs.py $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + endif + +$(VBOX_PATH_CROGL_GENFILES)/cr_gl.h: $(PATH_SUB_CURRENT)/cr_gl.py $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + +$(VBOX_PATH_CROGL_GENFILES)/windows_exports.asm: \ + $(PATH_SUB_CURRENT)/windows_i386_exports.py \ + $(VBOX_CROGL_API_FILES) $(PATH_SUB_CURRENT)/entrypoints.py \ + | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + + ifdef VBOX_WITH_WDDM + ifeq ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH),win.amd64) +$(VBOX_PATH_CROGL_GENFILES)/cropengl-x86.def: $(PATH_SUB_CURRENT)/defs.py $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + endif #ifeq ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH),win.amd64) + endif #ifdef VBOX_WITH_WDDM + + +else if1of ($(KBUILD_TARGET), freebsd linux solaris) + # FreeBSD, Linux, Solaris +$(VBOX_PATH_CROGL_GENFILES)/getprocaddress.c: $(PATH_SUB_CURRENT)/getprocaddress.py $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + + if !defined(VBoxOGL_DRI) && !defined(VBoxOGL_FAKEDRI) + ifeq ($(KBUILD_TARGET),solaris) +$(VBOX_PATH_CROGL_GENFILES)/solaris_exports.c: \ + $(PATH_SUB_CURRENT)/SunOS_exports.py \ + $(VBOX_CROGL_API_FILES) $(PATH_SUB_CURRENT)/entrypoints.py \ + | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + + else ifeq ($(KBUILD_TARGET),freebsd) +$(VBOX_PATH_CROGL_GENFILES)/freebsd_exports.c: \ + $(PATH_SUB_CURRENT)/FreeBSD_exports.py \ + $(VBOX_CROGL_API_FILES) $(PATH_SUB_CURRENT)/entrypoints.py \ + | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + + else +$(VBOX_PATH_CROGL_GENFILES)/linux_exports.c: \ + $(PATH_SUB_CURRENT)/Linux_exports.py \ + $(VBOX_CROGL_API_FILES) $(PATH_SUB_CURRENT)/entrypoints.py \ + | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + endif + + else ifdef VBoxOGL_DRI +$(VBOX_PATH_CROGL_GENFILES)/cr_gl.h: $(PATH_SUB_CURRENT)/cr_gl.py $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + +$(VBOX_PATH_CROGL_GENFILES)/DD_gl.h: $(PATH_SUB_CURRENT)/DD_glh.py $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + +$(VBOX_PATH_CROGL_GENFILES)/DD_gl.c: $(PATH_SUB_CURRENT)/DD_glc.py $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + + ifeq ($(KBUILD_TARGET),solaris) +$(VBOX_PATH_CROGL_GENFILES)/solaris_exports_dri.asm: \ + $(PATH_SUB_CURRENT)/SunOS_i386_exports_dri.py \ + $(VBOX_CROGL_API_FILES) $(PATH_SUB_CURRENT)/entrypoints.py \ + | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + + else ifeq ($(KBUILD_TARGET),freebsd) +$(VBOX_PATH_CROGL_GENFILES)/freebsd_exports_dri.asm: \ + $(PATH_SUB_CURRENT)/FreeBSD_i386_exports_dri.py \ + $(VBOX_CROGL_API_FILES) $(PATH_SUB_CURRENT)/entrypoints.py \ + | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + + else +$(VBOX_PATH_CROGL_GENFILES)/linux_exports_dri.asm: \ + $(PATH_SUB_CURRENT)/Linux_i386_exports_dri.py \ + $(VBOX_CROGL_API_FILES) $(PATH_SUB_CURRENT)/entrypoints.py \ + | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + endif + + else ifdef VBoxOGL_FAKEDRI +$(VBOX_PATH_CROGL_GENFILES)/cr_gl.h: $(PATH_SUB_CURRENT)/cr_gl.py $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + + ifndef VBOX_OGL_GLX_USE_CSTUBS + ifeq ($(KBUILD_TARGET),solaris) +$(VBOX_PATH_CROGL_GENFILES)/solaris_exports_dri.asm: \ + $(PATH_SUB_CURRENT)/SunOS_i386_exports_dri.py \ + $(VBOX_CROGL_API_FILES) $(PATH_SUB_CURRENT)/entrypoints.py \ + | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) +$(VBOX_PATH_CROGL_GENFILES)/solaris_glxapi_exports.asm: $(PATH_SUB_CURRENT)/SunOS_i386_glxapi_exports.py | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< + + else +$(VBOX_PATH_CROGL_GENFILES)/linux_exports_dri.asm: \ + $(PATH_SUB_CURRENT)/Linux_i386_exports_dri.py \ + $(VBOX_CROGL_API_FILES) $(PATH_SUB_CURRENT)/entrypoints.py \ + | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) +$(VBOX_PATH_CROGL_GENFILES)/linux_glxapi_exports.asm: $(PATH_SUB_CURRENT)/Linux_i386_glxapi_exports.py | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< + endif + + else + ifeq ($(KBUILD_TARGET),solaris) +$(VBOX_PATH_CROGL_GENFILES)/solaris_exports.c: \ + $(PATH_SUB_CURRENT)/SunOS_exports.py \ + $(VBOX_CROGL_API_FILES) $(PATH_SUB_CURRENT)/entrypoints.py \ + | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + + else ifeq ($(KBUILD_TARGET),freebsd) +$(VBOX_PATH_CROGL_GENFILES)/freebsd_exports.c: \ + $(PATH_SUB_CURRENT)/FreeBSD_exports.py \ + $(VBOX_CROGL_API_FILES) $(PATH_SUB_CURRENT)/entrypoints.py \ + | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + else +$(VBOX_PATH_CROGL_GENFILES)/linux_exports.c: \ + $(PATH_SUB_CURRENT)/Linux_exports.py \ + $(VBOX_CROGL_API_FILES) $(PATH_SUB_CURRENT)/entrypoints.py \ + | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + endif + + endif # VBOX_OGL_GLX_USE_CSTUBS + endif +endif + +# +# VBoxOGLarrayspu +# +VBoxOGLarrayspu_TEMPLATE = VBOXCROGLR3GUESTDLL +VBoxOGLarrayspu_INCS = \ + array \ + $(VBOX_GRAPHICS_INCS) +if1of ($(KBUILD_TARGET), linux solaris freebsd) + VBoxOGLarrayspu_INCS += \ + $(VBOX_GL_INCS) +endif +if defined(VBOX_SIGNING_MODE) && defined(VBOX_WITH_WDDM) + VBoxOGLarrayspu_INSTTYPE.win = none + VBoxOGLarrayspu_DEBUG_INSTTYPE.win = both +endif +VBoxOGLarrayspu_INCS.darwin += $(PATH_OUT)/obj/VBoxOGL +VBoxOGLarrayspu_INTERMEDIATES = \ + $(VBOX_PATH_CROGL_GENFILES)/state/cr_currentpointers.h \ + $(VBOX_PATH_CROGL_GENFILES)/state/cr_statefuncs.h +VBoxOGLarrayspu_SOURCES = \ + array/arrayspu.c \ + array/arrayspu_config.c \ + array/arrayspu_init.c +VBoxOGLarrayspu_SOURCES.win = \ + array/arrayspu.def \ + array/arrayspu.rc +VBoxOGLarrayspu_LIBS = \ + $(VBOX_LIB_OGL_CRUTIL) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLspuload$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLcrstate$(VBOX_SUFF_LIB) +ifdef VBOX_WITH_CRHGSMI +VBoxOGLarrayspu_DEFS.win += VBOX_WITH_CRHGSMI +endif +ifdef VBOX_WITH_WDDM +VBoxOGLarrayspu_DEFS.win += VBOX_WITH_WDDM +endif + +ifdef VBOX_WITH_WDDM +# +# VBoxOGLarrayspu-x86 - x86 version of VBoxOGLarrayspu built for amd64 build +# +VBoxOGLarrayspu-x86_EXTENDS = VBoxOGLarrayspu +VBoxOGLarrayspu-x86_BLD_TRG_ARCH = x86 +VBoxOGLarrayspu-x86_LIBS = $(VBOX_LIB_OGL_CRUTIL_X86) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLspuload-x86$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLcrstate-x86$(VBOX_SUFF_LIB) +VBoxOGLarrayspu-x86_DEFS = $(VBoxOGLarrayspu_DEFS) VBOX_WDDM_WOW64 +endif + +# +# VBoxOGLpassthroughspu +# +VBoxOGLpassthroughspu_TEMPLATE = VBOXCROGLR3GUESTDLL +VBoxOGLpassthroughspu_INCS = \ + passthrough \ + $(VBOX_GRAPHICS_INCS) +if1of ($(KBUILD_TARGET), linux solaris freebsd) + VBoxOGLpassthroughspu_INCS += \ + $(VBOX_GL_INCS) +endif +if defined(VBOX_SIGNING_MODE) && defined(VBOX_WITH_WDDM) + VBoxOGLpassthroughspu_INSTTYPE.win = none + VBoxOGLpassthroughspu_DEBUG_INSTTYPE.win = both +endif +VBoxOGLpassthroughspu_SOURCES = \ + passthrough/passthroughspu_init.c \ + $(VBOX_PATH_CROGL_GENFILES)/passthroughspu.c +VBoxOGLpassthroughspu_SOURCES.win = \ + passthrough/passthrough.def \ + passthrough/passthroughspu.rc +VBoxOGLpassthroughspu_CLEAN = \ + $(VBOX_PATH_CROGL_GENFILES)/passthroughspu.c +VBoxOGLpassthroughspu_LIBS = \ + $(VBOX_LIB_OGL_CRUTIL) +ifdef VBOX_WITH_CRHGSMI +VBoxOGLpassthroughspu_DEFS.win += VBOX_WITH_CRHGSMI +endif +ifdef VBOX_WITH_WDDM +VBoxOGLpassthroughspu_DEFS.win += VBOX_WITH_WDDM +endif + +ifdef VBOX_WITH_WDDM +# +# VBoxOGLpassthroughspu-x86 - x86 version of VBoxOGLpassthroughspu built for amd64 build +# +VBoxOGLpassthroughspu-x86_EXTENDS = VBoxOGLpassthroughspu +VBoxOGLpassthroughspu-x86_BLD_TRG_ARCH = x86 +VBoxOGLpassthroughspu-x86_LIBS = $(VBOX_LIB_OGL_CRUTIL_X86) +VBoxOGLpassthroughspu-x86_DEFS = $(VBoxOGLpassthroughspu_DEFS) VBOX_WDDM_WOW64 +endif + +# +# Generate files for VBoxOGLpassthroughspu. +# +$(VBOX_PATH_CROGL_GENFILES)/passthroughspu.c: $(PATH_SUB_CURRENT)/passthrough/passthrough.py $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) + +# +# VBoxOGLpackspu +# +VBoxOGLpackspu_TEMPLATE = VBOXCROGLR3GUESTDLL +VBoxOGLpackspu_DEFS = TRACKS_STATE=1 PACKS=1 +VBoxOGLpackspu_INCS = \ + pack \ + $(VBOX_GRAPHICS_INCS) +if1of ($(KBUILD_TARGET), linux solaris freebsd) + VBoxOGLpackspu_INCS += \ + $(VBOX_GL_INCS) +endif +if defined(VBOX_SIGNING_MODE) && defined(VBOX_WITH_WDDM) + VBoxOGLpackspu_INSTTYPE.win = none + VBoxOGLpackspu_DEBUG_INSTTYPE.win = both +endif +VBoxOGLpackspu_INTERMEDIATES = \ + $(VBOX_PATH_CROGL_GENFILES)/packspu_proto.h \ + $(VBOX_PATH_CROGL_GENFILES)/cr_packfunctions.h +VBoxOGLpackspu_SOURCES = \ + pack/packspu_bufferobject.c \ + pack/packspu_client.c \ + pack/packspu_config.c \ + pack/packspu_context.c \ + pack/packspu_getstring.c \ + pack/packspu_init.c \ + pack/packspu_misc.c \ + pack/packspu_net.c \ + pack/packspu_swapbuf.c \ + pack/packspu_pixel.c \ + pack/packspu_texture.c \ + pack/packspu_getshaders.c \ + pack/packspu_glsl.c \ + pack/packspu_framebuffer.c \ + $(VBOX_PATH_CROGL_GENFILES)/packspu.c \ + $(VBOX_PATH_CROGL_GENFILES)/packspu_get.c \ + $(VBOX_PATH_CROGL_GENFILES)/packspu_flush.c \ + $(VBOX_PATH_CROGL_GENFILES)/packspu_beginend.c +VBoxOGLpackspu_SOURCES.win = \ + pack/pack.def \ + pack/packspu.rc +VBoxOGLpackspu_CLEAN = \ + $(VBOX_PATH_CROGL_GENFILES)/packspu_proto.h \ + $(VBOX_PATH_CROGL_GENFILES)/packspu.c \ + $(VBOX_PATH_CROGL_GENFILES)/packspu_get.c \ + $(VBOX_PATH_CROGL_GENFILES)/packspu_flush.c \ + $(VBOX_PATH_CROGL_GENFILES)/packspu_beginend.c +VBoxOGLpackspu_LIBS = \ + $(VBOX_LIB_OGL_CRUTIL) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLspuload$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLcrstate$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLcrpacker$(VBOX_SUFF_LIB) +VBoxOGLpackspu_LIBS.win += \ + $(PATH_STAGE_LIB)/additions/VBoxDispMpLogger$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxWddmUmKmt$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxCrHgsmi$(VBOX_SUFF_LIB) + +ifdef VBOX_WITH_CRHGSMI +VBoxOGLpackspu_DEFS.win += VBOX_WITH_CRHGSMI +endif +ifdef VBOX_WITH_CRDUMPER +VBoxOGLpackspu_DEFS += VBOX_WITH_CRDUMPER +endif +ifdef VBOX_WITH_CRPACKSPU_DUMPER +VBoxOGLpackspu_DEFS += VBOX_WITH_CRPACKSPU_DUMPER +endif +ifdef VBOX_WITH_WDDM +VBoxOGLpackspu_DEFS.win += VBOX_WITH_WDDM +endif + +ifdef VBOX_WITH_WDDM +# +# VBoxOGLpackspu-x86 - x86 version of VBoxOGLpackspu built for amd64 build +# +VBoxOGLpackspu-x86_EXTENDS = VBoxOGLpackspu +VBoxOGLpackspu-x86_BLD_TRG_ARCH = x86 +VBoxOGLpackspu-x86_LIBS = $(VBOX_LIB_OGL_CRUTIL_X86) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLspuload-x86$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLcrstate-x86$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLcrpacker-x86$(VBOX_SUFF_LIB) +VBoxOGLpackspu-x86_LIBS.win += \ + $(PATH_STAGE_LIB)/additions/VBoxDispMpLogger-x86$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxWddmUmKmt-x86$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxCrHgsmi-x86$(VBOX_SUFF_LIB) +VBoxOGLpackspu-x86_DEFS = $(VBoxOGLpackspu_DEFS) VBOX_WDDM_WOW64 +endif + +# +# Generate files for VBoxOGLpackspu. +# +$(VBOX_PATH_CROGL_GENFILES)/packspu.c: $(addprefix $(PATH_SUB_CURRENT)/pack/,pack.py packspu_special packspu_unimplemented_special) $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) $(<D) + +$(VBOX_PATH_CROGL_GENFILES)/packspu_get.c: $(PATH_SUB_CURRENT)/pack/packspu_get.py $(PATH_SUB_CURRENT)/pack/packspu_special $(PATH_ROOT)/src/VBox/HostServices/SharedOpenGL/crserverlib/get_sizes.py $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) $(<D) + +$(VBOX_PATH_CROGL_GENFILES)/packspu_flush.c: $(PATH_SUB_CURRENT)/pack/packspu_flush.py $(PATH_SUB_CURRENT)/pack/packspu_flush_special $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) $(<D) + +$(VBOX_PATH_CROGL_GENFILES)/packspu_beginend.c: $(PATH_SUB_CURRENT)/pack/packspu_beginend.py $(PATH_SUB_CURRENT)/pack/packspu_vertex_special $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) $(<D) + +$(VBOX_PATH_CROGL_GENFILES)/packspu_proto.h: $(addprefix $(PATH_SUB_CURRENT)/pack/,packspu_proto.py packspu_special packspu_unimplemented_special) $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) $(<D) + +# +# VBoxOGLfeedbackspu +# +VBoxOGLfeedbackspu_TEMPLATE = VBOXCROGLR3GUESTDLL +VBoxOGLfeedbackspu_INCS = \ + feedback \ + $(VBOX_GRAPHICS_INCS) +if1of ($(KBUILD_TARGET), linux solaris freebsd) + VBoxOGLfeedbackspu_INCS += \ + $(VBOX_GL_INCS) +endif +if defined(VBOX_SIGNING_MODE) && defined(VBOX_WITH_WDDM) + VBoxOGLfeedbackspu_INSTTYPE.win = none + VBoxOGLfeedbackspu_DEBUG_INSTTYPE.win = both +endif +VBoxOGLarrayspu_INTERMEDIATES = \ + $(VBOX_PATH_CROGL_GENFILES)/feedbackspu_proto.h +VBoxOGLfeedbackspu_SOURCES = \ + feedback/feedbackspu_config.c \ + feedback/feedbackspu_init.c \ + feedback/feedback_context.c \ + $(VBOX_PATH_CROGL_GENFILES)/feedbackspu.c \ + $(VBOX_PATH_CROGL_GENFILES)/feedbackspu_state.c +VBoxOGLfeedbackspu_SOURCES.win = \ + feedback/feedback.def \ + feedback/feedbackspu.rc +VBoxOGLfeedbackspu_CLEAN = \ + $(VBOX_PATH_CROGL_GENFILES)/feedbackspu_proto.h \ + $(VBOX_PATH_CROGL_GENFILES)/feedbackspu.c \ + $(VBOX_PATH_CROGL_GENFILES)/feedbackspu_state.c +VBoxOGLfeedbackspu_LIBS = \ + $(VBOX_LIB_OGL_CRUTIL) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLspuload$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLcrstate$(VBOX_SUFF_LIB) +ifdef VBOX_WITH_CRHGSMI +VBoxOGLfeedbackspu_DEFS.win += VBOX_WITH_CRHGSMI +endif +ifdef VBOX_WITH_WDDM +VBoxOGLfeedbackspu_DEFS.win += VBOX_WITH_WDDM +endif + +ifdef VBOX_WITH_WDDM +# +# VBoxOGLfeedbackspu-x86 - x86 version of VBoxOGLfeedbackspu built for amd64 build +# +VBoxOGLfeedbackspu-x86_EXTENDS = VBoxOGLfeedbackspu +VBoxOGLfeedbackspu-x86_BLD_TRG_ARCH = x86 +VBoxOGLfeedbackspu-x86_LIBS = $(VBOX_LIB_OGL_CRUTIL_X86) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLspuload-x86$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_LIB)/additions/VBoxOGLcrstate-x86$(VBOX_SUFF_LIB) +VBoxOGLfeedbackspu-x86_DEFS = $(VBoxOGLfeedbackspu_DEFS) VBOX_WDDM_WOW64 +endif + +# +# Generate files for VBoxOGLfeedbackspu. +# +$(VBOX_PATH_CROGL_GENFILES)/feedbackspu.c: $(addprefix $(PATH_SUB_CURRENT)/feedback/,feedback.py feedback_special select_special feedback_state_special) $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) $(<D) + +$(VBOX_PATH_CROGL_GENFILES)/feedbackspu_state.c: $(addprefix $(PATH_SUB_CURRENT)/feedback/,feedback_state.py feedback_state_special) $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) $(<D) + +$(VBOX_PATH_CROGL_GENFILES)/feedbackspu_proto.h: $(addprefix $(PATH_SUB_CURRENT)/feedback/,feedbackspu_proto.py feedback_special select_special feedback_state_special) $(VBOX_CROGL_API_FILES) | $$(dir $$@) + $(call MSG_GENERATE,python,$@,$<) + $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) $(<D) + +VBoxEGL_TEMPLATE = VBOXCROGLR3GUESTDLL +VBoxEGL_SOURCES = egl.c +ifndef VBOX_USE_SYSTEM_GL_HEADERS + VBoxEGL_INCS = $(VBOX_PATH_X11_ROOT)/mesa-11.0.7 +endif +VBoxEGL_LIBS = $(VBOX_LIB_OGL) # $(VBOX_LIB_IPRT_GUEST_R3_SHARED) +VBoxEGL_SONAME.linux = libEGL.so.1 + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Additions/common/crOpenGL/NULLfuncs.py b/src/VBox/Additions/common/crOpenGL/NULLfuncs.py new file mode 100755 index 00000000..a6427837 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/NULLfuncs.py @@ -0,0 +1,58 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + + +from __future__ import print_function +import sys + +import apiutil + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - THIS FILE GENERATED BY THE NULLfuncs.py SCRIPT */ + +#include "cr_error.h" +#include "stub.h" +""") + +for func_name in keys: + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + + print("static %s SPULOAD_APIENTRY NULL_%s(%s)" % (return_type, func_name, apiutil.MakeDeclarationString(params))) + print("{") + print("\t/* do nothing */") + print("\tcrWarning(\"YOU ARE CALLING A NULLED FUNCTION (%s)\");" % func_name) + for (name, type, vecSize) in params: + print("\t(void) %s;" % name) + if return_type != "void": + print("\treturn 0;") + print("}") + print("") + + +print("DECLEXPORT(SPUDispatchTable) stubNULLDispatch = {") +for func_name in keys: + print("\tNULL_%s," % (func_name)) +print("\tNULL, /* copyList */") +print("\tNULL, /* copy_of */") +print("\t0, /* mark */") +print("\tNULL /* server */") +print("};") + +print("") +print("/* Declare and initialize the glim dispatch table here so that we */") +print("/* can initialize all entries to no-op routines. */") +print("SPUDispatchTable glim = {") +for func_name in keys: + print("\tNULL_%s," % (func_name)) +print("\tNULL, /* copyList */") +print("\tNULL, /* copy_of */") +print("\t0, /* mark */") +print("\tNULL /* server */") +print("};") diff --git a/src/VBox/Additions/common/crOpenGL/OSF1_exports.py b/src/VBox/Additions/common/crOpenGL/OSF1_exports.py new file mode 100644 index 00000000..8f63e0a5 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/OSF1_exports.py @@ -0,0 +1,11 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +import entrypoints + +hacks = [] + +entrypoints.GenerateEntrypoints(hacks) + diff --git a/src/VBox/Additions/common/crOpenGL/SunOS_exports.py b/src/VBox/Additions/common/crOpenGL/SunOS_exports.py new file mode 100644 index 00000000..8f63e0a5 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/SunOS_exports.py @@ -0,0 +1,11 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +import entrypoints + +hacks = [] + +entrypoints.GenerateEntrypoints(hacks) + diff --git a/src/VBox/Additions/common/crOpenGL/SunOS_i386_exports.py b/src/VBox/Additions/common/crOpenGL/SunOS_i386_exports.py new file mode 100755 index 00000000..b3591339 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/SunOS_i386_exports.py @@ -0,0 +1,98 @@ +""" +Copyright (C) 2009-2019 Oracle Corporation + +This file is part of VirtualBox Open Source Edition (OSE), as +available from http://www.virtualbox.org. This file is free software; +you can redistribute it and/or modify it under the terms of the GNU +General Public License (GPL) as published by the Free Software +Foundation, in version 2 as it comes in the "COPYING" file of the +VirtualBox OSE distribution. VirtualBox OSE is distributed in the +hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. +""" + +from __future__ import print_function +import sys + +import apiutil + + +def GenerateEntrypoints(): + + #apiutil.CopyrightC() + + # Get sorted list of dispatched functions. + # The order is very important - it must match cr_opcodes.h + # and spu_dispatch_table.h + print('%include "iprt/asmdefs.mac"') + print("") + print("%ifdef RT_ARCH_AMD64") + print("extern glim") + print("%else ; X86") + print("extern glim") + print("%endif") + print("") + + keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + + for index in range(len(keys)): + func_name = keys[index] + if apiutil.Category(func_name) == "Chromium": + continue + if apiutil.Category(func_name) == "VBox": + continue + + print("BEGINPROC_EXPORTED gl%s" % func_name) + print("%ifdef RT_ARCH_AMD64") + print("\tjmp \t[glim+%d wrt rip wrt ..gotpcrel]" % (8*index)) + print("%else ; X86") + print("\tjmp \t[glim+%d wrt ..gotpc]" % (4*index)) + print("%endif") + print("ENDPROC gl%s" % func_name) + print("") + + + print(';') + print('; Aliases') + print(';') + + # Now loop over all the functions and take care of any aliases + allkeys = apiutil.GetAllFunctions(sys.argv[1]+"/APIspec.txt") + for func_name in allkeys: + if "omit" in apiutil.ChromiumProps(func_name): + continue + + if func_name in keys: + # we already processed this function earlier + continue + + # alias is the function we're aliasing + alias = apiutil.Alias(func_name) + if alias: + # this dict lookup should never fail (raise an exception)! + index = keys.index(alias) + print("BEGINPROC_EXPORTED gl%s" % func_name) + print("%ifdef RT_ARCH_AMD64") + print("\tjmp \t[glim+%d wrt rip wrt ..gotpcrel]" % (8*index)) + print("%else ; X86") + print("\tjmp \t[glim+%d wrt ..gotpc]" % (4*index)) + print("%endif") + print("ENDPROC gl%s" % func_name) + print("") + + + print(';') + print('; No-op stubs') + print(';') + + # Now generate no-op stub functions + for func_name in allkeys: + if "stub" in apiutil.ChromiumProps(func_name): + print("BEGINPROC_EXPORTED gl%s" % func_name) + print("\tleave") + print("\tret") + print("ENDPROC gl%s" % func_name) + print("") + + +GenerateEntrypoints() + diff --git a/src/VBox/Additions/common/crOpenGL/SunOS_i386_exports_dri.py b/src/VBox/Additions/common/crOpenGL/SunOS_i386_exports_dri.py new file mode 100755 index 00000000..a8b951bd --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/SunOS_i386_exports_dri.py @@ -0,0 +1,98 @@ +""" +Copyright (C) 2009-2019 Oracle Corporation + +This file is part of VirtualBox Open Source Edition (OSE), as +available from http://www.virtualbox.org. This file is free software; +you can redistribute it and/or modify it under the terms of the GNU +General Public License (GPL) as published by the Free Software +Foundation, in version 2 as it comes in the "COPYING" file of the +VirtualBox OSE distribution. VirtualBox OSE is distributed in the +hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. +""" + +from __future__ import print_function +import sys + +import apiutil + + +def GenerateEntrypoints(): + + #apiutil.CopyrightC() + + # Get sorted list of dispatched functions. + # The order is very important - it must match cr_opcodes.h + # and spu_dispatch_table.h + print('%include "iprt/asmdefs.mac"') + print("") + print("%ifdef RT_ARCH_AMD64") + print("extern glim") + print("%else ; X86") + print("extern glim") + print("%endif") + print("") + + keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + + for index in range(len(keys)): + func_name = keys[index] + if apiutil.Category(func_name) == "Chromium": + continue + if apiutil.Category(func_name) == "VBox": + continue + + print("BEGINPROC_EXPORTED cr_gl%s" % func_name) + print("%ifdef RT_ARCH_AMD64") + print("\tjmp \t[glim+%d wrt rip wrt ..gotpcrel]" % (8*index)) + print("%else ; X86") + print("\tjmp \t[glim+%d wrt ..gotpc]" % (4*index)) + print("%endif") + print("ENDPROC cr_gl%s" % func_name) + print("") + + + print(';') + print('; Aliases') + print(';') + + # Now loop over all the functions and take care of any aliases + allkeys = apiutil.GetAllFunctions(sys.argv[1]+"/APIspec.txt") + for func_name in allkeys: + if "omit" in apiutil.ChromiumProps(func_name): + continue + + if func_name in keys: + # we already processed this function earlier + continue + + # alias is the function we're aliasing + alias = apiutil.Alias(func_name) + if alias: + # this dict lookup should never fail (raise an exception)! + index = keys.index(alias) + print("BEGINPROC_EXPORTED cr_gl%s" % func_name) + print("%ifdef RT_ARCH_AMD64") + print("\tjmp \t[glim+%d wrt rip wrt ..gotpcrel]" % (8*index)) + print("%else ; X86") + print("\tjmp \t[glim+%d wrt ..gotpc]" % (4*index)) + print("%endif") + print("ENDPROC cr_gl%s" % func_name) + print("") + + + print(';') + print('; No-op stubs') + print(';') + + # Now generate no-op stub functions + for func_name in allkeys: + if "stub" in apiutil.ChromiumProps(func_name): + print("BEGINPROC_EXPORTED cr_gl%s" % func_name) + print("\tleave") + print("\tret") + print("ENDPROC cr_gl%s" % func_name) + print("") + + +GenerateEntrypoints() + diff --git a/src/VBox/Additions/common/crOpenGL/SunOS_i386_glxapi_exports.py b/src/VBox/Additions/common/crOpenGL/SunOS_i386_glxapi_exports.py new file mode 100755 index 00000000..24d7cc53 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/SunOS_i386_glxapi_exports.py @@ -0,0 +1,103 @@ +""" +Copyright (C) 2009-2019 Oracle Corporation + +This file is part of VirtualBox Open Source Edition (OSE), as +available from http://www.virtualbox.org. This file is free software; +you can redistribute it and/or modify it under the terms of the GNU +General Public License (GPL) as published by the Free Software +Foundation, in version 2 as it comes in the "COPYING" file of the +VirtualBox OSE distribution. VirtualBox OSE is distributed in the +hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. +""" + +from __future__ import print_function +import sys + +#Note, this should match the fakedri_glxfuncsList.h order +glx_functions = [ +"CopyContext", +"UseXFont", +#"GetDriverConfig", +"GetProcAddress", +"QueryExtension", +"IsDirect", +"DestroyGLXPbufferSGIX", +"QueryGLXPbufferSGIX", +"CreateGLXPixmap", +"CreateGLXPixmapWithConfigSGIX", +"QueryContext", +"CreateContextWithConfigSGIX", +"SwapBuffers", +"CreateNewContext", +"SelectEventSGIX", +"GetCurrentDrawable", +"ChooseFBConfig", +"WaitGL", +"GetFBConfigs", +"CreatePixmap", +"GetSelectedEventSGIX", +"GetCurrentReadDrawable", +"GetCurrentDisplay", +"QueryServerString", +"CreateWindow", +"SelectEvent", +"GetVisualFromFBConfigSGIX", +"GetFBConfigFromVisualSGIX", +"QueryDrawable", +"CreateContext", +"GetConfig", +"CreateGLXPbufferSGIX", +"CreatePbuffer", +"ChooseFBConfigSGIX", +"WaitX", +"GetVisualFromFBConfig", +#"GetScreenDriver", +"GetFBConfigAttrib", +"GetCurrentContext", +"GetClientString", +"DestroyPixmap", +"MakeCurrent", +"DestroyContext", +"GetProcAddressARB", +"GetSelectedEvent", +"DestroyPbuffer", +"DestroyWindow", +"DestroyGLXPixmap", +"QueryVersion", +"ChooseVisual", +"MakeContextCurrent", +"QueryExtensionsString", +"GetFBConfigAttribSGIX", +"FreeMemoryMESA", +"QueryContextInfoEXT", +"ImportContextEXT", +"GetContextIDEXT", +"MakeCurrentReadSGI", +"AllocateMemoryMESA", +"GetMemoryOffsetMESA", +"CreateGLXPixmapMESA", +"GetCurrentDisplayEXT", +"FreeContextEXT" +]; + +print('%include "iprt/asmdefs.mac"') +print("") +print("%ifdef RT_ARCH_AMD64") +print("extern glxim") +print("%else ; X86") +print("extern glxim") +print("%endif") +print("") + +for index in range(len(glx_functions)): + func_name = glx_functions[index] + + print("BEGINPROC_EXPORTED vbox_glX%s" % func_name) + print("%ifdef RT_ARCH_AMD64") + print("\tjmp \t[glxim+%d wrt rip wrt ..gotpcrel]" % (8*index)) + print("%else ; X86") + print("\tjmp \t[glxim+%d wrt ..gotpc]" % (4*index)) + print("%endif") + print("ENDPROC vbox_glX%s" % func_name) + print("") + diff --git a/src/VBox/Additions/common/crOpenGL/VBoxCROGL.rc b/src/VBox/Additions/common/crOpenGL/VBoxCROGL.rc new file mode 100644 index 00000000..1cafaca7 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/VBoxCROGL.rc @@ -0,0 +1,70 @@ +/* $Id: VBoxCROGL.rc $ */ +/** @file + * VBoxCROGL - Resource file containing version info and icon. + */ + +/* + * Copyright (C) 2008-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include <windows.h> +#include <VBox/version.h> + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VBOX_RC_FILE_VERSION + PRODUCTVERSION VBOX_RC_FILE_VERSION + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS VBOX_RC_FILE_FLAGS + FILEFLAGS VBOX_RC_FILE_FLAGS + FILEOS VBOX_RC_FILE_OS + FILETYPE VBOX_RC_TYPE_DRV + FILESUBTYPE VFT2_DRV_DISPLAY +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "VirtualBox crOpenGL ICD\0" + VALUE "InternalName", "VBoxCROGL\0" +#ifdef VBOX_WDDM_WOW64 + VALUE "OriginalFilename", "VBoxCROGL-x86.dll\0" +#else + VALUE "OriginalFilename", "VBoxCROGL.dll\0" +#endif + VALUE "CompanyName", VBOX_RC_COMPANY_NAME + VALUE "FileVersion", VBOX_RC_FILE_VERSION_STR + VALUE "LegalCopyright", VBOX_RC_LEGAL_COPYRIGHT + VALUE "ProductName", VBOX_RC_PRODUCT_NAME_GA_STR + VALUE "ProductVersion", VBOX_RC_PRODUCT_VERSION_STR + VBOX_RC_MORE_STRINGS + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +1 RCDATA +BEGIN +// Machine dependent parameters + 17, // Height of vertical thumb + 17, // Width of horizontal thumb + 2, // Icon horiz compression factor + 2, // Icon vert compression factor + 1, // Cursor horz compression factor + 1, // Cursor vert compression factor + 0, // Kanji window height + 1, // cxBorder (thickness of vertical lines) + 1 // cyBorder (thickness of horizontal lines) +END diff --git a/src/VBox/Additions/common/crOpenGL/VBoxICDList.h b/src/VBox/Additions/common/crOpenGL/VBoxICDList.h new file mode 100644 index 00000000..dcc901da --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/VBoxICDList.h @@ -0,0 +1,385 @@ +/* $Id: VBoxICDList.h $ */ +/** @file + * VirtualBox Windows NT/2000/XP guest OpenGL ICD + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * File name: icd.c + * Author: Gregor Anich + * + * ICD (Installable Client Driver) interface. + * Based on the windows GDI/WGL driver. + */ + +ICD_ENTRY(NewList) /* 0 */ +ICD_ENTRY(EndList) /* 1 */ +ICD_ENTRY(CallList) /* 2 */ +ICD_ENTRY(CallLists) /* 3 */ +ICD_ENTRY(DeleteLists) /* 4 */ +ICD_ENTRY(GenLists) /* 5 */ +ICD_ENTRY(ListBase) /* 6 */ +ICD_ENTRY(Begin) /* 7 */ +ICD_ENTRY(Bitmap) /* 8 */ +ICD_ENTRY(Color3b) /* 9 */ +ICD_ENTRY(Color3bv) /* 10 */ +ICD_ENTRY(Color3d) /* 11 */ +ICD_ENTRY(Color3dv) /* 12 */ +ICD_ENTRY(Color3f) /* 13 */ +ICD_ENTRY(Color3fv) /* 14 */ +ICD_ENTRY(Color3i) /* 15 */ +ICD_ENTRY(Color3iv) /* 16 */ +ICD_ENTRY(Color3s) /* 17 */ +ICD_ENTRY(Color3sv) /* 18 */ +ICD_ENTRY(Color3ub) /* 19 */ +ICD_ENTRY(Color3ubv) /* 20 */ +ICD_ENTRY(Color3ui) /* 21 */ +ICD_ENTRY(Color3uiv) /* 22 */ +ICD_ENTRY(Color3us) /* 23 */ +ICD_ENTRY(Color3usv) /* 24 */ +ICD_ENTRY(Color4b) /* 25 */ +ICD_ENTRY(Color4bv) /* 26 */ +ICD_ENTRY(Color4d) /* 27 */ +ICD_ENTRY(Color4dv) /* 28 */ +ICD_ENTRY(Color4f) /* 29 */ +ICD_ENTRY(Color4fv) /* 30 */ +ICD_ENTRY(Color4i) /* 31 */ +ICD_ENTRY(Color4iv) /* 32 */ +ICD_ENTRY(Color4s) /* 33 */ +ICD_ENTRY(Color4sv) /* 34 */ +ICD_ENTRY(Color4ub) /* 35 */ +ICD_ENTRY(Color4ubv) /* 36 */ +ICD_ENTRY(Color4ui) /* 37 */ +ICD_ENTRY(Color4uiv) /* 38 */ +ICD_ENTRY(Color4us) /* 39 */ +ICD_ENTRY(Color4usv) /* 40 */ +ICD_ENTRY(EdgeFlag) /* 41 */ +ICD_ENTRY(EdgeFlagv) /* 42 */ +ICD_ENTRY(End) /* 43 */ +ICD_ENTRY(Indexd) /* 44 */ +ICD_ENTRY(Indexdv) /* 45 */ +ICD_ENTRY(Indexf) /* 46 */ +ICD_ENTRY(Indexfv) /* 47 */ +ICD_ENTRY(Indexi) /* 48 */ +ICD_ENTRY(Indexiv) /* 49 */ +ICD_ENTRY(Indexs) /* 50 */ +ICD_ENTRY(Indexsv) /* 51 */ +ICD_ENTRY(Normal3b) /* 52 */ +ICD_ENTRY(Normal3bv) /* 53 */ +ICD_ENTRY(Normal3d) /* 54 */ +ICD_ENTRY(Normal3dv) /* 55 */ +ICD_ENTRY(Normal3f) /* 56 */ +ICD_ENTRY(Normal3fv) /* 57 */ +ICD_ENTRY(Normal3i) /* 58 */ +ICD_ENTRY(Normal3iv) /* 59 */ +ICD_ENTRY(Normal3s) /* 60 */ +ICD_ENTRY(Normal3sv) /* 61 */ +ICD_ENTRY(RasterPos2d) /* 62 */ +ICD_ENTRY(RasterPos2dv) /* 63 */ +ICD_ENTRY(RasterPos2f) /* 64 */ +ICD_ENTRY(RasterPos2fv) /* 65 */ +ICD_ENTRY(RasterPos2i) /* 66 */ +ICD_ENTRY(RasterPos2iv) /* 67 */ +ICD_ENTRY(RasterPos2s) /* 68 */ +ICD_ENTRY(RasterPos2sv) /* 69 */ +ICD_ENTRY(RasterPos3d) /* 70 */ +ICD_ENTRY(RasterPos3dv) /* 71 */ +ICD_ENTRY(RasterPos3f) /* 72 */ +ICD_ENTRY(RasterPos3fv) /* 73 */ +ICD_ENTRY(RasterPos3i) /* 74 */ +ICD_ENTRY(RasterPos3iv) /* 75 */ +ICD_ENTRY(RasterPos3s) /* 76 */ +ICD_ENTRY(RasterPos3sv) /* 77 */ +ICD_ENTRY(RasterPos4d) /* 78 */ +ICD_ENTRY(RasterPos4dv) /* 79 */ +ICD_ENTRY(RasterPos4f) /* 80 */ +ICD_ENTRY(RasterPos4fv) /* 81 */ +ICD_ENTRY(RasterPos4i) /* 82 */ +ICD_ENTRY(RasterPos4iv) /* 83 */ +ICD_ENTRY(RasterPos4s) /* 84 */ +ICD_ENTRY(RasterPos4sv) /* 85 */ +ICD_ENTRY(Rectd) /* 86 */ +ICD_ENTRY(Rectdv) /* 87 */ +ICD_ENTRY(Rectf) /* 88 */ +ICD_ENTRY(Rectfv) /* 89 */ +ICD_ENTRY(Recti) /* 90 */ +ICD_ENTRY(Rectiv) /* 91 */ +ICD_ENTRY(Rects) /* 92 */ +ICD_ENTRY(Rectsv) /* 93 */ +ICD_ENTRY(TexCoord1d) /* 94 */ +ICD_ENTRY(TexCoord1dv) /* 95 */ +ICD_ENTRY(TexCoord1f) /* 96 */ +ICD_ENTRY(TexCoord1fv) /* 97 */ +ICD_ENTRY(TexCoord1i) /* 98 */ +ICD_ENTRY(TexCoord1iv) /* 99 */ +ICD_ENTRY(TexCoord1s) /* 100 */ +ICD_ENTRY(TexCoord1sv) /* 101 */ +ICD_ENTRY(TexCoord2d) /* 102 */ +ICD_ENTRY(TexCoord2dv) /* 103 */ +ICD_ENTRY(TexCoord2f) /* 104 */ +ICD_ENTRY(TexCoord2fv) /* 105 */ +ICD_ENTRY(TexCoord2i) /* 106 */ +ICD_ENTRY(TexCoord2iv) /* 107 */ +ICD_ENTRY(TexCoord2s) /* 108 */ +ICD_ENTRY(TexCoord2sv) /* 109 */ +ICD_ENTRY(TexCoord3d) /* 110 */ +ICD_ENTRY(TexCoord3dv) /* 111 */ +ICD_ENTRY(TexCoord3f) /* 112 */ +ICD_ENTRY(TexCoord3fv) /* 113 */ +ICD_ENTRY(TexCoord3i) /* 114 */ +ICD_ENTRY(TexCoord3iv) /* 115 */ +ICD_ENTRY(TexCoord3s) /* 116 */ +ICD_ENTRY(TexCoord3sv) /* 117 */ +ICD_ENTRY(TexCoord4d) /* 118 */ +ICD_ENTRY(TexCoord4dv) /* 119 */ +ICD_ENTRY(TexCoord4f) /* 120 */ +ICD_ENTRY(TexCoord4fv) /* 121 */ +ICD_ENTRY(TexCoord4i) /* 122 */ +ICD_ENTRY(TexCoord4iv) /* 123 */ +ICD_ENTRY(TexCoord4s) /* 124 */ +ICD_ENTRY(TexCoord4sv) /* 125 */ +ICD_ENTRY(Vertex2d) /* 126 */ +ICD_ENTRY(Vertex2dv) /* 127 */ +ICD_ENTRY(Vertex2f) /* 128 */ +ICD_ENTRY(Vertex2fv) /* 129 */ +ICD_ENTRY(Vertex2i) /* 130 */ +ICD_ENTRY(Vertex2iv) /* 131 */ +ICD_ENTRY(Vertex2s) /* 132 */ +ICD_ENTRY(Vertex2sv) /* 133 */ +ICD_ENTRY(Vertex3d) /* 134 */ +ICD_ENTRY(Vertex3dv) /* 135 */ +ICD_ENTRY(Vertex3f) /* 136 */ +ICD_ENTRY(Vertex3fv) /* 137 */ +ICD_ENTRY(Vertex3i) /* 138 */ +ICD_ENTRY(Vertex3iv) /* 139 */ +ICD_ENTRY(Vertex3s) /* 140 */ +ICD_ENTRY(Vertex3sv) /* 141 */ +ICD_ENTRY(Vertex4d) /* 142 */ +ICD_ENTRY(Vertex4dv) /* 143 */ +ICD_ENTRY(Vertex4f) /* 144 */ +ICD_ENTRY(Vertex4fv) /* 145 */ +ICD_ENTRY(Vertex4i) /* 146 */ +ICD_ENTRY(Vertex4iv) /* 147 */ +ICD_ENTRY(Vertex4s) /* 148 */ +ICD_ENTRY(Vertex4sv) /* 149 */ +ICD_ENTRY(ClipPlane) /* 150 */ +ICD_ENTRY(ColorMaterial) /* 151 */ +ICD_ENTRY(CullFace) /* 152 */ +ICD_ENTRY(Fogf) /* 153 */ +ICD_ENTRY(Fogfv) /* 154 */ +ICD_ENTRY(Fogi) /* 155 */ +ICD_ENTRY(Fogiv) /* 156 */ +ICD_ENTRY(FrontFace) /* 157 */ +ICD_ENTRY(Hint) /* 158 */ +ICD_ENTRY(Lightf) /* 159 */ +ICD_ENTRY(Lightfv) /* 160 */ +ICD_ENTRY(Lighti) /* 161 */ +ICD_ENTRY(Lightiv) /* 162 */ +ICD_ENTRY(LightModelf) /* 163 */ +ICD_ENTRY(LightModelfv) /* 164 */ +ICD_ENTRY(LightModeli) /* 165 */ +ICD_ENTRY(LightModeliv) /* 166 */ +ICD_ENTRY(LineStipple) /* 167 */ +ICD_ENTRY(LineWidth) /* 168 */ +ICD_ENTRY(Materialf) /* 169 */ +ICD_ENTRY(Materialfv) /* 170 */ +ICD_ENTRY(Materiali) /* 171 */ +ICD_ENTRY(Materialiv) /* 172 */ +ICD_ENTRY(PointSize) /* 173 */ +ICD_ENTRY(PolygonMode) /* 174 */ +ICD_ENTRY(PolygonStipple) /* 175 */ +ICD_ENTRY(Scissor) /* 176 */ +ICD_ENTRY(ShadeModel) /* 177 */ +ICD_ENTRY(TexParameterf) /* 178 */ +ICD_ENTRY(TexParameterfv) /* 179 */ +ICD_ENTRY(TexParameteri) /* 180 */ +ICD_ENTRY(TexParameteriv) /* 181 */ +ICD_ENTRY(TexImage1D) /* 182 */ +ICD_ENTRY(TexImage2D) /* 183 */ +ICD_ENTRY(TexEnvf) /* 184 */ +ICD_ENTRY(TexEnvfv) /* 185 */ +ICD_ENTRY(TexEnvi) /* 186 */ +ICD_ENTRY(TexEnviv) /* 187 */ +ICD_ENTRY(TexGend) /* 188 */ +ICD_ENTRY(TexGendv) /* 189 */ +ICD_ENTRY(TexGenf) /* 190 */ +ICD_ENTRY(TexGenfv) /* 191 */ +ICD_ENTRY(TexGeni) /* 192 */ +ICD_ENTRY(TexGeniv) /* 193 */ +ICD_ENTRY(FeedbackBuffer) /* 194 */ +ICD_ENTRY(SelectBuffer) /* 195 */ +ICD_ENTRY(RenderMode) /* 196 */ +ICD_ENTRY(InitNames) /* 197 */ +ICD_ENTRY(LoadName) /* 198 */ +ICD_ENTRY(PassThrough) /* 199 */ +ICD_ENTRY(PopName) /* 200 */ +ICD_ENTRY(PushName) /* 201 */ +ICD_ENTRY(DrawBuffer) /* 202 */ +ICD_ENTRY(Clear) /* 203 */ +ICD_ENTRY(ClearAccum) /* 204 */ +ICD_ENTRY(ClearIndex) /* 205 */ +ICD_ENTRY(ClearColor) /* 206 */ +ICD_ENTRY(ClearStencil) /* 207 */ +ICD_ENTRY(ClearDepth) /* 208 */ +ICD_ENTRY(StencilMask) /* 209 */ +ICD_ENTRY(ColorMask) /* 210 */ +ICD_ENTRY(DepthMask) /* 211 */ +ICD_ENTRY(IndexMask) /* 212 */ +ICD_ENTRY(Accum) /* 213 */ +ICD_ENTRY(Disable) /* 214 */ +ICD_ENTRY(Enable) /* 215 */ +ICD_ENTRY(Finish) /* 216 */ +ICD_ENTRY(Flush) /* 217 */ +ICD_ENTRY(PopAttrib) /* 218 */ +ICD_ENTRY(PushAttrib) /* 219 */ +ICD_ENTRY(Map1d) /* 220 */ +ICD_ENTRY(Map1f) /* 221 */ +ICD_ENTRY(Map2d) /* 222 */ +ICD_ENTRY(Map2f) /* 223 */ +ICD_ENTRY(MapGrid1d) /* 224 */ +ICD_ENTRY(MapGrid1f) /* 225 */ +ICD_ENTRY(MapGrid2d) /* 226 */ +ICD_ENTRY(MapGrid2f) /* 227 */ +ICD_ENTRY(EvalCoord1d) /* 228 */ +ICD_ENTRY(EvalCoord1dv) /* 229 */ +ICD_ENTRY(EvalCoord1f) /* 230 */ +ICD_ENTRY(EvalCoord1fv) /* 231 */ +ICD_ENTRY(EvalCoord2d) /* 232 */ +ICD_ENTRY(EvalCoord2dv) /* 233 */ +ICD_ENTRY(EvalCoord2f) /* 234 */ +ICD_ENTRY(EvalCoord2fv) /* 235 */ +ICD_ENTRY(EvalMesh1) /* 236 */ +ICD_ENTRY(EvalPoint1) /* 237 */ +ICD_ENTRY(EvalMesh2) /* 238 */ +ICD_ENTRY(EvalPoint2) /* 239 */ +ICD_ENTRY(AlphaFunc) /* 240 */ +ICD_ENTRY(BlendFunc) /* 241 */ +ICD_ENTRY(LogicOp) /* 242 */ +ICD_ENTRY(StencilFunc) /* 243 */ +ICD_ENTRY(StencilOp) /* 244 */ +ICD_ENTRY(DepthFunc) /* 245 */ +ICD_ENTRY(PixelZoom) /* 246 */ +ICD_ENTRY(PixelTransferf) /* 247 */ +ICD_ENTRY(PixelTransferi) /* 248 */ +ICD_ENTRY(PixelStoref) /* 249 */ +ICD_ENTRY(PixelStorei) /* 250 */ +ICD_ENTRY(PixelMapfv) /* 251 */ +ICD_ENTRY(PixelMapuiv) /* 252 */ +ICD_ENTRY(PixelMapusv) /* 253 */ +ICD_ENTRY(ReadBuffer) /* 254 */ +ICD_ENTRY(CopyPixels) /* 255 */ +ICD_ENTRY(ReadPixels) /* 256 */ +ICD_ENTRY(DrawPixels) /* 257 */ +ICD_ENTRY(GetBooleanv) /* 258 */ +ICD_ENTRY(GetClipPlane) /* 259 */ +ICD_ENTRY(GetDoublev) /* 260 */ +ICD_ENTRY(GetError) /* 261 */ +ICD_ENTRY(GetFloatv) /* 262 */ +ICD_ENTRY(GetIntegerv) /* 263 */ +ICD_ENTRY(GetLightfv) /* 264 */ +ICD_ENTRY(GetLightiv) /* 265 */ +ICD_ENTRY(GetMapdv) /* 266 */ +ICD_ENTRY(GetMapfv) /* 267 */ +ICD_ENTRY(GetMapiv) /* 268 */ +ICD_ENTRY(GetMaterialfv) /* 269 */ +ICD_ENTRY(GetMaterialiv) /* 270 */ +ICD_ENTRY(GetPixelMapfv) /* 271 */ +ICD_ENTRY(GetPixelMapuiv) /* 272 */ +ICD_ENTRY(GetPixelMapusv) /* 273 */ +ICD_ENTRY(GetPolygonStipple) /* 274 */ +ICD_ENTRY(GetString) /* 275 */ +ICD_ENTRY(GetTexEnvfv) /* 276 */ +ICD_ENTRY(GetTexEnviv) /* 277 */ +ICD_ENTRY(GetTexGendv) /* 278 */ +ICD_ENTRY(GetTexGenfv) /* 279 */ +ICD_ENTRY(GetTexGeniv) /* 280 */ +ICD_ENTRY(GetTexImage) /* 281 */ +ICD_ENTRY(GetTexParameterfv) /* 282 */ +ICD_ENTRY(GetTexParameteriv) /* 283 */ +ICD_ENTRY(GetTexLevelParameterfv) /* 284 */ +ICD_ENTRY(GetTexLevelParameteriv) /* 285 */ +ICD_ENTRY(IsEnabled) /* 286 */ +ICD_ENTRY(IsList) /* 287 */ +ICD_ENTRY(DepthRange) /* 288 */ +ICD_ENTRY(Frustum) /* 289 */ +ICD_ENTRY(LoadIdentity) /* 290 */ +ICD_ENTRY(LoadMatrixf) /* 291 */ +ICD_ENTRY(LoadMatrixd) /* 292 */ +ICD_ENTRY(MatrixMode) /* 293 */ +ICD_ENTRY(MultMatrixf) /* 294 */ +ICD_ENTRY(MultMatrixd) /* 295 */ +ICD_ENTRY(Ortho) /* 296 */ +ICD_ENTRY(PopMatrix) /* 297 */ +ICD_ENTRY(PushMatrix) /* 298 */ +ICD_ENTRY(Rotated) /* 299 */ +ICD_ENTRY(Rotatef) /* 300 */ +ICD_ENTRY(Scaled) /* 301 */ +ICD_ENTRY(Scalef) /* 302 */ +ICD_ENTRY(Translated) /* 303 */ +ICD_ENTRY(Translatef) /* 304 */ +ICD_ENTRY(Viewport) /* 305 */ +ICD_ENTRY(ArrayElement) /* 306 */ +ICD_ENTRY(BindTexture) /* 307 */ +ICD_ENTRY(ColorPointer) /* 308 */ +ICD_ENTRY(DisableClientState) /* 309 */ +ICD_ENTRY(DrawArrays) /* 310 */ +ICD_ENTRY(DrawElements) /* 311 */ +ICD_ENTRY(EdgeFlagPointer) /* 312 */ +ICD_ENTRY(EnableClientState) /* 313 */ +ICD_ENTRY(IndexPointer) /* 314 */ +ICD_ENTRY(Indexub) /* 315 */ +ICD_ENTRY(Indexubv) /* 316 */ +ICD_ENTRY(InterleavedArrays) /* 317 */ +ICD_ENTRY(NormalPointer) /* 318 */ +ICD_ENTRY(PolygonOffset) /* 319 */ +ICD_ENTRY(TexCoordPointer) /* 320 */ +ICD_ENTRY(VertexPointer) /* 321 */ +ICD_ENTRY(AreTexturesResident) /* 322 */ +ICD_ENTRY(CopyTexImage1D) /* 323 */ +ICD_ENTRY(CopyTexImage2D) /* 324 */ +ICD_ENTRY(CopyTexSubImage1D) /* 325 */ +ICD_ENTRY(CopyTexSubImage2D) /* 326 */ +ICD_ENTRY(DeleteTextures) /* 327 */ +ICD_ENTRY(GenTextures) /* 328 */ +ICD_ENTRY(GetPointerv) /* 329 */ +ICD_ENTRY(IsTexture) /* 330 */ +ICD_ENTRY(PrioritizeTextures) /* 331 */ +ICD_ENTRY(TexSubImage1D) /* 332 */ +ICD_ENTRY(TexSubImage2D) /* 333 */ +ICD_ENTRY(PopClientAttrib) /* 334 */ +ICD_ENTRY(PushClientAttrib) /* 335 */ diff --git a/src/VBox/Additions/common/crOpenGL/alias_exports.py b/src/VBox/Additions/common/crOpenGL/alias_exports.py new file mode 100644 index 00000000..5d16139a --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/alias_exports.py @@ -0,0 +1,168 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +aliases = [ + # GL_ARB_multitexture / OpenGL 1.2.1 + ('ActiveTexture', 'ActiveTextureARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('ClientActiveTexture', 'ClientActiveTextureARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord1d', 'MultiTexCoord1dARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord1dv','MultiTexCoord1dvARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord1f', 'MultiTexCoord1fARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord1fv','MultiTexCoord1fvARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord1i', 'MultiTexCoord1iARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord1iv','MultiTexCoord1ivARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord1s', 'MultiTexCoord1sARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord1sv','MultiTexCoord1svARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord2d', 'MultiTexCoord2dARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord2dv','MultiTexCoord2dvARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord2f', 'MultiTexCoord2fARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord2fv','MultiTexCoord2fvARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord2i', 'MultiTexCoord2iARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord2iv','MultiTexCoord2ivARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord2s', 'MultiTexCoord2sARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord2sv','MultiTexCoord2svARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord3d', 'MultiTexCoord3dARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord3dv','MultiTexCoord3dvARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord3f', 'MultiTexCoord3fARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord3fv','MultiTexCoord3fvARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord3i', 'MultiTexCoord3iARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord3iv','MultiTexCoord3ivARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord3s', 'MultiTexCoord3sARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord3sv','MultiTexCoord3svARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord4d', 'MultiTexCoord4dARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord4dv','MultiTexCoord4dvARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord4f', 'MultiTexCoord4fARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord4fv','MultiTexCoord4fvARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord4i', 'MultiTexCoord4iARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord4iv','MultiTexCoord4ivARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord4s', 'MultiTexCoord4sARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + ('MultiTexCoord4sv','MultiTexCoord4svARB', 'ARB_multitexture', 'CR_OPENGL_VERSION_1_2_1'), + # GL_ARB_transpose_matrix / OpenGL 1.3 + ('LoadTransposeMatrixf','LoadTransposeMatrixfARB', 'ARB_transpose_matrix', 'CR_OPENGL_VERSION_1_3'), + ('LoadTransposeMatrixd','LoadTransposeMatrixdARB', 'ARB_transpose_matrix', 'CR_OPENGL_VERSION_1_3'), + ('MultTransposeMatrixf','MultTransposeMatrixfARB', 'ARB_transpose_matrix', 'CR_OPENGL_VERSION_1_3'), + ('MultTransposeMatrixd','MultTransposeMatrixdARB', 'ARB_transpose_matrix', 'CR_OPENGL_VERSION_1_3'), + # GL_ARB_texture_compression / OpenGL 1.3 + ('CompressedTexImage3D', 'CompressedTexImage3DARB', 'ARB_texture_compression', 'CR_OPENGL_VERSION_1_3'), + ('CompressedTexImage2D', 'CompressedTexImage2DARB', 'ARB_texture_compression', 'CR_OPENGL_VERSION_1_3'), + ('CompressedTexImage1D', 'CompressedTexImage1DARB', 'ARB_texture_compression', 'CR_OPENGL_VERSION_1_3'), + ('CompressedTexSubImage3D', 'CompressedTexSubImage3DARB', 'ARB_texture_compression', 'CR_OPENGL_VERSION_1_3'), + ('CompressedTexSubImage2D', 'CompressedTexSubImage2DARB', 'ARB_texture_compression', 'CR_OPENGL_VERSION_1_3'), + ('CompressedTexSubImage1D', 'CompressedTexSubImage1DARB', 'ARB_texture_compression', 'CR_OPENGL_VERSION_1_3'), + ('GetCompressedTexImage', 'GetCompressedTexImageARB', 'ARB_texture_compression', 'CR_OPENGL_VERSION_1_3'), + # GL_ARB_multisample / OpenGL 1.3 + ('SampleCoverage', 'SampleCoverageARB', 'ARB_multisample', 'CR_OPENGL_VERSION_1_3'), + # GL_ARB_window_pos / OpenGL 1.4 + ('WindowPos2d', 'WindowPos2dARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + + ('WindowPos2dv', 'WindowPos2dvARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + ('WindowPos2f', 'WindowPos2fARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + ('WindowPos2fv', 'WindowPos2fvARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + ('WindowPos2i', 'WindowPos2iARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + ('WindowPos2iv', 'WindowPos2ivARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + ('WindowPos2s', 'WindowPos2sARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + ('WindowPos2sv', 'WindowPos2svARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + ('WindowPos3d', 'WindowPos3dARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + ('WindowPos3dv', 'WindowPos3dvARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + ('WindowPos3f', 'WindowPos3fARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + ('WindowPos3fv', 'WindowPos3fvARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + ('WindowPos3i', 'WindowPos3iARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + ('WindowPos3iv', 'WindowPos3ivARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + ('WindowPos3s', 'WindowPos3sARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + ('WindowPos3sv', 'WindowPos3svARB', 'ARB_window_pos', 'CR_OPENGL_VERSION_1_4'), + # GL_ARB_point_parameters / OpenGL 1.4 + ('PointParameterf', 'PointParameterfARB', 'ARB_point_parameters', 'CR_OPENGL_VERSION_1_4'), + ('PointParameterfv', 'PointParameterfvARB', 'ARB_point_parameters', 'CR_OPENGL_VERSION_1_4'), + # GL_EXT_blend_color / OpenGL 1.4 + ('BlendColor', 'BlendColorEXT', 'EXT_blend_color', 'CR_OPENGL_VERSION_1_4'), + # GL_EXT_blend_func_separate / OpenGL 1.4 + ('BlendFuncSeparate', 'BlendFuncSeparateEXT', 'EXT_blend_func_separate', 'CR_OPENGL_VERSION_1_4'), + # GL_EXT_blend_equation / OpenGL 1.4 + ('BlendEquation', 'BlendEquationEXT', 'EXT_blend_equation', 'CR_OPENGL_VERSION_1_4'), + # GL_EXT_multi_draw_arrays / OpenGL 1.4 + ('MultiDrawArrays', 'MultiDrawArraysEXT', 'EXT_multi_draw_arrays', 'CR_OPENGL_VERSION_1_4'), + ('MultiDrawElements', 'MultiDrawElementsEXT', 'EXT_multi_draw_arrays', 'CR_OPENGL_VERSION_1_4'), + # GL_EXT_secondary_color / OpenGL 1.4 + ('SecondaryColor3b', 'SecondaryColor3bEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3bv', 'SecondaryColor3bvEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3d', 'SecondaryColor3dEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3dv', 'SecondaryColor3dvEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3f', 'SecondaryColor3fEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3fv', 'SecondaryColor3fvEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3i', 'SecondaryColor3iEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3iv', 'SecondaryColor3ivEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3s', 'SecondaryColor3sEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3sv', 'SecondaryColor3svEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3ub', 'SecondaryColor3ubEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3ubv', 'SecondaryColor3ubvEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3ui', 'SecondaryColor3uiEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3uiv', 'SecondaryColor3uivEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3us', 'SecondaryColor3usEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColor3usv', 'SecondaryColor3usvEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + ('SecondaryColorPointer', 'SecondaryColorPointerEXT', 'EXT_secondary_color', 'CR_OPENGL_VERSION_1_4'), + # GL_EXT_fog_coord / OpenGL 1.4 + ('FogCoordf', 'FogCoordfEXT', 'EXT_fog_coord', 'CR_OPENGL_VERSION_1_4'), + ('FogCoordfv', 'FogCoordfvEXT', 'EXT_fog_coord', 'CR_OPENGL_VERSION_1_4'), + ('FogCoordd', 'FogCoorddEXT', 'EXT_fog_coord', 'CR_OPENGL_VERSION_1_4'), + ('FogCoorddv', 'FogCoorddvEXT', 'EXT_fog_coord', 'CR_OPENGL_VERSION_1_4'), + ('FogCoordPointer', 'FogCoordPointerEXT', 'EXT_fog_coord', 'CR_OPENGL_VERSION_1_4'), + # GL_EXT_texture_object / OpenGL 1.1 + ('AreTexturesResidentEXT', 'AreTexturesResident', 'EXT_texture_object', 'CR_OPENGL_VERSION_1_1'), + ('BindTextureEXT', 'BindTexture', 'EXT_texture_object', 'CR_OPENGL_VERSION_1_1'), + ('DeleteTexturesEXT', 'DeleteTextures', 'EXT_texture_object', 'CR_OPENGL_VERSION_1_1'), + ('GenTexturesEXT', 'GenTextures', 'EXT_texture_object', 'CR_OPENGL_VERSION_1_1'), + ('IsTextureEXT', 'IsTexture', 'EXT_texture_object', 'CR_OPENGL_VERSION_1_1'), + ('PrioritizeTexturesEXT', 'PrioritizeTextures', 'EXT_texture_object', 'CR_OPENGL_VERSION_1_1'), + # GL_EXT_texture3D / OpenGL 1.2 + ('TexSubImage3DEXT', 'TexSubImage3D', 'EXT_texture3D', 'CR_OPENGL_VERSION_1_2'), + + # GL_NV_vertex_program / GL_ARB_vertex_program + ('VertexAttrib1sNV', 'VertexAttrib1sARB', 'ARB_vertex_program', ''), + ('VertexAttrib1svNV', 'VertexAttrib1svARB', 'ARB_vertex_program', ''), + ('VertexAttrib1fNV', 'VertexAttrib1fARB', 'ARB_vertex_program', ''), + ('VertexAttrib1fvNV', 'VertexAttrib1fvARB', 'ARB_vertex_program', ''), + ('VertexAttrib1dNV', 'VertexAttrib1dARB', 'ARB_vertex_program', ''), + ('VertexAttrib1dvNV', 'VertexAttrib1dvARB', 'ARB_vertex_program', ''), + ('VertexAttrib2sNV', 'VertexAttrib2sARB', 'ARB_vertex_program', ''), + ('VertexAttrib2svNV', 'VertexAttrib2svARB', 'ARB_vertex_program', ''), + ('VertexAttrib2fNV', 'VertexAttrib2fARB', 'ARB_vertex_program', ''), + ('VertexAttrib2fvNV', 'VertexAttrib2fvARB', 'ARB_vertex_program', ''), + ('VertexAttrib2dNV', 'VertexAttrib2dARB', 'ARB_vertex_program', ''), + ('VertexAttrib2dvNV', 'VertexAttrib2dvARB', 'ARB_vertex_program', ''), + ('VertexAttrib3sNV', 'VertexAttrib3sARB', 'ARB_vertex_program', ''), + ('VertexAttrib3svNV', 'VertexAttrib3svARB', 'ARB_vertex_program', ''), + ('VertexAttrib3fNV', 'VertexAttrib3fARB', 'ARB_vertex_program', ''), + ('VertexAttrib3fvNV', 'VertexAttrib3fvARB', 'ARB_vertex_program', ''), + ('VertexAttrib3dNV', 'VertexAttrib3dARB', 'ARB_vertex_program', ''), + ('VertexAttrib3dvNV', 'VertexAttrib3dvARB', 'ARB_vertex_program', ''), + ('VertexAttrib4sNV', 'VertexAttrib4sARB', 'ARB_vertex_program', ''), + ('VertexAttrib4svNV', 'VertexAttrib4svARB', 'ARB_vertex_program', ''), + ('VertexAttrib4fNV', 'VertexAttrib4fARB', 'ARB_vertex_program', ''), + ('VertexAttrib4fvNV', 'VertexAttrib4fvARB', 'ARB_vertex_program', ''), + ('VertexAttrib4dNV', 'VertexAttrib4dARB', 'ARB_vertex_program', ''), + ('VertexAttrib4dvNV', 'VertexAttrib4dvARB', 'ARB_vertex_program', ''), + ('VertexAttrib4ubNV', 'VertexAttrib4NubARB', 'ARB_vertex_program', ''), + ('VertexAttrib4ubvNV', 'VertexAttrib4NubvARB', 'ARB_vertex_program', ''), + ('DeleteProgramsNV', 'DeleteProgramsARB', 'ARB_vertex_program', ''), + ('IsProgramNV', 'IsProgramARB', 'ARB_vertex_program', '') +] + +def AliasMap( func_name ): + for (aliased_func_name, real_func_name, ext_define, gl_version) in aliases: + if real_func_name == func_name: + return aliased_func_name; + return None + +def ExtDefine( func_name ): + for (aliased_func_name, real_func_name, ext_define, gl_version) in aliases: + if real_func_name == func_name: + return ext_define; + return None + +def GLversion( func_name ): + for (aliased_func_name, real_func_name, ext_define, gl_version) in aliases: + if real_func_name == func_name: + return gl_version; + return None diff --git a/src/VBox/Additions/common/crOpenGL/array/Makefile.kup b/src/VBox/Additions/common/crOpenGL/array/Makefile.kup new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/array/Makefile.kup diff --git a/src/VBox/Additions/common/crOpenGL/array/arrayspu.c b/src/VBox/Additions/common/crOpenGL/array/arrayspu.c new file mode 100644 index 00000000..da230ee5 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/array/arrayspu.c @@ -0,0 +1,944 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "cr_spu.h" +#include "cr_error.h" +#include "state/cr_limits.h" +#include "arrayspu.h" + +ArraySPU array_spu; + +#ifdef CHROMIUM_THREADSAFE +CRmutex _ArrayMutex; +#endif + +static void ARRAYSPU_APIENTRY arrayspu_ArrayElement( GLint index ) +{ + const CRClientState *c = &(crStateGetCurrent()->client); + const CRVertexArrays *array = &(c->array); + const GLboolean vpEnabled = crStateGetCurrent()->program.vpEnabled; + unsigned char *p; + unsigned int unit, attr; + + if (array->e.enabled) + { + p = array->e.p + index * array->e.stride; + +#ifdef CR_ARB_vertex_buffer_object + if (array->e.buffer && array->e.buffer->data) + { + p = (unsigned char *)(array->e.buffer->data) + (unsigned long)p; + } +#endif + + array_spu.self.EdgeFlagv(p); + } + + /* + * Vertex attribute arrays (GL_NV_vertex_program) have priority over + * the conventional vertex arrays. + */ + if (vpEnabled) + { + for (attr = 1; attr < VERT_ATTRIB_MAX; attr++) + { + if (array->a[attr].enabled) + { + GLint *iPtr; + p = array->a[attr].p + index * array->a[attr].stride; + +#ifdef CR_ARB_vertex_buffer_object + if (array->a[attr].buffer && array->a[attr].buffer->data) + { + p = (unsigned char *)(array->a[attr].buffer->data) + (unsigned long)p; + } +#endif + + switch (array->a[attr].type) + { + case GL_SHORT: + switch (array->a[attr].size) + { + case 1: array_spu.self.VertexAttrib1svARB(attr, (GLshort *)p); break; + case 2: array_spu.self.VertexAttrib2svARB(attr, (GLshort *)p); break; + case 3: array_spu.self.VertexAttrib3svARB(attr, (GLshort *)p); break; + case 4: array_spu.self.VertexAttrib4svARB(attr, (GLshort *)p); break; + } + break; + case GL_INT: + iPtr = (GLint *) p; + switch (array->a[attr].size) + { + case 1: array_spu.self.VertexAttrib1fARB(attr, p[0]); break; + case 2: array_spu.self.VertexAttrib2fARB(attr, p[0], p[1]); break; + case 3: array_spu.self.VertexAttrib3fARB(attr, p[0], p[1], p[2]); break; + case 4: array_spu.self.VertexAttrib4fARB(attr, p[0], p[1], p[2], p[3]); break; + } + break; + case GL_FLOAT: + switch (array->a[attr].size) + { + case 1: array_spu.self.VertexAttrib1fvARB(attr, (GLfloat *)p); break; + case 2: array_spu.self.VertexAttrib2fvARB(attr, (GLfloat *)p); break; + case 3: array_spu.self.VertexAttrib3fvARB(attr, (GLfloat *)p); break; + case 4: array_spu.self.VertexAttrib4fvARB(attr, (GLfloat *)p); break; + } + break; + case GL_DOUBLE: + switch (array->a[attr].size) + { + case 1: array_spu.self.VertexAttrib1dvARB(attr, (GLdouble *)p); break; + case 2: array_spu.self.VertexAttrib2dvARB(attr, (GLdouble *)p); break; + case 3: array_spu.self.VertexAttrib3dvARB(attr, (GLdouble *)p); break; + case 4: array_spu.self.VertexAttrib4dvARB(attr, (GLdouble *)p); break; + } + break; + default: + crWarning("Bad datatype for vertex attribute [%d] array: 0x%x\n", + attr, array->a[attr].type); + } + } + } + } + + /* Now do conventional arrays, unless overridden by generic arrays above */ + for (unit = 0 ; unit < crStateGetCurrent()->limits.maxTextureUnits ; unit++) + { + if (array->t[unit].enabled && !(vpEnabled && array->a[VERT_ATTRIB_TEX0+unit].enabled)) + { + p = array->t[unit].p + index * array->t[unit].stride; + +#ifdef CR_ARB_vertex_buffer_object + if (array->t[unit].buffer && array->t[unit].buffer->data) + { + p = (unsigned char *)(array->t[unit].buffer->data) + (unsigned long)p; + } +#endif + + switch (array->t[unit].type) + { + case GL_SHORT: + switch (array->t[unit].size) + { + case 1: array_spu.self.MultiTexCoord1svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; + case 2: array_spu.self.MultiTexCoord2svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; + case 3: array_spu.self.MultiTexCoord3svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; + case 4: array_spu.self.MultiTexCoord4svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; + } + break; + case GL_INT: + switch (array->t[unit].size) + { + case 1: array_spu.self.MultiTexCoord1ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; + case 2: array_spu.self.MultiTexCoord2ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; + case 3: array_spu.self.MultiTexCoord3ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; + case 4: array_spu.self.MultiTexCoord4ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; + } + break; + case GL_FLOAT: + switch (array->t[unit].size) + { + case 1: array_spu.self.MultiTexCoord1fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; + case 2: array_spu.self.MultiTexCoord2fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; + case 3: array_spu.self.MultiTexCoord3fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; + case 4: array_spu.self.MultiTexCoord4fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; + } + break; + case GL_DOUBLE: + switch (array->t[unit].size) + { + case 1: array_spu.self.MultiTexCoord1dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; + case 2: array_spu.self.MultiTexCoord2dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; + case 3: array_spu.self.MultiTexCoord3dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; + case 4: array_spu.self.MultiTexCoord4dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; + } + break; + } + } + } + if (array->i.enabled) + { + p = array->i.p + index * array->i.stride; + +#ifdef CR_ARB_vertex_buffer_object + if (array->i.buffer && array->i.buffer->data) + { + p = (unsigned char *)(array->i.buffer->data) + (unsigned long)p; + } +#endif + + switch (array->i.type) + { + case GL_SHORT: array_spu.self.Indexsv((GLshort *)p); break; + case GL_INT: array_spu.self.Indexiv((GLint *)p); break; + case GL_FLOAT: array_spu.self.Indexfv((GLfloat *)p); break; + case GL_DOUBLE: array_spu.self.Indexdv((GLdouble *)p); break; + } + } + if (array->c.enabled && !(vpEnabled && array->a[VERT_ATTRIB_COLOR0].enabled)) + { + p = array->c.p + index * array->c.stride; + +#ifdef CR_ARB_vertex_buffer_object + if (array->c.buffer && array->c.buffer->data) + { + p = (unsigned char *)(array->c.buffer->data) + (unsigned long)p; + } +#endif + + switch (array->c.type) + { + case GL_BYTE: + switch (array->c.size) + { + case 3: array_spu.self.Color3bv((GLbyte *)p); break; + case 4: array_spu.self.Color4bv((GLbyte *)p); break; + } + break; + case GL_UNSIGNED_BYTE: + switch (array->c.size) + { + case 3: array_spu.self.Color3ubv((GLubyte *)p); break; + case 4: array_spu.self.Color4ubv((GLubyte *)p); break; + } + break; + case GL_SHORT: + switch (array->c.size) + { + case 3: array_spu.self.Color3sv((GLshort *)p); break; + case 4: array_spu.self.Color4sv((GLshort *)p); break; + } + break; + case GL_UNSIGNED_SHORT: + switch (array->c.size) + { + case 3: array_spu.self.Color3usv((GLushort *)p); break; + case 4: array_spu.self.Color4usv((GLushort *)p); break; + } + break; + case GL_INT: + switch (array->c.size) + { + case 3: array_spu.self.Color3iv((GLint *)p); break; + case 4: array_spu.self.Color4iv((GLint *)p); break; + } + break; + case GL_UNSIGNED_INT: + switch (array->c.size) + { + case 3: array_spu.self.Color3uiv((GLuint *)p); break; + case 4: array_spu.self.Color4uiv((GLuint *)p); break; + } + break; + case GL_FLOAT: + switch (array->c.size) + { + case 3: array_spu.self.Color3fv((GLfloat *)p); break; + case 4: array_spu.self.Color4fv((GLfloat *)p); break; + } + break; + case GL_DOUBLE: + switch (array->c.size) + { + case 3: array_spu.self.Color3dv((GLdouble *)p); break; + case 4: array_spu.self.Color4dv((GLdouble *)p); break; + } + break; + } + } + if (array->n.enabled && !(vpEnabled && array->a[VERT_ATTRIB_NORMAL].enabled)) + { + p = array->n.p + index * array->n.stride; + +#ifdef CR_ARB_vertex_buffer_object + if (array->n.buffer && array->n.buffer->data) + { + p = (unsigned char *)(array->n.buffer->data) + (unsigned long)p; + } +#endif + + switch (array->n.type) + { + case GL_BYTE: array_spu.self.Normal3bv((GLbyte *)p); break; + case GL_SHORT: array_spu.self.Normal3sv((GLshort *)p); break; + case GL_INT: array_spu.self.Normal3iv((GLint *)p); break; + case GL_FLOAT: array_spu.self.Normal3fv((GLfloat *)p); break; + case GL_DOUBLE: array_spu.self.Normal3dv((GLdouble *)p); break; + } + } +#ifdef CR_EXT_secondary_color + if (array->s.enabled && !(vpEnabled && array->a[VERT_ATTRIB_COLOR1].enabled)) + { + p = array->s.p + index * array->s.stride; + +#ifdef CR_ARB_vertex_buffer_object + if (array->s.buffer && array->s.buffer->data) + { + p = (unsigned char *)(array->s.buffer->data) + (unsigned long)p; + } +#endif + + switch (array->s.type) + { + case GL_BYTE: + array_spu.self.SecondaryColor3bvEXT((GLbyte *)p); break; + case GL_UNSIGNED_BYTE: + array_spu.self.SecondaryColor3ubvEXT((GLubyte *)p); break; + case GL_SHORT: + array_spu.self.SecondaryColor3svEXT((GLshort *)p); break; + case GL_UNSIGNED_SHORT: + array_spu.self.SecondaryColor3usvEXT((GLushort *)p); break; + case GL_INT: + array_spu.self.SecondaryColor3ivEXT((GLint *)p); break; + case GL_UNSIGNED_INT: + array_spu.self.SecondaryColor3uivEXT((GLuint *)p); break; + case GL_FLOAT: + array_spu.self.SecondaryColor3fvEXT((GLfloat *)p); break; + case GL_DOUBLE: + array_spu.self.SecondaryColor3dvEXT((GLdouble *)p); break; + } + } +#endif // CR_EXT_secondary_color +#ifdef CR_EXT_fog_coord + if (array->f.enabled && !(vpEnabled && array->a[VERT_ATTRIB_FOG].enabled)) + { + p = array->f.p + index * array->f.stride; + +#ifdef CR_ARB_vertex_buffer_object + if (array->f.buffer && array->f.buffer->data) + { + p = (unsigned char *)(array->f.buffer->data) + (unsigned long)p; + } +#endif + + array_spu.self.FogCoordfEXT( *((GLfloat *) p) ); + } +#endif // CR_EXT_fog_coord + + /* Need to do attrib[0] / vertex position last */ + if (array->a[VERT_ATTRIB_POS].enabled) { + GLint *iPtr; + p = array->a[VERT_ATTRIB_POS].p + index * array->a[VERT_ATTRIB_POS].stride; + +#ifdef CR_ARB_vertex_buffer_object + if (array->a[VERT_ATTRIB_POS].buffer && array->a[VERT_ATTRIB_POS].buffer->data) + { + p = (unsigned char *)(array->a[VERT_ATTRIB_POS].buffer->data) + (unsigned long)p; + } +#endif + + switch (array->a[VERT_ATTRIB_POS].type) + { + case GL_SHORT: + switch (array->a[VERT_ATTRIB_POS].size) + { + case 1: array_spu.self.VertexAttrib1svARB(0, (GLshort *)p); break; + case 2: array_spu.self.VertexAttrib2svARB(0, (GLshort *)p); break; + case 3: array_spu.self.VertexAttrib3svARB(0, (GLshort *)p); break; + case 4: array_spu.self.VertexAttrib4svARB(0, (GLshort *)p); break; + } + break; + case GL_INT: + iPtr = (GLint *) p; + switch (array->a[VERT_ATTRIB_POS].size) + { + case 1: array_spu.self.VertexAttrib1fARB(0, p[0]); break; + case 2: array_spu.self.VertexAttrib2fARB(0, p[0], p[1]); break; + case 3: array_spu.self.VertexAttrib3fARB(0, p[0], p[1], p[2]); break; + case 4: array_spu.self.VertexAttrib4fARB(0, p[0], p[1], p[2], p[3]); break; + } + break; + case GL_FLOAT: + switch (array->a[VERT_ATTRIB_POS].size) + { + case 1: array_spu.self.VertexAttrib1fvARB(0, (GLfloat *)p); break; + case 2: array_spu.self.VertexAttrib2fvARB(0, (GLfloat *)p); break; + case 3: array_spu.self.VertexAttrib3fvARB(0, (GLfloat *)p); break; + case 4: array_spu.self.VertexAttrib4fvARB(0, (GLfloat *)p); break; + } + break; + case GL_DOUBLE: + switch (array->a[VERT_ATTRIB_POS].size) + { + case 1: array_spu.self.VertexAttrib1dvARB(0, (GLdouble *)p); break; + case 2: array_spu.self.VertexAttrib2dvARB(0, (GLdouble *)p); break; + case 3: array_spu.self.VertexAttrib3dvARB(0, (GLdouble *)p); break; + case 4: array_spu.self.VertexAttrib4dvARB(0, (GLdouble *)p); break; + } + break; + default: + crWarning("Bad datatype for vertex attribute [0] array: 0x%x\n", array->a[0].type); + } + } + else if (array->v.enabled) + { + p = array->v.p + index * array->v.stride; + +#ifdef CR_ARB_vertex_buffer_object + if (array->v.buffer && array->v.buffer->data) + { + p = (unsigned char *)(array->v.buffer->data) + (unsigned long)p; + } +#endif + + switch (array->v.type) + { + case GL_SHORT: + switch (array->v.size) + { + case 2: array_spu.self.Vertex2sv((GLshort *)p); break; + case 3: array_spu.self.Vertex3sv((GLshort *)p); break; + case 4: array_spu.self.Vertex4sv((GLshort *)p); break; + } + break; + case GL_INT: + switch (array->v.size) + { + case 2: array_spu.self.Vertex2iv((GLint *)p); break; + case 3: array_spu.self.Vertex3iv((GLint *)p); break; + case 4: array_spu.self.Vertex4iv((GLint *)p); break; + } + break; + case GL_FLOAT: + switch (array->v.size) + { + case 2: array_spu.self.Vertex2fv((GLfloat *)p); break; + case 3: array_spu.self.Vertex3fv((GLfloat *)p); break; + case 4: array_spu.self.Vertex4fv((GLfloat *)p); break; + } + break; + case GL_DOUBLE: + switch (array->v.size) + { + case 2: array_spu.self.Vertex2dv((GLdouble *)p); break; + case 3: array_spu.self.Vertex3dv((GLdouble *)p); break; + case 4: array_spu.self.Vertex4dv((GLdouble *)p); break; + } + break; + default: + crWarning("Bad datatype for vertex array: 0x%x\n", array->v.type); + } + } +} + +static void ARRAYSPU_APIENTRY arrayspu_DrawArrays(GLenum mode, GLint first, GLsizei count) +{ + int i; + + if (count < 0) + { + crError("array_spu.self.DrawArrays passed negative count: %d", count); + } + + if (mode > GL_POLYGON) + { + crError("array_spu.self.DrawArrays called with invalid mode: %d", mode); + } + + array_spu.self.Begin(mode); + for (i=0; i<count; i++) + { + array_spu.self.ArrayElement(first++); + } + array_spu.self.End(); +} + +static void ARRAYSPU_APIENTRY arrayspu_DrawElements(GLenum mode, GLsizei count, + GLenum type, const GLvoid *indices) +{ + int i; + GLubyte *p = (GLubyte *)indices; +#ifdef CR_ARB_vertex_buffer_object + CRBufferObject *elementsBuffer = crStateGetCurrent()->bufferobject.elementsBuffer; +#endif + + if (count < 0) + { + crError("array_spu.self.DrawElements passed negative count: %d", count); + } + + if (mode > GL_POLYGON) + { + crError("array_spu.self.DrawElements called with invalid mode: %d", mode); + } + + if (type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT && type != GL_UNSIGNED_INT) + { + crError("array_spu.self.DrawElements called with invalid type: %d", type); + } + +#ifdef CR_ARB_vertex_buffer_object + if (elementsBuffer && elementsBuffer->data) + { + p = (unsigned char *)(elementsBuffer->data) + (unsigned long)p; + } +#endif + //crDebug("arrayspu_DrawElements mode:0x%x, count:%d, type:0x%x", mode, count, type); + + + array_spu.self.Begin(mode); + switch (type) + { + case GL_UNSIGNED_BYTE: + for (i=0; i<count; i++) + { + array_spu.self.ArrayElement((GLint) *p++); + } + break; + case GL_UNSIGNED_SHORT: + for (i=0; i<count; i++) + { + array_spu.self.ArrayElement((GLint) * (GLushort *) p); + p+=sizeof (GLushort); + } + break; + case GL_UNSIGNED_INT: + for (i=0; i<count; i++) + { + array_spu.self.ArrayElement((GLint) * (GLuint *) p); + p+=sizeof (GLuint); + } + break; + default: + crError( "this can't happen: array_spu.self.DrawElements" ); + break; + } + array_spu.self.End(); +} + +static void ARRAYSPU_APIENTRY arrayspu_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) +{ + if (start>end) + { + crError("array_spu.self.arrayspu_DrawRangeElements start>end (%d>%d)", start, end); + } + + arrayspu_DrawElements(mode, count, type, indices); +} + +static void ARRAYSPU_APIENTRY arrayspu_ColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) +{ + crStateColorPointer(size, type, stride, pointer); + array_spu.child.ColorPointer(size, type, stride, pointer); +} + +static void ARRAYSPU_APIENTRY arrayspu_SecondaryColorPointerEXT( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) +{ + crStateSecondaryColorPointerEXT(size, type, stride, pointer); + array_spu.child.SecondaryColorPointerEXT(size, type, stride, pointer); +} + +static void ARRAYSPU_APIENTRY arrayspu_VertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) +{ + crStateVertexPointer(size, type, stride, pointer); + array_spu.child.VertexPointer(size, type, stride, pointer); +} + +static void ARRAYSPU_APIENTRY arrayspu_TexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) +{ + crStateTexCoordPointer(size, type, stride, pointer); + array_spu.child.TexCoordPointer(size, type, stride, pointer); +} + +static void ARRAYSPU_APIENTRY arrayspu_NormalPointer( GLenum type, GLsizei stride, const GLvoid *pointer ) +{ + crStateNormalPointer(type, stride, pointer); + array_spu.child.NormalPointer(type, stride, pointer); +} + +static void ARRAYSPU_APIENTRY arrayspu_IndexPointer( GLenum type, GLsizei stride, const GLvoid *pointer ) +{ + crStateIndexPointer(type, stride, pointer); + array_spu.child.IndexPointer(type, stride, pointer); +} + +static void ARRAYSPU_APIENTRY arrayspu_EdgeFlagPointer( GLsizei stride, const GLvoid *pointer ) +{ + crStateEdgeFlagPointer(stride, pointer); + array_spu.child.EdgeFlagPointer(stride, pointer); +} + +static void ARRAYSPU_APIENTRY arrayspu_VertexAttribPointerNV( GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer ) +{ + crStateVertexAttribPointerNV(index, size, type, stride, pointer); + array_spu.child.VertexAttribPointerNV(index, size, type, stride, pointer); +} + +static void ARRAYSPU_APIENTRY arrayspu_FogCoordPointerEXT( GLenum type, GLsizei stride, const GLvoid *pointer ) +{ + crStateFogCoordPointerEXT(type, stride, pointer); + array_spu.child.FogCoordPointerEXT(type, stride, pointer); +} + +static void ARRAYSPU_APIENTRY arrayspu_GetPointerv( GLenum pname, GLvoid **params ) +{ + crStateGetPointerv(pname, params); +} + +static void ARRAYSPU_APIENTRY arrayspu_EnableClientState( GLenum array ) +{ + crStateEnableClientState(array); + array_spu.child.EnableClientState(array); +} + +static void ARRAYSPU_APIENTRY arrayspu_DisableClientState( GLenum array ) +{ + crStateDisableClientState(array); + array_spu.child.DisableClientState(array); +} + +static void ARRAYSPU_APIENTRY arrayspu_ClientActiveTextureARB( GLenum texture ) +{ + crStateClientActiveTextureARB(texture); + array_spu.child.ClientActiveTextureARB(texture); +} + +static void ARRAYSPU_APIENTRY arrayspu_MultiDrawArraysEXT(GLenum mode, GLint *first, GLsizei *count, GLsizei primcount) +{ + int i; + + if (primcount < 0) + { + crError("array_spu.self.MultiDrawArraysEXT passed negative count: %d", primcount); + } + + if (mode > GL_POLYGON) + { + crError("array_spu.self.MultiDrawArraysEXT called with invalid mode: %d", mode); + } + + for (i = 0; i < primcount; i++) + { + array_spu.self.DrawArrays(mode, first[i], count[i]); + } +} + +static void ARRAYSPU_APIENTRY arrayspu_MultiDrawElementsEXT(GLenum mode, GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount) +{ + int i; + + if (primcount < 0) + { + crError("array_spu.self.MultiDrawElementsEXT passed negative count: %d", primcount); + } + + if (mode > GL_POLYGON) + { + crError("array_spu.self.MultiDrawElementsEXT called with invalid mode: %d", mode); + } + + if (type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT && type != GL_UNSIGNED_INT) + { + crError("array_spu.self.MultiDrawElementsEXT called with invalid type: %d", type); + } + + for (i = 0; i < primcount; i++) + { + array_spu.self.DrawElements(mode, count[i], type, indices[i]); + } +} + +/* + * We need to know when vertex program mode is enabled/disabled + * in order to handle vertex attribute arrays correctly. + */ +static void ARRAYSPU_APIENTRY arrayspu_Enable(GLenum cap) +{ + if (cap == GL_VERTEX_PROGRAM_NV) { + crStateGetCurrent()->program.vpEnabled = GL_TRUE; + } + array_spu.child.Enable(cap); +} + + +static void ARRAYSPU_APIENTRY arrayspu_Disable(GLenum cap) +{ + if (cap == GL_VERTEX_PROGRAM_NV) { + crStateGetCurrent()->program.vpEnabled = GL_FALSE; + } + array_spu.child.Disable(cap); +} + +/** @todo it's a hack, as GLSL shouldn't blindly reuse this bit from nv_vertex_program*/ +static void ARRAYSPU_APIENTRY arrayspu_UseProgram(GLuint program) +{ + crStateGetCurrent()->program.vpEnabled = program>0; + array_spu.child.UseProgram(program); +} + +static void ARRAYSPU_APIENTRY +arrayspu_VertexAttribPointerARB(GLuint index, GLint size, GLenum type, + GLboolean normalized, GLsizei stride, + const GLvoid *pointer) +{ + crStateVertexAttribPointerARB(index, size, type, normalized, stride, pointer); + array_spu.child.VertexAttribPointerARB(index, size, type, normalized, stride, pointer); +} + + +static void ARRAYSPU_APIENTRY +arrayspu_EnableVertexAttribArrayARB(GLuint index) +{ + crStateEnableVertexAttribArrayARB(index); +} + + +static void ARRAYSPU_APIENTRY +arrayspu_DisableVertexAttribArrayARB(GLuint index) +{ + crStateDisableVertexAttribArrayARB(index); +} + + +/* We need to implement Push/PopClientAttrib here so that _our_ state + * tracker gets used. Also, pass the call onto the next SPU (in case + * it's the GL_CLIENT_PIXEL_STORE_BIT, etc). + */ +static void ARRAYSPU_APIENTRY +arrayspu_PushClientAttrib( GLbitfield mask ) +{ + crStatePushClientAttrib(mask); + array_spu.child.PushClientAttrib(mask); +} + + +static void ARRAYSPU_APIENTRY +arrayspu_PopClientAttrib( void ) +{ + crStatePopClientAttrib(); + array_spu.child.PopClientAttrib(); +} + + +static void ARRAYSPU_APIENTRY +arrayspu_GenBuffersARB( GLsizei n, GLuint * buffers ) +{ + array_spu.child.GenBuffersARB(n, buffers); +} + +static void ARRAYSPU_APIENTRY +arrayspu_DeleteBuffersARB( GLsizei n, const GLuint *buffers ) +{ + crStateDeleteBuffersARB(n, buffers); + array_spu.child.DeleteBuffersARB(n, buffers); +} + +static void ARRAYSPU_APIENTRY +arrayspu_BindBufferARB( GLenum target, GLuint buffer ) +{ + crStateBindBufferARB(target, buffer); + array_spu.child.BindBufferARB(target, buffer); +} + +static GLboolean ARRAYSPU_APIENTRY +arrayspu_IsBufferARB (GLuint buffer) +{ + return array_spu.child.IsBufferARB(buffer); +} + +static void ARRAYSPU_APIENTRY +arrayspu_BufferDataARB( GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage ) +{ + crStateBufferDataARB(target, size, data, usage); + array_spu.child.BufferDataARB(target, size, data, usage); +} + +static void ARRAYSPU_APIENTRY +arrayspu_BufferSubDataARB( GLenum target, GLintptrARB offset, + GLsizeiptrARB size, const GLvoid * data ) +{ + crStateBufferSubDataARB(target, offset, size, data); + array_spu.child.BufferSubDataARB(target, offset, size, data); +} + +static void ARRAYSPU_APIENTRY +arrayspu_GetBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data) +{ + crStateGetBufferSubDataARB(target, offset, size, data); +} + +static void * ARRAYSPU_APIENTRY +arrayspu_MapBufferARB(GLenum target, GLenum access) +{ + return crStateMapBufferARB(target, access); +} + +static GLboolean ARRAYSPU_APIENTRY +arrayspu_UnmapBufferARB(GLenum target) +{ + crStateUnmapBufferARB(target); + return array_spu.child.UnmapBufferARB(target); +} + +static void ARRAYSPU_APIENTRY +arrayspu_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params) +{ + crStateGetBufferParameterivARB(target, pname, params); +} + +static void ARRAYSPU_APIENTRY +arrayspu_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params) +{ + crStateGetBufferPointervARB(target, pname, params); +} + +static void ARRAYSPU_APIENTRY +arrayspu_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *p) +{ + crStateInterleavedArrays(format, stride, p); +} + +static GLint ARRAYSPU_APIENTRY +arrayspu_CreateContext( const char *dpyName, GLint visual, GLint shareCtx ) +{ + GLint ctx, slot; + +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&_ArrayMutex); +#endif + + ctx = array_spu.child.CreateContext(dpyName, visual, shareCtx); + + /* find an empty context slot */ + for (slot = 0; slot < array_spu.numContexts; slot++) { + if (!array_spu.context[slot].clientState) { + /* found empty slot */ + break; + } + } + if (slot == array_spu.numContexts) { + array_spu.numContexts++; + } + + array_spu.context[slot].clientState = crStateCreateContext(NULL, visual, NULL); + array_spu.context[slot].clientCtx = ctx; +#ifdef CR_ARB_vertex_buffer_object + array_spu.context[slot].clientState->bufferobject.retainBufferData = GL_TRUE; +#endif + +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&_ArrayMutex); +#endif + + return ctx; +} + +static void ARRAYSPU_APIENTRY +arrayspu_MakeCurrent( GLint window, GLint nativeWindow, GLint ctx ) +{ +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&_ArrayMutex); +#endif + array_spu.child.MakeCurrent(window, nativeWindow, ctx); + + if (ctx) { + int slot; + + for (slot=0; slot<array_spu.numContexts; ++slot) + if (array_spu.context[slot].clientCtx == ctx) break; + CRASSERT(slot < array_spu.numContexts); + + crStateMakeCurrent(array_spu.context[slot].clientState); + } + else + { + crStateMakeCurrent(NULL); + } + +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&_ArrayMutex); +#endif +} + +static void ARRAYSPU_APIENTRY +arrayspu_DestroyContext( GLint ctx ) +{ +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&_ArrayMutex); +#endif + array_spu.child.DestroyContext(ctx); + + if (ctx) { + int slot; + + for (slot=0; slot<array_spu.numContexts; ++slot) + if (array_spu.context[slot].clientCtx == ctx) break; + CRASSERT(slot < array_spu.numContexts); + + crStateDestroyContext(array_spu.context[slot].clientState); + + array_spu.context[slot].clientState = NULL; + array_spu.context[slot].clientCtx = 0; + } + +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&_ArrayMutex); +#endif +} + +static void ARRAYSPU_APIENTRY +arrayspu_VBoxAttachThread(void) +{ + crStateVBoxAttachThread(); + array_spu.child.VBoxAttachThread(); +} + +static void ARRAYSPU_APIENTRY +arrayspu_VBoxDetachThread(void) +{ + crStateVBoxDetachThread(); + array_spu.child.VBoxDetachThread(); +} + + +SPUNamedFunctionTable _cr_array_table[] = { + { "ArrayElement", (SPUGenericFunction) arrayspu_ArrayElement }, + { "DrawArrays", (SPUGenericFunction) arrayspu_DrawArrays}, + { "DrawElements", (SPUGenericFunction) arrayspu_DrawElements}, + { "DrawRangeElements", (SPUGenericFunction) arrayspu_DrawRangeElements}, + { "ColorPointer", (SPUGenericFunction) arrayspu_ColorPointer}, + { "SecondaryColorPointerEXT", (SPUGenericFunction) arrayspu_SecondaryColorPointerEXT}, + { "VertexPointer", (SPUGenericFunction) arrayspu_VertexPointer}, + { "TexCoordPointer", (SPUGenericFunction) arrayspu_TexCoordPointer}, + { "NormalPointer", (SPUGenericFunction) arrayspu_NormalPointer}, + { "IndexPointer", (SPUGenericFunction) arrayspu_IndexPointer}, + { "EdgeFlagPointer", (SPUGenericFunction) arrayspu_EdgeFlagPointer}, + { "VertexAttribPointerNV", (SPUGenericFunction) arrayspu_VertexAttribPointerNV}, + { "FogCoordPointerEXT", (SPUGenericFunction) arrayspu_FogCoordPointerEXT}, + { "GetPointerv", (SPUGenericFunction) arrayspu_GetPointerv}, + { "EnableClientState", (SPUGenericFunction) arrayspu_EnableClientState}, + { "DisableClientState", (SPUGenericFunction) arrayspu_DisableClientState}, + { "ClientActiveTextureARB", (SPUGenericFunction) arrayspu_ClientActiveTextureARB }, + { "MultiDrawArraysEXT", (SPUGenericFunction) arrayspu_MultiDrawArraysEXT }, + { "MultiDrawElementsEXT", (SPUGenericFunction) arrayspu_MultiDrawElementsEXT }, + { "Enable", (SPUGenericFunction) arrayspu_Enable }, + { "Disable", (SPUGenericFunction) arrayspu_Disable }, + { "PushClientAttrib", (SPUGenericFunction) arrayspu_PushClientAttrib }, + { "PopClientAttrib", (SPUGenericFunction) arrayspu_PopClientAttrib }, + { "VertexAttribPointerARB", (SPUGenericFunction) arrayspu_VertexAttribPointerARB }, + { "EnableVertexAttribArrayARB", (SPUGenericFunction) arrayspu_EnableVertexAttribArrayARB }, + { "DisableVertexAttribArrayARB", (SPUGenericFunction) arrayspu_DisableVertexAttribArrayARB }, + { "GenBuffersARB", (SPUGenericFunction) arrayspu_GenBuffersARB }, + { "DeleteBuffersARB", (SPUGenericFunction) arrayspu_DeleteBuffersARB }, + { "BindBufferARB", (SPUGenericFunction) arrayspu_BindBufferARB }, + { "IsBufferARB", (SPUGenericFunction) arrayspu_IsBufferARB }, + { "BufferDataARB", (SPUGenericFunction) arrayspu_BufferDataARB }, + { "BufferSubDataARB", (SPUGenericFunction) arrayspu_BufferSubDataARB }, + { "GetBufferSubDataARB", (SPUGenericFunction) arrayspu_GetBufferSubDataARB }, + { "MapBufferARB", (SPUGenericFunction) arrayspu_MapBufferARB }, + { "UnmapBufferARB", (SPUGenericFunction) arrayspu_UnmapBufferARB }, + { "GetBufferParameterivARB", (SPUGenericFunction) arrayspu_GetBufferParameterivARB}, + { "GetBufferPointervARB", (SPUGenericFunction) arrayspu_GetBufferPointervARB}, + { "InterleavedArrays", (SPUGenericFunction) arrayspu_InterleavedArrays}, + { "CreateContext", (SPUGenericFunction) arrayspu_CreateContext}, + { "MakeCurrent", (SPUGenericFunction) arrayspu_MakeCurrent}, + { "DestroyContext", (SPUGenericFunction) arrayspu_DestroyContext}, + { "UseProgram", (SPUGenericFunction) arrayspu_UseProgram}, + { "VBoxAttachThread", (SPUGenericFunction) arrayspu_VBoxAttachThread}, + { "VBoxDetachThread", (SPUGenericFunction) arrayspu_VBoxDetachThread}, + { NULL, NULL } +}; diff --git a/src/VBox/Additions/common/crOpenGL/array/arrayspu.def b/src/VBox/Additions/common/crOpenGL/array/arrayspu.def new file mode 100644 index 00000000..9edc7163 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/array/arrayspu.def @@ -0,0 +1,6 @@ +; Copyright (c) 2001, Stanford University +; All rights reserved. +; +; See the file LICENSE.txt for information on redistributing this software. +EXPORTS +SPULoad diff --git a/src/VBox/Additions/common/crOpenGL/array/arrayspu.h b/src/VBox/Additions/common/crOpenGL/array/arrayspu.h new file mode 100644 index 00000000..f31dea5c --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/array/arrayspu.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved. + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#ifndef GA_INCLUDED_SRC_common_crOpenGL_array_arrayspu_h +#define GA_INCLUDED_SRC_common_crOpenGL_array_arrayspu_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#ifdef WINDOWS +#define ARRAYSPU_APIENTRY __stdcall +#else +#define ARRAYSPU_APIENTRY +#endif + +#include "cr_spu.h" +#include "cr_glstate.h" + +void arrayspuSetVBoxConfiguration( void ); + +typedef struct context_info_t ContextInfo; + +struct context_info_t { + CRContext *clientState; /* used to store client-side GL state */ + GLint clientCtx; /* client context ID */ +}; + +typedef struct { + int id; + int has_child; + CRContext *defaultctx; + SPUDispatchTable self, child, super; + int numContexts; + ContextInfo context[CR_MAX_CONTEXTS]; +} ArraySPU; + +extern ArraySPU array_spu; + +#ifdef CHROMIUM_THREADSAFE +extern CRmutex _ArrayMutex; +#endif + +#endif /* !GA_INCLUDED_SRC_common_crOpenGL_array_arrayspu_h */ diff --git a/src/VBox/Additions/common/crOpenGL/array/arrayspu.rc b/src/VBox/Additions/common/crOpenGL/array/arrayspu.rc new file mode 100644 index 00000000..894a6584 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/array/arrayspu.rc @@ -0,0 +1,69 @@ +/* $Id: arrayspu.rc $ */ +/** @file + * VBoxOGLarrayspu - Resource file containing version info and icon. + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include <windows.h> +#include <VBox/version.h> + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VBOX_RC_FILE_VERSION + PRODUCTVERSION VBOX_RC_FILE_VERSION + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS VBOX_RC_FILE_FLAGS + FILEOS VBOX_RC_FILE_OS + FILETYPE VBOX_RC_TYPE_DRV + FILESUBTYPE VFT2_DRV_DISPLAY +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "VirtualBox crOpenGL ICD\0" + VALUE "InternalName", "VBoxOGLarrayspu\0" +#ifdef VBOX_WDDM_WOW64 + VALUE "OriginalFilename", "VBoxOGLarrayspu-x86.dll\0" +#else + VALUE "OriginalFilename", "VBoxOGLarrayspu.dll\0" +#endif + VALUE "CompanyName", VBOX_RC_COMPANY_NAME + VALUE "FileVersion", VBOX_RC_FILE_VERSION_STR + VALUE "LegalCopyright", VBOX_RC_LEGAL_COPYRIGHT + VALUE "ProductName", VBOX_RC_PRODUCT_NAME_GA_STR + VALUE "ProductVersion", VBOX_RC_PRODUCT_VERSION_STR + VBOX_RC_MORE_STRINGS + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +1 RCDATA +BEGIN +// Machine dependent parameters + 17, // Height of vertical thumb + 17, // Width of horizontal thumb + 2, // Icon horiz compression factor + 2, // Icon vert compression factor + 1, // Cursor horz compression factor + 1, // Cursor vert compression factor + 0, // Kanji window height + 1, // cxBorder (thickness of vertical lines) + 1 // cyBorder (thickness of horizontal lines) +END diff --git a/src/VBox/Additions/common/crOpenGL/array/arrayspu_config.c b/src/VBox/Additions/common/crOpenGL/array/arrayspu_config.c new file mode 100644 index 00000000..d2161739 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/array/arrayspu_config.c @@ -0,0 +1,27 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "arrayspu.h" + +#include "cr_string.h" + +#include <stdio.h> + +static void __setDefaults( void ) +{ +} + +/* No SPU options yet. + */ +SPUOptions arraySPUOptions[] = { + { NULL, CR_BOOL, 0, NULL, NULL, NULL, NULL, NULL }, +}; + + +void arrayspuSetVBoxConfiguration( void ) +{ + __setDefaults(); +} diff --git a/src/VBox/Additions/common/crOpenGL/array/arrayspu_init.c b/src/VBox/Additions/common/crOpenGL/array/arrayspu_init.c new file mode 100644 index 00000000..bd773f59 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/array/arrayspu_init.c @@ -0,0 +1,86 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_spu.h" +#include "arrayspu.h" +#include "cr_mem.h" +#include <stdio.h> + +extern SPUNamedFunctionTable _cr_array_table[]; + +extern SPUOptions arraySPUOptions[]; + +static SPUFunctions array_functions = { + NULL, /* CHILD COPY */ + NULL, /* DATA */ + _cr_array_table /* THE ACTUAL FUNCTIONS */ +}; + +static SPUFunctions *arraySPUInit( int id, SPU *child, SPU *self, + unsigned int context_id, + unsigned int num_contexts ) +{ + + (void) context_id; + (void) num_contexts; + +#ifdef CHROMIUM_THREADSAFE + crInitMutex(&_ArrayMutex); +#endif + + array_spu.id = id; + array_spu.has_child = 0; + if (child) + { + crSPUInitDispatchTable( &(array_spu.child) ); + crSPUCopyDispatchTable( &(array_spu.child), &(child->dispatch_table) ); + array_spu.has_child = 1; + } + crSPUInitDispatchTable( &(array_spu.super) ); + crSPUCopyDispatchTable( &(array_spu.super), &(self->superSPU->dispatch_table) ); + arrayspuSetVBoxConfiguration(); + + crStateInit(); +/** @todo seems default context ain't needed at all*/ + array_spu.defaultctx = crStateCreateContext( NULL, 0, NULL ); +#ifdef CR_ARB_vertex_buffer_object + array_spu.defaultctx->bufferobject.retainBufferData = GL_TRUE; +#endif + /* we call SetCurrent instead of MakeCurrent as the differencer + * isn't setup yet anyway */ + crStateSetCurrent( array_spu.defaultctx ); + + array_spu.numContexts = 0; + crMemZero(array_spu.context, CR_MAX_CONTEXTS * sizeof(ContextInfo)); + + return &array_functions; +} + +static void arraySPUSelfDispatch(SPUDispatchTable *self) +{ + crSPUInitDispatchTable( &(array_spu.self) ); + crSPUCopyDispatchTable( &(array_spu.self), self ); +} + +static int arraySPUCleanup(void) +{ + return 1; +} + +int SPULoad( char **name, char **super, SPUInitFuncPtr *init, + SPUSelfDispatchFuncPtr *self, SPUCleanupFuncPtr *cleanup, + SPUOptionsPtr *options, int *flags ) +{ + *name = "array"; + *super = "passthrough"; + *init = arraySPUInit; + *self = arraySPUSelfDispatch; + *cleanup = arraySPUCleanup; + *options = arraySPUOptions; + *flags = (SPU_NO_PACKER|SPU_NOT_TERMINAL|SPU_MAX_SERVERS_ZERO); + + return 1; +} diff --git a/src/VBox/Additions/common/crOpenGL/context.c b/src/VBox/Additions/common/crOpenGL/context.c new file mode 100644 index 00000000..29b93aa1 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/context.c @@ -0,0 +1,1463 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +/** + * \mainpage OpenGL_stub + * + * \section OpenGL_stubIntroduction Introduction + * + * Chromium consists of all the top-level files in the cr + * directory. The OpenGL_stub module basically takes care of API dispatch, + * and OpenGL state management. + * + */ + +/** + * This file manages OpenGL rendering contexts in the faker library. + * The big issue is switching between Chromium and native GL context + * management. This is where we support multiple client OpenGL + * windows. Typically, one window is handled by Chromium while any + * other windows are handled by the native OpenGL library. + */ + +#include "chromium.h" +#include "cr_error.h" +#include "cr_spu.h" +#include "cr_mem.h" +#include "cr_string.h" +#include "cr_environment.h" +#include "stub.h" + +/** + * This function should be called from MakeCurrent(). It'll detect if + * we're in a multi-thread situation, and do the right thing for dispatch. + */ +#ifdef CHROMIUM_THREADSAFE + static void +stubCheckMultithread( void ) +{ + static unsigned long knownID; + static GLboolean firstCall = GL_TRUE; + + if (stub.threadSafe) + return; /* nothing new, nothing to do */ + + if (firstCall) { + knownID = crThreadID(); + firstCall = GL_FALSE; + } + else if (knownID != crThreadID()) { + /* going thread-safe now! */ + stub.threadSafe = GL_TRUE; + crSPUCopyDispatchTable(&glim, &stubThreadsafeDispatch); + } +} +#endif + + +/** + * Install the given dispatch table as the table used for all gl* calls. + */ + static void +stubSetDispatch( SPUDispatchTable *table ) +{ + CRASSERT(table); + +#ifdef CHROMIUM_THREADSAFE + /* always set the per-thread dispatch pointer */ + crSetTSD(&stub.dispatchTSD, (void *) table); + if (stub.threadSafe) { + /* Do nothing - the thread-safe dispatch functions will call GetTSD() + * to get a pointer to the dispatch table, and jump through it. + */ + } + else +#endif + { + /* Single thread mode - just install the caller's dispatch table */ + /* This conditional is an optimization to try to avoid unnecessary + * copying. It seems to work with atlantis, multiwin, etc. but + * _could_ be a problem. (Brian) + */ + if (glim.copy_of != table->copy_of) + crSPUCopyDispatchTable(&glim, table); + } +} + +void stubForcedFlush(GLint con) +{ +#if 0 + GLint buffer; + stub.spu->dispatch_table.GetIntegerv(GL_DRAW_BUFFER, &buffer); + stub.spu->dispatch_table.DrawBuffer(GL_FRONT); + stub.spu->dispatch_table.Flush(); + stub.spu->dispatch_table.DrawBuffer(buffer); +#else + if (con) + { + stub.spu->dispatch_table.VBoxConFlush(con); + } + else + { + stub.spu->dispatch_table.Flush(); + } +#endif +} + +void stubConChromiumParameteriCR(GLint con, GLenum param, GLint value) +{ +// if (con) + stub.spu->dispatch_table.VBoxConChromiumParameteriCR(con, param, value); +// else +// crError("VBoxConChromiumParameteriCR called with null connection"); +} + +void stubConChromiumParametervCR(GLint con, GLenum target, GLenum type, GLsizei count, const GLvoid *values) +{ +// if (con) + stub.spu->dispatch_table.VBoxConChromiumParametervCR(con, target, type, count, values); +// else +// crError("VBoxConChromiumParameteriCR called with null connection"); +} + +void stubConFlush(GLint con) +{ + if (con) + stub.spu->dispatch_table.VBoxConFlush(con); + else + crError("stubConFlush called with null connection"); +} + +static void stubWindowCleanupForContextsCB(unsigned long key, void *data1, void *data2) +{ + ContextInfo *context = (ContextInfo *) data1; + RT_NOREF(key); + + CRASSERT(context); + + if (context->currentDrawable == data2) + context->currentDrawable = NULL; +} + +void stubDestroyWindow( GLint con, GLint window ) +{ + WindowInfo *winInfo = (WindowInfo *) + crHashtableSearch(stub.windowTable, (unsigned int) window); + if (winInfo && winInfo->type == CHROMIUM && stub.spu) + { + crHashtableLock(stub.windowTable); + + stub.spu->dispatch_table.VBoxWindowDestroy(con, winInfo->spuWindow ); + +#ifdef WINDOWS + if (winInfo->hVisibleRegion != INVALID_HANDLE_VALUE) + { + DeleteObject(winInfo->hVisibleRegion); + } +#elif defined(GLX) + if (winInfo->pVisibleRegions) + { + XFree(winInfo->pVisibleRegions); + } +# ifdef CR_NEWWINTRACK + if (winInfo->syncDpy) + { + XCloseDisplay(winInfo->syncDpy); + } +# endif +#endif + + stubForcedFlush(con); + + crHashtableWalk(stub.contextTable, stubWindowCleanupForContextsCB, winInfo); + + crHashtableDelete(stub.windowTable, window, crFree); + + crHashtableUnlock(stub.windowTable); + } +} + +/** + * Create a new _Chromium_ window, not GLX, WGL or CGL. + * Called by crWindowCreate() only. + */ + GLint +stubNewWindow( const char *dpyName, GLint visBits ) +{ + WindowInfo *winInfo; + GLint spuWin, size[2]; + + spuWin = stub.spu->dispatch_table.WindowCreate( dpyName, visBits ); + if (spuWin < 0) { + return -1; + } + + winInfo = (WindowInfo *) crCalloc(sizeof(WindowInfo)); + if (!winInfo) { + stub.spu->dispatch_table.WindowDestroy(spuWin); + return -1; + } + + winInfo->type = CHROMIUM; + + /* Ask the head SPU for the initial window size */ + size[0] = size[1] = 0; + stub.spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, 0, GL_INT, 2, size); + if (size[0] == 0 && size[1] == 0) { + /* use some reasonable defaults */ + size[0] = size[1] = 512; + } + winInfo->width = size[0]; + winInfo->height = size[1]; +#ifdef VBOX_WITH_WDDM + if (stub.bRunningUnderWDDM) + { + crError("Should not be here: WindowCreate/Destroy & VBoxPackGetInjectID require connection id!"); + winInfo->mapped = 0; + } + else +#endif + { + winInfo->mapped = 1; + } + + if (!dpyName) + dpyName = ""; + + crStrncpy(winInfo->dpyName, dpyName, MAX_DPY_NAME); + winInfo->dpyName[MAX_DPY_NAME-1] = 0; + + /* Use spuWin as the hash table index and GLX/WGL handle */ +#ifdef WINDOWS + winInfo->drawable = (HDC) spuWin; + winInfo->hVisibleRegion = INVALID_HANDLE_VALUE; +#elif defined(Darwin) + winInfo->drawable = (CGSWindowID) spuWin; +#elif defined(GLX) + winInfo->drawable = (GLXDrawable) spuWin; + winInfo->pVisibleRegions = NULL; + winInfo->cVisibleRegions = 0; +#endif +#ifdef CR_NEWWINTRACK + winInfo->u32ClientID = stub.spu->dispatch_table.VBoxPackGetInjectID(0); +#endif + winInfo->spuWindow = spuWin; + + crHashtableAdd(stub.windowTable, (unsigned int) spuWin, winInfo); + + return spuWin; +} + +#ifdef GLX +# if 0 /* unused */ +static XErrorHandler oldErrorHandler; +static unsigned char lastXError = Success; + +static int +errorHandler (Display *dpy, XErrorEvent *e) +{ + RT_NOREF(dpy); + + lastXError = e->error_code; + return 0; +} +# endif /* unused */ +#endif + +GLboolean +stubIsWindowVisible(WindowInfo *win) +{ +#if defined(WINDOWS) +# ifdef VBOX_WITH_WDDM + if (stub.bRunningUnderWDDM) + return win->mapped; +# endif + return GL_TRUE; +#elif defined(Darwin) + return GL_TRUE; +#elif defined(GLX) + Display *dpy = stubGetWindowDisplay(win); + if (dpy) + { + XWindowAttributes attr; + XLOCK(dpy); + XGetWindowAttributes(dpy, win->drawable, &attr); + XUNLOCK(dpy); + + if (attr.map_state == IsUnmapped) + { + return GL_FALSE; + } +# if 1 + return GL_TRUE; +# else + if (attr.override_redirect) + { + return GL_TRUE; + } + + if (!stub.bXExtensionsChecked) + { + stubCheckXExtensions(win); + } + + if (!stub.bHaveXComposite) + { + return GL_TRUE; + } + else + { + Pixmap p; + + crLockMutex(&stub.mutex); + + XLOCK(dpy); + XSync(dpy, false); + oldErrorHandler = XSetErrorHandler(errorHandler); + /** @todo this will create new pixmap for window every call*/ + p = XCompositeNameWindowPixmap(dpy, win->drawable); + XSync(dpy, false); + XSetErrorHandler(oldErrorHandler); + XUNLOCK(dpy); + + switch (lastXError) + { + case Success: + XFreePixmap(dpy, p); + crUnlockMutex(&stub.mutex); + return GL_FALSE; + break; + case BadMatch: + /*Window isn't redirected*/ + lastXError = Success; + break; + default: + crWarning("Unexpected XError %i", (int)lastXError); + lastXError = Success; + } + + crUnlockMutex(&stub.mutex); + + return GL_TRUE; + } +# endif + } + else { + /* probably created by crWindowCreate() */ + return win->mapped; + } +#endif +} + + +/** + * Given a Windows HDC or GLX Drawable, return the corresponding + * WindowInfo structure. Create a new one if needed. + */ +WindowInfo * +#ifdef WINDOWS + stubGetWindowInfo( HDC drawable ) +#elif defined(Darwin) + stubGetWindowInfo( CGSWindowID drawable ) +#elif defined(GLX) +stubGetWindowInfo( Display *dpy, GLXDrawable drawable ) +#endif +{ +#ifndef WINDOWS + WindowInfo *winInfo = (WindowInfo *) crHashtableSearch(stub.windowTable, (unsigned int) drawable); +#else + WindowInfo *winInfo; + HWND hwnd; + hwnd = WindowFromDC(drawable); + + if (!hwnd) + { + return NULL; + } + + winInfo = (WindowInfo *) crHashtableSearch(stub.windowTable, (unsigned int) hwnd); +#endif + if (!winInfo) { + winInfo = (WindowInfo *) crCalloc(sizeof(WindowInfo)); + if (!winInfo) + return NULL; +#ifdef GLX + crStrncpy(winInfo->dpyName, DisplayString(dpy), MAX_DPY_NAME); + winInfo->dpyName[MAX_DPY_NAME-1] = 0; + winInfo->dpy = dpy; + winInfo->pVisibleRegions = NULL; +#elif defined(Darwin) + winInfo->connection = _CGSDefaultConnection(); // store our connection as default +#elif defined(WINDOWS) + winInfo->hVisibleRegion = INVALID_HANDLE_VALUE; + winInfo->hWnd = hwnd; +#endif + winInfo->drawable = drawable; + winInfo->type = UNDECIDED; + winInfo->spuWindow = -1; +#ifdef VBOX_WITH_WDDM + if (stub.bRunningUnderWDDM) + winInfo->mapped = 0; + else +#endif + { + winInfo->mapped = -1; /* don't know */ + } + winInfo->pOwner = NULL; +#ifdef CR_NEWWINTRACK + winInfo->u32ClientID = -1; +#endif +#ifndef WINDOWS + crHashtableAdd(stub.windowTable, (unsigned int) drawable, winInfo); +#else + crHashtableAdd(stub.windowTable, (unsigned int) hwnd, winInfo); +#endif + } +#ifdef WINDOWS + else + { + winInfo->drawable = drawable; + } +#endif + return winInfo; +} + +static void stubWindowCheckOwnerCB(unsigned long key, void *data1, void *data2); + +static void +stubContextFree( ContextInfo *context ) +{ + crMemZero(context, sizeof(ContextInfo)); /* just to be safe */ + crFree(context); +} + +static void +stubDestroyContextLocked( ContextInfo *context ) +{ + unsigned long contextId = context->id; + if (context->type == NATIVE) { +#ifdef WINDOWS + stub.wsInterface.wglDeleteContext( context->hglrc ); +#elif defined(Darwin) + stub.wsInterface.CGLDestroyContext( context->cglc ); +#elif defined(GLX) + stub.wsInterface.glXDestroyContext( context->dpy, context->glxContext ); +#endif + } + else if (context->type == CHROMIUM) { + /* Have pack SPU or tilesort SPU, etc. destroy the context */ + CRASSERT(context->spuContext >= 0); + stub.spu->dispatch_table.DestroyContext( context->spuContext ); + crHashtableWalk(stub.windowTable, stubWindowCheckOwnerCB, context); +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + if (context->spuConnection) + { + stub.spu->dispatch_table.VBoxConDestroy(context->spuConnection); + context->spuConnection = 0; + } +#endif + } + +#ifdef GLX + crFreeHashtable(context->pGLXPixmapsHash, crFree); +#endif + + crHashtableDelete(stub.contextTable, contextId, NULL); +} + +#ifdef CHROMIUM_THREADSAFE +static DECLCALLBACK(void) stubContextDtor(void*pvContext) +{ + stubContextFree((ContextInfo*)pvContext); +} +#endif + +/** + * Allocate a new ContextInfo object, initialize it, put it into the + * context hash table. If type==CHROMIUM, call the head SPU's + * CreateContext() function too. + */ + ContextInfo * +stubNewContext(char *dpyName, GLint visBits, ContextType type, unsigned long shareCtx +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , struct VBOXUHGSMI *pHgsmi +#endif + ) +{ + GLint spuContext = -1, spuShareCtx = 0, spuConnection = 0; + ContextInfo *context; + + if (shareCtx > 0) { + /* translate shareCtx to a SPU context ID */ + context = (ContextInfo *) + crHashtableSearch(stub.contextTable, shareCtx); + if (context) + spuShareCtx = context->spuContext; + } + + if (type == CHROMIUM) { +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + if (pHgsmi) + { + spuConnection = stub.spu->dispatch_table.VBoxConCreate(pHgsmi); + if (!spuConnection) + { + crWarning("VBoxConCreate failed"); + return NULL; + } + } +#endif + spuContext + = stub.spu->dispatch_table.VBoxCreateContext(spuConnection, dpyName, visBits, spuShareCtx); + if (spuContext < 0) + { + crWarning("VBoxCreateContext failed"); +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + if (spuConnection) + stub.spu->dispatch_table.VBoxConDestroy(spuConnection); +#endif + return NULL; + } + } + + context = crCalloc(sizeof(ContextInfo)); + if (!context) { + stub.spu->dispatch_table.DestroyContext(spuContext); +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + if (spuConnection) + stub.spu->dispatch_table.VBoxConDestroy(spuConnection); +#endif + return NULL; + } + + if (!dpyName) + dpyName = ""; + + context->id = stub.freeContextNumber++; + context->type = type; + context->spuContext = spuContext; + context->visBits = visBits; + context->currentDrawable = NULL; + crStrncpy(context->dpyName, dpyName, MAX_DPY_NAME); + context->dpyName[MAX_DPY_NAME-1] = 0; + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + context->spuConnection = spuConnection; + context->pHgsmi = pHgsmi; +#endif + +#ifdef CHROMIUM_THREADSAFE + VBoxTlsRefInit(context, stubContextDtor); +#endif + +#if defined(GLX) || defined(DARWIN) + context->share = (ContextInfo *) + crHashtableSearch(stub.contextTable, (unsigned long) shareCtx); +#endif + +#ifdef GLX + context->pGLXPixmapsHash = crAllocHashtable(); + context->damageQueryFailed = GL_FALSE; + context->damageEventsBase = 0; +#endif + + crHashtableAdd(stub.contextTable, context->id, (void *) context); + + return context; +} + + +#ifdef Darwin + +#define SET_ATTR(l,i,a) ( (l)[(i)++] = (a) ) +#define SET_ATTR_V(l,i,a,v) ( SET_ATTR(l,i,a), SET_ATTR(l,i,v) ) + +void stubSetPFA( ContextInfo *ctx, CGLPixelFormatAttribute *attribs, int size, GLint *num ) { + GLuint visual = ctx->visBits; + int i = 0; + + CRASSERT(visual & CR_RGB_BIT); + + SET_ATTR_V(attribs, i, kCGLPFAColorSize, 8); + + if( visual & CR_DEPTH_BIT ) + SET_ATTR_V(attribs, i, kCGLPFADepthSize, 16); + + if( visual & CR_ACCUM_BIT ) + SET_ATTR_V(attribs, i, kCGLPFAAccumSize, 1); + + if( visual & CR_STENCIL_BIT ) + SET_ATTR_V(attribs, i, kCGLPFAStencilSize, 1); + + if( visual & CR_ALPHA_BIT ) + SET_ATTR_V(attribs, i, kCGLPFAAlphaSize, 1); + + if( visual & CR_DOUBLE_BIT ) + SET_ATTR(attribs, i, kCGLPFADoubleBuffer); + + if( visual & CR_STEREO_BIT ) + SET_ATTR(attribs, i, kCGLPFAStereo); + +/* SET_ATTR_V(attribs, i, kCGLPFASampleBuffers, 1); + SET_ATTR_V(attribs, i, kCGLPFASamples, 0); + SET_ATTR_V(attribs, i, kCGLPFADisplayMask, 0); */ + SET_ATTR(attribs, i, kCGLPFABackingStore); + //SET_ATTR(attribs, i, kCGLPFAWindow); // kCGLPFAWindow deprecated starting from OSX 10.7 + SET_ATTR_V(attribs, i, kCGLPFADisplayMask, ctx->disp_mask); + + SET_ATTR(attribs, i, 0); + + *num = i; +} + +#endif + +#ifndef GLX +/** + * This creates a native GLX/WGL context. + */ +static GLboolean +InstantiateNativeContext( WindowInfo *window, ContextInfo *context ) +{ +#ifdef WINDOWS + context->hglrc = stub.wsInterface.wglCreateContext( window->drawable ); + return context->hglrc ? GL_TRUE : GL_FALSE; +#elif defined(Darwin) + CGLContextObj shareCtx = NULL; + CGLPixelFormatObj pix; + long npix; + + CGLPixelFormatAttribute attribs[16]; + GLint ind = 0; + + if( context->share ) { + if( context->cglc != context->share->cglc ) { + crWarning("CGLCreateContext() is trying to share a non-existant " + "CGL context. Setting share context to zero."); + shareCtx = 0; + } + else + shareCtx = context->cglc; + } + + stubSetPFA( context, attribs, 16, &ind ); + + stub.wsInterface.CGLChoosePixelFormat( attribs, &pix, &npix ); + stub.wsInterface.CGLCreateContext( pix, shareCtx, &context->cglc ); + if( !context->cglc ) + crError("InstantiateNativeContext: Couldn't Create the context!"); + + stub.wsInterface.CGLDestroyPixelFormat( pix ); + + if( context->parambits ) { + /* Set the delayed parameters */ + if( context->parambits & VISBIT_SWAP_RECT ) + stub.wsInterface.CGLSetParameter( context->cglc, kCGLCPSwapRectangle, context->swap_rect ); + + if( context->parambits & VISBIT_SWAP_INTERVAL ) + stub.wsInterface.CGLSetParameter( context->cglc, kCGLCPSwapInterval, &(context->swap_interval) ); + + if( context->parambits & VISBIT_CLIENT_STORAGE ) + stub.wsInterface.CGLSetParameter( context->cglc, kCGLCPClientStorage, (long*)&(context->client_storage) ); + + context->parambits = 0; + } + + return context->cglc ? GL_TRUE : GL_FALSE; +#elif defined(GLX) + GLXContext shareCtx = 0; + + /* sort out context sharing here */ + if (context->share) { + if (context->glxContext != context->share->glxContext) { + crWarning("glXCreateContext() is trying to share a non-existant " + "GLX context. Setting share context to zero."); + shareCtx = 0; + } + else { + shareCtx = context->glxContext; + } + } + + context->glxContext = stub.wsInterface.glXCreateContext( window->dpy, + context->visual, shareCtx, context->direct ); + + return context->glxContext ? GL_TRUE : GL_FALSE; +#endif +} +#endif /* !GLX */ + + +/** + * Utility functions to get window size and titlebar text. + */ +#ifdef WINDOWS + +void +stubGetWindowGeometry(WindowInfo *window, int *x, int *y, + unsigned int *w, unsigned int *h ) +{ + RECT rect; + + if (!window->drawable || !window->hWnd) { + *w = *h = 0; + return; + } + + if (window->hWnd!=WindowFromDC(window->drawable)) + { + crWarning("Window(%i) DC is no longer valid", window->spuWindow); + return; + } + + if (!GetClientRect(window->hWnd, &rect)) + { + crWarning("GetClientRect failed for %p", window->hWnd); + *w = *h = 0; + return; + } + *w = rect.right - rect.left; + *h = rect.bottom - rect.top; + + if (!ClientToScreen( window->hWnd, (LPPOINT) &rect )) + { + crWarning("ClientToScreen failed for %p", window->hWnd); + *w = *h = 0; + return; + } + *x = rect.left; + *y = rect.top; +} + +static void +GetWindowTitle( const WindowInfo *window, char *title ) +{ + /* XXX - we don't handle recurseUp */ + if (window->hWnd) + GetWindowText(window->hWnd, title, 100); + else + title[0] = 0; +} + +static void +GetCursorPosition(WindowInfo *window, int pos[2]) +{ + RECT rect; + POINT point; + GLint size[2], x, y; + unsigned int NativeHeight, NativeWidth, ChromiumHeight, ChromiumWidth; + float WidthRatio, HeightRatio; + static int DebugFlag = 0; + + // apparently the "window" parameter passed to this + // function contains the native window information + HWND NATIVEhwnd = window->hWnd; + + if (NATIVEhwnd!=WindowFromDC(window->drawable)) + { + crWarning("Window(%i) DC is no longer valid", window->spuWindow); + return; + } + + // get the native window's height and width + stubGetWindowGeometry(window, &x, &y, &NativeWidth, &NativeHeight); + + // get the spu window's height and width + stub.spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, window->spuWindow, GL_INT, 2, size); + ChromiumWidth = size[0]; + ChromiumHeight = size[1]; + + // get the ratio of the size of the native window to the cr window + WidthRatio = (float)ChromiumWidth / (float)NativeWidth; + HeightRatio = (float)ChromiumHeight / (float)NativeHeight; + + // output some debug information at the beginning + if(DebugFlag) + { + DebugFlag = 0; + crDebug("Native Window Handle = %d", NATIVEhwnd); + crDebug("Native Width = %i", NativeWidth); + crDebug("Native Height = %i", NativeHeight); + crDebug("Chromium Width = %i", ChromiumWidth); + crDebug("Chromium Height = %i", ChromiumHeight); + } + + if (NATIVEhwnd) + { + GetClientRect( NATIVEhwnd, &rect ); + GetCursorPos (&point); + + // make sure these coordinates are relative to the native window, + // not the whole desktop + ScreenToClient(NATIVEhwnd, &point); + + // calculate the new position of the virtual cursor + pos[0] = (int)(point.x * WidthRatio); + pos[1] = (int)((NativeHeight - point.y) * HeightRatio); + } + else + { + pos[0] = 0; + pos[1] = 0; + } +} + +#elif defined(Darwin) + +extern OSStatus CGSGetScreenRectForWindow( CGSConnectionID cid, CGSWindowID wid, float *outRect ); +extern OSStatus CGSGetWindowBounds( CGSConnectionID cid, CGSWindowID wid, float *bounds ); + +void +stubGetWindowGeometry( const WindowInfo *window, int *x, int *y, unsigned int *w, unsigned int *h ) +{ + float rect[4]; + + if( !window || + !window->connection || + !window->drawable || + CGSGetWindowBounds( window->connection, window->drawable, rect ) != noErr ) + { + *x = *y = 0; + *w = *h = 0; + } else { + *x = (int) rect[0]; + *y = (int) rect[1]; + *w = (int) rect[2]; + *h = (int) rect[3]; + } +} + + +static void +GetWindowTitle( const WindowInfo *window, char *title ) +{ + /* XXX \todo Darwin window Title */ + title[0] = '\0'; +} + + +static void +GetCursorPosition( const WindowInfo *window, int pos[2] ) +{ + Point mouse_pos; + float window_rect[4]; + + GetMouse( &mouse_pos ); + CGSGetScreenRectForWindow( window->connection, window->drawable, window_rect ); + + pos[0] = mouse_pos.h - (int) window_rect[0]; + pos[1] = (int) window_rect[3] - (mouse_pos.v - (int) window_rect[1]); + + /*crDebug( "%i %i", pos[0], pos[1] );*/ +} + +#elif defined(GLX) + +void +stubGetWindowGeometry(WindowInfo *window, int *x, int *y, unsigned int *w, unsigned int *h) +{ + Window root, child; + unsigned int border, depth; + Display *dpy; + + dpy = stubGetWindowDisplay(window); + + /// @todo Performing those checks is expensive operation, especially for simple apps with high FPS. + // Disabling those triples glxgears fps, thus using xevents instead of per frame polling is much more preferred. + /// @todo Check similar on windows guests, though doubtful as there're no XSync like calls on windows. + if (window && dpy) + { + XLOCK(dpy); + } + + if (!window + || !dpy + || !window->drawable + || !XGetGeometry(dpy, window->drawable, &root, x, y, w, h, &border, &depth) + || !XTranslateCoordinates(dpy, window->drawable, root, 0, 0, x, y, &child)) + { + crWarning("Failed to get windows geometry for %p, try xwininfo", window); + *x = *y = 0; + *w = *h = 0; + } + + if (window && dpy) + { + XUNLOCK(dpy); + } +} + +static char * +GetWindowTitleHelper( Display *dpy, Window window, GLboolean recurseUp ) +{ + while (1) { + char *name; + if (!XFetchName(dpy, window, &name)) + return NULL; + if (name[0]) { + return name; + } + else if (recurseUp) { + /* This window has no name, try the parent */ + Status stat; + Window root, parent, *children; + unsigned int numChildren; + stat = XQueryTree( dpy, window, &root, &parent, + &children, &numChildren ); + if (!stat || window == root) + return NULL; + if (children) + XFree(children); + window = parent; + } + else { + XFree(name); + return NULL; + } + } +} + +static void +GetWindowTitle( const WindowInfo *window, char *title ) +{ + char *t = GetWindowTitleHelper(window->dpy, window->drawable, GL_TRUE); + if (t) { + crStrcpy(title, t); + XFree(t); + } + else { + title[0] = 0; + } +} + + +/** + *Return current cursor position in local window coords. + */ +static void +GetCursorPosition(WindowInfo *window, int pos[2] ) +{ + int rootX, rootY; + Window root, child; + unsigned int mask; + int x, y; + + XLOCK(window->dpy); + + Bool q = XQueryPointer(window->dpy, window->drawable, &root, &child, + &rootX, &rootY, &pos[0], &pos[1], &mask); + if (q) { + unsigned int w, h; + stubGetWindowGeometry( window, &x, &y, &w, &h ); + /* invert Y */ + pos[1] = (int) h - pos[1] - 1; + } + else { + pos[0] = pos[1] = 0; + } + + XUNLOCK(window->dpy); +} + +#endif + + +/** + * This function is called by MakeCurrent() and determines whether or + * not a new rendering context should be bound to Chromium or the native + * OpenGL. + * \return GL_FALSE if native OpenGL should be used, or GL_TRUE if Chromium + * should be used. + */ +static GLboolean +stubCheckUseChromium( WindowInfo *window ) +{ + int x, y; + unsigned int w, h; + + /* If the provided window is CHROMIUM, we're clearly intended + * to create a CHROMIUM context. + */ + if (window->type == CHROMIUM) + return GL_TRUE; + + if (stub.ignoreFreeglutMenus) { + const char *glutMenuTitle = "freeglut menu"; + char title[1000]; + GetWindowTitle(window, title); + if (crStrcmp(title, glutMenuTitle) == 0) { + crDebug("GL faker: Ignoring freeglut menu window"); + return GL_FALSE; + } + } + + /* If the user's specified a window count for Chromium, see if + * this window satisfies that criterium. + */ + stub.matchChromiumWindowCounter++; + if (stub.matchChromiumWindowCount > 0) { + if (stub.matchChromiumWindowCounter != stub.matchChromiumWindowCount) { + crDebug("Using native GL, app window doesn't meet match_window_count"); + return GL_FALSE; + } + } + + /* If the user's specified a window list to ignore, see if this + * window satisfies that criterium. + */ + if (stub.matchChromiumWindowID) { + GLuint i; + + for (i = 0; i <= stub.numIgnoreWindowID; i++) { + if (stub.matchChromiumWindowID[i] == stub.matchChromiumWindowCounter) { + crDebug("Ignore window ID %d, using native GL", stub.matchChromiumWindowID[i]); + return GL_FALSE; + } + } + } + + /* If the user's specified a minimum window size for Chromium, see if + * this window satisfies that criterium. + */ + if (stub.minChromiumWindowWidth > 0 && + stub.minChromiumWindowHeight > 0) { + stubGetWindowGeometry( window, &x, &y, &w, &h ); + if (w >= stub.minChromiumWindowWidth && + h >= stub.minChromiumWindowHeight) { + + /* Check for maximum sized window now too */ + if (stub.maxChromiumWindowWidth && + stub.maxChromiumWindowHeight) { + if (w < stub.maxChromiumWindowWidth && + h < stub.maxChromiumWindowHeight) + return GL_TRUE; + else + return GL_FALSE; + } + + return GL_TRUE; + } + crDebug("Using native GL, app window doesn't meet minimum_window_size"); + return GL_FALSE; + } + else if (stub.matchWindowTitle) { + /* If the user's specified a window title for Chromium, see if this + * window satisfies that criterium. + */ + GLboolean wildcard = GL_FALSE; + char title[1000]; + char *titlePattern; + int len; + /* check for leading '*' wildcard */ + if (stub.matchWindowTitle[0] == '*') { + titlePattern = crStrdup( stub.matchWindowTitle + 1 ); + wildcard = GL_TRUE; + } + else { + titlePattern = crStrdup( stub.matchWindowTitle ); + } + /* check for trailing '*' wildcard */ + len = crStrlen(titlePattern); + if (len > 0 && titlePattern[len - 1] == '*') { + titlePattern[len - 1] = '\0'; /* terminate here */ + wildcard = GL_TRUE; + } + + GetWindowTitle( window, title ); + if (title[0]) { + if (wildcard) { + if (crStrstr(title, titlePattern)) { + crFree(titlePattern); + return GL_TRUE; + } + } + else if (crStrcmp(title, titlePattern) == 0) { + crFree(titlePattern); + return GL_TRUE; + } + } + crFree(titlePattern); + crDebug("Using native GL, app window title doesn't match match_window_title string (\"%s\" != \"%s\")", title, stub.matchWindowTitle); + return GL_FALSE; + } + + /* Window title and size don't matter */ + CRASSERT(stub.minChromiumWindowWidth == 0); + CRASSERT(stub.minChromiumWindowHeight == 0); + CRASSERT(stub.matchWindowTitle == NULL); + + /* User hasn't specified a width/height or window title. + * We'll use chromium for this window (and context) if no other is. + */ + + return GL_TRUE; /* use Chromium! */ +} + +static void stubWindowCheckOwnerCB(unsigned long key, void *data1, void *data2) +{ + WindowInfo *pWindow = (WindowInfo *) data1; + ContextInfo *pCtx = (ContextInfo *) data2; + + RT_NOREF(key); + + + if (pWindow->pOwner == pCtx) + { +#ifdef WINDOWS + /* Note: can't use WindowFromDC(context->pOwnWindow->drawable) here + because GL context is already released from DC and actual guest window + could be destroyed. + */ + stubDestroyWindow(CR_CTX_CON(pCtx), (GLint)pWindow->hWnd); +#else + stubDestroyWindow(CR_CTX_CON(pCtx), (GLint)pWindow->drawable); +#endif + } +} + +GLboolean stubCtxCreate(ContextInfo *context) +{ + /* + * Create a Chromium context. + */ +#if defined(GLX) || defined(DARWIN) + GLint spuShareCtx = context->share ? context->share->spuContext : 0; +#else + GLint spuShareCtx = 0; +#endif + GLint spuConnection = 0; + CRASSERT(stub.spu); + CRASSERT(stub.spu->dispatch_table.CreateContext); + context->type = CHROMIUM; + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + if (context->pHgsmi) + { + spuConnection = stub.spu->dispatch_table.VBoxConCreate(context->pHgsmi); + if (!spuConnection) + { + crError("VBoxConCreate failed"); + return GL_FALSE; + } + context->spuConnection = spuConnection; + } +#endif + + context->spuContext + = stub.spu->dispatch_table.VBoxCreateContext(spuConnection, context->dpyName, + context->visBits, + spuShareCtx); + + return GL_TRUE; +} + +GLboolean stubCtxCheckCreate(ContextInfo *context) +{ + if (context->type == UNDECIDED) + return stubCtxCreate(context); + return CHROMIUM == context->type; +} + + +GLboolean +stubMakeCurrent( WindowInfo *window, ContextInfo *context ) +{ + GLboolean retVal = GL_FALSE; + + /* + * Get WindowInfo and ContextInfo pointers. + */ + + if (!context || !window) { + ContextInfo * currentContext = stubGetCurrentContext(); + if (currentContext) + currentContext->currentDrawable = NULL; + if (context) + context->currentDrawable = NULL; + stubSetCurrentContext(NULL); + return GL_TRUE; /* OK */ + } + +#ifdef CHROMIUM_THREADSAFE + stubCheckMultithread(); +#endif + + if (context->type == UNDECIDED) { + /* Here's where we really create contexts */ +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&stub.mutex); +#endif + + if (stubCheckUseChromium(window)) { + GLint spuConnection = 0; + + if (!stubCtxCreate(context)) + { + crWarning("stubCtxCreate failed"); + return GL_FALSE; + } + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + spuConnection = context->spuConnection; +#endif + + if (window->spuWindow == -1) + { + /*crDebug("(1)stubMakeCurrent ctx=%p(%i) window=%p(%i)", context, context->spuContext, window, window->spuWindow);*/ + window->spuWindow = stub.spu->dispatch_table.VBoxWindowCreate(spuConnection, window->dpyName, context->visBits ); +#ifdef CR_NEWWINTRACK + window->u32ClientID = stub.spu->dispatch_table.VBoxPackGetInjectID(spuConnection); +#endif + } + } +#ifndef GLX + else { + /* + * Create a native OpenGL context. + */ + if (!InstantiateNativeContext(window, context)) + { +# ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&stub.mutex); +# endif + return 0; /* false */ + } + context->type = NATIVE; + } +#endif /* !GLX */ + +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&stub.mutex); +#endif + } + + + if (context->type == NATIVE) { + /* + * Native OpenGL MakeCurrent(). + */ +#ifdef WINDOWS + retVal = (GLboolean) stub.wsInterface.wglMakeCurrent( window->drawable, context->hglrc ); +#elif defined(Darwin) + // XXX \todo We need to differentiate between these two.. + retVal = ( stub.wsInterface.CGLSetSurface(context->cglc, window->connection, window->drawable, window->surface) == noErr ); + retVal = ( stub.wsInterface.CGLSetCurrentContext(context->cglc) == noErr ); +#elif defined(GLX) + retVal = (GLboolean) stub.wsInterface.glXMakeCurrent( window->dpy, window->drawable, context->glxContext ); +#endif + } + else { + /* + * SPU chain MakeCurrent(). + */ + CRASSERT(context->type == CHROMIUM); + CRASSERT(context->spuContext >= 0); + + /*if (context->currentDrawable && context->currentDrawable != window) + crDebug("Rebinding context %p to a different window", context);*/ + + if (window->type == NATIVE) { + crWarning("Can't rebind a chromium context to a native window\n"); + retVal = 0; + } + else { + if (window->spuWindow == -1) + { + /*crDebug("(2)stubMakeCurrent ctx=%p(%i) window=%p(%i)", context, context->spuContext, window, window->spuWindow);*/ + window->spuWindow = stub.spu->dispatch_table.VBoxWindowCreate( +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + context->spuConnection, +#else + 0, +#endif + window->dpyName, context->visBits ); +#ifdef CR_NEWWINTRACK + window->u32ClientID = stub.spu->dispatch_table.VBoxPackGetInjectID( +# if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + context->spuConnection +# else + 0 +# endif + ); +#endif + if (context->currentDrawable && context->currentDrawable->type==CHROMIUM + && context->currentDrawable->pOwner==context) + { +#ifdef WINDOWS + if (context->currentDrawable->hWnd!=WindowFromDC(context->currentDrawable->drawable)) + { + stubDestroyWindow(CR_CTX_CON(context), (GLint)context->currentDrawable->hWnd); + } +#else + Window root; + int x, y; + unsigned int border, depth, w, h; + + XLOCK(context->currentDrawable->dpy); + if (!XGetGeometry(context->currentDrawable->dpy, context->currentDrawable->drawable, &root, &x, &y, &w, &h, &border, &depth)) + { + stubDestroyWindow(CR_CTX_CON(context), (GLint)context->currentDrawable->drawable); + } + XUNLOCK(context->currentDrawable->dpy); +#endif + + } + } + + if (window->spuWindow != (GLint)window->drawable) + stub.spu->dispatch_table.MakeCurrent( window->spuWindow, (GLint) window->drawable, context->spuContext ); + else + stub.spu->dispatch_table.MakeCurrent( window->spuWindow, 0, /* native window handle */ context->spuContext ); + + retVal = 1; + } + } + + window->type = context->type; + window->pOwner = context; + context->currentDrawable = window; + stubSetCurrentContext(context); + + if (retVal) { + /* Now, if we've transitions from Chromium to native rendering, or + * vice versa, we have to change all the OpenGL entrypoint pointers. + */ + if (context->type == NATIVE) { + /* Switch to native API */ + /*printf(" Switching to native API\n");*/ + stubSetDispatch(&stub.nativeDispatch); + } + else if (context->type == CHROMIUM) { + /* Switch to stub (SPU) API */ + /*printf(" Switching to spu API\n");*/ + stubSetDispatch(&stub.spuDispatch); + } + else { + /* no API switch needed */ + } + } + + if (!window->width && window->type == CHROMIUM) { + /* One time window setup */ + int x, y; + unsigned int winW, winH; + + stubGetWindowGeometry( window, &x, &y, &winW, &winH ); + + /* If we're not using GLX/WGL (no app window) we'll always get + * a width and height of zero here. In that case, skip the viewport + * call since we're probably using a tilesort SPU with fake_window_dims + * which the tilesort SPU will use for the viewport. + */ + window->width = winW; + window->height = winH; +#if defined(WINDOWS) && defined(VBOX_WITH_WDDM) + if (stubIsWindowVisible(window)) +#endif + { + if (stub.trackWindowSize) + stub.spuDispatch.WindowSize( window->spuWindow, winW, winH ); + if (stub.trackWindowPos) + stub.spuDispatch.WindowPosition(window->spuWindow, x, y); + if (winW > 0 && winH > 0) + stub.spu->dispatch_table.Viewport( 0, 0, winW, winH ); + } +#ifdef VBOX_WITH_WDDM + if (stub.trackWindowVisibleRgn) + stub.spu->dispatch_table.WindowVisibleRegion(window->spuWindow, 0, NULL); +#endif + } + + /* Update window mapping state. + * Basically, this lets us hide render SPU windows which correspond + * to unmapped application windows. Without this, "pertly" (for example) + * opens *lots* of temporary windows which otherwise clutter the screen. + */ + if (stub.trackWindowVisibility && window->type == CHROMIUM && window->drawable) { + const int mapped = stubIsWindowVisible(window); + if (mapped != window->mapped) { + crDebug("Dispatched: WindowShow(%i, %i)", window->spuWindow, mapped); + stub.spu->dispatch_table.WindowShow(window->spuWindow, mapped); + window->mapped = mapped; + } + } + + return retVal; +} + +void +stubDestroyContext( unsigned long contextId ) +{ + ContextInfo *context; + + if (!stub.contextTable) { + return; + } + + /* the lock order is windowTable->contextTable (see wglMakeCurrent_prox, glXMakeCurrent) + * this is why we need to take a windowTable lock since we will later do stub.windowTable access & locking */ + crHashtableLock(stub.windowTable); + crHashtableLock(stub.contextTable); + + context = (ContextInfo *) crHashtableSearch(stub.contextTable, contextId); + if (context) + stubDestroyContextLocked(context); + else + crError("No context."); + +#ifdef CHROMIUM_THREADSAFE + if (stubGetCurrentContext() == context) { + stubSetCurrentContext(NULL); + } + + VBoxTlsRefMarkDestroy(context); + VBoxTlsRefRelease(context); +#else + if (stubGetCurrentContext() == context) { + stubSetCurrentContext(NULL); + } + stubContextFree(context); +#endif + crHashtableUnlock(stub.contextTable); + crHashtableUnlock(stub.windowTable); +} + +void +stubSwapBuffers(WindowInfo *window, GLint flags) +{ + if (!window) + return; + + /* Determine if this window is being rendered natively or through + * Chromium. + */ + + if (window->type == NATIVE) { + /*printf("*** Swapping native window %d\n", (int) drawable);*/ +#ifdef WINDOWS + (void) stub.wsInterface.wglSwapBuffers( window->drawable ); +#elif defined(Darwin) + /* ...is this ok? */ +/* stub.wsInterface.CGLFlushDrawable( context->cglc ); */ + crDebug("stubSwapBuffers: unable to swap (no context!)"); +#elif defined(GLX) + stub.wsInterface.glXSwapBuffers( window->dpy, window->drawable ); +#endif + } + else if (window->type == CHROMIUM) { + /* Let the SPU do the buffer swap */ + /*printf("*** Swapping chromium window %d\n", (int) drawable);*/ + if (stub.appDrawCursor) { + int pos[2]; + GetCursorPosition(window, pos); + stub.spu->dispatch_table.ChromiumParametervCR(GL_CURSOR_POSITION_CR, GL_INT, 2, pos); + } + stub.spu->dispatch_table.SwapBuffers( window->spuWindow, flags ); + } + else { + crDebug("Calling SwapBuffers on a window we haven't seen before (no-op)."); + } +} diff --git a/src/VBox/Additions/common/crOpenGL/cr_gl.py b/src/VBox/Additions/common/crOpenGL/cr_gl.py new file mode 100755 index 00000000..12e332ad --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/cr_gl.py @@ -0,0 +1,65 @@ +from __future__ import print_function +print(""" +/** @file + * VBox OpenGL chromium functions header + */ + +/* + * Copyright (C) 2008-2016 """ """Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ +""") +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +import sys + +import apiutil + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - THIS FILE GENERATED BY THE cr_gl.py SCRIPT */ +#ifndef __CR_GL_H__ +#define __CR_GL_H__ + +#include "chromium.h" +#include "cr_string.h" +#include "cr_version.h" +#include "stub.h" + +#ifdef WINDOWS +#pragma warning( disable: 4055 ) +#endif + +""") + + +# Extern-like declarations +keys = apiutil.GetAllFunctions(sys.argv[1]+"/APIspec.txt") +for func_name in keys: + if "Chromium" == apiutil.Category(func_name): + continue + if "VBox" == apiutil.Category(func_name): + continue + if func_name == "BoundsInfoCR": + continue + if "GL_chromium" == apiutil.Category(func_name): + pass #continue + + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + + print("extern %s cr_gl%s(%s);" % (return_type, func_name, + apiutil.MakeDeclarationString( params ))) + +print("#endif /* __CR_GL_H__ */") diff --git a/src/VBox/Additions/common/crOpenGL/defs.py b/src/VBox/Additions/common/crOpenGL/defs.py new file mode 100755 index 00000000..c0703088 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/defs.py @@ -0,0 +1,505 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + +apiutil.CopyrightDef() + +# NOTE: if we need a LIBRARY statement, we would need to create a defs-x86.py to generate a .def file for VBoxOGL-x86 library +#print "LIBRARY VBoxOGL" +#print "DESCRIPTION \"\"" - warning LNK4017: DESCRIPTION statement not supported for the target platform; ignored +print("EXPORTS") + +# XXX can't these values be automatically computed by analyzing parameters? + +stack_sizes = { + 'Accum': 8, + 'AlphaFunc': 8, + 'AreTexturesResident': 12, + 'ArrayElement': 4, + 'Begin': 4, + 'BindTexture': 8, + 'Bitmap': 28, + 'BlendFunc': 8, + 'CallList': 4, + 'CallLists': 12, + 'Clear': 4, + 'ClearAccum': 16, + 'ClearColor': 16, + 'ClearDepth': 8, + 'ClearIndex': 4, + 'ClearStencil': 4, + 'ClipPlane': 8, + 'Color3b': 12, + 'Color3bv': 4, + 'Color3d': 24, + 'Color3dv': 4, + 'Color3f': 12, + 'Color3fv': 4, + 'Color3i': 12, + 'Color3iv': 4, + 'Color3s': 12, + 'Color3sv': 4, + 'Color3ub': 12, + 'Color3ubv': 4, + 'Color3ui': 12, + 'Color3uiv': 4, + 'Color3us': 12, + 'Color3usv': 4, + 'Color4b': 16, + 'Color4bv': 4, + 'Color4d': 32, + 'Color4dv': 4, + 'Color4f': 16, + 'Color4fv': 4, + 'Color4i': 16, + 'Color4iv': 4, + 'Color4s': 16, + 'Color4sv': 4, + 'Color4ub': 16, + 'Color4ubv': 4, + 'Color4ui': 16, + 'Color4uiv': 4, + 'Color4us': 16, + 'Color4usv': 4, + 'ColorMask': 16, + 'ColorMaterial': 8, + 'ColorPointer': 16, + 'CopyPixels': 20, + 'CopyTexImage1D': 28, + 'CopyTexImage2D': 32, + 'CopyTexSubImage1D': 24, + 'CopyTexSubImage2D': 32, + 'CullFace': 4, + 'DebugEntry': 8, + 'DeleteLists': 8, + 'DeleteTextures': 8, + 'DepthFunc': 4, + 'DepthMask': 4, + 'DepthRange': 16, + 'Disable': 4, + 'DisableClientState': 4, + 'DrawArrays': 12, + 'DrawBuffer': 4, + 'DrawElements': 16, + 'DrawPixels': 20, + 'EdgeFlag': 4, + 'EdgeFlagPointer': 8, + 'EdgeFlagv': 4, + 'Enable': 4, + 'EnableClientState': 4, + 'End': 0, + 'EndList': 0, + 'EvalCoord1d': 8, + 'EvalCoord1dv': 4, + 'EvalCoord1f': 4, + 'EvalCoord1fv': 4, + 'EvalCoord2d': 16, + 'EvalCoord2dv': 4, + 'EvalCoord2f': 8, + 'EvalCoord2fv': 4, + 'EvalMesh1': 12, + 'EvalMesh2': 20, + 'EvalPoint1': 4, + 'EvalPoint2': 8, + 'FeedbackBuffer': 12, + 'Finish': 0, + 'Flush': 0, + 'Fogf': 8, + 'Fogfv': 8, + 'Fogi': 8, + 'Fogiv': 8, + 'FrontFace': 4, + 'Frustum': 48, + 'GenLists': 4, + 'GenTextures': 8, + 'GetBooleanv': 8, + 'GetClipPlane': 8, + 'GetDoublev': 8, + 'GetError': 0, + 'GetFloatv': 8, + 'GetIntegerv': 8, + 'GetLightfv': 12, + 'GetLightiv': 12, + 'GetMapdv': 12, + 'GetMapfv': 12, + 'GetMapiv': 12, + 'GetMaterialfv': 12, + 'GetMaterialiv': 12, + 'GetPixelMapfv': 8, + 'GetPixelMapuiv': 8, + 'GetPixelMapusv': 8, + 'GetPointerv': 8, + 'GetPolygonStipple': 4, + 'GetString': 4, + 'GetTexEnvfv': 12, + 'GetTexEnviv': 12, + 'GetTexGendv': 12, + 'GetTexGenfv': 12, + 'GetTexGeniv': 12, + 'GetTexImage': 20, + 'GetTexLevelParameterfv': 16, + 'GetTexLevelParameteriv': 16, + 'GetTexParameterfv': 12, + 'GetTexParameteriv': 12, + 'Hint': 8, + 'IndexMask': 4, + 'IndexPointer': 12, + 'Indexd': 8, + 'Indexdv': 4, + 'Indexf': 4, + 'Indexfv': 4, + 'Indexi': 4, + 'Indexiv': 4, + 'Indexs': 4, + 'Indexsv': 4, + 'Indexub': 4, + 'Indexubv': 4, + 'InitNames': 0, + 'InterleavedArrays': 12, + 'IsEnabled': 4, + 'IsList': 4, + 'IsTexture': 4, + 'LightModelf': 8, + 'LightModelfv': 8, + 'LightModeli': 8, + 'LightModeliv': 8, + 'Lightf': 12, + 'Lightfv': 12, + 'Lighti': 12, + 'Lightiv': 12, + 'LineStipple': 8, + 'LineWidth': 4, + 'ListBase': 4, + 'LoadIdentity': 0, + 'LoadMatrixd': 4, + 'LoadMatrixf': 4, + 'LoadName': 4, + 'LogicOp': 4, + 'Map1d': 32, + 'Map1f': 24, + 'Map2d': 56, + 'Map2f': 40, + 'MapGrid1d': 20, + 'MapGrid1f': 12, + 'MapGrid2d': 40, + 'MapGrid2f': 24, + 'Materialf': 12, + 'Materialfv': 12, + 'Materiali': 12, + 'Materialiv': 12, + 'MatrixMode': 4, + 'MultMatrixd': 4, + 'MultMatrixf': 4, + 'NewList': 8, + 'Normal3b': 12, + 'Normal3bv': 4, + 'Normal3d': 24, + 'Normal3dv': 4, + 'Normal3f': 12, + 'Normal3fv': 4, + 'Normal3i': 12, + 'Normal3iv': 4, + 'Normal3s': 12, + 'Normal3sv': 4, + 'NormalPointer': 12, + 'Ortho': 48, + 'PassThrough': 4, + 'PixelMapfv': 12, + 'PixelMapuiv': 12, + 'PixelMapusv': 12, + 'PixelStoref': 8, + 'PixelStorei': 8, + 'PixelTransferf': 8, + 'PixelTransferi': 8, + 'PixelZoom': 8, + 'PointSize': 4, + 'PolygonMode': 8, + 'PolygonOffset': 8, + 'PolygonStipple': 4, + 'PopAttrib': 0, + 'PopClientAttrib': 0, + 'PopMatrix': 0, + 'PopName': 0, + 'PrioritizeTextures': 12, + 'PushAttrib': 4, + 'PushClientAttrib': 4, + 'PushMatrix': 0, + 'PushName': 4, + 'RasterPos2d': 16, + 'RasterPos2dv': 4, + 'RasterPos2f': 8, + 'RasterPos2fv': 4, + 'RasterPos2i': 8, + 'RasterPos2iv': 4, + 'RasterPos2s': 8, + 'RasterPos2sv': 4, + 'RasterPos3d': 24, + 'RasterPos3dv': 4, + 'RasterPos3f': 12, + 'RasterPos3fv': 4, + 'RasterPos3i': 12, + 'RasterPos3iv': 4, + 'RasterPos3s': 12, + 'RasterPos3sv': 4, + 'RasterPos4d': 32, + 'RasterPos4dv': 4, + 'RasterPos4f': 16, + 'RasterPos4fv': 4, + 'RasterPos4i': 16, + 'RasterPos4iv': 4, + 'RasterPos4s': 16, + 'RasterPos4sv': 4, + 'ReadBuffer': 4, + 'ReadPixels': 28, + 'Rectd': 32, + 'Rectdv': 8, + 'Rectf': 16, + 'Rectfv': 8, + 'Recti': 16, + 'Rectiv': 8, + 'Rects': 16, + 'Rectsv': 8, + 'RenderMode': 4, + 'Rotated': 32, + 'Rotatef': 16, + 'Scaled': 24, + 'Scalef': 12, + 'Scissor': 16, + 'SelectBuffer': 8, + 'ShadeModel': 4, + 'StencilFunc': 12, + 'StencilMask': 4, + 'StencilOp': 12, + 'TexCoord1d': 8, + 'TexCoord1dv': 4, + 'TexCoord1f': 4, + 'TexCoord1fv': 4, + 'TexCoord1i': 4, + 'TexCoord1iv': 4, + 'TexCoord1s': 4, + 'TexCoord1sv': 4, + 'TexCoord2d': 16, + 'TexCoord2dv': 4, + 'TexCoord2f': 8, + 'TexCoord2fv': 4, + 'TexCoord2i': 8, + 'TexCoord2iv': 4, + 'TexCoord2s': 8, + 'TexCoord2sv': 4, + 'TexCoord3d': 24, + 'TexCoord3dv': 4, + 'TexCoord3f': 12, + 'TexCoord3fv': 4, + 'TexCoord3i': 12, + 'TexCoord3iv': 4, + 'TexCoord3s': 12, + 'TexCoord3sv': 4, + 'TexCoord4d': 32, + 'TexCoord4dv': 4, + 'TexCoord4f': 16, + 'TexCoord4fv': 4, + 'TexCoord4i': 16, + 'TexCoord4iv': 4, + 'TexCoord4s': 16, + 'TexCoord4sv': 4, + 'TexCoordPointer': 16, + 'TexEnvf': 12, + 'TexEnvfv': 12, + 'TexEnvi': 12, + 'TexEnviv': 12, + 'TexGend': 16, + 'TexGendv': 12, + 'TexGenf': 12, + 'TexGenfv': 12, + 'TexGeni': 12, + 'TexGeniv': 12, + 'TexImage1D': 32, + 'TexImage2D': 36, + 'TexImage3D': 36, + 'TexParameterf': 12, + 'TexParameterfv': 12, + 'TexParameteri': 12, + 'TexParameteriv': 12, + 'TexSubImage1D': 28, + 'TexSubImage2D': 36, + 'Translated': 24, + 'Translatef': 12, + 'Vertex2d': 16, + 'Vertex2dv': 4, + 'Vertex2f': 8, + 'Vertex2fv': 4, + 'Vertex2i': 8, + 'Vertex2iv': 4, + 'Vertex2s': 8, + 'Vertex2sv': 4, + 'Vertex3d': 24, + 'Vertex3dv': 4, + 'Vertex3f': 12, + 'Vertex3fv': 4, + 'Vertex3i': 12, + 'Vertex3iv': 4, + 'Vertex3s': 12, + 'Vertex3sv': 4, + 'Vertex4d': 32, + 'Vertex4dv': 4, + 'Vertex4f': 16, + 'Vertex4fv': 4, + 'Vertex4i': 16, + 'Vertex4iv': 4, + 'Vertex4s': 16, + 'Vertex4sv': 4, + 'VertexPointer': 16, + 'Viewport': 16, + 'wglChoosePixelFormat': 8, + 'wglCopyContext': 12, + 'wglCreateContext': 4, + 'wglCreateLayerContext': 8, + 'wglDeleteContext': 4, + 'wglDescribeLayerPlane': 20, + 'wglDescribePixelFormat': 16, + 'wglGetCurrentContext': 0, + 'wglGetCurrentDC': 0, + 'wglGetDefaultProcAddress': 4, + 'wglGetLayerPaletteEntries': 20, + 'wglGetPixelFormat': 4, + 'wglGetProcAddress': 4, + 'wglMakeCurrent': 8, + 'wglRealizeLayerPalette': 12, + 'wglSetLayerPaletteEntries': 20, + 'wglSetPixelFormat': 12, + 'wglShareLists': 8, + 'wglSwapBuffers': 4, + 'wglSwapLayerBuffers': 8, + 'wglSwapMultipleBuffers': 8, + 'wglUseFontBitmapsA': 16, + 'wglUseFontBitmapsW': 16, + 'wglUseFontOutlinesA': 32, + 'wglUseFontOutlinesW': 32, + 'wglChoosePixelFormatEXT' : 24, + 'wglGetPixelFormatAttribivEXT' : 24, + 'wglGetPixelFormatAttribfvEXT' : 24, + 'wglGetExtensionsStringEXT' : 4, + 'CopyContext' : 12, + 'CreateContext' : 4, + 'CreateLayerContext' : 8, + 'DeleteContext' : 4, + 'DescribeLayerPlane' : 20, + 'DescribePixelFormat' : 16, + 'GetLayerPaletteEntries' : 20, + 'GetProcAddress' : 4, + 'RealizeLayerPalette' : 12, + 'ReleaseContext' : 4, + 'SetContext' : 12, + 'SetLayerPaletteEntries' : 20, + 'SetPixelFormat' : 12, + 'ShareLists' : 8, + 'SwapBuffers' : 4, + 'SwapLayerBuffers' : 8, + 'ValidateVersion' : 4, +} + +noexport_special = [ + "BoundsInfoCR", + "CreateContext", + "DestroyContext", + "MakeCurrent", + "WindowCreate", + "WindowDestroy", + "WindowSize", + "WindowPosition", + "WindowVisibleRegion", + "WindowShow", + "SwapBuffers" +] + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +for func_name in keys: + if func_name in noexport_special: + continue + try: + print("gl%s@%d = cr_gl%s" % (func_name,stack_sizes[func_name],func_name)) + except KeyError: + pass + +for func_name in ( "wglChoosePixelFormat", + "wglCopyContext", + "wglCreateContext", + "wglCreateLayerContext", + "wglDeleteContext", + "wglDescribeLayerPlane", + "wglDescribePixelFormat", + "wglGetCurrentContext", + "wglGetCurrentDC", + "wglGetLayerPaletteEntries", + "wglGetPixelFormat", + "wglGetProcAddress", + "wglMakeCurrent", + "wglRealizeLayerPalette", + "wglSetLayerPaletteEntries", + "wglSetPixelFormat", + "wglShareLists", + "wglSwapBuffers", + "wglSwapLayerBuffers", + "wglSwapMultipleBuffers", + "wglUseFontBitmapsA", + "wglUseFontBitmapsW", + "wglUseFontOutlinesA", + "wglUseFontOutlinesW", + "wglChoosePixelFormatEXT", + "wglGetPixelFormatAttribivEXT", + "wglGetPixelFormatAttribfvEXT", + "wglGetExtensionsStringEXT"): + print("%s = %s_prox" % (func_name,func_name)) + +""" +for func_name in ( "CopyContext", + "CreateContext", + "CreateLayerContext", + "DeleteContext", + "DescribeLayerPlane", + "DescribePixelFormat", + "GetLayerPaletteEntries", + "GetProcAddress", + "RealizeLayerPalette", + "SetLayerPaletteEntries", + "ShareLists", + "SwapBuffers", + "SwapLayerBuffers"): + print "Drv%s@%d = wgl%s_prox" % (func_name,stack_sizes[func_name],func_name) +""" + +print("""DrvCopyContext +DrvCreateContext +DrvCreateLayerContext +DrvDeleteContext +DrvDescribeLayerPlane +DrvDescribePixelFormat +DrvGetLayerPaletteEntries +DrvGetProcAddress = wglGetProcAddress_prox +DrvRealizeLayerPalette +DrvSetLayerPaletteEntries +DrvShareLists +DrvSwapBuffers +DrvSwapLayerBuffers +DrvReleaseContext@4 = DrvReleaseContext +DrvSetContext@12 = DrvSetContext +DrvValidateVersion@4 = DrvValidateVersion +DrvSetPixelFormat@8 = DrvSetPixelFormat""") + +print("""crCreateContext +crMakeCurrent +crSwapBuffers +crGetProcAddress +VBoxCreateContext +VBoxCtxChromiumParameteriCR +VBoxGetWindowId +VBoxGetContextId +VBoxFlushToHost""") +#print "DllMain" diff --git a/src/VBox/Additions/common/crOpenGL/defs64.py b/src/VBox/Additions/common/crOpenGL/defs64.py new file mode 100755 index 00000000..58971b9b --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/defs64.py @@ -0,0 +1,485 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + +apiutil.CopyrightDef() + +#print "LIBRARY VBoxOGL" +#print "DESCRIPTION \"\"" - warning LNK4017: DESCRIPTION statement not supported for the target platform; ignored +print("EXPORTS") + +# XXX can't these values be automatically computed by analyzing parameters? + +exports_special = [ + 'Accum', + 'AlphaFunc', + 'AreTexturesResident', + 'ArrayElement', + 'Begin', + 'BindTexture', + 'Bitmap', + 'BlendFunc', + 'CallList', + 'CallLists', + 'Clear', + 'ClearAccum', + 'ClearColor', + 'ClearDepth', + 'ClearIndex', + 'ClearStencil', + 'ClipPlane', + 'Color3b', + 'Color3bv', + 'Color3d', + 'Color3dv', + 'Color3f', + 'Color3fv', + 'Color3i', + 'Color3iv', + 'Color3s', + 'Color3sv', + 'Color3ub', + 'Color3ubv', + 'Color3ui', + 'Color3uiv', + 'Color3us', + 'Color3usv', + 'Color4b', + 'Color4bv', + 'Color4d', + 'Color4dv', + 'Color4f', + 'Color4fv', + 'Color4i', + 'Color4iv', + 'Color4s', + 'Color4sv', + 'Color4ub', + 'Color4ubv', + 'Color4ui', + 'Color4uiv', + 'Color4us', + 'Color4usv', + 'ColorMask', + 'ColorMaterial', + 'ColorPointer', + 'CopyPixels', + 'CopyTexImage1D', + 'CopyTexImage2D', + 'CopyTexSubImage1D', + 'CopyTexSubImage2D', + 'CullFace', + 'DebugEntry', + 'DeleteLists', + 'DeleteTextures', + 'DepthFunc', + 'DepthMask', + 'DepthRange', + 'Disable', + 'DisableClientState', + 'DrawArrays', + 'DrawBuffer', + 'DrawElements', + 'DrawPixels', + 'EdgeFlag', + 'EdgeFlagPointer', + 'EdgeFlagv', + 'Enable', + 'EnableClientState', + 'End', + 'EndList', + 'EvalCoord1d', + 'EvalCoord1dv', + 'EvalCoord1f', + 'EvalCoord1fv', + 'EvalCoord2d', + 'EvalCoord2dv', + 'EvalCoord2f', + 'EvalCoord2fv', + 'EvalMesh1', + 'EvalMesh2', + 'EvalPoint1', + 'EvalPoint2', + 'FeedbackBuffer', + 'Finish', + 'Flush', + 'Fogf', + 'Fogfv', + 'Fogi', + 'Fogiv', + 'FrontFace', + 'Frustum', + 'GenLists', + 'GenTextures', + 'GetBooleanv', + 'GetClipPlane', + 'GetDoublev', + 'GetError', + 'GetFloatv', + 'GetIntegerv', + 'GetLightfv', + 'GetLightiv', + 'GetMapdv', + 'GetMapfv', + 'GetMapiv', + 'GetMaterialfv', + 'GetMaterialiv', + 'GetPixelMapfv', + 'GetPixelMapuiv', + 'GetPixelMapusv', + 'GetPointerv', + 'GetPolygonStipple', + 'GetString', + 'GetTexEnvfv', + 'GetTexEnviv', + 'GetTexGendv', + 'GetTexGenfv', + 'GetTexGeniv', + 'GetTexImage', + 'GetTexLevelParameterfv', + 'GetTexLevelParameteriv', + 'GetTexParameterfv', + 'GetTexParameteriv', + 'Hint', + 'IndexMask', + 'IndexPointer', + 'Indexd', + 'Indexdv', + 'Indexf', + 'Indexfv', + 'Indexi', + 'Indexiv', + 'Indexs', + 'Indexsv', + 'Indexub', + 'Indexubv', + 'InitNames', + 'InterleavedArrays', + 'IsEnabled', + 'IsList', + 'IsTexture', + 'LightModelf', + 'LightModelfv', + 'LightModeli', + 'LightModeliv', + 'Lightf', + 'Lightfv', + 'Lighti', + 'Lightiv', + 'LineStipple', + 'LineWidth', + 'ListBase', + 'LoadIdentity', + 'LoadMatrixd', + 'LoadMatrixf', + 'LoadName', + 'LogicOp', + 'Map1d', + 'Map1f', + 'Map2d', + 'Map2f', + 'MapGrid1d', + 'MapGrid1f', + 'MapGrid2d', + 'MapGrid2f', + 'Materialf', + 'Materialfv', + 'Materiali', + 'Materialiv', + 'MatrixMode', + 'MultMatrixd', + 'MultMatrixf', + 'NewList', + 'Normal3b', + 'Normal3bv', + 'Normal3d', + 'Normal3dv', + 'Normal3f', + 'Normal3fv', + 'Normal3i', + 'Normal3iv', + 'Normal3s', + 'Normal3sv', + 'NormalPointer', + 'Ortho', + 'PassThrough', + 'PixelMapfv', + 'PixelMapuiv', + 'PixelMapusv', + 'PixelStoref', + 'PixelStorei', + 'PixelTransferf', + 'PixelTransferi', + 'PixelZoom', + 'PointSize', + 'PolygonMode', + 'PolygonOffset', + 'PolygonStipple', + 'PopAttrib', + 'PopClientAttrib', + 'PopMatrix', + 'PopName', + 'PrioritizeTextures', + 'PushAttrib', + 'PushClientAttrib', + 'PushMatrix', + 'PushName', + 'RasterPos2d', + 'RasterPos2dv', + 'RasterPos2f', + 'RasterPos2fv', + 'RasterPos2i', + 'RasterPos2iv', + 'RasterPos2s', + 'RasterPos2sv', + 'RasterPos3d', + 'RasterPos3dv', + 'RasterPos3f', + 'RasterPos3fv', + 'RasterPos3i', + 'RasterPos3iv', + 'RasterPos3s', + 'RasterPos3sv', + 'RasterPos4d', + 'RasterPos4dv', + 'RasterPos4f', + 'RasterPos4fv', + 'RasterPos4i', + 'RasterPos4iv', + 'RasterPos4s', + 'RasterPos4sv', + 'ReadBuffer', + 'ReadPixels', + 'Rectd', + 'Rectdv', + 'Rectf', + 'Rectfv', + 'Recti', + 'Rectiv', + 'Rects', + 'Rectsv', + 'RenderMode', + 'Rotated', + 'Rotatef', + 'Scaled', + 'Scalef', + 'Scissor', + 'SelectBuffer', + 'ShadeModel', + 'StencilFunc', + 'StencilMask', + 'StencilOp', + 'TexCoord1d', + 'TexCoord1dv', + 'TexCoord1f', + 'TexCoord1fv', + 'TexCoord1i', + 'TexCoord1iv', + 'TexCoord1s', + 'TexCoord1sv', + 'TexCoord2d', + 'TexCoord2dv', + 'TexCoord2f', + 'TexCoord2fv', + 'TexCoord2i', + 'TexCoord2iv', + 'TexCoord2s', + 'TexCoord2sv', + 'TexCoord3d', + 'TexCoord3dv', + 'TexCoord3f', + 'TexCoord3fv', + 'TexCoord3i', + 'TexCoord3iv', + 'TexCoord3s', + 'TexCoord3sv', + 'TexCoord4d', + 'TexCoord4dv', + 'TexCoord4f', + 'TexCoord4fv', + 'TexCoord4i', + 'TexCoord4iv', + 'TexCoord4s', + 'TexCoord4sv', + 'TexCoordPointer', + 'TexEnvf', + 'TexEnvfv', + 'TexEnvi', + 'TexEnviv', + 'TexGend', + 'TexGendv', + 'TexGenf', + 'TexGenfv', + 'TexGeni', + 'TexGeniv', + 'TexImage1D', + 'TexImage2D', + 'TexImage3D', + 'TexParameterf', + 'TexParameterfv', + 'TexParameteri', + 'TexParameteriv', + 'TexSubImage1D', + 'TexSubImage2D', + 'Translated', + 'Translatef', + 'Vertex2d', + 'Vertex2dv', + 'Vertex2f', + 'Vertex2fv', + 'Vertex2i', + 'Vertex2iv', + 'Vertex2s', + 'Vertex2sv', + 'Vertex3d', + 'Vertex3dv', + 'Vertex3f', + 'Vertex3fv', + 'Vertex3i', + 'Vertex3iv', + 'Vertex3s', + 'Vertex3sv', + 'Vertex4d', + 'Vertex4dv', + 'Vertex4f', + 'Vertex4fv', + 'Vertex4i', + 'Vertex4iv', + 'Vertex4s', + 'Vertex4sv', + 'VertexPointer', + 'Viewport', + 'wglChoosePixelFormat', + 'wglCopyContext', + 'wglCreateContext', + 'wglCreateLayerContext', + 'wglDeleteContext', + 'wglDescribeLayerPlane', + 'wglDescribePixelFormat', + 'wglGetCurrentContext', + 'wglGetCurrentDC', + 'wglGetDefaultProcAddress', + 'wglGetLayerPaletteEntries', + 'wglGetPixelFormat', + 'wglGetProcAddress', + 'wglMakeCurrent', + 'wglRealizeLayerPalette', + 'wglSetLayerPaletteEntries', + 'wglSetPixelFormat', + 'wglShareLists', + 'wglSwapBuffers', + 'wglSwapLayerBuffers', + 'wglSwapMultipleBuffers', + 'wglUseFontBitmapsA', + 'wglUseFontBitmapsW', + 'wglUseFontOutlinesA', + 'wglUseFontOutlinesW', + 'wglChoosePixelFormatEXT', + 'wglGetPixelFormatAttribivEXT', + 'wglGetPixelFormatAttribfvEXT', + 'wglGetExtensionsStringEXT', + 'CopyContext', + 'CreateContext', + 'CreateLayerContext', + 'DeleteContext', + 'DescribeLayerPlane', + 'DescribePixelFormat', + 'GetLayerPaletteEntries', + 'GetProcAddress', + 'RealizeLayerPalette', + 'ReleaseContext', + 'SetContext', + 'SetLayerPaletteEntries', + 'SetPixelFormat', + 'ShareLists', + 'SwapBuffers', + 'SwapLayerBuffers', + 'ValidateVersion', +] + +noexport_special = [ + "BoundsInfoCR", + "CreateContext", + "DestroyContext", + "MakeCurrent", + "WindowCreate", + "WindowDestroy", + "WindowSize", + "WindowPosition", + "WindowVisibleRegion", + "WindowShow", + "SwapBuffers" +] + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +for func_name in keys: + if func_name in noexport_special: + continue + if func_name in exports_special: + print("gl%s = cr_gl%s" % (func_name,func_name)) + +for func_name in ( "wglChoosePixelFormat", + "wglCopyContext", + "wglCreateContext", + "wglCreateLayerContext", + "wglDeleteContext", + "wglDescribeLayerPlane", + "wglDescribePixelFormat", + "wglGetCurrentContext", + "wglGetCurrentDC", + "wglGetLayerPaletteEntries", + "wglGetPixelFormat", + "wglGetProcAddress", + "wglMakeCurrent", + "wglRealizeLayerPalette", + "wglSetLayerPaletteEntries", + "wglSetPixelFormat", + "wglShareLists", + "wglSwapBuffers", + "wglSwapLayerBuffers", + "wglSwapMultipleBuffers", + "wglUseFontBitmapsA", + "wglUseFontBitmapsW", + "wglUseFontOutlinesA", + "wglUseFontOutlinesW", + "wglChoosePixelFormatEXT", + "wglGetPixelFormatAttribivEXT", + "wglGetPixelFormatAttribfvEXT", + "wglGetExtensionsStringEXT"): + print("%s = %s_prox" % (func_name,func_name)) + +print("""DrvCopyContext +DrvCreateContext +DrvCreateLayerContext +DrvDeleteContext +DrvDescribeLayerPlane +DrvDescribePixelFormat +DrvGetLayerPaletteEntries +DrvGetProcAddress = wglGetProcAddress_prox +DrvRealizeLayerPalette +DrvSetLayerPaletteEntries +DrvShareLists +DrvSwapBuffers +DrvSwapLayerBuffers +DrvReleaseContext = DrvReleaseContext +DrvSetContext = DrvSetContext +DrvValidateVersion = DrvValidateVersion +DrvSetPixelFormat = DrvSetPixelFormat""") + +print("""crCreateContext +crMakeCurrent +crSwapBuffers +crGetProcAddress +VBoxCreateContext +VBoxCtxChromiumParameteriCR +VBoxGetWindowId +VBoxGetContextId +VBoxFlushToHost""") +#print "DllMain" diff --git a/src/VBox/Additions/common/crOpenGL/dri_drv.c b/src/VBox/Additions/common/crOpenGL/dri_drv.c new file mode 100644 index 00000000..de206624 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/dri_drv.c @@ -0,0 +1,1012 @@ +/* $Id: dri_drv.c $ */ + +/** @file + * VBox OpenGL DRI driver functions + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * -------------------------------------------------------------------- + * + * This file is based in part on the tdfx driver from X.Org/Mesa, with the + * following copyright notice: + * + * Copyright 2000 VA Linux Systems Inc., Fremont, California. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Original rewrite: + * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000 + * + * Authors: + * Gareth Hughes <gareth@valinux.com> + */ + +#include "cr_error.h" +#include "cr_gl.h" +#include "stub.h" +#include "dri_drv.h" +#include "DD_gl.h" + +/** @todo some of those are or'ed with GL_VERSIONS and ain't needed here*/ +#define need_GL_ARB_occlusion_query +#define need_GL_ARB_point_parameters +#define need_GL_NV_point_sprite +#define need_GL_ARB_texture_compression +#define need_GL_ARB_transpose_matrix +#define need_GL_ARB_vertex_buffer_object +#define need_GL_ARB_vertex_program +#define need_GL_ARB_window_pos +#define need_GL_EXT_blend_color +#define need_GL_EXT_blend_minmax +#define need_GL_EXT_blend_func_separate +#define need_GL_EXT_fog_coord +#define need_GL_EXT_multi_draw_arrays +#define need_GL_EXT_secondary_color +#define need_GL_EXT_texture_object +#define need_GL_EXT_texture3D +#define need_GL_VERSION_1_3 +#define need_GL_VERSION_1_4 +#define need_GL_VERSION_1_5 + +#include "drivers/dri/common/extension_helper.h" + +/** @todo add more which are supported by chromium like GL_NV_vertex_program etc.*/ +static const struct dri_extension vbox_extensions[] = { + { "GL_ARB_depth_texture", NULL }, + { "GL_ARB_fragment_program", NULL }, + { "GL_ARB_multitexture", NULL }, + { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions }, + { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions }, + { "GL_NV_point_sprite", GL_NV_point_sprite_functions }, + { "GL_ARB_shadow", NULL }, + { "GL_ARB_shadow_ambient", NULL }, + { "GL_ARB_texture_border_clamp", NULL }, + { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions }, + { "GL_ARB_texture_cube_map", NULL }, + { "GL_ARB_texture_env_add", NULL }, + { "GL_ARB_texture_env_combine", NULL }, + { "GL_EXT_texture_env_combine", NULL }, + { "GL_ARB_texture_env_crossbar", NULL }, + { "GL_ARB_texture_env_dot3", NULL }, + { "GL_EXT_texture_env_dot3", NULL }, + { "GL_ARB_texture_mirrored_repeat", NULL }, + { "GL_ARB_texture_non_power_of_two", NULL }, + { "GL_ARB_transpose_matrix", GL_ARB_transpose_matrix_functions }, + { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions }, + { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions }, + { "GL_ARB_window_pos", GL_ARB_window_pos_functions }, + { "GL_EXT_blend_color", GL_EXT_blend_color_functions }, + { "GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions }, + { "GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions }, + { "GL_EXT_blend_subtract", NULL }, + { "GL_EXT_texture_env_add", NULL }, /** @todo that's an alias to GL_ARB version, remove it?*/ + { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions }, + { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions }, + { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions }, + { "GL_EXT_shadow_funcs", NULL }, + { "GL_EXT_stencil_wrap", NULL }, + { "GL_EXT_texture_cube_map", NULL }, /** @todo another alias*/ + { "GL_EXT_texture_edge_clamp", NULL }, + { "GL_EXT_texture_filter_anisotropic", NULL }, + { "GL_EXT_texture_lod_bias", NULL }, + { "GL_EXT_texture_object", GL_EXT_texture_object_functions }, + { "GL_EXT_texture3D", GL_EXT_texture3D_functions }, + { "GL_NV_texgen_reflection", NULL }, + { "GL_ARB_texture_rectangle", NULL }, + { "GL_SGIS_generate_mipmap", NULL }, + { "GL_SGIS_texture_edge_clamp", NULL } /** @todo another alias*/ +}; + +static void +vboxdriInitExtensions(GLcontext * ctx) +{ + /** @todo have to check extensions supported by host here first */ + driInitExtensions(ctx, vbox_extensions, GL_FALSE); +} + +static GLvertexformat vboxdriTnlVtxFmt; + + +/* This callback tells us that Mesa's internal state has changed. We probably + * don't need to handle this ourselves, so just pass it on to other parts of + * Mesa we may be using, as the swrast driver and others do */ +static void +vboxDDUpdateState(GLcontext * ctx, GLuint new_state) +{ + _swrast_InvalidateState(ctx, new_state); + _swsetup_InvalidateState(ctx, new_state); + _vbo_InvalidateState(ctx, new_state); + _tnl_InvalidateState(ctx, new_state); +} + +#if 0 /* See comment in vboxdriInitFuncs */ +static void +vboxDDGetBufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height) +{ + /*do something, note it's obsolete*/ +} + +static void +vboxDDResizeBuffer( GLcontext *ctx, GLframebuffer *fb, + GLuint width, GLuint height) +{ + /*do something, note it's obsolete*/ +} + +static void +vboxDDError(GLcontext *ctx) +{ + //__GLcontextRec::ErrorValue contains the error value. +} +#endif + +static void +vboxDDDrawPixels(GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels) +{ +} + +static void +vboxDDReadPixels(GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + GLvoid *dest) +{ +} + +static void +vboxDDCopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, + GLsizei width, GLsizei height, + GLint dstx, GLint dsty, GLenum type) +{ +} + +static void +vboxDDBitmap(GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap) +{ +} + +static void +vboxDDTexImage1D(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ +} + +static void +vboxDDTexImage2D(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ +} + +static void +vboxDDTexImage3D(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint depth, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ +} + +static void +vboxDDTexSubImage1D(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ +} + +static void +vboxDDTexSubImage2D(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ +} + + +static void +vboxDDTexSubImage3D(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ +} + + +static void +vboxDDGetTexImage(GLcontext *ctx, GLenum target, GLint level, + GLenum format, GLenum type, GLvoid *pixels, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ +} + +static void +vboxDDBindTexture(GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj) +{ +} + +static GLboolean +vboxDDIsTextureResident(GLcontext *ctx, struct gl_texture_object *t) +{ +} + +static void +vboxDDPrioritizeTexture(GLcontext *ctx, struct gl_texture_object *t, + GLclampf priority) +{ +} + +static void +vboxDDBlendColor(GLcontext *ctx, const GLfloat color[4]) +{ +} + +static void +vboxDDClearColor(GLcontext *ctx, const GLfloat color[4]) +{ +} + +static void +vboxDDClearIndex(GLcontext *ctx, GLuint index) +{ +} + +static void +vboxDDClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation) +{ +} + +/** @todo Enable or disable server-side gl capabilities, not related to glEnable? */ +static void +vboxDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) +{ + if (state) + cr_glEnable(cap); + else + cr_glDisable(cap); +} + +static void +vboxDDRenderMode(GLcontext *ctx, GLenum mode) +{ + cr_glRenderMode(mode); +} + +static void +vboxDDTexParameter(GLcontext *ctx, GLenum target, + struct gl_texture_object *texObj, + GLenum pname, const GLfloat *params) +{ +} + +/*Note, checking glGetError before and after those calls is the only way + *to return if we succeeded to get value or not, but it will add 2 sync calls and + *will reset glGetError value returned in case application calls it explicitly + */ +static GLboolean +vboxDDGetBooleanv(GLcontext *ctx, GLenum pname, GLboolean *result) +{ + cr_glGetBooleanv(pname, result); + return GL_TRUE; +} + +static GLboolean +vboxDDGetDoublev(GLcontext *ctx, GLenum pname, GLdouble *result) +{ + cr_glGetDoublev(pname, result); + return GL_TRUE; +} + +static GLboolean +vboxDDGetFloatv(GLcontext *ctx, GLenum pname, GLfloat *result) +{ + cr_glGetFloatv(pname, result); + return GL_TRUE; +} + +static GLboolean +vboxDDGetIntegerv(GLcontext *ctx, GLenum pname, GLint *result) +{ + cr_glGetIntegerv(pname, result); + return GL_TRUE; +} + +static GLboolean +vboxDDGetPointerv(GLcontext *ctx, GLenum pname, GLvoid **result) +{ + cr_glGetPointerv(pname, result); + return GL_TRUE; +} + +/** @todo + * change stub's createcontext to reuse driver private part of mesa's ctx to store stub ctx info. + */ +#define VBOX_GL_FUNC(func) vboxDD_gl##func +static void +vboxdriInitFuncs(struct dd_function_table *driver) +{ + driver->GetString = VBOX_GL_FUNC(GetString); + driver->UpdateState = vboxDDUpdateState; +#if 0 + /* I assume that we don't need to change these. In that case, prefer the + * default implementation over a stub. */ + driver->GetBufferSize = vboxDDGetBufferSize; + driver->ResizeBuffers = vboxDDResizeBuffer; + driver->Error = vboxDDError; +#endif + + driver->Finish = VBOX_GL_FUNC(Finish); + driver->Flush = VBOX_GL_FUNC(Flush); + + /* framebuffer/image functions */ + driver->Clear = VBOX_GL_FUNC(Clear); + driver->Accum = VBOX_GL_FUNC(Accum); + // driver->RasterPos = VBOX_GL_FUNC(RasterPos); /* No such element in *driver */ + driver->DrawPixels = vboxDDDrawPixels; + driver->ReadPixels = vboxDDReadPixels; + driver->CopyPixels = vboxDDCopyPixels; + driver->Bitmap = vboxDDBitmap; + + /* Texture functions */ + /** @todo deal with texnames and gl_texture_object pointers which are passed here*/ + driver->ChooseTextureFormat = NULL; + driver->TexImage1D = vboxDDTexImage1D; + driver->TexImage2D = vboxDDTexImage2D; + driver->TexImage3D = vboxDDTexImage3D; + driver->TexSubImage1D = vboxDDTexSubImage1D; + driver->TexSubImage2D = vboxDDTexSubImage2D; + driver->TexSubImage3D = vboxDDTexSubImage3D; + driver->GetTexImage = vboxDDGetTexImage; + driver->CopyTexImage1D = VBOX_GL_FUNC(CopyTexImage1D); + driver->CopyTexImage2D = VBOX_GL_FUNC(CopyTexImage2D); + driver->CopyTexSubImage1D = VBOX_GL_FUNC(CopyTexSubImage1D); + driver->CopyTexSubImage2D = VBOX_GL_FUNC(CopyTexSubImage2D); + driver->CopyTexSubImage3D = VBOX_GL_FUNC(CopyTexSubImage3D); + // driver->GenerateMipmap = VBOX_GL_FUNC(GenerateMipmap); /** @todo or NULL */ + // driver->TestProxyTexImage = vboxDDTestProxyTexImage; /** @todo just pass to glTexImage as we take care or proxy textures there */ + // driver->CompressedTexImage1D = VBOX_GL_FUNC(CompressedTexImage1D); + // driver->CompressedTexImage2D = VBOX_GL_FUNC(CompressedTexImage2D); + // driver->CompressedTexImage3D = VBOX_GL_FUNC(CompressedTexImage3D); + // driver->CompressedTexSubImage1D = VBOX_GL_FUNC(CompressedTexSubImage1D); + // driver->CompressedTexSubImage2D = VBOX_GL_FUNC(CompressedTexSubImage2D); + // driver->CompressedTexSubImage3D = VBOX_GL_FUNC(CompressedTexSubImage3D); + // driver->GetCompressedTexImage = VBOX_GL_FUNC(GetCompressedTexImage); + // driver->CompressedTextureSize = NULL; /** @todo */ + driver->BindTexture = vboxDDBindTexture; + // driver->NewTextureObject = vboxDDNewTextureObject; /** @todo */ + // driver->DeleteTexture = vboxDDDeleteTexture; /** @todo */ + // driver->NewTextureImage = vboxDDNewTextureImage; /** @todo */ + // driver->FreeTexImageData = vboxDDFreeTexImageData; /** @todo */ + // driver->MapTexture = vboxDDMapTexture; /** @todo */ + // driver->UnmapTexture = vboxDDUnmapTexture; /** @todo */ + // driver->TextureMemCpy = vboxDDTextureMemCpy; /** @todo */ + driver->IsTextureResident = vboxDDIsTextureResident; + driver->PrioritizeTexture = vboxDDPrioritizeTexture; + driver->ActiveTexture = VBOX_GL_FUNC(ActiveTextureARB); + // driver->UpdateTexturePalette = vboxDDUpdateTexturePalette; /** @todo */ + + /* imaging */ + /*driver->CopyColorTable = _swrast_CopyColorTable; + driver->CopyColorSubTable = _swrast_CopyColorSubTable; + driver->CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; + driver->CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;*/ + + /* Vertex/fragment programs */ + driver->BindProgram = NULL; + // driver->NewProgram = _mesa_new_program; /** @todo */ + // driver->DeleteProgram = _mesa_delete_program; /** @todo */ + driver->ProgramStringNotify = NULL; +#if FEATURE_MESA_program_debug + // driver->GetProgramRegister = _mesa_get_program_register; /** @todo */ +#endif /* FEATURE_MESA_program_debug */ + driver->IsProgramNative = NULL; + + /* simple state commands */ + driver->AlphaFunc = VBOX_GL_FUNC(AlphaFunc); + driver->BlendColor = vboxDDBlendColor; + // driver->BlendEquationSeparate = VBOX_GL_FUNC(BlendEquationSeparate); /** @todo */ + driver->BlendFuncSeparate = VBOX_GL_FUNC(BlendFuncSeparateEXT); + driver->ClearColor = vboxDDClearColor; + driver->ClearDepth = VBOX_GL_FUNC(ClearDepth); + driver->ClearIndex = vboxDDClearIndex; + driver->ClearStencil = VBOX_GL_FUNC(ClearStencil); + driver->ClipPlane = vboxDDClipPlane; + driver->ColorMask = VBOX_GL_FUNC(ColorMask); + driver->ColorMaterial = VBOX_GL_FUNC(ColorMaterial); + driver->CullFace = VBOX_GL_FUNC(CullFace); + driver->DrawBuffer = VBOX_GL_FUNC(DrawBuffer); /** @todo */ + // driver->DrawBuffers = VBOX_GL_FUNC(DrawBuffers); /** @todo */ + driver->FrontFace = VBOX_GL_FUNC(FrontFace); + driver->DepthFunc = VBOX_GL_FUNC(DepthFunc); + driver->DepthMask = VBOX_GL_FUNC(DepthMask); + driver->DepthRange = VBOX_GL_FUNC(DepthRange); + driver->Enable = vboxDDEnable; + driver->Fogfv = VBOX_GL_FUNC(Fogfv); + driver->Hint = VBOX_GL_FUNC(Hint); + driver->IndexMask = VBOX_GL_FUNC(IndexMask); + driver->Lightfv = VBOX_GL_FUNC(Lightfv); + driver->LightModelfv = VBOX_GL_FUNC(LightModelfv); + driver->LineStipple = VBOX_GL_FUNC(LineStipple); + driver->LineWidth = VBOX_GL_FUNC(LineWidth); + // driver->LogicOpcode = VBOX_GL_FUNC(LogicOpcode); /** @todo */ + driver->PointParameterfv = VBOX_GL_FUNC(PointParameterfvARB); + driver->PointSize = VBOX_GL_FUNC(PointSize); + driver->PolygonMode = VBOX_GL_FUNC(PolygonMode); + driver->PolygonOffset = VBOX_GL_FUNC(PolygonOffset); + driver->PolygonStipple = VBOX_GL_FUNC(PolygonStipple); + driver->ReadBuffer = VBOX_GL_FUNC(ReadBuffer); + driver->RenderMode = vboxDDRenderMode; + driver->Scissor = VBOX_GL_FUNC(Scissor); + driver->ShadeModel = VBOX_GL_FUNC(ShadeModel); + // driver->StencilFuncSeparate = VBOX_GL_FUNC(StencilFuncSeparate); /** @todo */ + // driver->StencilOpSeparate = VBOX_GL_FUNC(StencilOpSeparate); /** @todo */ + // driver->StencilMaskSeparate = VBOX_GL_FUNC(StencilMaskSeparate); /** @todo */ + driver->TexGen = VBOX_GL_FUNC(TexGenfv); + driver->TexEnv = VBOX_GL_FUNC(TexEnvfv); + driver->TexParameter = vboxDDTexParameter; + // driver->TextureMatrix = VBOX_GL_FUNC(TextureMatrix); /** @todo */ + driver->Viewport = VBOX_GL_FUNC(Viewport); + + /* vertex arrays */ + driver->VertexPointer = VBOX_GL_FUNC(VertexPointer); + driver->NormalPointer = VBOX_GL_FUNC(NormalPointer); + driver->ColorPointer = VBOX_GL_FUNC(ColorPointer); + driver->FogCoordPointer = VBOX_GL_FUNC(FogCoordPointerEXT); + driver->IndexPointer = VBOX_GL_FUNC(IndexPointer); + driver->SecondaryColorPointer = VBOX_GL_FUNC(SecondaryColorPointerEXT); + driver->TexCoordPointer = VBOX_GL_FUNC(TexCoordPointer); + driver->EdgeFlagPointer = VBOX_GL_FUNC(EdgeFlagPointer); + // driver->VertexAttribPointer = VBOX_GL_FUNC(VertexAttribPointer); /** @todo */ + // driver->LockArraysEXT = VBOX_GL_FUNC(LockArraysEXT); /** @todo */ + // driver->UnlockArraysEXT = VBOX_GL_FUNC(UnlockArraysEXT); /** @todo */ + + /* state queries */ + driver->GetBooleanv = vboxDDGetBooleanv; + driver->GetDoublev = vboxDDGetDoublev; + driver->GetFloatv = vboxDDGetFloatv; + driver->GetIntegerv = vboxDDGetIntegerv; + driver->GetPointerv = vboxDDGetPointerv; + +/** @todo */ +#if FEATURE_ARB_vertex_buffer_object + // driver->NewBufferObject = _mesa_new_buffer_object; + // driver->DeleteBuffer = _mesa_delete_buffer_object; + // driver->BindBuffer = NULL; + // driver->BufferData = _mesa_buffer_data; + // driver->BufferSubData = _mesa_buffer_subdata; + // driver->GetBufferSubData = _mesa_buffer_get_subdata; + // driver->MapBuffer = _mesa_buffer_map; + // driver->UnmapBuffer = _mesa_buffer_unmap; +#endif + +/** @todo */ +#if FEATURE_EXT_framebuffer_object + // driver->NewFramebuffer = _mesa_new_framebuffer; + // driver->NewRenderbuffer = _mesa_new_soft_renderbuffer; + // driver->RenderTexture = _mesa_render_texture; + // driver->FinishRenderTexture = _mesa_finish_render_texture; + // driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer; +#endif + +/** @todo */ +#if FEATURE_EXT_framebuffer_blit + // driver->BlitFramebuffer = _swrast_BlitFramebuffer; +#endif + + /* query objects */ + // driver->NewQueryObject = VBOX_GL_FUNC(NewQueryObject); /** @todo */ + // driver->DeleteQuery = VBOX_GL_FUNC(DeleteQuery); /** @todo */ + // driver->BeginQuery = VBOX_GL_FUNC(BeginQuery); /** @todo */ + // driver->EndQuery = VBOX_GL_FUNC(EndQuery); /** @todo */ + // driver->WaitQuery = VBOX_GL_FUNC(WaitQuery); /** @todo */ + + /* APPLE_vertex_array_object */ +/* + driver->NewArrayObject = _mesa_new_array_object; + driver->DeleteArrayObject = _mesa_delete_array_object; + driver->BindArrayObject = NULL; +*/ + + /* T&L stuff */ + driver->NeedValidate = GL_FALSE; + driver->ValidateTnlModule = NULL; + driver->CurrentExecPrimitive = 0; + driver->CurrentSavePrimitive = 0; + driver->NeedFlush = 0; + driver->SaveNeedFlush = 0; + + // driver->ProgramStringNotify = _tnl_program_string; /** @todo */ + driver->FlushVertices = NULL; + driver->SaveFlushVertices = NULL; + driver->NotifySaveBegin = NULL; + driver->LightingSpaceChange = NULL; + + /* display list */ + driver->NewList = VBOX_GL_FUNC(NewList); + driver->EndList = VBOX_GL_FUNC(EndList); + // driver->BeginCallList = VBOX_GL_FUNC(BeginCallList); /** @todo */ + // driver->EndCallList = VBOX_GL_FUNC(EndCallList); /** @todo */ + + + /* shaders */ + /* + driver->AttachShader = _mesa_attach_shader; + driver->BindAttribLocation = _mesa_bind_attrib_location; + driver->CompileShader = _mesa_compile_shader; + driver->CreateProgram = _mesa_create_program; + driver->CreateShader = _mesa_create_shader; + driver->DeleteProgram2 = _mesa_delete_program2; + driver->DeleteShader = _mesa_delete_shader; + driver->DetachShader = _mesa_detach_shader; + driver->GetActiveAttrib = _mesa_get_active_attrib; + driver->GetActiveUniform = _mesa_get_active_uniform; + driver->GetAttachedShaders = _mesa_get_attached_shaders; + driver->GetAttribLocation = _mesa_get_attrib_location; + driver->GetHandle = _mesa_get_handle; + driver->GetProgramiv = _mesa_get_programiv; + driver->GetProgramInfoLog = _mesa_get_program_info_log; + driver->GetShaderiv = _mesa_get_shaderiv; + driver->GetShaderInfoLog = _mesa_get_shader_info_log; + driver->GetShaderSource = _mesa_get_shader_source; + driver->GetUniformfv = _mesa_get_uniformfv; + driver->GetUniformiv = _mesa_get_uniformiv; + driver->GetUniformLocation = _mesa_get_uniform_location; + driver->IsProgram = _mesa_is_program; + driver->IsShader = _mesa_is_shader; + driver->LinkProgram = _mesa_link_program; + driver->ShaderSource = _mesa_shader_source; + driver->Uniform = _mesa_uniform; + driver->UniformMatrix = _mesa_uniform_matrix; + driver->UseProgram = _mesa_use_program; + driver->ValidateProgram = _mesa_validate_program; + */ +} + +static void +vboxdriInitTnlVtxFmt(GLvertexformat *pVtxFmt) +{ + pVtxFmt->ArrayElement = VBOX_GL_FUNC(ArrayElement); + pVtxFmt->Begin = VBOX_GL_FUNC(Begin); + pVtxFmt->CallList = VBOX_GL_FUNC(CallList); + pVtxFmt->CallLists = VBOX_GL_FUNC(CallLists); + pVtxFmt->Color3f = VBOX_GL_FUNC(Color3f); + pVtxFmt->Color3fv = VBOX_GL_FUNC(Color3fv); + pVtxFmt->Color4f = VBOX_GL_FUNC(Color4f); + pVtxFmt->Color4fv = VBOX_GL_FUNC(Color4fv); + pVtxFmt->EdgeFlag = VBOX_GL_FUNC(EdgeFlag); + pVtxFmt->End = VBOX_GL_FUNC(End); + pVtxFmt->EvalCoord1f = VBOX_GL_FUNC(EvalCoord1f); + pVtxFmt->EvalCoord1fv = VBOX_GL_FUNC(EvalCoord1fv); + pVtxFmt->EvalCoord2f = VBOX_GL_FUNC(EvalCoord2f); + pVtxFmt->EvalCoord2fv = VBOX_GL_FUNC(EvalCoord2fv); + pVtxFmt->EvalPoint1 = VBOX_GL_FUNC(EvalPoint1); + pVtxFmt->EvalPoint2 = VBOX_GL_FUNC(EvalPoint2); + pVtxFmt->FogCoordfEXT = VBOX_GL_FUNC(FogCoordfEXT); + pVtxFmt->FogCoordfvEXT = VBOX_GL_FUNC(FogCoordfvEXT); + pVtxFmt->Indexf = VBOX_GL_FUNC(Indexf); + pVtxFmt->Indexfv = VBOX_GL_FUNC(Indexfv); + pVtxFmt->Materialfv = VBOX_GL_FUNC(Materialfv); + pVtxFmt->MultiTexCoord1fARB = VBOX_GL_FUNC(MultiTexCoord1fARB); + pVtxFmt->MultiTexCoord1fvARB = VBOX_GL_FUNC(MultiTexCoord1fvARB); + pVtxFmt->MultiTexCoord2fARB = VBOX_GL_FUNC(MultiTexCoord2fARB); + pVtxFmt->MultiTexCoord2fvARB = VBOX_GL_FUNC(MultiTexCoord2fvARB); + pVtxFmt->MultiTexCoord3fARB = VBOX_GL_FUNC(MultiTexCoord3fARB); + pVtxFmt->MultiTexCoord3fvARB = VBOX_GL_FUNC(MultiTexCoord3fvARB); + pVtxFmt->MultiTexCoord4fARB = VBOX_GL_FUNC(MultiTexCoord4fARB); + pVtxFmt->MultiTexCoord4fvARB = VBOX_GL_FUNC(MultiTexCoord4fvARB); + pVtxFmt->Normal3f = VBOX_GL_FUNC(Normal3f); + pVtxFmt->Normal3fv = VBOX_GL_FUNC(Normal3fv); + pVtxFmt->SecondaryColor3fEXT = VBOX_GL_FUNC(SecondaryColor3fEXT); + pVtxFmt->SecondaryColor3fvEXT = VBOX_GL_FUNC(SecondaryColor3fvEXT); + pVtxFmt->TexCoord1f = VBOX_GL_FUNC(TexCoord1f); + pVtxFmt->TexCoord1fv = VBOX_GL_FUNC(TexCoord1fv); + pVtxFmt->TexCoord2f = VBOX_GL_FUNC(TexCoord2f); + pVtxFmt->TexCoord2fv = VBOX_GL_FUNC(TexCoord2fv); + pVtxFmt->TexCoord3f = VBOX_GL_FUNC(TexCoord3f); + pVtxFmt->TexCoord3fv = VBOX_GL_FUNC(TexCoord3fv); + pVtxFmt->TexCoord4f = VBOX_GL_FUNC(TexCoord4f); + pVtxFmt->TexCoord4fv = VBOX_GL_FUNC(TexCoord4fv); + pVtxFmt->Vertex2f = VBOX_GL_FUNC(Vertex2f); + pVtxFmt->Vertex2fv = VBOX_GL_FUNC(Vertex2fv); + pVtxFmt->Vertex3f = VBOX_GL_FUNC(Vertex3f); + pVtxFmt->Vertex3fv = VBOX_GL_FUNC(Vertex3fv); + pVtxFmt->Vertex4f = VBOX_GL_FUNC(Vertex4f); + pVtxFmt->Vertex4fv = VBOX_GL_FUNC(Vertex4fv); + pVtxFmt->VertexAttrib1fNV = VBOX_GL_FUNC(VertexAttrib1fARB); + pVtxFmt->VertexAttrib1fvNV = VBOX_GL_FUNC(VertexAttrib1fvARB); + pVtxFmt->VertexAttrib2fNV = VBOX_GL_FUNC(VertexAttrib2fARB); + pVtxFmt->VertexAttrib2fvNV = VBOX_GL_FUNC(VertexAttrib2fvARB); + pVtxFmt->VertexAttrib3fNV = VBOX_GL_FUNC(VertexAttrib3fARB); + pVtxFmt->VertexAttrib3fvNV = VBOX_GL_FUNC(VertexAttrib3fvARB); + pVtxFmt->VertexAttrib4fNV = VBOX_GL_FUNC(VertexAttrib4fARB); + pVtxFmt->VertexAttrib4fvNV = VBOX_GL_FUNC(VertexAttrib4fvARB); + pVtxFmt->VertexAttrib1fARB = VBOX_GL_FUNC(VertexAttrib1fARB); + pVtxFmt->VertexAttrib1fvARB = VBOX_GL_FUNC(VertexAttrib1fvARB); + pVtxFmt->VertexAttrib2fARB = VBOX_GL_FUNC(VertexAttrib2fARB); + pVtxFmt->VertexAttrib2fvARB = VBOX_GL_FUNC(VertexAttrib2fvARB); + pVtxFmt->VertexAttrib3fARB = VBOX_GL_FUNC(VertexAttrib3fARB); + pVtxFmt->VertexAttrib3fvARB = VBOX_GL_FUNC(VertexAttrib3fvARB); + pVtxFmt->VertexAttrib4fARB = VBOX_GL_FUNC(VertexAttrib4fARB); + pVtxFmt->VertexAttrib4fvARB = VBOX_GL_FUNC(VertexAttrib4fvARB); + + pVtxFmt->EvalMesh1 = VBOX_GL_FUNC(EvalMesh1); + pVtxFmt->EvalMesh2 = VBOX_GL_FUNC(EvalMesh2); + pVtxFmt->Rectf = VBOX_GL_FUNC(Rectf); + + pVtxFmt->DrawArrays = VBOX_GL_FUNC(DrawArrays); + pVtxFmt->DrawElements = VBOX_GL_FUNC(DrawElements); + pVtxFmt->DrawRangeElements = VBOX_GL_FUNC(DrawRangeElements); +} +#undef VBOX_GL_FUNC + +static void +vboxdriExtSetTexOffset(__DRIcontext *pDRICtx, GLint texname, + unsigned long long offset, GLint depth, GLuint pitch) +{ +} + + +static void +vboxdriExtSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv) +{ +} + +/** @todo not sure we need it from start*/ +static const __DRItexOffsetExtension vboxdriTexOffsetExtension = { + { __DRI_TEX_OFFSET }, + vboxdriExtSetTexOffset, +}; + +/* This DRI extension is required to support EXT_texture_from_pixmap, + * which in turn is required by compiz. + */ +static const __DRItexBufferExtension vboxdriTexBufferExtension = { + { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, + vboxdriExtSetTexBuffer, +}; + +/* List of DRI extensions supported by VBox DRI driver */ +static const __DRIextension *vboxdriExtensions[] = { + &vboxdriTexOffsetExtension.base, + &vboxdriTexBufferExtension.base, + NULL +}; + +static __GLcontextModes *vboxdriFillInModes(unsigned pixel_bits, + unsigned depth_bits, + unsigned stencil_bits, + GLboolean have_back_buffer) +{ + unsigned deep = (depth_bits > 17); + + /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy + * enough to add support. Basically, if a context is created with an + * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping + * will never be used. + */ + + static const GLenum db_modes[2] = { GLX_NONE, GLX_SWAP_UNDEFINED_OML }; + uint8_t depth_bits_array[4]; + uint8_t stencil_bits_array[4]; + if(deep) { + depth_bits_array[0] = 0; + depth_bits_array[1] = 24; + stencil_bits_array[0] = 0; + stencil_bits_array[1] = 8; + } else { + depth_bits_array[0] = depth_bits; + depth_bits_array[1] = 0; + depth_bits_array[2] = depth_bits; + depth_bits_array[3] = 0; + stencil_bits_array[0] = 0; + stencil_bits_array[1] = 0; + stencil_bits_array[2] = 8; + stencil_bits_array[3] = 8; + } + + return driCreateConfigs( + deep ? GL_RGBA : GL_RGB, + deep ? GL_UNSIGNED_INT_8_8_8_8 : GL_UNSIGNED_SHORT_5_6_5, + depth_bits_array, + stencil_bits_array, + deep ? 2 : 4, + db_modes, 2); +} + +/** + * This is the driver specific part of the createNewScreen entry point. + * Called when using legacy DRI. + * + * return the __GLcontextModes supported by this driver + */ +static const __DRIconfig **vboxdriInitScreen(__DRIscreenPrivate *psp) +{ + static const __DRIversion ddx_expected = { 1, 1, 0 }; + static const __DRIversion dri_expected = { 4, 0, 0 }; + static const __DRIversion drm_expected = { 1, 0, 0 }; + //PVBoxDRI = (PVBoxDRI) psp->pDevPrivate; + + /* Initialise our call table in chromium. */ + if (!stubInit()) + { + crDebug("vboxdriInitScreen: stubInit failed"); + return NULL; + } + + if ( ! driCheckDriDdxDrmVersions2( "tdfx", + &psp->dri_version, & dri_expected, + &psp->ddx_version, & ddx_expected, + &psp->drm_version, & drm_expected ) ) + return NULL; + + /* Calling driInitExtensions here, with a NULL context pointer, + * does not actually enable the extensions. It just makes sure + * that all the dispatch offsets for all the extensions that + * *might* be enables are known. This is needed because the + * dispatch offsets need to be known when _mesa_context_create is + * called, but we can't enable the extensions until we have a + * context pointer. + * + * Hello chicken. Hello egg. How are you two today? + */ + vboxdriInitExtensions(NULL); + + /** @todo check size of DRIRec (passed from X.Org driver), allocate private + * structure if necessary, parse options if necessary, map VRAM if + * necessary. */ + psp->extensions = vboxdriExtensions; + + /* Initialise VtxFmt call table. */ + vboxdriInitTnlVtxFmt(&vboxdriTnlVtxFmt); + + /*return (const __DRIconfig **) + vboxdriFillInModes(psp, dri_priv->cpp * 8, + (dri_priv->cpp == 2) ? 16 : 24, + (dri_priv->cpp == 2) ? 0 : 8, 1);*/ + + /** @todo This should depend on what the host can do, not the guest. + * However, we will probably want to discover that in the X.Org driver, + * not here. */ + return (const __DRIconfig **) vboxdriFillInModes(psp, 24, 24, 8, 1); +} + +static void +vboxdriDestroyScreen(__DRIscreenPrivate * sPriv) +{ + crDebug("vboxdriDestroyScreen"); +#if 0 /* From the tdfx driver */ + /* free all option information */ + driDestroyOptionInfo (&sPriv->private->optionCache); + FREE(sPriv->private); + sPriv->private = NULL; +#endif +} + +static GLboolean +vboxdriCreateContext(const __GLcontextModes * mesaVis, + __DRIcontextPrivate * driContextPriv, + void *sharedContextPrivate) +{ + //__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; + struct dd_function_table functions; + GLcontext *ctx, *shareCtx; + +#if 0 /* We shouldn't need this sort of thing. */ + XVisualInfo *vis; + vis->visual->visualid; + context->dpy = dpy; + context->visual = vis; + + GLXContext vboxctx = glXCreateContext(dpy, mesaVis->visualID, GL_TRUE); +#endif + /* We should be allocating a private context structure, where we will + * remember the Mesa context (ctx) among other things. The TDFX driver + * also saves importand information in driContextPriv in there - is this + * not always available to us? */ + //driContextPriv->driverPrivate = vboxctx; + + /* Initialise the default driver functions then plug in our vbox ones, + * which will actually replace most of the defaults. */ + /** @todo we should also pass some information from the visual back to the + * host. */ + _mesa_init_driver_functions(&functions); + vboxdriInitFuncs(&functions); + + /* Allocate context information for Mesa. */ + if (sharedContextPrivate) + shareCtx = ((tdfxContextPtr) sharedContextPrivate)->glCtx; + else + shareCtx = NULL; + /** @todo save ctx, or be more confident that we can don't need to. */ + ctx = _mesa_create_context(mesaVis, shareCtx, &functions, + driContextPriv->driverPrivate); + if (!ctx) + { + crDebug("vboxdriCreateContext: _mesa_create_context failed"); + return GL_FALSE; + } + + /* The TDFX driver parses its configuration files here, via + * driParseConfigFiles. We will probably get any information via guest + * properties. */ + + /* Set various context configuration. We take these values from the + * TDFX driver. */ + /** @r=Leonid, stub.spu->dispatch_table.GetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&value) etc. + * Those would be cached where possible, see include/state/cr_limits.h, VBoxOGLgen/packspu_get.c + * Note, that ctx->Const.MaxTextureImageUnits is *not* related to GL_MAX_TEXTURE_UNITS_ARB, + * use GL_MAX_TEXTURE_IMAGE_UNITS_ARB instead. + * Also, those could fail if we haven't made ctx in our stub yet. + */ + ctx->Const.MaxTextureLevels = 9; + ctx->Const.MaxTextureUnits = 1; + ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits; + ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits; + + /* No wide points. + */ + ctx->Const.MinPointSize = 1.0; + ctx->Const.MinPointSizeAA = 1.0; + ctx->Const.MaxPointSize = 1.0; + ctx->Const.MaxPointSizeAA = 1.0; + + /* Disable wide lines as we can't antialias them correctly in + * hardware. + */ + /** @note That applies to the TDFX, not to us, but as I don't yet know + * what to use instead I am leaving the values for now. */ + ctx->Const.MinLineWidth = 1.0; + ctx->Const.MinLineWidthAA = 1.0; + ctx->Const.MaxLineWidth = 1.0; + ctx->Const.MaxLineWidthAA = 1.0; + ctx->Const.LineWidthGranularity = 1.0; + + /* Initialize the software rasterizer and helper modules - again, TDFX */ + _swrast_CreateContext( ctx ); + _vbo_CreateContext( ctx ); + _tnl_CreateContext( ctx ); + _swsetup_CreateContext( ctx ); + + /* Install the customized pipeline, TDFX */ + _tnl_destroy_pipeline( ctx ); + _tnl_install_pipeline( ctx, tdfx_pipeline ); + + /* Configure swrast and T&L to match hardware characteristics, TDFX */ + _swrast_allow_pixel_fog( ctx, GL_TRUE ); + _swrast_allow_vertex_fog( ctx, GL_FALSE ); + _tnl_allow_pixel_fog( ctx, GL_TRUE ); + _tnl_allow_vertex_fog( ctx, GL_FALSE ); + /*ctx->DriverCtx = ;*/ + + /* This was *not* in the TDFX driver. */ + _mesa_install_exec_vtxfmt(ctx, &vboxdriTnlVtxFmt); + + vboxdriInitExtensions(ctx); + + return GL_TRUE; +} + + +static void +vboxdriDestroyContext(__DRIcontextPrivate *driContextPriv) +{ + // glXDestroyContext(driContextPriv->driverPrivate); + //_mesa_destroy_context ? +} + +/** + * This is called when we need to set up GL rendering to a new X window. + */ +static GLboolean +vboxdriCreateBuffer(__DRIscreenPrivate * driScrnPriv, + __DRIdrawablePrivate * driDrawPriv, + const __GLcontextModes * mesaVis, GLboolean isPixmap) +{ + return GL_FALSE; +} + +static void +vboxdriDestroyBuffer(__DRIdrawablePrivate * driDrawPriv) +{ +} + +static void +vboxdriSwapBuffers(__DRIdrawablePrivate * dPriv) +{ +} + + +GLboolean +vboxdriMakeCurrent(__DRIcontextPrivate * driContextPriv, + __DRIdrawablePrivate * driDrawPriv, + __DRIdrawablePrivate * driReadPriv) +{ + return GL_FALSE; +} + +GLboolean +vboxdriUnbindContext(__DRIcontextPrivate * driContextPriv) +{ + return GL_TRUE; +} + + +/* This structure is used by dri_util from mesa, don't rename it! */ +DECLEXPORT(const struct __DriverAPIRec) driDriverAPI = { + .InitScreen = vboxdriInitScreen, + .DestroyScreen = vboxdriDestroyScreen, + .CreateContext = vboxdriCreateContext, + .DestroyContext = vboxdriDestroyContext, + .CreateBuffer = vboxdriCreateBuffer, + .DestroyBuffer = vboxdriDestroyBuffer, + .SwapBuffers = vboxdriSwapBuffers, + .MakeCurrent = vboxdriMakeCurrent, + .UnbindContext = vboxdriUnbindContext, + .GetSwapInfo = NULL, + .WaitForMSC = NULL, + .WaitForSBC = NULL, + .SwapBuffersMSC = NULL, + .CopySubBuffer = NULL, + .GetDrawableMSC = NULL, + .InitScreen2 = NULL +}; diff --git a/src/VBox/Additions/common/crOpenGL/dri_drv.h b/src/VBox/Additions/common/crOpenGL/dri_drv.h new file mode 100644 index 00000000..7c11c3ba --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/dri_drv.h @@ -0,0 +1,32 @@ +/* $Id: dri_drv.h $ */ + +/** @file + * + * VirtualBox guest OpenGL DRI header + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#ifndef GA_INCLUDED_SRC_common_crOpenGL_dri_drv_h +#define GA_INCLUDED_SRC_common_crOpenGL_dri_drv_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "src/mesa/main/mtypes.h" +#include "src/mesa/drivers/dri/common/dri_util.h" +#include "src/mesa/glapi/dispatch.h" +#include "src/mesa/main/dd.h" + +#endif /* !GA_INCLUDED_SRC_common_crOpenGL_dri_drv_h */ + diff --git a/src/VBox/Additions/common/crOpenGL/dri_glx.h b/src/VBox/Additions/common/crOpenGL/dri_glx.h new file mode 100644 index 00000000..237c93a3 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/dri_glx.h @@ -0,0 +1,165 @@ +/* $Id: dri_glx.h $ */ + +/** @file + * + * VirtualBox guest OpenGL DRI GLX header + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#ifndef GA_INCLUDED_SRC_common_crOpenGL_dri_glx_h +#define GA_INCLUDED_SRC_common_crOpenGL_dri_glx_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "chromium.h" +#include "stub.h" + +#if defined(VBOXOGL_FAKEDRI) || defined(VBOXOGL_DRI) + #define VBOXGLXTAG(Func) vboxstub_##Func + #define VBOXGLXENTRYTAG(Func) vbox_##Func + #define VBOXGLTAG(Func) cr_##Func +#else + #define VBOXGLXTAG(Func) Func + #define VBOXGLXENTRYTAG(Func) Func + #define VBOXGLTAG(Func) Func +#endif + +#ifdef VBOXOGL_FAKEDRI +extern DECLEXPORT(const char *) VBOXGLXTAG(glXGetDriverConfig)(const char *driverName); +extern DECLEXPORT(void) VBOXGLXTAG(glXFreeMemoryMESA)(Display *dpy, int scrn, void *pointer); +extern DECLEXPORT(GLXContext) VBOXGLXTAG(glXImportContextEXT)(Display *dpy, GLXContextID contextID); +extern DECLEXPORT(GLXContextID) VBOXGLXTAG(glXGetContextIDEXT)(const GLXContext ctx); +extern DECLEXPORT(Bool) VBOXGLXTAG(glXMakeCurrentReadSGI)(Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +extern DECLEXPORT(const char *) VBOXGLXTAG(glXGetScreenDriver)(Display *dpy, int scrNum); +extern DECLEXPORT(Display *) VBOXGLXTAG(glXGetCurrentDisplayEXT)(void); +extern DECLEXPORT(void) VBOXGLXTAG(glXFreeContextEXT)(Display *dpy, GLXContext ctx); +/*Mesa internal*/ +extern DECLEXPORT(int) VBOXGLXTAG(glXQueryContextInfoEXT)(Display *dpy, GLXContext ctx); +extern DECLEXPORT(void *) VBOXGLXTAG(glXAllocateMemoryMESA)(Display *dpy, int scrn, + size_t size, float readFreq, + float writeFreq, float priority); +extern DECLEXPORT(GLuint) VBOXGLXTAG(glXGetMemoryOffsetMESA)(Display *dpy, int scrn, const void *pointer ); +extern DECLEXPORT(GLXPixmap) VBOXGLXTAG(glXCreateGLXPixmapMESA)(Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap); +#endif + +/*Common glX functions*/ +extern DECLEXPORT(void) VBOXGLXTAG(glXCopyContext)( Display *dpy, GLXContext src, GLXContext dst, +#if defined(SunOS) +unsigned long mask); +#else +unsigned long mask); +#endif +extern DECLEXPORT(void) VBOXGLXTAG(glXUseXFont)(Font font, int first, int count, int listBase); +extern DECLEXPORT(CR_GLXFuncPtr) VBOXGLXTAG(glXGetProcAddress)(const GLubyte *name); +extern DECLEXPORT(Bool) VBOXGLXTAG(glXQueryExtension)(Display *dpy, int *errorBase, int *eventBase); +extern DECLEXPORT(Bool) VBOXGLXTAG(glXIsDirect)(Display *dpy, GLXContext ctx); +extern DECLEXPORT(GLXPixmap) VBOXGLXTAG(glXCreateGLXPixmap)(Display *dpy, XVisualInfo *vis, Pixmap pixmap); +extern DECLEXPORT(void) VBOXGLXTAG(glXSwapBuffers)(Display *dpy, GLXDrawable drawable); +extern DECLEXPORT(GLXDrawable) VBOXGLXTAG(glXGetCurrentDrawable)(void); +extern DECLEXPORT(void) VBOXGLXTAG(glXWaitGL)(void); +extern DECLEXPORT(Display *) VBOXGLXTAG(glXGetCurrentDisplay)(void); +extern DECLEXPORT(const char *) VBOXGLXTAG(glXQueryServerString)(Display *dpy, int screen, int name); +extern DECLEXPORT(GLXContext) VBOXGLXTAG(glXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext share, Bool direct); +extern DECLEXPORT(int) VBOXGLXTAG(glXGetConfig)(Display *dpy, XVisualInfo *vis, int attrib, int *value); +extern DECLEXPORT(void) VBOXGLXTAG(glXWaitX)(void); +extern DECLEXPORT(GLXContext) VBOXGLXTAG(glXGetCurrentContext)(void); +extern DECLEXPORT(const char *) VBOXGLXTAG(glXGetClientString)(Display *dpy, int name); +extern DECLEXPORT(Bool) VBOXGLXTAG(glXMakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx); +extern DECLEXPORT(void) VBOXGLXTAG(glXDestroyContext)(Display *dpy, GLXContext ctx); +extern DECLEXPORT(CR_GLXFuncPtr) VBOXGLXTAG(glXGetProcAddressARB)(const GLubyte *name); +extern DECLEXPORT(void) VBOXGLXTAG(glXDestroyGLXPixmap)(Display *dpy, GLXPixmap pix); +extern DECLEXPORT(Bool) VBOXGLXTAG(glXQueryVersion)(Display *dpy, int *major, int *minor); +extern DECLEXPORT(XVisualInfo *) VBOXGLXTAG(glXChooseVisual)(Display *dpy, int screen, int *attribList); +extern DECLEXPORT(const char *) VBOXGLXTAG(glXQueryExtensionsString)(Display *dpy, int screen); + +/** + * Set this to 1 if you want to build stub functions for the + * GL_SGIX_pbuffer and GLX_SGIX_fbconfig extensions. + * This used to be disabled, due to "messy compilation issues", + * according to the earlier comment; but they're needed just + * to resolve symbols for OpenInventor applications, and I + * haven't found any reference to exactly what the "messy compilation + * issues" are, so I'm re-enabling the code by default. + */ +#define GLX_EXTRAS 1 + +#define GLX_SGIX_video_resize 1 + +/** + * Prototypes, in case they're not in glx.h or glxext.h + * Unfortunately, there's some inconsistency between the extension + * specs, and the SGI, NVIDIA, XFree86 and common glxext.h header + * files. + */ +#if defined(GLX_GLXEXT_VERSION) +/* match glxext.h, XFree86, Mesa */ +#define ATTRIB_TYPE const int +#else +#define ATTRIB_TYPE int +#endif + +#if GLX_EXTRAS +extern DECLEXPORT(GLXPbufferSGIX) VBOXGLXTAG(glXCreateGLXPbufferSGIX) +(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list); + +extern DECLEXPORT(int) VBOXGLXTAG(glXQueryGLXPbufferSGIX) +(Display *dpy, GLXPbuffer pbuf, int attribute, unsigned int *value); + +extern DECLEXPORT(GLXFBConfigSGIX *) VBOXGLXTAG(glXChooseFBConfigSGIX) +(Display *dpy, int screen, int *attrib_list, int *nelements); + +extern DECLEXPORT(void) VBOXGLXTAG(glXDestroyGLXPbufferSGIX)(Display *dpy, GLXPbuffer pbuf); +extern DECLEXPORT(void) VBOXGLXTAG(glXSelectEventSGIX)(Display *dpy, GLXDrawable drawable, unsigned long mask); +extern DECLEXPORT(void) VBOXGLXTAG(glXGetSelectedEventSGIX)(Display *dpy, GLXDrawable drawable, unsigned long *mask); + +extern DECLEXPORT(GLXFBConfigSGIX) VBOXGLXTAG(glXGetFBConfigFromVisualSGIX)(Display *dpy, XVisualInfo *vis); +extern DECLEXPORT(XVisualInfo *) VBOXGLXTAG(glXGetVisualFromFBConfigSGIX)(Display *dpy, GLXFBConfig config); +extern DECLEXPORT(GLXContext) VBOXGLXTAG(glXCreateContextWithConfigSGIX) +(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); + +extern DECLEXPORT(GLXPixmap) VBOXGLXTAG(glXCreateGLXPixmapWithConfigSGIX)(Display *dpy, GLXFBConfig config, Pixmap pixmap); +extern DECLEXPORT(int) VBOXGLXTAG(glXGetFBConfigAttribSGIX)(Display *dpy, GLXFBConfig config, int attribute, int *value); + +/* + * GLX 1.3 functions + */ +extern DECLEXPORT(GLXFBConfig *) VBOXGLXTAG(glXChooseFBConfig)(Display *dpy, int screen, ATTRIB_TYPE *attrib_list, int *nelements); +extern DECLEXPORT(GLXPbuffer) VBOXGLXTAG(glXCreatePbuffer)(Display *dpy, GLXFBConfig config, ATTRIB_TYPE *attrib_list); +extern DECLEXPORT(GLXPixmap) VBOXGLXTAG(glXCreatePixmap)(Display *dpy, GLXFBConfig config, Pixmap pixmap, ATTRIB_TYPE *attrib_list); +extern DECLEXPORT(GLXWindow) VBOXGLXTAG(glXCreateWindow)(Display *dpy, GLXFBConfig config, Window win, ATTRIB_TYPE *attrib_list); +extern DECLEXPORT(GLXContext) VBOXGLXTAG(glXCreateNewContext) +(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); + +extern DECLEXPORT(void) VBOXGLXTAG(glXDestroyPbuffer)(Display *dpy, GLXPbuffer pbuf); +extern DECLEXPORT(void) VBOXGLXTAG(glXDestroyPixmap)(Display *dpy, GLXPixmap pixmap); +extern DECLEXPORT(void) VBOXGLXTAG(glXDestroyWindow)(Display *dpy, GLXWindow win); +extern DECLEXPORT(GLXDrawable) VBOXGLXTAG(glXGetCurrentReadDrawable)(void); +extern DECLEXPORT(int) VBOXGLXTAG(glXGetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int *value); +extern DECLEXPORT(GLXFBConfig *) VBOXGLXTAG(glXGetFBConfigs)(Display *dpy, int screen, int *nelements); +extern DECLEXPORT(void) VBOXGLXTAG(glXGetSelectedEvent)(Display *dpy, GLXDrawable draw, unsigned long *event_mask); +extern DECLEXPORT(XVisualInfo *) VBOXGLXTAG(glXGetVisualFromFBConfig)(Display *dpy, GLXFBConfig config); +extern DECLEXPORT(Bool) VBOXGLXTAG(glXMakeContextCurrent)(Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +extern DECLEXPORT(int) VBOXGLXTAG(glXQueryContext)(Display *dpy, GLXContext ctx, int attribute, int *value); +extern DECLEXPORT(void) VBOXGLXTAG(glXQueryDrawable)(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); +extern DECLEXPORT(void) VBOXGLXTAG(glXSelectEvent)(Display *dpy, GLXDrawable draw, unsigned long event_mask); + +#ifdef CR_EXT_texture_from_pixmap +extern DECLEXPORT(void) VBOXGLXTAG(glXBindTexImageEXT)(Display *dpy, GLXDrawable draw, int buffer, const int *attrib_list); +extern DECLEXPORT(void) VBOXGLXTAG(glXReleaseTexImageEXT)(Display *dpy, GLXDrawable draw, int buffer); +#endif + +#endif /* GLX_EXTRAS */ + +#endif /* !GA_INCLUDED_SRC_common_crOpenGL_dri_glx_h */ diff --git a/src/VBox/Additions/common/crOpenGL/dri_util.c b/src/VBox/Additions/common/crOpenGL/dri_util.c new file mode 100644 index 00000000..5041e07f --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/dri_util.c @@ -0,0 +1,1117 @@ +/* $XFree86: xc/lib/GL/dri/dri_util.c,v 1.7 2003/04/28 17:01:25 dawes Exp $ */ +/** + * \file dri_util.c + * DRI utility functions. + * + * This module acts as glue between GLX and the actual hardware driver. A DRI + * driver doesn't really \e have to use any of this - it's optional. But, some + * useful stuff is done here that otherwise would have to be duplicated in most + * drivers. + * + * Basically, these utility functions take care of some of the dirty details of + * screen initialization, context creation, context binding, DRM setup, etc. + * + * These functions are compiled into each DRI driver so libGL.so knows nothing + * about them. + */ + + +#include <assert.h> +#include <stdarg.h> +#include <unistd.h> +#include <sys/mman.h> +#include <stdio.h> + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#include "imports.h" +#define None 0 + +#include "dri_util.h" +#include "drm_sarea.h" +#include "utils.h" + +#ifndef GLX_OML_sync_control +typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator); +#endif + +/** + * This is just a token extension used to signal that the driver + * supports setting a read drawable. + */ +const __DRIextension driReadDrawableExtension = { + __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION +}; + +/** + * Print message to \c stderr if the \c LIBGL_DEBUG environment variable + * is set. + * + * Is called from the drivers. + * + * \param f \c printf like format string. + */ +void +__driUtilMessage(const char *f, ...) +{ + va_list args; + + if (getenv("LIBGL_DEBUG")) { + fprintf(stderr, "libGL error: \n"); + va_start(args, f); + vfprintf(stderr, f, args); + va_end(args); + fprintf(stderr, "\n"); + } +} + +GLint +driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 ) +{ + if (rect2.x1 > rect1.x1) rect1.x1 = rect2.x1; + if (rect2.x2 < rect1.x2) rect1.x2 = rect2.x2; + if (rect2.y1 > rect1.y1) rect1.y1 = rect2.y1; + if (rect2.y2 < rect1.y2) rect1.y2 = rect2.y2; + + if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0; + + return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1); +} + +/*****************************************************************/ +/** \name Context (un)binding functions */ +/*****************************************************************/ +/*@{*/ + +/** + * Unbind context. + * + * \param scrn the screen. + * \param gc context. + * + * \return \c GL_TRUE on success, or \c GL_FALSE on failure. + * + * \internal + * This function calls __DriverAPIRec::UnbindContext, and then decrements + * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful + * return. + * + * While casting the opaque private pointers associated with the parameters + * into their respective real types it also assures they are not \c NULL. + */ +static int driUnbindContext(__DRIcontext *pcp) +{ + __DRIscreen *psp; + __DRIdrawable *pdp; + __DRIdrawable *prp; + + /* + ** Assume error checking is done properly in glXMakeCurrent before + ** calling driUnbindContext. + */ + + if (pcp == NULL) + return GL_FALSE; + + psp = pcp->driScreenPriv; + pdp = pcp->driDrawablePriv; + prp = pcp->driReadablePriv; + + /* Let driver unbind drawable from context */ + (*psp->DriverAPI.UnbindContext)(pcp); + + if (pdp->refcount == 0) { + /* ERROR!!! */ + return GL_FALSE; + } + + pdp->refcount--; + + if (prp != pdp) { + if (prp->refcount == 0) { + /* ERROR!!! */ + return GL_FALSE; + } + + prp->refcount--; + } + + + /* XXX this is disabled so that if we call SwapBuffers on an unbound + * window we can determine the last context bound to the window and + * use that context's lock. (BrianP, 2-Dec-2000) + */ +#if 0 + /* Unbind the drawable */ + pcp->driDrawablePriv = NULL; + pdp->driContextPriv = &psp->dummyContextPriv; +#endif + + return GL_TRUE; +} + + +/** + * This function takes both a read buffer and a draw buffer. This is needed + * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent + * function. + */ +static int driBindContext(__DRIcontext *pcp, + __DRIdrawable *pdp, + __DRIdrawable *prp) +{ + __DRIscreenPrivate *psp; + + /* + ** Assume error checking is done properly in glXMakeCurrent before + ** calling driBindContext. + */ + + if (pcp == NULL || pdp == None || prp == None) + return GL_FALSE; + + /* Bind the drawable to the context */ + pcp->driDrawablePriv = pdp; + pcp->driReadablePriv = prp; + pdp->driContextPriv = pcp; + pdp->refcount++; + if ( pdp != prp ) { + prp->refcount++; + } + + /* + ** Now that we have a context associated with this drawable, we can + ** initialize the drawable information if has not been done before. + */ + + psp = pcp->driScreenPriv; + if (psp->dri2.enabled) { + __driParseEvents(pcp, pdp); + __driParseEvents(pcp, prp); + } else { + if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) { + DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); + __driUtilUpdateDrawableInfo(pdp); + DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); + } + + if ((pdp != prp) && (!prp->pStamp || *prp->pStamp != prp->lastStamp)) { + DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); + __driUtilUpdateDrawableInfo(prp); + DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); + } + } + + /* Call device-specific MakeCurrent */ + (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp); + + return GL_TRUE; +} + +/*@}*/ + + +/*****************************************************************/ +/** \name Drawable handling functions */ +/*****************************************************************/ +/*@{*/ + +/** + * Update private drawable information. + * + * \param pdp pointer to the private drawable information to update. + * + * This function basically updates the __DRIdrawablePrivate struct's + * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo. + * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which + * compares the __DRIdrwablePrivate pStamp and lastStamp values. If + * the values are different that means we have to update the clipping + * info. + */ +void +__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp) +{ + __DRIscreenPrivate *psp = pdp->driScreenPriv; + __DRIcontextPrivate *pcp = pdp->driContextPriv; + + if (!pcp + || ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) { + /* ERROR!!! + * ...but we must ignore it. There can be many contexts bound to a + * drawable. + */ + } + + if (pdp->pClipRects) { + _mesa_free(pdp->pClipRects); + pdp->pClipRects = NULL; + } + + if (pdp->pBackClipRects) { + _mesa_free(pdp->pBackClipRects); + pdp->pBackClipRects = NULL; + } + + DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); + + if (! (*psp->getDrawableInfo->getDrawableInfo)(pdp, + &pdp->index, &pdp->lastStamp, + &pdp->x, &pdp->y, &pdp->w, &pdp->h, + &pdp->numClipRects, &pdp->pClipRects, + &pdp->backX, + &pdp->backY, + &pdp->numBackClipRects, + &pdp->pBackClipRects, + pdp->loaderPrivate)) { + /* Error -- eg the window may have been destroyed. Keep going + * with no cliprects. + */ + pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */ + pdp->numClipRects = 0; + pdp->pClipRects = NULL; + pdp->numBackClipRects = 0; + pdp->pBackClipRects = NULL; + } + else + pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp); + + DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); +} + + +int +__driParseEvents(__DRIcontextPrivate *pcp, __DRIdrawablePrivate *pdp) +{ + __DRIscreenPrivate *psp = pdp->driScreenPriv; + __DRIDrawableConfigEvent *dc, *last_dc; + __DRIBufferAttachEvent *ba, *last_ba; + unsigned int tail, mask, *p, end, total, size, changed; + unsigned char *data; + size_t rect_size; + + /* Check for wraparound. */ + if (pcp && psp->dri2.buffer->prealloc - pdp->dri2.tail > psp->dri2.buffer->size) { + /* If prealloc overlaps into what we just parsed, the + * server overwrote it and we have to reset our tail + * pointer. */ + DRM_UNLOCK(psp->fd, psp->lock, pcp->hHWContext); + (*psp->dri2.loader->reemitDrawableInfo)(pdp, &pdp->dri2.tail, + pdp->loaderPrivate); + DRM_LIGHT_LOCK(psp->fd, psp->lock, pcp->hHWContext); + } + + total = psp->dri2.buffer->head - pdp->dri2.tail; + mask = psp->dri2.buffer->size - 1; + end = psp->dri2.buffer->head; + data = psp->dri2.buffer->data; + + changed = 0; + last_dc = NULL; + last_ba = NULL; + + for (tail = pdp->dri2.tail; tail != end; tail += size) { + p = (unsigned int *) (data + (tail & mask)); + size = DRI2_EVENT_SIZE(*p); + if (size > total || (tail & mask) + size > psp->dri2.buffer->size) { + /* illegal data, bail out. */ + fprintf(stderr, "illegal event size\n"); + break; + } + + switch (DRI2_EVENT_TYPE(*p)) { + case DRI2_EVENT_DRAWABLE_CONFIG: + dc = (__DRIDrawableConfigEvent *) p; + if (dc->drawable == pdp->dri2.drawable_id) + last_dc = dc; + break; + + case DRI2_EVENT_BUFFER_ATTACH: + ba = (__DRIBufferAttachEvent *) p; + if (ba->drawable == pdp->dri2.drawable_id && + ba->buffer.attachment == DRI_DRAWABLE_BUFFER_FRONT_LEFT) + last_ba = ba; + break; + } + } + + if (last_dc) { + if (pdp->w != last_dc->width || pdp->h != last_dc->height) + changed = 1; + + pdp->x = last_dc->x; + pdp->y = last_dc->y; + pdp->w = last_dc->width; + pdp->h = last_dc->height; + + pdp->backX = 0; + pdp->backY = 0; + pdp->numBackClipRects = 1; + pdp->pBackClipRects[0].x1 = 0; + pdp->pBackClipRects[0].y1 = 0; + pdp->pBackClipRects[0].x2 = pdp->w; + pdp->pBackClipRects[0].y2 = pdp->h; + + pdp->numClipRects = last_dc->num_rects; + _mesa_free(pdp->pClipRects); + rect_size = last_dc->num_rects * sizeof last_dc->rects[0]; + pdp->pClipRects = _mesa_malloc(rect_size); + memcpy(pdp->pClipRects, last_dc->rects, rect_size); + } + + /* We only care about the most recent drawable config. */ + if (last_dc && changed) + (*psp->DriverAPI.HandleDrawableConfig)(pdp, pcp, last_dc); + + /* Front buffer attachments are special, they typically mean that + * we're rendering to a redirected window (or a child window of a + * redirected window) and that it got resized. Resizing the root + * window on randr events is a special case of this. Other causes + * may be a window transitioning between redirected and + * non-redirected, or a window getting reparented between parents + * with different window pixmaps (eg two redirected windows). + * These events are special in that the X server allocates the + * buffer and that the buffer may be shared by other child + * windows. When our window share the window pixmap with its + * parent, drawable config events doesn't affect the front buffer. + * We only care about the last such event in the buffer; in fact, + * older events will refer to invalid buffer objects.*/ + if (last_ba) + (*psp->DriverAPI.HandleBufferAttach)(pdp, pcp, last_ba); + + /* If there was a drawable config event in the buffer and it + * changed the size of the window, all buffer auxiliary buffer + * attachments prior to that are invalid (as opposed to the front + * buffer case discussed above). In that case we can start + * looking for buffer attachment after the last drawable config + * event. If there is no drawable config event in this batch of + * events, we have to assume that the last batch might have had + * one and process all buffer attach events.*/ + if (last_dc && changed) + tail = (unsigned char *) last_dc - data; + else + tail = pdp->dri2.tail; + + for ( ; tail != end; tail += size) { + ba = (__DRIBufferAttachEvent *) (data + (tail & mask)); + size = DRI2_EVENT_SIZE(ba->event_header); + + if (DRI2_EVENT_TYPE(ba->event_header) != DRI2_EVENT_BUFFER_ATTACH) + continue; + if (ba->drawable != pdp->dri2.drawable_id) + continue; + if (last_ba == ba) + continue; + + (*psp->DriverAPI.HandleBufferAttach)(pdp, pcp, ba); + changed = 1; + } + + pdp->dri2.tail = tail; + + return changed || last_ba; +} + +/*@}*/ + +/*****************************************************************/ +/** \name GLX callbacks */ +/*****************************************************************/ +/*@{*/ + +static void driReportDamage(__DRIdrawable *pdp, + struct drm_clip_rect *pClipRects, int numClipRects) +{ + __DRIscreen *psp = pdp->driScreenPriv; + + /* Check that we actually have the new damage report method */ + if (psp->dri2.enabled) { + (*psp->dri2.loader->postDamage)(pdp, + pClipRects, + numClipRects, + pdp->loaderPrivate); + } else if (psp->damage) { + /* Report the damage. Currently, all our drivers draw + * directly to the front buffer, so we report the damage there + * rather than to the backing storein (if any). + */ + (*psp->damage->reportDamage)(pdp, + pdp->x, pdp->y, + pClipRects, numClipRects, + GL_TRUE, pdp->loaderPrivate); + } +} + + +/** + * Swap buffers. + * + * \param drawablePrivate opaque pointer to the per-drawable private info. + * + * \internal + * This function calls __DRIdrawablePrivate::swapBuffers. + * + * Is called directly from glXSwapBuffers(). + */ +static void driSwapBuffers(__DRIdrawable *dPriv) +{ + __DRIscreen *psp = dPriv->driScreenPriv; + + if (!dPriv->numClipRects) + return; + + if (psp->dri2.enabled) + __driParseEvents(NULL, dPriv); + + psp->DriverAPI.SwapBuffers(dPriv); + + driReportDamage(dPriv, dPriv->pClipRects, dPriv->numClipRects); +} + +static int driDrawableGetMSC( __DRIscreen *sPriv, __DRIdrawable *dPriv, + int64_t *msc ) +{ + return sPriv->DriverAPI.GetDrawableMSC(sPriv, dPriv, msc); +} + + +static int driWaitForMSC(__DRIdrawable *dPriv, int64_t target_msc, + int64_t divisor, int64_t remainder, + int64_t * msc, int64_t * sbc) +{ + __DRIswapInfo sInfo; + int status; + + status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc, + divisor, remainder, + msc ); + + /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync + * is supported but GLX_OML_sync_control is not. Therefore, don't return + * an error value if GetSwapInfo() is not implemented. + */ + if ( status == 0 + && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) { + status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo ); + *sbc = sInfo.swap_count; + } + + return status; +} + + +const __DRImediaStreamCounterExtension driMediaStreamCounterExtension = { + { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION }, + driWaitForMSC, + driDrawableGetMSC, +}; + + +static void driCopySubBuffer(__DRIdrawable *dPriv, + int x, int y, int w, int h) +{ + drm_clip_rect_t rect; + + rect.x1 = x; + rect.y1 = dPriv->h - y - h; + rect.x2 = x + w; + rect.y2 = rect.y1 + h; + driReportDamage(dPriv, &rect, 1); + + dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h); +} + +const __DRIcopySubBufferExtension driCopySubBufferExtension = { + { __DRI_COPY_SUB_BUFFER, __DRI_COPY_SUB_BUFFER_VERSION }, + driCopySubBuffer +}; + +static void driSetSwapInterval(__DRIdrawable *dPriv, unsigned int interval) +{ + dPriv->swap_interval = interval; +} + +static unsigned int driGetSwapInterval(__DRIdrawable *dPriv) +{ + return dPriv->swap_interval; +} + +const __DRIswapControlExtension driSwapControlExtension = { + { __DRI_SWAP_CONTROL, __DRI_SWAP_CONTROL_VERSION }, + driSetSwapInterval, + driGetSwapInterval +}; + + +/** + * This is called via __DRIscreenRec's createNewDrawable pointer. + */ +static __DRIdrawable * +driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config, + drm_drawable_t hwDrawable, int renderType, + const int *attrs, void *data) +{ + __DRIdrawable *pdp; + + /* Since pbuffers are not yet supported, no drawable attributes are + * supported either. + */ + (void) attrs; + + pdp = _mesa_malloc(sizeof *pdp); + if (!pdp) { + return NULL; + } + + pdp->loaderPrivate = data; + pdp->hHWDrawable = hwDrawable; + pdp->refcount = 0; + pdp->pStamp = NULL; + pdp->lastStamp = 0; + pdp->index = 0; + pdp->x = 0; + pdp->y = 0; + pdp->w = 0; + pdp->h = 0; + pdp->numClipRects = 0; + pdp->numBackClipRects = 0; + pdp->pClipRects = NULL; + pdp->pBackClipRects = NULL; + pdp->vblSeq = 0; + pdp->vblFlags = 0; + + pdp->driScreenPriv = psp; + pdp->driContextPriv = &psp->dummyContextPriv; + + if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes, + renderType == GLX_PIXMAP_BIT)) { + _mesa_free(pdp); + return NULL; + } + + pdp->msc_base = 0; + + /* This special default value is replaced with the configured + * default value when the drawable is first bound to a direct + * rendering context. + */ + pdp->swap_interval = (unsigned)-1; + + return pdp; +} + + +static __DRIdrawable * +dri2CreateNewDrawable(__DRIscreen *screen, const __DRIconfig *config, + unsigned int drawable_id, unsigned int head, void *data) +{ + __DRIdrawable *pdraw; + + pdraw = driCreateNewDrawable(screen, config, 0, 0, NULL, data); + if (!pdraw) + return NULL; + + pdraw->dri2.drawable_id = drawable_id; + pdraw->dri2.tail = head; + pdraw->pBackClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects); + + return pdraw; +} + + +static void +driDestroyDrawable(__DRIdrawable *pdp) +{ + __DRIscreenPrivate *psp; + + if (pdp) { + psp = pdp->driScreenPriv; + (*psp->DriverAPI.DestroyBuffer)(pdp); + if (pdp->pClipRects) { + _mesa_free(pdp->pClipRects); + pdp->pClipRects = NULL; + } + if (pdp->pBackClipRects) { + _mesa_free(pdp->pBackClipRects); + pdp->pBackClipRects = NULL; + } + _mesa_free(pdp); + } +} + +/*@}*/ + + +/*****************************************************************/ +/** \name Context handling functions */ +/*****************************************************************/ +/*@{*/ + +/** + * Destroy the per-context private information. + * + * \internal + * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls + * drmDestroyContext(), and finally frees \p contextPrivate. + */ +static void +driDestroyContext(__DRIcontext *pcp) +{ + if (pcp) { + (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp); + _mesa_free(pcp); + } +} + + +/** + * Create the per-drawable private driver information. + * + * \param render_type Type of rendering target. \c GLX_RGBA is the only + * type likely to ever be supported for direct-rendering. + * \param shared Context with which to share textures, etc. or NULL + * + * \returns An opaque pointer to the per-context private information on + * success, or \c NULL on failure. + * + * \internal + * This function allocates and fills a __DRIcontextPrivateRec structure. It + * performs some device independent initialization and passes all the + * relevant information to __DriverAPIRec::CreateContext to create the + * context. + * + */ +static __DRIcontext * +driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config, + int render_type, __DRIcontext *shared, + drm_context_t hwContext, void *data) +{ + __DRIcontext *pcp; + void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; + + pcp = _mesa_malloc(sizeof *pcp); + if (!pcp) + return NULL; + + pcp->driScreenPriv = psp; + pcp->driDrawablePriv = NULL; + + /* When the first context is created for a screen, initialize a "dummy" + * context. + */ + + if (!psp->dri2.enabled && !psp->dummyContextPriv.driScreenPriv) { + psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context; + psp->dummyContextPriv.driScreenPriv = psp; + psp->dummyContextPriv.driDrawablePriv = NULL; + psp->dummyContextPriv.driverPrivate = NULL; + /* No other fields should be used! */ + } + + pcp->hHWContext = hwContext; + + if ( !(*psp->DriverAPI.CreateContext)(&config->modes, pcp, shareCtx) ) { + _mesa_free(pcp); + return NULL; + } + + return pcp; +} + + +static __DRIcontext * +dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config, + __DRIcontext *shared, void *data) +{ + drm_context_t hwContext; + DRM_CAS_RESULT(ret); + + /* DRI2 doesn't use kernel with context IDs, we just need an ID that's + * different from the kernel context ID to make drmLock() happy. */ + + do { + hwContext = screen->dri2.lock->next_id; + DRM_CAS(&screen->dri2.lock->next_id, hwContext, hwContext + 1, ret); + } while (ret); + + return driCreateNewContext(screen, config, 0, shared, hwContext, data); +} + + +static int +driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask) +{ + return GL_FALSE; +} + +/*@}*/ + + +/*****************************************************************/ +/** \name Screen handling functions */ +/*****************************************************************/ +/*@{*/ + +/** + * Destroy the per-screen private information. + * + * \internal + * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls + * drmClose(), and finally frees \p screenPrivate. + */ +static void driDestroyScreen(__DRIscreen *psp) +{ + if (psp) { + /* No interaction with the X-server is possible at this point. This + * routine is called after XCloseDisplay, so there is no protocol + * stream open to the X-server anymore. + */ + + if (psp->DriverAPI.DestroyScreen) + (*psp->DriverAPI.DestroyScreen)(psp); + + if (psp->dri2.enabled) { +#ifdef TTM_API + drmBOUnmap(psp->fd, &psp->dri2.sareaBO); + drmBOUnreference(psp->fd, &psp->dri2.sareaBO); +#endif + } else { + (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX); + (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize); + (void)drmCloseOnce(psp->fd); + } + + _mesa_free(psp); + } +} + +static void +setupLoaderExtensions(__DRIscreen *psp, + const __DRIextension **extensions) +{ + int i; + + for (i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, __DRI_GET_DRAWABLE_INFO) == 0) + psp->getDrawableInfo = (__DRIgetDrawableInfoExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_DAMAGE) == 0) + psp->damage = (__DRIdamageExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_SYSTEM_TIME) == 0) + psp->systemTime = (__DRIsystemTimeExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_LOADER) == 0) + psp->dri2.loader = (__DRIloaderExtension *) extensions[i]; + } +} + +/** + * This is the bootstrap function for the driver. libGL supplies all of the + * requisite information about the system, and the driver initializes itself. + * This routine also fills in the linked list pointed to by \c driver_modes + * with the \c __GLcontextModes that the driver can support for windows or + * pbuffers. + * + * For legacy DRI. + * + * \param scrn Index of the screen + * \param ddx_version Version of the 2D DDX. This may not be meaningful for + * all drivers. + * \param dri_version Version of the "server-side" DRI. + * \param drm_version Version of the kernel DRM. + * \param frame_buffer Data describing the location and layout of the + * framebuffer. + * \param pSAREA Pointer to the SAREA. + * \param fd Device handle for the DRM. + * \param extensions ?? + * \param driver_modes Returns modes supported by the driver + * \param loaderPrivate ?? + * + * \note There is no need to check the minimum API version in this + * function. Since the name of this function is versioned, it is + * impossible for a loader that is too old to even load this driver. + */ +static __DRIscreen * +driCreateNewScreen(int scrn, + const __DRIversion *ddx_version, + const __DRIversion *dri_version, + const __DRIversion *drm_version, + const __DRIframebuffer *frame_buffer, + drmAddress pSAREA, int fd, + const __DRIextension **extensions, + const __DRIconfig ***driver_modes, + void *loaderPrivate) +{ + static const __DRIextension *emptyExtensionList[] = { NULL }; + __DRIscreen *psp; + + psp = _mesa_malloc(sizeof *psp); + if (!psp) + return NULL; + + setupLoaderExtensions(psp, extensions); + + /* + ** NOT_DONE: This is used by the X server to detect when the client + ** has died while holding the drawable lock. The client sets the + ** drawable lock to this value. + */ + psp->drawLockID = 1; + + psp->drm_version = *drm_version; + psp->ddx_version = *ddx_version; + psp->dri_version = *dri_version; + + psp->pSAREA = pSAREA; + psp->lock = (drmLock *) &psp->pSAREA->lock; + + psp->pFB = frame_buffer->base; + psp->fbSize = frame_buffer->size; + psp->fbStride = frame_buffer->stride; + psp->fbWidth = frame_buffer->width; + psp->fbHeight = frame_buffer->height; + psp->devPrivSize = frame_buffer->dev_priv_size; + psp->pDevPriv = frame_buffer->dev_priv; + psp->fbBPP = psp->fbStride * 8 / frame_buffer->width; + + psp->extensions = emptyExtensionList; + psp->fd = fd; + psp->myNum = scrn; + psp->dri2.enabled = GL_FALSE; + + /* + ** Do not init dummy context here; actual initialization will be + ** done when the first DRI context is created. Init screen priv ptr + ** to NULL to let CreateContext routine that it needs to be inited. + */ + psp->dummyContextPriv.driScreenPriv = NULL; + + psp->DriverAPI = driDriverAPI; + + *driver_modes = driDriverAPI.InitScreen(psp); + if (*driver_modes == NULL) { + _mesa_free(psp); + return NULL; + } + + return psp; +} + + +/** + * DRI2 + */ +static __DRIscreen * +dri2CreateNewScreen(int scrn, int fd, unsigned int sarea_handle, + const __DRIextension **extensions, + const __DRIconfig ***driver_configs, void *data) +{ +#ifdef TTM_API + static const __DRIextension *emptyExtensionList[] = { NULL }; + __DRIscreen *psp; + unsigned int *p; + drmVersionPtr version; + + if (driDriverAPI.InitScreen2 == NULL) + return NULL; + + psp = _mesa_malloc(sizeof(*psp)); + if (!psp) + return NULL; + + setupLoaderExtensions(psp, extensions); + + version = drmGetVersion(fd); + if (version) { + psp->drm_version.major = version->version_major; + psp->drm_version.minor = version->version_minor; + psp->drm_version.patch = version->version_patchlevel; + drmFreeVersion(version); + } + + psp->extensions = emptyExtensionList; + psp->fd = fd; + psp->myNum = scrn; + psp->dri2.enabled = GL_TRUE; + + if (drmBOReference(psp->fd, sarea_handle, &psp->dri2.sareaBO)) { + fprintf(stderr, "Failed to reference DRI2 sarea BO\n"); + _mesa_free(psp); + return NULL; + } + + if (drmBOMap(psp->fd, &psp->dri2.sareaBO, + DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &psp->dri2.sarea)) { + drmBOUnreference(psp->fd, &psp->dri2.sareaBO); + _mesa_free(psp); + return NULL; + } + + p = psp->dri2.sarea; + while (DRI2_SAREA_BLOCK_TYPE(*p)) { + switch (DRI2_SAREA_BLOCK_TYPE(*p)) { + case DRI2_SAREA_BLOCK_LOCK: + psp->dri2.lock = (__DRILock *) p; + break; + case DRI2_SAREA_BLOCK_EVENT_BUFFER: + psp->dri2.buffer = (__DRIEventBuffer *) p; + break; + } + p = DRI2_SAREA_BLOCK_NEXT(p); + } + + psp->lock = (drmLock *) &psp->dri2.lock->lock; + + psp->DriverAPI = driDriverAPI; + *driver_configs = driDriverAPI.InitScreen2(psp); + if (*driver_configs == NULL) { + drmBOUnmap(psp->fd, &psp->dri2.sareaBO); + drmBOUnreference(psp->fd, &psp->dri2.sareaBO); + _mesa_free(psp); + return NULL; + } + + psp->DriverAPI = driDriverAPI; + + return psp; +#else + return NULL; +#endif +} + +static const __DRIextension **driGetExtensions(__DRIscreen *psp) +{ + return psp->extensions; +} + +/** Legacy DRI interface */ +const __DRIlegacyExtension driLegacyExtension = { + { __DRI_LEGACY, __DRI_LEGACY_VERSION }, + driCreateNewScreen, + driCreateNewDrawable, + driCreateNewContext +}; + +/** DRI2 interface */ +const __DRIcoreExtension driCoreExtension = { + { __DRI_CORE, __DRI_CORE_VERSION }, + dri2CreateNewScreen, + driDestroyScreen, + driGetExtensions, + driGetConfigAttrib, + driIndexConfigAttrib, + dri2CreateNewDrawable, + driDestroyDrawable, + driSwapBuffers, + dri2CreateNewContext, + driCopyContext, + driDestroyContext, + driBindContext, + driUnbindContext +}; + +/* This is the table of extensions that the loader will dlsym() for. */ +PUBLIC const __DRIextension *__driDriverExtensions[] = { + &driCoreExtension.base, + &driLegacyExtension.base, + NULL +}; + +static int +driFrameTracking(__DRIdrawable *drawable, GLboolean enable) +{ + return GLX_BAD_CONTEXT; +} + +static int +driQueryFrameTracking(__DRIdrawable *dpriv, + int64_t * sbc, int64_t * missedFrames, + float * lastMissedUsage, float * usage) +{ + __DRIswapInfo sInfo; + int status; + int64_t ust; + __DRIscreenPrivate *psp = dpriv->driScreenPriv; + + status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo ); + if ( status == 0 ) { + *sbc = sInfo.swap_count; + *missedFrames = sInfo.swap_missed_count; + *lastMissedUsage = sInfo.swap_missed_usage; + + (*psp->systemTime->getUST)( & ust ); + *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust ); + } + + return status; +} + +const __DRIframeTrackingExtension driFrameTrackingExtension = { + { __DRI_FRAME_TRACKING, __DRI_FRAME_TRACKING_VERSION }, + driFrameTracking, + driQueryFrameTracking +}; + +/** + * Calculate amount of swap interval used between GLX buffer swaps. + * + * The usage value, on the range [0,max], is the fraction of total swap + * interval time used between GLX buffer swaps is calculated. + * + * \f$p = t_d / (i * t_r)\f$ + * + * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the + * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time + * required for a single vertical refresh period (as returned by \c + * glXGetMscRateOML). + * + * See the documentation for the GLX_MESA_swap_frame_usage extension for more + * details. + * + * \param dPriv Pointer to the private drawable structure. + * \return If less than a single swap interval time period was required + * between GLX buffer swaps, a number greater than 0 and less than + * 1.0 is returned. If exactly one swap interval time period is + * required, 1.0 is returned, and if more than one is required then + * a number greater than 1.0 will be returned. + * + * \sa glXSwapIntervalSGI glXGetMscRateOML + * + * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it + * be possible to cache the sync rate? + */ +float +driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust, + int64_t current_ust ) +{ + int32_t n; + int32_t d; + int interval; + float usage = 1.0; + __DRIscreenPrivate *psp = dPriv->driScreenPriv; + + if ( (*psp->systemTime->getMSCRate)(dPriv, &n, &d, dPriv->loaderPrivate) ) { + interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1; + + + /* We want to calculate + * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get + * current_UST by calling __glXGetUST. last_swap_UST is stored in + * dPriv->swap_ust. interval has already been calculated. + * + * The only tricky part is us_per_refresh. us_per_refresh is + * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it + * around and say us_per_refresh = 1000000 * d / n. Since this goes in + * the denominator of the final calculation, we calculate + * (interval * 1000000 * d) and move n into the numerator. + */ + + usage = (current_ust - last_swap_ust); + usage *= n; + usage /= (interval * d); + usage /= 1000000.0; + } + + return usage; +} + +/*@}*/ diff --git a/src/VBox/Additions/common/crOpenGL/drirenderbuffer.c b/src/VBox/Additions/common/crOpenGL/drirenderbuffer.c new file mode 100644 index 00000000..d36af3e5 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/drirenderbuffer.c @@ -0,0 +1,215 @@ + +#include "mtypes.h" +#include "drirenderbuffer.h" +#include "framebuffer.h" +#include "renderbuffer.h" +#include "imports.h" + + +/** + * This will get called when a window (gl_framebuffer) is resized (probably + * via driUpdateFramebufferSize(), below). + * Just update width, height and internal format fields for now. + * There's usually no memory allocation above because the present + * DRI drivers use statically-allocated full-screen buffers. If that's not + * the case for a DRI driver, a different AllocStorage method should + * be used. + */ +static GLboolean +driRenderbufferStorage(GLcontext *ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, GLuint width, GLuint height) +{ + rb->Width = width; + rb->Height = height; + rb->InternalFormat = internalFormat; + return GL_TRUE; +} + + +static void +driDeleteRenderbuffer(struct gl_renderbuffer *rb) +{ + /* don't free rb->Data Chances are it's a memory mapped region for + * the dri drivers. + */ + _mesa_free(rb); +} + + +/** + * Allocate a new driRenderbuffer object. + * Individual drivers are free to implement different versions of + * this function. + * + * At this time, this function can only be used for window-system + * renderbuffers, not user-created RBOs. + * + * \param format Either GL_RGBA, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, + * GL_DEPTH_COMPONENT32, or GL_STENCIL_INDEX8_EXT (for now). + * \param addr address in main memory of the buffer. Probably a memory + * mapped region. + * \param cpp chars or bytes per pixel + * \param offset start of renderbuffer with respect to start of framebuffer + * \param pitch pixels per row + */ +driRenderbuffer * +driNewRenderbuffer(GLenum format, GLvoid *addr, + GLint cpp, GLint offset, GLint pitch, + __DRIdrawablePrivate *dPriv) +{ + driRenderbuffer *drb; + + assert(format == GL_RGBA || + format == GL_RGB5 || + format == GL_RGBA8 || + format == GL_DEPTH_COMPONENT16 || + format == GL_DEPTH_COMPONENT24 || + format == GL_DEPTH_COMPONENT32 || + format == GL_STENCIL_INDEX8_EXT); + + assert(cpp > 0); + assert(pitch > 0); + + drb = _mesa_calloc(sizeof(driRenderbuffer)); + if (drb) { + const GLuint name = 0; + + _mesa_init_renderbuffer(&drb->Base, name); + + /* Make sure we're using a null-valued GetPointer routine */ + assert(drb->Base.GetPointer(NULL, &drb->Base, 0, 0) == NULL); + + drb->Base.InternalFormat = format; + + if (format == GL_RGBA || format == GL_RGB5 || format == GL_RGBA8) { + /* Color */ + drb->Base._BaseFormat = GL_RGBA; + drb->Base.DataType = GL_UNSIGNED_BYTE; + if (format == GL_RGB5) { + drb->Base.RedBits = 5; + drb->Base.GreenBits = 6; + drb->Base.BlueBits = 5; + } + else { + drb->Base.RedBits = + drb->Base.GreenBits = + drb->Base.BlueBits = + drb->Base.AlphaBits = 8; + } + } + else if (format == GL_DEPTH_COMPONENT16) { + /* Depth */ + drb->Base._BaseFormat = GL_DEPTH_COMPONENT; + /* we always Get/Put 32-bit Z values */ + drb->Base.DataType = GL_UNSIGNED_INT; + drb->Base.DepthBits = 16; + } + else if (format == GL_DEPTH_COMPONENT24) { + /* Depth */ + drb->Base._BaseFormat = GL_DEPTH_COMPONENT; + /* we always Get/Put 32-bit Z values */ + drb->Base.DataType = GL_UNSIGNED_INT; + drb->Base.DepthBits = 24; + } + else if (format == GL_DEPTH_COMPONENT32) { + /* Depth */ + drb->Base._BaseFormat = GL_DEPTH_COMPONENT; + /* we always Get/Put 32-bit Z values */ + drb->Base.DataType = GL_UNSIGNED_INT; + drb->Base.DepthBits = 32; + } + else { + /* Stencil */ + ASSERT(format == GL_STENCIL_INDEX8_EXT); + drb->Base._BaseFormat = GL_STENCIL_INDEX; + drb->Base.DataType = GL_UNSIGNED_BYTE; + drb->Base.StencilBits = 8; + } + + /* XXX if we were allocating a user-created renderbuffer, we'd have + * to fill in the Red/Green/Blue/.../Bits values too. + */ + + drb->Base.AllocStorage = driRenderbufferStorage; + drb->Base.Delete = driDeleteRenderbuffer; + + drb->Base.Data = addr; + + /* DRI renderbuffer-specific fields: */ + drb->dPriv = dPriv; + drb->offset = offset; + drb->pitch = pitch; + drb->cpp = cpp; + + /* may be changed if page flipping is active: */ + drb->flippedOffset = offset; + drb->flippedPitch = pitch; + drb->flippedData = addr; + } + return drb; +} + + +/** + * Update the front and back renderbuffers' flippedPitch/Offset/Data fields. + * If stereo, flip both the left and right pairs. + * This is used when we do double buffering via page flipping. + * \param fb the framebuffer we're page flipping + * \param flipped if true, set flipped values, else set non-flipped values + */ +void +driFlipRenderbuffers(struct gl_framebuffer *fb, GLboolean flipped) +{ + const GLuint count = fb->Visual.stereoMode ? 2 : 1; + GLuint lr; /* left or right */ + + /* we shouldn't really call this function if single-buffered, but + * play it safe. + */ + if (!fb->Visual.doubleBufferMode) + return; + + for (lr = 0; lr < count; lr++) { + GLuint frontBuf = (lr == 0) ? BUFFER_FRONT_LEFT : BUFFER_FRONT_RIGHT; + GLuint backBuf = (lr == 0) ? BUFFER_BACK_LEFT : BUFFER_BACK_RIGHT; + driRenderbuffer *front_drb + = (driRenderbuffer *) fb->Attachment[frontBuf].Renderbuffer; + driRenderbuffer *back_drb + = (driRenderbuffer *) fb->Attachment[backBuf].Renderbuffer; + + if (flipped) { + front_drb->flippedOffset = back_drb->offset; + front_drb->flippedPitch = back_drb->pitch; + front_drb->flippedData = back_drb->Base.Data; + back_drb->flippedOffset = front_drb->offset; + back_drb->flippedPitch = front_drb->pitch; + back_drb->flippedData = front_drb->Base.Data; + } + else { + front_drb->flippedOffset = front_drb->offset; + front_drb->flippedPitch = front_drb->pitch; + front_drb->flippedData = front_drb->Base.Data; + back_drb->flippedOffset = back_drb->offset; + back_drb->flippedPitch = back_drb->pitch; + back_drb->flippedData = back_drb->Base.Data; + } + } +} + + +/** + * Check that the gl_framebuffer associated with dPriv is the right size. + * Resize the gl_framebuffer if needed. + * It's expected that the dPriv->driverPrivate member points to a + * gl_framebuffer object. + */ +void +driUpdateFramebufferSize(GLcontext *ctx, const __DRIdrawablePrivate *dPriv) +{ + struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate; + if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) { + ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h); + assert(fb->Width == dPriv->w); + assert(fb->Height == dPriv->h); + } +} diff --git a/src/VBox/Additions/common/crOpenGL/egl.c b/src/VBox/Additions/common/crOpenGL/egl.c new file mode 100644 index 00000000..3d8a636d --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/egl.c @@ -0,0 +1,967 @@ +/* $Id: egl.c $ */ + +/** @file + * VBox OpenGL EGL implentation. + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <iprt/cdefs.h> +#include <iprt/types.h> + +#include <EGL/egl.h> +#include <GL/glx.h> +#include <X11/Xlib.h> + +#include <dlfcn.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define EGL_ASSERT(expr) \ + if (!(expr)) { printf("Assertion failed: %s\n", #expr); exit(1); } + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ + +struct VBEGLTLS +{ + /** The last EGL error. */ + EGLint cErr; + /** The EGL API currently bound to this thread. */ + EGLenum enmAPI; + /** The current context. */ + EGLContext hCurrent; + /** The display bound to the current context. */ + EGLDisplay hCurrentDisplay; + /** The draw surface bound to the current context. */ + EGLSurface hCurrentDraw; + /** The read surface bound to the current context. */ + EGLSurface hCurrentRead; +}; + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +/** @note IDs returned for surfaces should always be lower than these constants. + */ +/** This is OR-ed with a surface ID to mark it as a window, as GLX needs to + * know. */ +#define VBEGL_WINDOW_SURFACE 0x20000000 +/** This is OR-ed with a surface ID to mark it as a pbuffer, as GLX needs to + * know. */ +#define VBEGL_PBUFFER_SURFACE 0x40000000 +/** This is OR-ed with a surface ID to mark it as a pixmap, as GLX needs to + * know. */ +#define VBEGL_PIXMAP_SURFACE 0x80000000 +#define VBEGL_ANY_SURFACE (VBEGL_WINDOW_SURFACE | VBEGL_PBUFFER_SURFACE | VBEGL_PIXMAP_SURFACE) + + +/********************************************************************************************************************************* +* Global variables * +*********************************************************************************************************************************/ + +static pthread_key_t g_tls; +static pthread_once_t g_tlsOnce = PTHREAD_ONCE_INIT; +static Display *g_pDefaultDisplay = NULL; +static pthread_once_t g_defaultDisplayOnce = PTHREAD_ONCE_INIT; + +static void tlsInitOnce(void) +{ + pthread_key_create(&g_tls, NULL); +} + +static struct VBEGLTLS *getTls(void) +{ + struct VBEGLTLS *pTls; + + pthread_once(&g_tlsOnce, tlsInitOnce); + pTls = (struct VBEGLTLS *)pthread_getspecific(g_tls); + if (RT_LIKELY(pTls)) + return pTls; + pTls = (struct VBEGLTLS *)malloc(sizeof(*pTls)); + if (!pTls) + return NULL; + pTls->cErr = EGL_SUCCESS; + pTls->enmAPI = EGL_NONE; + pTls->hCurrent = EGL_NO_CONTEXT; + pTls->hCurrentDisplay = EGL_NO_DISPLAY; + pTls->hCurrentDraw = EGL_NO_SURFACE; + pTls->hCurrentRead = EGL_NO_SURFACE; + if (pthread_setspecific(g_tls, pTls) == 0) + return pTls; + free(pTls); + return NULL; +} + +static void defaultDisplayInitOnce(void) +{ + g_pDefaultDisplay = XOpenDisplay(NULL); +} + +static EGLBoolean clearEGLError(void) +{ + struct VBEGLTLS *pTls = getTls(); + + if (!VALID_PTR(pTls)) + return EGL_FALSE; + pTls->cErr = EGL_SUCCESS; + return EGL_TRUE; +} + +static EGLBoolean setEGLError(EGLint cErr) +{ + struct VBEGLTLS *pTls = getTls(); + + if (pTls) + pTls->cErr = cErr; + return EGL_FALSE; +} + +static EGLBoolean testValidDisplay(EGLNativeDisplayType hDisplay) +{ + void *pSymbol = dlsym(NULL, "gbm_create_device"); + + if (hDisplay == EGL_DEFAULT_DISPLAY) + return EGL_TRUE; + if ((void *)hDisplay == NULL) + return EGL_FALSE; + /* This is the test that Mesa uses to see if this is a GBM "display". Not + * very pretty, but since no one can afford to break Mesa it should be + * safe. We need this to detect when the X server tries to load us. */ + if (pSymbol != NULL && *(void **)hDisplay == pSymbol) + return EGL_FALSE; + return EGL_TRUE; +} + +DECLEXPORT(EGLDisplay) eglGetDisplay(EGLNativeDisplayType hDisplay) +{ + Display *pDisplay; + + if (!testValidDisplay(hDisplay)) + return EGL_NO_DISPLAY; + if (!clearEGLError()) /* Set up our tls. */ + return EGL_NO_DISPLAY; + if (hDisplay != EGL_DEFAULT_DISPLAY) + pDisplay = hDisplay; + else + { + pthread_once(&g_defaultDisplayOnce, defaultDisplayInitOnce); + pDisplay = g_pDefaultDisplay; + } + if (pDisplay && !strcmp(glXGetClientString(pDisplay, GLX_VENDOR), "Chromium")) + return (EGLDisplay) pDisplay; + return EGL_NO_DISPLAY; +} + +DECLEXPORT(EGLint) eglGetError(void) +{ + struct VBEGLTLS *pTls = getTls(); + + if (pTls) + return pTls->cErr; + return EGL_NOT_INITIALIZED; +} + +DECLEXPORT(EGLBoolean) eglInitialize (EGLDisplay hDisplay, EGLint *pcMajor, EGLint *pcMinor) +{ + if (hDisplay == EGL_NO_DISPLAY) + return EGL_FALSE; + if (!VALID_PTR(hDisplay)) + return setEGLError(EGL_BAD_DISPLAY); + if (pcMajor) + *pcMajor = 1; + if (pcMinor) + *pcMinor = 4; + return clearEGLError(); +} + +/** @todo This function should terminate all allocated resources. */ +DECLEXPORT(EGLBoolean) eglTerminate(EGLDisplay hDisplay) +{ + if (!VALID_PTR(hDisplay)) + return EGL_FALSE; + return EGL_TRUE; +} + +DECLEXPORT(const char *) eglQueryString(EGLDisplay hDisplay, EGLint name) +{ + RT_NOREF(hDisplay); + switch (name) + { + case EGL_CLIENT_APIS: + return "OpenGL"; + case EGL_VENDOR: + return "Chromium"; + case EGL_VERSION: + return "1.4 Chromium"; + case EGL_EXTENSIONS: + return ""; + default: + return NULL; + } +} + +DECLEXPORT(EGLBoolean) eglGetConfigs (EGLDisplay hDisplay, EGLConfig *paConfigs, EGLint caConfigs, EGLint *pcaConfigs) +{ + Display *pDisplay = (Display *)hDisplay; + GLXFBConfig *paFBConfigs; + int caFBConfigs, i; + + if (!VALID_PTR(pDisplay)) + return setEGLError(EGL_NOT_INITIALIZED); + if (!VALID_PTR(pcaConfigs)) + return setEGLError(EGL_BAD_PARAMETER); + if (caConfigs > 0 && !VALID_PTR(paConfigs)) + return setEGLError(EGL_BAD_PARAMETER); + paFBConfigs = glXGetFBConfigs(pDisplay, DefaultScreen(pDisplay), &caFBConfigs); + if (!VALID_PTR(paFBConfigs)) + return setEGLError(EGL_BAD_PARAMETER); + if (caFBConfigs > caConfigs) + caFBConfigs = caConfigs; + *pcaConfigs = caFBConfigs; + for (i = 0; i < caFBConfigs; ++i) + paConfigs[i] = (EGLConfig)paFBConfigs[i]; + XFree(paFBConfigs); + return clearEGLError(); +} + +static int convertEGLAttribToGLX(EGLint a_EGLAttrib) +{ + switch (a_EGLAttrib) + { + case EGL_BUFFER_SIZE: + return GLX_BUFFER_SIZE; + case EGL_RED_SIZE: + return GLX_RED_SIZE; + case EGL_GREEN_SIZE: + return GLX_GREEN_SIZE; + case EGL_BLUE_SIZE: + return GLX_BLUE_SIZE; + case EGL_LUMINANCE_SIZE: + return GLX_RED_SIZE; + case EGL_ALPHA_SIZE: + return GLX_ALPHA_SIZE; + /* case EGL_ALPHA_MASK_SIZE: */ + /* case EGL_BIND_TO_TEXTURE_RGB: */ + /* case EGL_BIND_TO_TEXTURE_RGBA: */ + /* case EGL_COLOR_BUFFER_TYPE: */ + /* case EGL_CONFIG_CAVEAT: */ + case EGL_CONFIG_ID: + return GLX_FBCONFIG_ID; + /* case EGL_CONFORMANT: */ + case EGL_DEPTH_SIZE: + return GLX_DEPTH_SIZE; + case EGL_LEVEL: + return GLX_LEVEL; + case EGL_MAX_PBUFFER_WIDTH: + return GLX_MAX_PBUFFER_WIDTH; + case EGL_MAX_PBUFFER_HEIGHT: + return GLX_MAX_PBUFFER_HEIGHT; + case EGL_MAX_PBUFFER_PIXELS: + return GLX_MAX_PBUFFER_PIXELS; + /* case EGL_MATCH_NATIVE_PIXMAP: */ + /* case EGL_MAX_SWAP_INTERVAL: */ + /* case EGL_MIN_SWAP_INTERVAL: */ + case EGL_NATIVE_RENDERABLE: + return GLX_X_RENDERABLE; + case EGL_NATIVE_VISUAL_ID: + return GLX_VISUAL_ID; + /* case EGL_NATIVE_VISUAL_TYPE: */ + /* case EGL_RENDERABLE_TYPE: */ + case EGL_SAMPLE_BUFFERS: + return GLX_SAMPLE_BUFFERS; + case EGL_SAMPLES: + return GLX_SAMPLES; + case EGL_STENCIL_SIZE: + return GLX_STENCIL_SIZE; + /* case EGL_SURFACE_TYPE: */ + /* case EGL_TRANSPARENT_TYPE: */ + case EGL_TRANSPARENT_RED_VALUE: + return GLX_TRANSPARENT_RED_VALUE; + case EGL_TRANSPARENT_GREEN_VALUE: + return GLX_TRANSPARENT_GREEN_VALUE; + case EGL_TRANSPARENT_BLUE_VALUE: + return GLX_TRANSPARENT_BLUE_VALUE; + default: + return None; + } +} + +DECLEXPORT(EGLBoolean) eglChooseConfig (EGLDisplay hDisplay, const EGLint *paAttribs, EGLConfig *paConfigs, EGLint caConfigs, + EGLint *pcConfigs) +{ + Display *pDisplay = (Display *)hDisplay; + int aAttribList[256]; /* The list cannot be this long. */ + unsigned cAttribs = 0, i; + const EGLint *pAttrib, *pAttrib2; + EGLint cRenderableType = EGL_OPENGL_ES_BIT; + unsigned cConfigCaveat = GLX_DONT_CARE, cConformant = GLX_DONT_CARE; + GLXFBConfig *paFBConfigs; + int caFBConfigs; + + if (!VALID_PTR(hDisplay)) + return setEGLError(EGL_NOT_INITIALIZED); + if (!VALID_PTR(pcConfigs)) + return setEGLError(EGL_BAD_PARAMETER); + if (caConfigs > 0 && !VALID_PTR(paConfigs)) + return setEGLError(EGL_BAD_PARAMETER); + for (pAttrib = paAttribs; pAttrib != NULL && *pAttrib != EGL_NONE; pAttrib += 2) + { + bool fSkip = false; + int cGLXAttrib; + + /* Check for illegal values. */ + if ((*pAttrib == EGL_LEVEL || *pAttrib == EGL_MATCH_NATIVE_PIXMAP) && pAttrib[1] == EGL_DONT_CARE) + return setEGLError(EGL_BAD_ATTRIBUTE); + /* Check for values we can't handle. */ + if ( (*pAttrib == EGL_ALPHA_MASK_SIZE) + && pAttrib[1] != EGL_DONT_CARE && pAttrib[1] != 0) + return setEGLError(EGL_BAD_ACCESS); + /** @todo try creating a pixmap from a native one with the configurations returned. */ + if (*pAttrib == EGL_MATCH_NATIVE_PIXMAP) + return setEGLError(EGL_BAD_ACCESS); + if ( ( *pAttrib == EGL_MIN_SWAP_INTERVAL || *pAttrib == EGL_MAX_SWAP_INTERVAL + || *pAttrib == EGL_BIND_TO_TEXTURE_RGB || *pAttrib == EGL_BIND_TO_TEXTURE_RGBA) + && pAttrib[1] != EGL_DONT_CARE) + return setEGLError(EGL_BAD_ACCESS); + /* Ignore attributes which are repeated later. */ + for (pAttrib2 = pAttrib + 2; *pAttrib2 != EGL_NONE; pAttrib2 += 2) + if (*pAttrib2 == *pAttrib) + { + fSkip = true; + break; + } + + if (fSkip) + continue; + cGLXAttrib = convertEGLAttribToGLX(*pAttrib); + if (cGLXAttrib != None) + { + aAttribList[cAttribs] = cGLXAttrib; + if (pAttrib[1] == EGL_DONT_CARE) + aAttribList[cAttribs + 1] = GLX_DONT_CARE; + else + aAttribList[cAttribs + 1] = pAttrib[1]; + cAttribs += 2; + } + else + { + switch (*pAttrib) + { + case EGL_COLOR_BUFFER_TYPE: + aAttribList[cAttribs] = GLX_X_VISUAL_TYPE; + aAttribList[cAttribs + 1] = pAttrib[1] == EGL_DONT_CARE ? GLX_DONT_CARE + : pAttrib[1] == EGL_RGB_BUFFER ? GLX_TRUE_COLOR + : pAttrib[1] == EGL_LUMINANCE_BUFFER ? GLX_GRAY_SCALE + : GL_FALSE; + if ( *pAttrib == EGL_COLOR_BUFFER_TYPE + && pAttrib[1] != EGL_DONT_CARE && pAttrib[1] != EGL_RGB_BUFFER) + return setEGLError(EGL_BAD_ACCESS); + break; + case EGL_CONFIG_CAVEAT: + cConfigCaveat = pAttrib[1] == EGL_DONT_CARE ? GLX_DONT_CARE + : pAttrib[1] == EGL_NONE ? GLX_NONE + : pAttrib[1] == EGL_SLOW_CONFIG ? GLX_SLOW_CONFIG + : pAttrib[1] == EGL_NON_CONFORMANT_CONFIG ? GLX_NON_CONFORMANT_CONFIG + : GL_FALSE; + if (!cConfigCaveat) + return setEGLError(EGL_BAD_ATTRIBUTE); + cAttribs -= 2; + break; + case EGL_CONFORMANT: + if (pAttrib[1] != EGL_OPENGL_BIT && pAttrib[1] != 0) + return setEGLError(EGL_BAD_ACCESS); + cConformant = pAttrib[1] == EGL_OPENGL_BIT ? GL_TRUE : GL_FALSE; + cAttribs -= 2; + break; + case EGL_NATIVE_VISUAL_TYPE: + aAttribList[cAttribs] = GLX_X_VISUAL_TYPE; + aAttribList[cAttribs + 1] = pAttrib[1] == EGL_DONT_CARE ? GLX_DONT_CARE + : pAttrib[1] == StaticGray ? GLX_STATIC_GRAY + : pAttrib[1] == StaticColor ? GLX_STATIC_COLOR + : pAttrib[1] == TrueColor ? GLX_TRUE_COLOR + : pAttrib[1] == GrayScale ? GLX_GRAY_SCALE + : pAttrib[1] == PseudoColor ? GLX_PSEUDO_COLOR + : pAttrib[1] == DirectColor ? GLX_DIRECT_COLOR + : GL_FALSE; + break; + case EGL_RENDERABLE_TYPE: + cRenderableType = pAttrib[1]; + cAttribs -= 2; /* We did not add anything to the list. */ + break; + case EGL_SURFACE_TYPE: + if (pAttrib[1] & ~(EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT)) + return setEGLError(EGL_BAD_ACCESS); + aAttribList[cAttribs] = GLX_DRAWABLE_TYPE; + aAttribList[cAttribs + 1] = (pAttrib[1] & EGL_PBUFFER_BIT ? GLX_PBUFFER_BIT : 0) + | (pAttrib[1] & EGL_PIXMAP_BIT ? GLX_PIXMAP_BIT : 0) + | (pAttrib[1] & EGL_WINDOW_BIT ? GLX_WINDOW_BIT : 0); + break; + case EGL_TRANSPARENT_TYPE: + aAttribList[cAttribs] = GLX_TRANSPARENT_TYPE; + aAttribList[cAttribs + 1] = pAttrib[1] == EGL_DONT_CARE ? GLX_DONT_CARE + : pAttrib[1] == EGL_NONE ? GLX_NONE + : pAttrib[1] == EGL_TRANSPARENT_RGB ? GLX_TRANSPARENT_RGB + : GL_FALSE; + break; + default: + return setEGLError(EGL_BAD_ATTRIBUTE); + } + cAttribs += 2; + } + } + if (cConfigCaveat != GLX_DONT_CARE || cConformant != GLX_DONT_CARE) + { + aAttribList[cAttribs] = GLX_CONFIG_CAVEAT; + aAttribList[cAttribs + 1] = cConformant == GL_FALSE ? GLX_NON_CONFORMANT_CONFIG + : cConfigCaveat == EGL_SLOW_CONFIG ? GLX_SLOW_CONFIG + : GLX_NONE; + cAttribs += 2; + } + aAttribList[cAttribs] = GLX_RENDER_TYPE; + aAttribList[cAttribs + 1] = GLX_RGBA_BIT; + cAttribs += 2; + if (paAttribs != NULL) + { + aAttribList[cAttribs] = None; + EGL_ASSERT(cAttribs < RT_ELEMENTS(aAttribList)); + if (!(cRenderableType & EGL_OPENGL_BIT)) + return setEGLError(EGL_BAD_ACCESS); + } + paFBConfigs = glXChooseFBConfig(pDisplay, DefaultScreen(pDisplay), paAttribs != NULL ? aAttribList : NULL, &caFBConfigs); + if (paFBConfigs == NULL) + return setEGLError(EGL_BAD_ACCESS); + *pcConfigs = caFBConfigs; + for (i = 0; (GLint)i < caConfigs && (GLint)i < caFBConfigs; ++i) + paConfigs[i] = (EGLConfig)paFBConfigs[i]; + XFree(paFBConfigs); + return clearEGLError(); +} + +DECLEXPORT(EGLBoolean) eglGetConfigAttrib (EGLDisplay hDisplay, EGLConfig cConfig, EGLint cAttribute, EGLint *pValue) +{ + Display *pDisplay = (Display *)hDisplay; + int cGLXAttribute = convertEGLAttribToGLX(cAttribute); + int cValue; + + if (!VALID_PTR(hDisplay)) + return setEGLError(EGL_NOT_INITIALIZED); + if (!VALID_PTR(pValue)) + return setEGLError(EGL_BAD_PARAMETER); + if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_FBCONFIG_ID, &cValue)) + return setEGLError(EGL_BAD_CONFIG); + if (cGLXAttribute != None) + { + if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, cGLXAttribute, &cValue)) + return setEGLError(EGL_BAD_ACCESS); + *pValue = cValue; + return clearEGLError(); + } + switch (cAttribute) + { + case EGL_ALPHA_MASK_SIZE: + *pValue = 0; + return clearEGLError(); + case EGL_LUMINANCE_SIZE: + if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_X_VISUAL_TYPE, &cValue)) + return setEGLError(EGL_BAD_ACCESS); + if (cValue == GLX_STATIC_GRAY || cValue == GLX_GRAY_SCALE) + { + if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_RED_SIZE, &cValue)) + return setEGLError(EGL_BAD_ACCESS); + *pValue = cValue; + } + else + *pValue = 0; + return clearEGLError(); + case EGL_COLOR_BUFFER_TYPE: + if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_X_VISUAL_TYPE, &cValue)) + return setEGLError(EGL_BAD_ACCESS); + if (cValue == GLX_STATIC_GRAY || cValue == GLX_GRAY_SCALE) + *pValue = EGL_LUMINANCE_BUFFER; + else + *pValue = EGL_RGB_BUFFER; + return clearEGLError(); + case EGL_CONFIG_CAVEAT: + if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_CONFIG_CAVEAT, &cValue)) + return setEGLError(EGL_BAD_ACCESS); + *pValue = cValue == GLX_NONE ? EGL_NONE : cValue == GLX_SLOW_CONFIG ? EGL_SLOW_CONFIG : GLX_NON_CONFORMANT_CONFIG; + return clearEGLError(); + case EGL_CONFORMANT: + if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_CONFIG_CAVEAT, &cValue)) + return setEGLError(EGL_BAD_ACCESS); + *pValue = cValue == GLX_NON_CONFORMANT_CONFIG ? 0 : EGL_OPENGL_BIT; + return clearEGLError(); + case EGL_MATCH_NATIVE_PIXMAP: + case EGL_MIN_SWAP_INTERVAL: + case EGL_MAX_SWAP_INTERVAL: + return setEGLError(EGL_BAD_ACCESS); + case EGL_NATIVE_VISUAL_TYPE: + if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_X_VISUAL_TYPE, &cValue)) + return setEGLError(EGL_BAD_ACCESS); + *pValue = cValue == GLX_STATIC_GRAY ? StaticGray + : cValue == GLX_STATIC_COLOR ? StaticColor + : cValue == GLX_TRUE_COLOR ? TrueColor + : cValue == GLX_GRAY_SCALE ? GrayScale + : cValue == GLX_PSEUDO_COLOR ? PseudoColor + : cValue == GLX_DIRECT_COLOR ? DirectColor + : -1; + return clearEGLError(); + case EGL_RENDERABLE_TYPE: + *pValue = EGL_OPENGL_BIT; + return clearEGLError(); + case EGL_SURFACE_TYPE: + if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_DRAWABLE_TYPE, &cValue)) + return setEGLError(EGL_BAD_ACCESS); + *pValue = (cValue & GLX_PBUFFER_BIT ? EGL_PBUFFER_BIT : 0) + | (cValue & GLX_PIXMAP_BIT ? EGL_PIXMAP_BIT : 0) + | (cValue & GLX_WINDOW_BIT ? EGL_WINDOW_BIT : 0); + return clearEGLError(); + case EGL_TRANSPARENT_TYPE: + if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_TRANSPARENT_TYPE, &cValue)) + return setEGLError(EGL_BAD_ACCESS); + *pValue = cValue == GLX_NONE ? EGL_NONE + : cValue == GLX_TRANSPARENT_RGB ? EGL_TRANSPARENT_RGB + : EGL_FALSE; + return *pValue != EGL_FALSE ? clearEGLError() : setEGLError(EGL_BAD_ACCESS); + default: + return setEGLError(EGL_BAD_ATTRIBUTE); + } + return clearEGLError(); +} + +DECLEXPORT(EGLSurface) eglCreateWindowSurface(EGLDisplay hDisplay, EGLConfig config, EGLNativeWindowType hWindow, + const EGLint *paAttributes) +{ + Display *pDisplay = (Display *)hDisplay; + GLXWindow hGLXWindow; + + if (!VALID_PTR(hDisplay)) + { + setEGLError(EGL_NOT_INITIALIZED); + return EGL_NO_SURFACE; + } + if (paAttributes != NULL) /* Sanity test only. */ + while (*paAttributes != EGL_NONE) + { + if (*paAttributes != EGL_RENDER_BUFFER) + { + setEGLError(EGL_BAD_MATCH); + return EGL_NO_SURFACE; + } + paAttributes += 2; + } + hGLXWindow = glXCreateWindow(pDisplay, (GLXFBConfig)config, (Window)hWindow, NULL); + if (hGLXWindow == None) + { + setEGLError(EGL_BAD_ALLOC); + return EGL_NO_SURFACE; + } + EGL_ASSERT(hGLXWindow < VBEGL_WINDOW_SURFACE); /* Greater than the maximum XID. */ + clearEGLError(); + return (EGLSurface)(hGLXWindow | VBEGL_WINDOW_SURFACE); +} + +static void setAttribute(int *pcStoreIndex, int *pcCurIndex, int *paGLXAttributes, int cAttribute, int cValue) +{ + if (*pcStoreIndex < 0) + { + *pcStoreIndex = *pcCurIndex; + *pcCurIndex += 2; + paGLXAttributes[*pcStoreIndex] = cAttribute; + } + paGLXAttributes[*pcStoreIndex + 1] = cValue; +} + +DECLEXPORT(EGLSurface) eglCreatePbufferSurface(EGLDisplay hDisplay, EGLConfig config, EGLint const *paAttributes) +{ + Display *pDisplay = (Display *)hDisplay; + enum { CPS_WIDTH = 0, CPS_HEIGHT, CPS_LARGEST, CPS_PRESERVED, CPS_TEX_FORMAT, CPS_TEX_TARGET, CPS_MIPMAP_TEX, CPS_END }; + int acIndices[CPS_END]; + int aAttributes[CPS_END * 2]; + int cIndex = 0; + unsigned i; + GLXPbuffer hPbuffer; + + if (!VALID_PTR(hDisplay)) + { + setEGLError(EGL_NOT_INITIALIZED); + return EGL_NO_SURFACE; + } + for (i = 0; i < RT_ELEMENTS(acIndices); ++i) + acIndices[i] = -1; + if (paAttributes != NULL) + while (*paAttributes != EGL_NONE) + { + switch (*paAttributes) + { + case EGL_WIDTH: + setAttribute(&acIndices[CPS_WIDTH], &cIndex, aAttributes, GLX_PBUFFER_WIDTH, paAttributes[1]); + break; + case EGL_HEIGHT: + setAttribute(&acIndices[CPS_HEIGHT], &cIndex, aAttributes, GLX_LARGEST_PBUFFER, paAttributes[1]); + break; + case EGL_LARGEST_PBUFFER: + setAttribute(&acIndices[CPS_LARGEST], &cIndex, aAttributes, GLX_PBUFFER_HEIGHT, paAttributes[1]); + break; + case EGL_BUFFER_PRESERVED: + setAttribute(&acIndices[CPS_PRESERVED], &cIndex, aAttributes, GLX_PRESERVED_CONTENTS, paAttributes[1]); + break; + case EGL_TEXTURE_FORMAT: + setAttribute(&acIndices[CPS_TEX_FORMAT], &cIndex, aAttributes, GLX_TEXTURE_FORMAT_EXT, paAttributes[1]); + break; + case EGL_TEXTURE_TARGET: + setAttribute(&acIndices[CPS_TEX_TARGET], &cIndex, aAttributes, GLX_TEXTURE_TARGET_EXT, paAttributes[1]); + break; + case EGL_MIPMAP_TEXTURE: + setAttribute(&acIndices[CPS_MIPMAP_TEX], &cIndex, aAttributes, GLX_MIPMAP_TEXTURE_EXT, paAttributes[1]); + break; + case EGL_VG_ALPHA_FORMAT: + case EGL_VG_COLORSPACE: + { + setEGLError(EGL_BAD_MATCH); + return EGL_NO_SURFACE; + } + } + paAttributes += 2; + } + EGL_ASSERT((unsigned)cIndex < RT_ELEMENTS(aAttributes) - 1U); + aAttributes[cIndex + 1] = None; + hPbuffer = glXCreatePbuffer(pDisplay, (GLXFBConfig)config, aAttributes); + if (hPbuffer == None) + { + setEGLError(EGL_BAD_ALLOC); + return EGL_NO_SURFACE; + } + EGL_ASSERT(hPbuffer < VBEGL_WINDOW_SURFACE); /* Greater than the maximum XID. */ + clearEGLError(); + return (EGLSurface)(hPbuffer | VBEGL_PBUFFER_SURFACE); +} + +DECLEXPORT(EGLSurface) eglCreatePixmapSurface(EGLDisplay hDisplay, EGLConfig config, EGLNativePixmapType hPixmap, + const EGLint *paAttributes) +{ + Display *pDisplay = (Display *)hDisplay; + GLXPixmap hGLXPixmap; + + if (!VALID_PTR(hDisplay)) + { + setEGLError(EGL_NOT_INITIALIZED); + return EGL_NO_SURFACE; + } + if (paAttributes != NULL) /* Sanity test only. */ + if (*paAttributes != EGL_NONE) + { + if (*paAttributes == EGL_VG_COLORSPACE || *paAttributes == EGL_VG_ALPHA_FORMAT) + { + setEGLError(EGL_BAD_MATCH); + return EGL_NO_SURFACE; + } + else + { + setEGLError(EGL_BAD_ATTRIBUTE); + return EGL_NO_SURFACE; + } + } + hGLXPixmap = glXCreatePixmap(pDisplay, (GLXFBConfig)config, (Pixmap)hPixmap, NULL); + if (hGLXPixmap == None) + { + setEGLError(EGL_BAD_MATCH); + return EGL_NO_SURFACE; + } + EGL_ASSERT(hGLXPixmap < VBEGL_WINDOW_SURFACE); /* Greater than the maximum XID. */ + clearEGLError(); + return (EGLSurface)(hGLXPixmap | VBEGL_PIXMAP_SURFACE); +} + +DECLEXPORT(EGLBoolean) eglDestroySurface(EGLDisplay hDisplay, EGLSurface hSurface) +{ + Display *pDisplay = (Display *)hDisplay; + + if (!VALID_PTR(hDisplay)) + return setEGLError(EGL_NOT_INITIALIZED); + switch ((GLXDrawable)hSurface & VBEGL_ANY_SURFACE) + { + case VBEGL_WINDOW_SURFACE: + glXDestroyWindow(pDisplay, (GLXWindow)hSurface & ~VBEGL_WINDOW_SURFACE); + return clearEGLError(); + case VBEGL_PBUFFER_SURFACE: + glXDestroyPbuffer(pDisplay, (GLXPbuffer)hSurface & ~VBEGL_PBUFFER_SURFACE); + return clearEGLError(); + case VBEGL_PIXMAP_SURFACE: + glXDestroyPixmap(pDisplay, (GLXPixmap)hSurface & ~VBEGL_PIXMAP_SURFACE); + return clearEGLError(); + default: + return setEGLError(EGL_BAD_SURFACE); + } +} + +DECLEXPORT(EGLBoolean) eglSurfaceAttrib(EGLDisplay hDisplay, EGLSurface hSurface, EGLint cAttribute, EGLint cValue) +{ + NOREF(hDisplay); + NOREF(hSurface); + NOREF(cValue); + switch (cAttribute) + { + case EGL_MIPMAP_LEVEL: + case EGL_MULTISAMPLE_RESOLVE: + case EGL_SWAP_BEHAVIOR: + return setEGLError(EGL_BAD_MATCH); + default: + return setEGLError(EGL_BAD_ATTRIBUTE); + } +} + +DECLEXPORT(EGLBoolean) eglQuerySurface(EGLDisplay hDisplay, EGLSurface hSurface, EGLint cAttribute, EGLint *cValue) +{ + NOREF(hDisplay); + NOREF(hSurface); + NOREF(cAttribute); + NOREF(cValue); + return setEGLError(EGL_BAD_MATCH); +} + +DECLEXPORT(EGLBoolean) eglBindTexImage(EGLDisplay hDisplay, EGLSurface hSurface, EGLint cBuffer) +{ + NOREF(hDisplay); + NOREF(hSurface); + NOREF(cBuffer); + return setEGLError(EGL_BAD_MATCH); +} + +DECLEXPORT(EGLBoolean) eglReleaseTexImage(EGLDisplay hDisplay, EGLSurface hSurface, EGLint cBuffer) +{ + NOREF(hDisplay); + NOREF(hSurface); + NOREF(cBuffer); + return setEGLError(EGL_BAD_MATCH); +} + +DECLEXPORT(EGLBoolean) eglBindAPI(EGLenum enmApi) +{ + return enmApi == EGL_OPENGL_API ? clearEGLError() : setEGLError(EGL_BAD_PARAMETER); +} + +DECLEXPORT(EGLenum) eglQueryAPI(void) +{ + return EGL_OPENGL_API; +} + +DECLEXPORT(EGLContext) eglCreateContext(EGLDisplay hDisplay, EGLConfig hConfig, EGLContext hSharedContext, + const EGLint *paAttribs) +{ + Display *pDisplay = (Display *)hDisplay; + GLXContext hNewContext; + + if (!VALID_PTR(hDisplay)) + { + setEGLError(EGL_NOT_INITIALIZED); + return EGL_NO_CONTEXT; + } + if (paAttribs != NULL && *paAttribs != EGL_NONE) + { + setEGLError(EGL_BAD_ATTRIBUTE); + return EGL_NO_CONTEXT; + } + hNewContext = glXCreateNewContext(pDisplay, (GLXFBConfig)hConfig, GLX_RGBA_TYPE, (GLXContext)hSharedContext, true); + if (hNewContext) + { + clearEGLError(); + return (EGLContext)hNewContext; + } + setEGLError(EGL_BAD_MATCH); + return EGL_NO_CONTEXT; +} + +DECLEXPORT(EGLBoolean) eglDestroyContext(EGLDisplay hDisplay, EGLContext hContext) +{ + Display *pDisplay = (Display *)hDisplay; + + if (!VALID_PTR(hDisplay)) + return setEGLError(EGL_NOT_INITIALIZED); + glXDestroyContext(pDisplay, (GLXContext) hContext); + return clearEGLError(); +} + +DECLEXPORT(EGLBoolean) eglMakeCurrent(EGLDisplay hDisplay, EGLSurface hDraw, EGLSurface hRead, EGLContext hContext) +{ + Display *pDisplay = (Display *)hDisplay; + GLXDrawable hGLXDraw = hDraw == EGL_NO_SURFACE ? None : (GLXDrawable)hDraw & ~VBEGL_ANY_SURFACE; + GLXDrawable hGLXRead = hRead == EGL_NO_SURFACE ? None : (GLXDrawable)hRead & ~VBEGL_ANY_SURFACE; + GLXContext hGLXContext = hContext == EGL_NO_CONTEXT ? None : (GLXContext)hContext; + struct VBEGLTLS *pTls = getTls(); + + if (!VALID_PTR(hDisplay) || !VALID_PTR(pTls)) + return setEGLError(EGL_NOT_INITIALIZED); + if (glXMakeContextCurrent(pDisplay, hGLXDraw, hGLXRead, hGLXContext)) + { + pTls->hCurrent = hContext; + pTls->hCurrentDraw = hDraw; + pTls->hCurrentRead = hRead; + return clearEGLError(); + } + else + return setEGLError(EGL_BAD_MATCH); +} + +DECLEXPORT(EGLContext) eglGetCurrentContext(void) +{ + struct VBEGLTLS *pTls = getTls(); + + if (!VALID_PTR(pTls)) + return EGL_NO_CONTEXT; + clearEGLError(); + return pTls->hCurrent; +} + +DECLEXPORT(EGLSurface) eglGetCurrentSurface(EGLint cOp) +{ + struct VBEGLTLS *pTls = getTls(); + + if (!VALID_PTR(pTls)) + return EGL_NO_SURFACE; + clearEGLError(); + switch (cOp) + { + case EGL_DRAW: + return pTls->hCurrentDraw; + case EGL_READ: + return pTls->hCurrentRead; + default: + setEGLError(EGL_BAD_PARAMETER); + return EGL_NO_SURFACE; + } +} + +DECLEXPORT(EGLDisplay) eglGetCurrentDisplay(void) +{ + struct VBEGLTLS *pTls; + + pTls = getTls(); + if (!VALID_PTR(pTls)) + return EGL_NO_DISPLAY; + clearEGLError(); + return pTls->hCurrentDisplay; +} + +DECLEXPORT(EGLBoolean) eglQueryContext(EGLDisplay hDisplay, EGLContext hContext, EGLint cAttribute, EGLint *pcValue) +{ + Display *pDisplay = (Display *)hDisplay; + + if (!VALID_PTR(hDisplay)) + return setEGLError(EGL_NOT_INITIALIZED); + if (!VALID_PTR(pcValue)) + return setEGLError(EGL_BAD_PARAMETER); + switch (cAttribute) + { + case EGL_CONFIG_ID: + { + int cValue = 0; + + if (glXQueryContext(pDisplay, (GLXContext)hContext, GLX_FBCONFIG_ID, &cValue) == Success) + { + *pcValue = cValue; + return clearEGLError(); + } + return setEGLError(EGL_BAD_MATCH); + } + case EGL_CONTEXT_CLIENT_TYPE: + *pcValue = EGL_OPENGL_API; + return clearEGLError(); + case EGL_CONTEXT_CLIENT_VERSION: + *pcValue = 0; + return clearEGLError(); + case EGL_RENDER_BUFFER: + *pcValue = EGL_BACK_BUFFER; + return clearEGLError(); + default: + return setEGLError(EGL_BAD_ATTRIBUTE); + } +} + +DECLEXPORT(EGLBoolean) eglWaitClient(void) +{ + glXWaitGL(); + return clearEGLError(); +} + +DECLEXPORT(EGLBoolean) eglWaitGL(void) +{ + return setEGLError(EGL_BAD_PARAMETER); /* OpenGL ES only. */ +} + +DECLEXPORT(EGLBoolean) eglWaitNative(EGLint cEngine) +{ + if (cEngine != EGL_CORE_NATIVE_ENGINE) + return setEGLError(EGL_BAD_PARAMETER); + glXWaitX(); + return clearEGLError(); +} + +DECLEXPORT(EGLBoolean) eglSwapBuffers(EGLDisplay hDisplay, EGLSurface hSurface) +{ + Display *pDisplay = (Display *)hDisplay; + + if (!VALID_PTR(hDisplay)) + return setEGLError(EGL_NOT_INITIALIZED); + glXSwapBuffers(pDisplay, (GLXDrawable)hSurface & ~VBEGL_ANY_SURFACE); + return clearEGLError(); +} + +/** @todo Work out how this fits over what Chromium has to offer. */ +DECLEXPORT(EGLBoolean) eglCopyBuffers(EGLDisplay hDisplay, EGLSurface hSurface, EGLNativePixmapType hPixmap) +{ + Display *pDisplay = (Display *)hDisplay; + + if (!VALID_PTR(pDisplay)) + return setEGLError(EGL_NOT_INITIALIZED); + + NOREF(hSurface); + NOREF(hPixmap); + return setEGLError(EGL_BAD_MATCH); +} + +DECLEXPORT(EGLBoolean) eglSwapInterval (EGLDisplay dpy, EGLint interval) +{ + NOREF(dpy); + NOREF(interval); + return EGL_TRUE; +} + +typedef void (*VBEGLFuncPtr)(void); +DECLEXPORT(VBEGLFuncPtr)eglGetProcAddress(const char *pszName) +{ + clearEGLError(); + return glXGetProcAddress((const GLubyte *)pszName); +} + +DECLEXPORT(EGLBoolean) eglReleaseThread() +{ + struct VBEGLTLS *pTls = getTls(); + + if (!(pTls)) + return EGL_TRUE; + free(pTls); + /* Can this fail with ENOMEM? */ + pthread_setspecific(g_tls, NULL); + return EGL_TRUE; +} diff --git a/src/VBox/Additions/common/crOpenGL/entrypoints.py b/src/VBox/Additions/common/crOpenGL/entrypoints.py new file mode 100755 index 00000000..bdd93e75 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/entrypoints.py @@ -0,0 +1,180 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + + +""" +This module generates C entrypoints for all the OpenGL functions +and the special Chromium meta/glue functions. +""" + + +from __future__ import print_function +import sys + +import apiutil + + +def GenerateEntrypoints(hacks = []): + """Emit code for all the OpenGL/Chromium entrypoints. + hacks is an optional list of functions which are special cased. + """ + + apiutil.CopyrightC() + + print('#define GL_GLEXT_PROTOTYPES') + print('#include <stdio.h>') + print('#include <stdlib.h>') + print('#include <GL/gl.h>') + print('#include "chromium.h"') + print('#include "stub.h"') + print('#include "dri_glx.h"') + print('') + print('#ifdef __GNUC__') + print('# if (__GNUC__ << 16) + __GNUC_MINOR__ >= 0x40002') + print('# pragma GCC diagnostic ignored "-Wunused-parameter"') + print('# endif') + print('#endif') + + + # Get sorted list of dispatched functions. + # The order is very important - it must match cr_opcodes.h + # and spu_dispatch_table.h + keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + + for index in range(len(keys)): + func_name = keys[index] + if apiutil.Category(func_name) == "Chromium": + # this function is defined in stub.c + continue + + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + + if func_name in hacks: + print("/* hacked entrypoint: %s */" % func_name) + if func_name == "TexImage3D": + # Pretty common: internalformat is GLenum, not GLint + print("void glTexImage3D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels )") + print("{") + print("\tglim.TexImage3D( target, level, (GLint) internalformat, width, height, depth, border, format, type, pixels );") + print("}") + elif func_name == "TexImage2D": + # Pretty common: internalformat is GLenum, not GLint + print("void glTexImage2D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels )") + print("{") + print("\tglim.TexImage2D( target, level, (GLint) internalformat, width, height, border, format, type, pixels );") + print("}") + elif func_name == "TexImage1D": + # Pretty common: internalformat is GLenum, not GLint + print("void glTexImage1D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels )") + print("{") + print("\tglim.TexImage1D( target, level, (GLint) internalformat, width, border, format, type, pixels );") + print("}") + elif func_name == "EdgeFlagPointer": + # second arg is GLboolean instead of GLvoid + print("void glEdgeFlagPointer( GLsizei stride, const GLboolean *pointer )") + print("{") + print("\tglim.EdgeFlagPointer( stride, pointer );") + print("}") + elif func_name == "ProgramParameters4fvNV": + print("void glProgramParameters4fvNV( GLenum target, GLuint index, GLuint num, const GLfloat *params )") + print("{") + print("\tglim.ProgramParameters4fvNV( target, index, num, params );") + print("}") + elif func_name == "MultiDrawElementsEXT": + print("void glMultiDrawElementsEXT(GLenum mode, GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount)") + print("{") + print("\tglim.MultiDrawElementsEXT(mode, count,type, indices, primcount);") + print("}") + elif func_name == "ProgramParameters4dvNV": + print("void glProgramParameters4dvNV( GLenum target, GLuint index, GLuint num, const GLdouble *params )") + print("{") + print("\tglim.ProgramParameters4dvNV( target, index, num, params );") + print("}") + else: + # the usual path + print("%s VBOXGLTAG(gl%s)(%s);" % (return_type, func_name, apiutil.MakeDeclarationString(params))) + print("") + print("%s VBOXGLTAG(gl%s)(%s)" % (return_type, func_name, apiutil.MakeDeclarationString(params))) + print("{") + print("\t", end="") + if return_type != "void": + print("return ", end=" ") + print("glim.%s(%s);" % (func_name, apiutil.MakeCallString(params))) + print("}") + print("") + + print('/*') + print('* Aliases') + print('*/') + + # Now loop over all the functions and take care of any aliases + allkeys = apiutil.GetAllFunctions(sys.argv[1]+"/APIspec.txt") + for func_name in allkeys: + if "omit" in apiutil.ChromiumProps(func_name): + continue + + if func_name in keys: + # we already processed this function earlier + continue + + # alias is the function we're aliasing + alias = apiutil.Alias(func_name) + if alias: + if func_name in hacks: + print("/* hacked entrypoint: %s */" % func_name) + if func_name == "MultiDrawArrays": + print("void glMultiDrawArrays( GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount )") + print("{") + print("\tglim.MultiDrawArraysEXT( mode, (GLint*)first, (GLsizei*)count, primcount );") + print("}") + elif func_name == "BufferData": + print("void glBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)") + print("{") + print("\tglim.BufferDataARB(target, size, data, usage);") + print("}") + elif func_name == "BufferSubData": + print("void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)") + print("{") + print("\tglim.BufferSubDataARB(target, offset, size, data);") + print("}") + elif func_name == "GetBufferSubData": + print("void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data)") + print("{") + print("\tglim.GetBufferSubDataARB(target, offset, size, data);") + print("}") + else: + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + print("%s VBOXGLTAG(gl%s)(%s);" % (return_type, func_name, apiutil.MakeDeclarationString(params))) + print("") + print("%s VBOXGLTAG(gl%s)(%s)" % (return_type, func_name, apiutil.MakeDeclarationString(params))) + print("{") + print("\t", end="") + if return_type != "void": + print("return ", end=" ") + print("glim.%s(%s);" % (alias, apiutil.MakeCallString(params))) + print("}") + print("") + + print('/*') + print('* No-op stubs') + print('*/') + + # Now generate no-op stub functions + for func_name in allkeys: + if "stub" in apiutil.ChromiumProps(func_name): + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + + print("%s VBOXGLTAG(gl%s)(%s);" % (return_type, func_name, apiutil.MakeDeclarationString(params))) + print("") + print("%s VBOXGLTAG(gl%s)(%s)" % (return_type, func_name, apiutil.MakeDeclarationString(params))) + print("{") + if return_type != "void": + print("return (%s) 0" % return_type) + print("}") + print("") + diff --git a/src/VBox/Additions/common/crOpenGL/fakedri_drv.c b/src/VBox/Additions/common/crOpenGL/fakedri_drv.c new file mode 100644 index 00000000..1fab45b0 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/fakedri_drv.c @@ -0,0 +1,878 @@ +/* $Id: fakedri_drv.c $ */ +/** @file + * VBox OpenGL DRI driver functions + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#define _GNU_SOURCE 1 + +#include "cr_error.h" +#include "cr_gl.h" +#include "cr_mem.h" +#include "stub.h" +#include "fakedri_drv.h" +#include "dri_glx.h" +#include "iprt/mem.h" +#include <iprt/errcore.h> +#include <dlfcn.h> +#include <elf.h> +#include <unistd.h> + +#if defined(RT_OS_FREEBSD) +#include <sys/param.h> +#include <fcntl.h> +#include <gelf.h> +#include <libelf.h> +#include <string.h> +#endif + +/** X server message type definitions. */ +typedef enum { + X_PROBED, /* Value was probed */ + X_CONFIG, /* Value was given in the config file */ + X_DEFAULT, /* Value is a default */ + X_CMDLINE, /* Value was given on the command line */ + X_NOTICE, /* Notice */ + X_ERROR, /* Error message */ + X_WARNING, /* Warning message */ + X_INFO, /* Informational message */ + X_NONE, /* No prefix */ + X_NOT_IMPLEMENTED, /* Not implemented */ + X_UNKNOWN = -1 /* unknown -- this must always be last */ +} MessageType; + +#define VBOX_NO_MESA_PATCH_REPORTS + +//#define DEBUG_DRI_CALLS + +/// @todo this could be different... +#ifdef RT_ARCH_AMD64 +# ifdef RT_OS_FREEBSD +# define DRI_DEFAULT_DRIVER_DIR "/usr/local/lib/dri" +# define DRI_XORG_DRV_DIR "/usr/local/lib/xorg/modules/drivers/" +# else +# define DRI_DEFAULT_DRIVER_DIR "/usr/lib64/dri:/usr/lib/dri:/usr/lib/x86_64-linux-gnu/dri:/usr/lib/xorg/modules/dri" +# define DRI_XORG_DRV_DIR "/usr/lib/xorg/modules/drivers/" +# endif +#else +# ifdef RT_OS_FREEBSD +# define DRI_DEFAULT_DRIVER_DIR "/usr/local/lib/dri" +# define DRI_XORG_DRV_DIR "/usr/local/lib/xorg/modules/drivers/" +# else +# define DRI_DEFAULT_DRIVER_DIR "/usr/lib/dri:/usr/lib/i386-linux-gnu/dri:/usr/lib/xorg/modules/dri" +# define DRI_XORG_DRV_DIR "/usr/lib/xorg/modules/drivers/" +# endif +#endif + +#ifdef DEBUG_DRI_CALLS + #define SWDRI_SHOWNAME(pext, func) \ + crDebug("SWDRI: sc %s->%s", #pext, #func) +#else + #define SWDRI_SHOWNAME(pext, func) +#endif + +#define SWDRI_SAFECALL(pext, func, ...) \ + SWDRI_SHOWNAME(pext, func); \ + if (pext && pext->func){ \ + (*pext->func)(__VA_ARGS__); \ + } else { \ + crDebug("swcore_call NULL for "#func); \ + } + +#define SWDRI_SAFERET(pext, func, ...) \ + SWDRI_SHOWNAME(pext, func); \ + if (pext && pext->func){ \ + return (*pext->func)(__VA_ARGS__); \ + } else { \ + crDebug("swcore_call NULL for "#func); \ + return 0; \ + } + +#define SWDRI_SAFERET_CORE(func, ...) SWDRI_SAFERET(gpSwDriCoreExternsion, func, __VA_ARGS__) +#define SWDRI_SAFECALL_CORE(func, ...) SWDRI_SAFECALL(gpSwDriCoreExternsion, func, __VA_ARGS__) +#define SWDRI_SAFERET_SWRAST(func, ...) SWDRI_SAFERET(gpSwDriSwrastExtension, func, __VA_ARGS__) +#define SWDRI_SAFECALL_SWRAST(func, ...) SWDRI_SAFECALL(gpSwDriSwrastExtension, func, __VA_ARGS__) + +#ifndef PAGESIZE +#define PAGESIZE 4096 +#endif + +#ifdef RT_ARCH_AMD64 +# define DRI_ELFSYM Elf64_Sym +#else +# define DRI_ELFSYM Elf32_Sym +#endif + +#ifdef RT_ARCH_AMD64 +typedef struct _FAKEDRI_PatchNode +{ + const char* psFuncName; + void *pDstStart, *pDstEnd; + const void *pSrcStart, *pSrcEnd; + + struct _FAKEDRI_PatchNode *pNext; +} FAKEDRI_PatchNode; +static FAKEDRI_PatchNode *g_pFreeList=NULL, *g_pRepatchList=NULL; +#endif + +static struct _glapi_table* vbox_glapi_table = NULL; +fakedri_glxapi_table glxim; + +static const __DRIextension **gppSwDriExternsion = NULL; +static const __DRIcoreExtension *gpSwDriCoreExternsion = NULL; +static const __DRIswrastExtension *gpSwDriSwrastExtension = NULL; + +extern const __DRIextension * __driDriverExtensions[]; + +#define VBOX_SET_MESA_FUNC(table, name, func) \ + if (_glapi_get_proc_offset(name)>=0) SET_by_offset(table, _glapi_get_proc_offset(name), func); \ + else crWarning("%s not found in mesa table", name) + +#define GLAPI_ENTRY(Func) VBOX_SET_MESA_FUNC(vbox_glapi_table, "gl"#Func, cr_gl##Func); + +static void +vboxPatchMesaExport(const char* psFuncName, const void *pStart, const void *pEnd); + +static void +vboxPatchMesaGLAPITable() +{ + void *pGLTable; + + pGLTable = (void *)_glapi_get_dispatch(); + vbox_glapi_table = crAlloc(_glapi_get_dispatch_table_size() * sizeof (void *)); + if (!vbox_glapi_table) + { + crError("Not enough memory to allocate dispatch table"); + } + crMemcpy(vbox_glapi_table, pGLTable, _glapi_get_dispatch_table_size() * sizeof (void *)); + + #include "fakedri_glfuncsList.h" + + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glBlendEquationSeparateEXT", cr_glBlendEquationSeparate); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glSampleMaskSGIS", cr_glSampleMaskEXT); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glSamplePatternSGIS", cr_glSamplePatternEXT); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2dMESA", cr_glWindowPos2d); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2dvMESA", cr_glWindowPos2dv); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2fMESA", cr_glWindowPos2f); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2fvMESA", cr_glWindowPos2fv); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2iMESA", cr_glWindowPos2i); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2ivMESA", cr_glWindowPos2iv); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2sMESA", cr_glWindowPos2s); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos2svMESA", cr_glWindowPos2sv); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3dMESA", cr_glWindowPos3d); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3dvMESA", cr_glWindowPos3dv); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3fMESA", cr_glWindowPos3f); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3fvMESA", cr_glWindowPos3fv); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3iMESA", cr_glWindowPos3i); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3ivMESA", cr_glWindowPos3iv); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3sMESA", cr_glWindowPos3s); + VBOX_SET_MESA_FUNC(vbox_glapi_table, "glWindowPos3svMESA", cr_glWindowPos3sv); + + _glapi_set_dispatch(vbox_glapi_table); +}; +#undef GLAPI_ENTRY + +#define GLXAPI_ENTRY(Func) pGLXTable->Func = VBOXGLXTAG(glX##Func); +static void +vboxFillGLXAPITable(fakedri_glxapi_table *pGLXTable) +{ + #include "fakedri_glxfuncsList.h" +} +#undef GLXAPI_ENTRY + +static void +vboxApplyPatch(const char* psFuncName, void *pDst, const void *pSrc, unsigned long size) +{ + void *alPatch; + int rv; + + /* Get aligned start address we're going to patch*/ + alPatch = (void*) ((uintptr_t)pDst & ~(uintptr_t)(PAGESIZE-1)); + +#ifndef VBOX_NO_MESA_PATCH_REPORTS + crDebug("MProtecting: %p, %li", alPatch, pDst-alPatch+size); +#endif + + /* Get write access to mesa functions */ + rv = RTMemProtect(alPatch, pDst-alPatch+size, RTMEM_PROT_READ|RTMEM_PROT_WRITE|RTMEM_PROT_EXEC); + if (RT_FAILURE(rv)) + { + crError("mprotect failed with %x (%s)", rv, psFuncName); + } + +#ifndef VBOX_NO_MESA_PATCH_REPORTS + crDebug("Writing %li bytes to %p from %p", size, pDst, pSrc); +#endif + + crMemcpy(pDst, pSrc, size); + + /** @todo Restore the protection, probably have to check what was it before us...*/ + rv = RTMemProtect(alPatch, pDst-alPatch+size, RTMEM_PROT_READ|RTMEM_PROT_EXEC); + if (RT_FAILURE(rv)) + { + crError("mprotect2 failed with %x (%s)", rv, psFuncName); + } +} + +#define FAKEDRI_JMP64_PATCH_SIZE 13 + +#if defined(RT_OS_FREEBSD) +/* Provide basic dladdr1 flags */ +enum { + RTLD_DL_SYMENT = 1 +}; + +/* Provide a minimal local version of dladdr1 */ +static int +dladdr1(const void *address, Dl_info *dlip, void **info, int flags) +{ + static DRI_ELFSYM desym; + GElf_Sym sym; + GElf_Shdr shdr; + Elf *elf; + Elf_Scn *scn; + Elf_Data *data; + int ret, fd, count, i; + + /* Initialize variables */ + fd = -1; + elf = NULL; + + /* Call dladdr first */ + ret = dladdr(address, dlip); + if (ret == 0) goto err_exit; + + /* Check for supported flags */ + if (flags != RTLD_DL_SYMENT) return 1; + + /* Open shared library's ELF file */ + if (elf_version(EV_CURRENT) == EV_NONE) goto err_exit; + fd = open(dlip->dli_fname, O_RDONLY); + if (fd < 0) goto err_exit; + elf = elf_begin(fd, ELF_C_READ, NULL); + if (elf == NULL) goto err_exit; + + /* Find the '.dynsym' section */ + scn = elf_nextscn(elf, NULL); + while (scn != NULL) { + if (gelf_getshdr(scn, &shdr) == NULL) goto err_exit; + if (shdr.sh_type == SHT_DYNSYM) break; + scn = elf_nextscn(elf, scn); + } + if (scn == NULL) goto err_exit; + + /* Search for the requested symbol by name and offset */ + data = elf_getdata(scn, NULL); + count = shdr.sh_size / shdr.sh_entsize; + for (i = 0; i < count; i++) { + gelf_getsym(data, i, &sym); + if ((strcmp(dlip->dli_sname, + elf_strptr(elf, shdr.sh_link, sym.st_name)) == 0) && + (sym.st_value == (dlip->dli_saddr - dlip->dli_fbase))) { + break; + } + } + + /* Close ELF file */ + elf_end(elf); + close(fd); + + /* Return symbol entry in native format */ + desym.st_name = sym.st_name; + desym.st_info = sym.st_info; + desym.st_other = sym.st_other; + desym.st_shndx = sym.st_shndx; + desym.st_value = sym.st_value; + desym.st_size = sym.st_size; + *info = &desym; + return 1; + + /* Error handler */ +err_exit: + if (elf != NULL) elf_end(elf); + if (fd >= 0) close(fd); + return 0; +} +#endif + +static void +vboxPatchMesaExport(const char* psFuncName, const void *pStart, const void *pEnd) +{ + Dl_info dlip; + DRI_ELFSYM* sym=0; + int rv; + void *alPatch; + void *pMesaEntry; + char patch[FAKEDRI_JMP64_PATCH_SIZE]; + void *shift; + int ignore_size=false; + +#ifndef VBOX_NO_MESA_PATCH_REPORTS + crDebug("\nvboxPatchMesaExport: %s", psFuncName); +#endif + + pMesaEntry = dlsym(RTLD_DEFAULT, psFuncName); + + if (!pMesaEntry) + { + crDebug("%s not defined in current scope, are we being loaded by mesa's libGL.so?", psFuncName); + return; + } + + rv = dladdr1(pMesaEntry, &dlip, (void**)&sym, RTLD_DL_SYMENT); + if (!rv || !sym) + { + crError("Failed to get size for %p(%s)", pMesaEntry, psFuncName); + return; + } + +#if VBOX_OGL_GLX_USE_CSTUBS + { + Dl_info dlip1; + DRI_ELFSYM* sym1=0; + int rv; + + rv = dladdr1(pStart, &dlip1, (void**)&sym1, RTLD_DL_SYMENT); + if (!rv || !sym1) + { + crError("Failed to get size for vbox %p", pStart); + return; + } + + pEnd = pStart + sym1->st_size; +# ifndef VBOX_NO_MESA_PATCH_REPORTS + crDebug("VBox Entry: %p, start: %p(%s:%s), size: %li", pStart, dlip1.dli_saddr, dlip1.dli_fname, dlip1.dli_sname, sym1->st_size); +# endif + } +#endif + +#ifndef VBOX_NO_MESA_PATCH_REPORTS + crDebug("Mesa Entry: %p, start: %p(%s:%s), size: %li", pMesaEntry, dlip.dli_saddr, dlip.dli_fname, dlip.dli_sname, sym->st_size); + crDebug("VBox code: start: %p, end %p, size: %li", pStart, pEnd, pEnd-pStart); +#endif + +#ifndef VBOX_OGL_GLX_USE_CSTUBS + if (sym->st_size<(pEnd-pStart)) +#endif + { +#ifdef RT_ARCH_AMD64 + int64_t offset; +#endif + /* Try to insert 5 bytes jmp/jmpq to our stub code */ + + if (sym->st_size<5) + { + /** @todo we don't really know the size of targeted static function, but it's long enough in practice. We will also patch same place twice, but it's ok.*/ + if (!crStrcmp(psFuncName, "glXDestroyContext") || !crStrcmp(psFuncName, "glXFreeContextEXT")) + { + if (((unsigned char*)dlip.dli_saddr)[0]==0xEB) + { + /*it's a rel8 jmp, so we're going to patch the place it targets instead of jmp itself*/ + dlip.dli_saddr = (void*) ((intptr_t)dlip.dli_saddr + ((char*)dlip.dli_saddr)[1] + 2); + ignore_size = true; + } + else + { + crError("Can't patch size is too small.(%s)", psFuncName); + return; + } + } + else if (!crStrcmp(psFuncName, "glXCreateGLXPixmapMESA")) + { + /** @todo it's just a return 0, which we're fine with for now*/ + return; + } + else + { + crError("Can't patch size is too small.(%s)", psFuncName); + return; + } + } + + shift = (void*)((intptr_t)pStart-((intptr_t)dlip.dli_saddr+5)); +#ifdef RT_ARCH_AMD64 + offset = (intptr_t)shift; + if (offset>INT32_MAX || offset<INT32_MIN) + { + /*try to insert 64bit abs jmp*/ + if (sym->st_size>=FAKEDRI_JMP64_PATCH_SIZE || ignore_size) + { +# ifndef VBOX_NO_MESA_PATCH_REPORTS + crDebug("Inserting movq/jmp instead"); +# endif + /*add 64bit abs jmp*/ + patch[0] = 0x49; /*movq %r11,imm64*/ + patch[1] = 0xBB; + crMemcpy(&patch[2], &pStart, 8); + patch[10] = 0x41; /*jmp *%r11*/ + patch[11] = 0xFF; + patch[12] = 0xE3; + pStart = &patch[0]; + pEnd = &patch[FAKEDRI_JMP64_PATCH_SIZE]; + } + else + { + FAKEDRI_PatchNode *pNode; +# ifndef VBOX_NO_MESA_PATCH_REPORTS + crDebug("Can't patch offset is too big. Pushing for 2nd pass(%s)", psFuncName); +# endif + /*Add patch node to repatch with chain jmps in 2nd pass*/ + pNode = (FAKEDRI_PatchNode *)crAlloc(sizeof(FAKEDRI_PatchNode)); + if (!pNode) + { + crError("Not enough memory."); + return; + } + pNode->psFuncName = psFuncName; + pNode->pDstStart = dlip.dli_saddr; + pNode->pDstEnd = dlip.dli_saddr+sym->st_size; + pNode->pSrcStart = pStart; + pNode->pSrcEnd = pEnd; + pNode->pNext = g_pRepatchList; + g_pRepatchList = pNode; + return; + } + } + else +#endif + { +#ifndef VBOX_NO_MESA_PATCH_REPORTS + crDebug("Inserting jmp[q] with shift %p instead", shift); +#endif + patch[0] = 0xE9; + crMemcpy(&patch[1], &shift, 4); + pStart = &patch[0]; + pEnd = &patch[5]; + } + } + + vboxApplyPatch(psFuncName, dlip.dli_saddr, pStart, pEnd-pStart); + +#ifdef RT_ARCH_AMD64 + /*Add rest of mesa function body to free list*/ + if (sym->st_size-(pEnd-pStart)>=FAKEDRI_JMP64_PATCH_SIZE) + { + FAKEDRI_PatchNode *pNode = (FAKEDRI_PatchNode *)crAlloc(sizeof(FAKEDRI_PatchNode)); + if (pNode) + { + pNode->psFuncName = psFuncName; + pNode->pDstStart = dlip.dli_saddr+(pEnd-pStart); + pNode->pDstEnd = dlip.dli_saddr+sym->st_size; + pNode->pSrcStart = dlip.dli_saddr; + pNode->pSrcEnd = NULL; + pNode->pNext = g_pFreeList; + g_pFreeList = pNode; +# ifndef VBOX_NO_MESA_PATCH_REPORTS + crDebug("Added free node %s, func start=%p, free start=%p, size=%#lx", + psFuncName, pNode->pSrcStart, pNode->pDstStart, pNode->pDstEnd-pNode->pDstStart); +# endif + } + } +#endif +} + +#ifdef RT_ARCH_AMD64 +static void +vboxRepatchMesaExports(void) +{ + FAKEDRI_PatchNode *pFreeNode, *pPatchNode; + int64_t offset; + char patch[FAKEDRI_JMP64_PATCH_SIZE]; + + pPatchNode = g_pRepatchList; + while (pPatchNode) + { +# ifndef VBOX_NO_MESA_PATCH_REPORTS + crDebug("\nvboxRepatchMesaExports %s", pPatchNode->psFuncName); +# endif + /*find free place in mesa functions, to place 64bit jump to our stub code*/ + pFreeNode = g_pFreeList; + while (pFreeNode) + { + if (pFreeNode->pDstEnd-pFreeNode->pDstStart>=FAKEDRI_JMP64_PATCH_SIZE) + { + offset = ((intptr_t)pFreeNode->pDstStart-((intptr_t)pPatchNode->pDstStart+5)); + if (offset<=INT32_MAX && offset>=INT32_MIN) + { + break; + } + } + pFreeNode=pFreeNode->pNext; + } + + if (!pFreeNode) + { + crError("Failed to find free space, to place repatch for %s.", pPatchNode->psFuncName); + return; + } + + /*add 32bit rel jmp, from mesa orginal function to free space in other mesa function*/ + patch[0] = 0xE9; + crMemcpy(&patch[1], &offset, 4); +# ifndef VBOX_NO_MESA_PATCH_REPORTS + crDebug("Adding jmp from mesa %s to mesa %s+%#lx", pPatchNode->psFuncName, pFreeNode->psFuncName, + pFreeNode->pDstStart-pFreeNode->pSrcStart); +# endif + vboxApplyPatch(pPatchNode->psFuncName, pPatchNode->pDstStart, &patch[0], 5); + + /*add 64bit abs jmp, from free space to our stub code*/ + patch[0] = 0x49; /*movq %r11,imm64*/ + patch[1] = 0xBB; + crMemcpy(&patch[2], &pPatchNode->pSrcStart, 8); + patch[10] = 0x41; /*jmp *%r11*/ + patch[11] = 0xFF; + patch[12] = 0xE3; +# ifndef VBOX_NO_MESA_PATCH_REPORTS + crDebug("Adding jmp from mesa %s+%#lx to vbox %s", pFreeNode->psFuncName, pFreeNode->pDstStart-pFreeNode->pSrcStart, + pPatchNode->psFuncName); +# endif + vboxApplyPatch(pFreeNode->psFuncName, pFreeNode->pDstStart, &patch[0], FAKEDRI_JMP64_PATCH_SIZE); + /*mark this space as used*/ + pFreeNode->pDstStart = pFreeNode->pDstStart+FAKEDRI_JMP64_PATCH_SIZE; + + pPatchNode = pPatchNode->pNext; + } +} + +static void +vboxFakeDriFreeList(FAKEDRI_PatchNode *pList) +{ + FAKEDRI_PatchNode *pNode; + + while (pList) + { + pNode=pList; + pList=pNode->pNext; + crFree(pNode); + } +} +#endif + +#ifdef VBOX_OGL_GLX_USE_CSTUBS +static void +# define GLXAPI_ENTRY(Func) vboxPatchMesaExport("glX"#Func, &vbox_glX##Func, NULL); +vboxPatchMesaExports() +#else +static void +# define GLXAPI_ENTRY(Func) vboxPatchMesaExport("glX"#Func, &vbox_glX##Func, &vbox_glX##Func##_EndProc); +vboxPatchMesaExports() +#endif +{ + crDebug("Patching mesa glx entries"); + #include "fakedri_glxfuncsList.h" + +#ifdef RT_ARCH_AMD64 + vboxRepatchMesaExports(); + vboxFakeDriFreeList(g_pRepatchList); + g_pRepatchList = NULL; + vboxFakeDriFreeList(g_pFreeList); + g_pFreeList = NULL; +#endif +} +#undef GLXAPI_ENTRY + +bool vbox_load_sw_dri() +{ + const char *libPaths, *p, *next;; + char realDriverName[200]; + void *handle; + int len, i; + + /*code from Mesa-7.2/src/glx/x11/dri_common.c:driOpenDriver*/ + + libPaths = NULL; + if (geteuid() == getuid()) { + /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */ + libPaths = getenv("LIBGL_DRIVERS_PATH"); + if (!libPaths) + libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */ + } + if (libPaths == NULL) + libPaths = DRI_DEFAULT_DRIVER_DIR; + + handle = NULL; + for (p = libPaths; *p; p = next) + { + next = strchr(p, ':'); + if (next == NULL) + { + len = strlen(p); + next = p + len; + } + else + { + len = next - p; + next++; + } + + snprintf(realDriverName, sizeof realDriverName, "%.*s/%s_dri.so", len, p, "swrast"); + crDebug("trying %s", realDriverName); + handle = dlopen(realDriverName, RTLD_NOW | RTLD_LOCAL); + if (handle) break; + } + + /*end code*/ + + if (handle) gppSwDriExternsion = dlsym(handle, "__driDriverExtensions"); + + if (!gppSwDriExternsion) + { + crDebug("%s doesn't export __driDriverExtensions", realDriverName); + return false; + } + crDebug("loaded %s", realDriverName); + + for (i = 0; gppSwDriExternsion[i]; i++) + { + if (strcmp(gppSwDriExternsion[i]->name, __DRI_CORE) == 0) + gpSwDriCoreExternsion = (__DRIcoreExtension *) gppSwDriExternsion[i]; + if (strcmp(gppSwDriExternsion[i]->name, __DRI_SWRAST) == 0) + gpSwDriSwrastExtension = (__DRIswrastExtension *) gppSwDriExternsion[i]; + } + + return gpSwDriCoreExternsion && gpSwDriSwrastExtension; +} + +void __attribute__ ((constructor)) vbox_install_into_mesa(void) +{ + { +#ifdef _X_ATTRIBUTE_PRINTF + void (*pxf86Msg)(MessageType type, const char *format, ...) _X_ATTRIBUTE_PRINTF(2,3); +#else + void (*pxf86Msg)(MessageType type, const char *format, ...) _printf_attribute(2,3); +#endif + + pxf86Msg = dlsym(RTLD_DEFAULT, "xf86Msg"); + if (pxf86Msg) + { + pxf86Msg(X_INFO, "Next line is added to allow vboxvideo_drv.so to appear as whitelisted driver\n"); + pxf86Msg(X_INFO, "The file referenced, is *NOT* loaded\n"); + pxf86Msg(X_INFO, "Loading %s/ati_drv.so\n", DRI_XORG_DRV_DIR); + + /* we're failing to proxy software dri driver calls for certain xservers, so just make sure we're unloaded for now */ + __driDriverExtensions[0] = NULL; + return; + } + } + + if (!stubInit()) + { + crDebug("vboxdriInitScreen: stubInit failed"); + return; + } + + /* Load swrast_dri.so to proxy dri related calls there. */ + if (!vbox_load_sw_dri()) + { + crDebug("vboxdriInitScreen: vbox_load_sw_dri failed...going to fail badly"); + return; + } + + /* Handle gl api. + * In the end application call would look like this: + * app call glFoo->(mesa asm dispatch stub)->cr_glFoo(vbox asm dispatch stub)->SPU Foo function(packspuFoo or alike) + * Note, we don't need to install extension functions via _glapi_add_dispatch, because we'd override glXGetProcAddress. + */ + /* Mesa's dispatch table is different across library versions, have to modify mesa's table using offset info functions*/ + vboxPatchMesaGLAPITable(); + + /* Handle glx api. + * In the end application call would look like this: + * app call glxFoo->(mesa asm dispatch stub patched with vbox_glXFoo:jmp glxim[Foo's index])->VBOXGLXTAG(glxFoo) + */ + /* Fill structure used by our assembly stubs */ + vboxFillGLXAPITable(&glxim); + /* Now patch functions exported by libGL.so */ + vboxPatchMesaExports(); +} + +/* + * @todo we're missing first glx related call from the client application. + * Luckily, this doesn't add much problems, except for some cases. + */ + +/* __DRIcoreExtension */ + +static __DRIscreen * +vboxdriCreateNewScreen(int screen, int fd, unsigned int sarea_handle, + const __DRIextension **extensions, const __DRIconfig ***driverConfigs, + void *loaderPrivate) +{ + (void) fd; + (void) sarea_handle; + SWDRI_SAFERET_SWRAST(createNewScreen, screen, extensions, driverConfigs, loaderPrivate); +} + +static void +vboxdriDestroyScreen(__DRIscreen *screen) +{ + SWDRI_SAFECALL_CORE(destroyScreen, screen); +} + +static const __DRIextension ** +vboxdriGetExtensions(__DRIscreen *screen) +{ + SWDRI_SAFERET_CORE(getExtensions, screen); +} + +static int +vboxdriGetConfigAttrib(const __DRIconfig *config, + unsigned int attrib, + unsigned int *value) +{ + SWDRI_SAFERET_CORE(getConfigAttrib, config, attrib, value); +} + +static int +vboxdriIndexConfigAttrib(const __DRIconfig *config, int index, + unsigned int *attrib, unsigned int *value) +{ + SWDRI_SAFERET_CORE(indexConfigAttrib, config, index, attrib, value); +} + +static __DRIdrawable * +vboxdriCreateNewDrawable(__DRIscreen *screen, + const __DRIconfig *config, + unsigned int drawable_id, + unsigned int head, + void *loaderPrivate) +{ + (void) drawable_id; + (void) head; + SWDRI_SAFERET_SWRAST(createNewDrawable, screen, config, loaderPrivate); +} + +static void +vboxdriDestroyDrawable(__DRIdrawable *drawable) +{ + SWDRI_SAFECALL_CORE(destroyDrawable, drawable); +} + +static void +vboxdriSwapBuffers(__DRIdrawable *drawable) +{ + SWDRI_SAFECALL_CORE(swapBuffers, drawable); +} + +static __DRIcontext * +vboxdriCreateNewContext(__DRIscreen *screen, + const __DRIconfig *config, + __DRIcontext *shared, + void *loaderPrivate) +{ + SWDRI_SAFERET_CORE(createNewContext, screen, config, shared, loaderPrivate); +} + +static int +vboxdriCopyContext(__DRIcontext *dest, + __DRIcontext *src, + unsigned long mask) +{ + SWDRI_SAFERET_CORE(copyContext, dest, src, mask); +} + +static void +vboxdriDestroyContext(__DRIcontext *context) +{ + SWDRI_SAFECALL_CORE(destroyContext, context); +} + +static int +vboxdriBindContext(__DRIcontext *ctx, + __DRIdrawable *pdraw, + __DRIdrawable *pread) +{ + SWDRI_SAFERET_CORE(bindContext, ctx, pdraw, pread); +} + +static int +vboxdriUnbindContext(__DRIcontext *ctx) +{ + SWDRI_SAFERET_CORE(unbindContext, ctx) +} + +/* __DRIlegacyExtension */ + +static __DRIscreen * +vboxdriCreateNewScreen_Legacy(int scrn, + const __DRIversion *ddx_version, + const __DRIversion *dri_version, + const __DRIversion *drm_version, + const __DRIframebuffer *frame_buffer, + drmAddress pSAREA, int fd, + const __DRIextension **extensions, + const __DRIconfig ***driver_modes, + void *loaderPrivate) +{ + (void) ddx_version; + (void) dri_version; + (void) frame_buffer; + (void) pSAREA; + (void) fd; + SWDRI_SAFERET_SWRAST(createNewScreen, scrn, extensions, driver_modes, loaderPrivate); +} + +static __DRIdrawable * +vboxdriCreateNewDrawable_Legacy(__DRIscreen *psp, const __DRIconfig *config, + drm_drawable_t hwDrawable, int renderType, + const int *attrs, void *data) +{ + (void) hwDrawable; + (void) renderType; + (void) attrs; + (void) data; + SWDRI_SAFERET_SWRAST(createNewDrawable, psp, config, data); +} + +static __DRIcontext * +vboxdriCreateNewContext_Legacy(__DRIscreen *psp, const __DRIconfig *config, + int render_type, __DRIcontext *shared, + drm_context_t hwContext, void *data) +{ + (void) render_type; + (void) hwContext; + return vboxdriCreateNewContext(psp, config, shared, data); +} + + +static const __DRIlegacyExtension vboxdriLegacyExtension = { + { __DRI_LEGACY, __DRI_LEGACY_VERSION }, + vboxdriCreateNewScreen_Legacy, + vboxdriCreateNewDrawable_Legacy, + vboxdriCreateNewContext_Legacy +}; + +static const __DRIcoreExtension vboxdriCoreExtension = { + { __DRI_CORE, __DRI_CORE_VERSION }, + vboxdriCreateNewScreen, /* driCreateNewScreen */ + vboxdriDestroyScreen, + vboxdriGetExtensions, + vboxdriGetConfigAttrib, + vboxdriIndexConfigAttrib, + vboxdriCreateNewDrawable, /* driCreateNewDrawable */ + vboxdriDestroyDrawable, + vboxdriSwapBuffers, + vboxdriCreateNewContext, + vboxdriCopyContext, + vboxdriDestroyContext, + vboxdriBindContext, + vboxdriUnbindContext +}; + +/* This structure is used by dri_util from mesa, don't rename it! */ +DECLEXPORT(const __DRIextension *) __driDriverExtensions[] = { + &vboxdriLegacyExtension.base, + &vboxdriCoreExtension.base, + NULL +}; diff --git a/src/VBox/Additions/common/crOpenGL/fakedri_drv.h b/src/VBox/Additions/common/crOpenGL/fakedri_drv.h new file mode 100644 index 00000000..5f77bd85 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/fakedri_drv.h @@ -0,0 +1,123 @@ +/* $Id: fakedri_drv.h $ */ +/** @file + * VirtualBox guest OpenGL DRI header + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#ifndef GA_INCLUDED_SRC_common_crOpenGL_fakedri_drv_h +#define GA_INCLUDED_SRC_common_crOpenGL_fakedri_drv_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "src/mesa/main/mtypes.h" +#include "src/mesa/main/dd.h" +#include "src/mesa/glapi/dispatch.h" +#include "src/mesa/glapi/glapi.h" +#include "src/mesa/glapi/glapitable.h" +#include "src/mesa/glapi/glapioffsets.h" +#include "src/mesa/drivers/dri/common/dri_util.h" +#include "GL/internal/dri_interface.h" + +#include "glx_proto.h" + +#ifdef VBOX_OGL_GLX_USE_CSTUBS +# include "dri_glx.h" +#endif + +typedef struct _vbox_glxapi_table +{ + #define GLXAPI_ENTRY(Func) PGLXFUNC_##Func Func; + #include "fakedri_glxfuncsList.h" + #undef GLXAPI_ENTRY +} fakedri_glxapi_table; + +extern fakedri_glxapi_table glxim; + +#ifdef VBOX_OGL_GLX_USE_CSTUBS +/* Extern declarations for our C stubs */ +extern void VBOXGLXENTRYTAG(glXFreeMemoryMESA)(Display *dpy, int scrn, void *pointer) ; +extern GLXContext VBOXGLXENTRYTAG(glXImportContextEXT)(Display *dpy, GLXContextID contextID) ; +extern GLXContextID VBOXGLXENTRYTAG(glXGetContextIDEXT)(const GLXContext ctx) ; +extern Bool VBOXGLXENTRYTAG(glXMakeCurrentReadSGI)(Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx) ; +extern Display * VBOXGLXENTRYTAG(glXGetCurrentDisplayEXT)(void) ; +extern void VBOXGLXENTRYTAG(glXFreeContextEXT)(Display *dpy, GLXContext ctx) ; +extern int VBOXGLXENTRYTAG(glXQueryContextInfoEXT)(Display *dpy, GLXContext ctx) ; +extern void * VBOXGLXENTRYTAG(glXAllocateMemoryMESA)(Display *dpy, int scrn, + size_t size, float readFreq, + float writeFreq, float priority); +extern GLuint VBOXGLXENTRYTAG(glXGetMemoryOffsetMESA)(Display *dpy, int scrn, const void *pointer ) ; +extern GLXPixmap VBOXGLXENTRYTAG(glXCreateGLXPixmapMESA)(Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap) ; +extern void VBOXGLXENTRYTAG(glXCopyContext)( Display *dpy, GLXContext src, GLXContext dst, unsigned long mask); +extern void VBOXGLXENTRYTAG(glXUseXFont)(Font font, int first, int count, int listBase) ; +extern CR_GLXFuncPtr VBOXGLXENTRYTAG(glXGetProcAddress)(const GLubyte *name) ; +extern Bool VBOXGLXENTRYTAG(glXQueryExtension)(Display *dpy, int *errorBase, int *eventBase) ; +extern Bool VBOXGLXENTRYTAG(glXIsDirect)(Display *dpy, GLXContext ctx) ; +extern GLXPixmap VBOXGLXENTRYTAG(glXCreateGLXPixmap)(Display *dpy, XVisualInfo *vis, Pixmap pixmap) ; +extern void VBOXGLXENTRYTAG(glXSwapBuffers)(Display *dpy, GLXDrawable drawable) ; +extern GLXDrawable VBOXGLXENTRYTAG(glXGetCurrentDrawable)(void) ; +extern void VBOXGLXENTRYTAG(glXWaitGL)(void) ; +extern Display * VBOXGLXENTRYTAG(glXGetCurrentDisplay)(void) ; +extern const char * VBOXGLXENTRYTAG(glXQueryServerString)(Display *dpy, int screen, int name) ; +extern GLXContext VBOXGLXENTRYTAG(glXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext share, Bool direct) ; +extern int VBOXGLXENTRYTAG(glXGetConfig)(Display *dpy, XVisualInfo *vis, int attrib, int *value) ; +extern void VBOXGLXENTRYTAG(glXWaitX)(void) ; +extern GLXContext VBOXGLXENTRYTAG(glXGetCurrentContext)(void) ; +extern const char * VBOXGLXENTRYTAG(glXGetClientString)(Display *dpy, int name) ; +extern Bool VBOXGLXENTRYTAG(glXMakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx) ; +extern void VBOXGLXENTRYTAG(glXDestroyContext)(Display *dpy, GLXContext ctx) ; +extern CR_GLXFuncPtr VBOXGLXENTRYTAG(glXGetProcAddressARB)(const GLubyte *name) ; +extern void VBOXGLXENTRYTAG(glXDestroyGLXPixmap)(Display *dpy, GLXPixmap pix) ; +extern Bool VBOXGLXENTRYTAG(glXQueryVersion)(Display *dpy, int *major, int *minor) ; +extern XVisualInfo * VBOXGLXENTRYTAG(glXChooseVisual)(Display *dpy, int screen, int *attribList) ; +extern const char * VBOXGLXENTRYTAG(glXQueryExtensionsString)(Display *dpy, int screen) ; +extern GLXPbufferSGIX VBOXGLXENTRYTAG(glXCreateGLXPbufferSGIX)(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list); +extern int VBOXGLXENTRYTAG(glXQueryGLXPbufferSGIX)(Display *dpy, GLXPbuffer pbuf, int attribute, unsigned int *value); +extern GLXFBConfigSGIX * VBOXGLXENTRYTAG(glXChooseFBConfigSGIX)(Display *dpy, int screen, int *attrib_list, int *nelements); +extern void VBOXGLXENTRYTAG(glXDestroyGLXPbufferSGIX)(Display *dpy, GLXPbuffer pbuf) ; +extern void VBOXGLXENTRYTAG(glXSelectEventSGIX)(Display *dpy, GLXDrawable drawable, unsigned long mask) ; +extern void VBOXGLXENTRYTAG(glXGetSelectedEventSGIX)(Display *dpy, GLXDrawable drawable, unsigned long *mask) ; +extern GLXFBConfigSGIX VBOXGLXENTRYTAG(glXGetFBConfigFromVisualSGIX)(Display *dpy, XVisualInfo *vis) ; +extern XVisualInfo * VBOXGLXENTRYTAG(glXGetVisualFromFBConfigSGIX)(Display *dpy, GLXFBConfig config) ; +extern GLXContext VBOXGLXENTRYTAG(glXCreateContextWithConfigSGIX)(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +extern GLXPixmap VBOXGLXENTRYTAG(glXCreateGLXPixmapWithConfigSGIX)(Display *dpy, GLXFBConfig config, Pixmap pixmap) ; +extern int VBOXGLXENTRYTAG(glXGetFBConfigAttribSGIX)(Display *dpy, GLXFBConfig config, int attribute, int *value) ; +extern GLXFBConfig * VBOXGLXENTRYTAG(glXChooseFBConfig)(Display *dpy, int screen, ATTRIB_TYPE *attrib_list, int *nelements) ; +extern GLXPbuffer VBOXGLXENTRYTAG(glXCreatePbuffer)(Display *dpy, GLXFBConfig config, ATTRIB_TYPE *attrib_list) ; +extern GLXPixmap VBOXGLXENTRYTAG(glXCreatePixmap)(Display *dpy, GLXFBConfig config, Pixmap pixmap, const ATTRIB_TYPE *attrib_list) ; +extern GLXWindow VBOXGLXENTRYTAG(glXCreateWindow)(Display *dpy, GLXFBConfig config, Window win, ATTRIB_TYPE *attrib_list) ; +extern GLXContext VBOXGLXENTRYTAG(glXCreateNewContext)(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +extern void VBOXGLXENTRYTAG(glXDestroyPbuffer)(Display *dpy, GLXPbuffer pbuf) ; +extern void VBOXGLXENTRYTAG(glXDestroyPixmap)(Display *dpy, GLXPixmap pixmap) ; +extern void VBOXGLXENTRYTAG(glXDestroyWindow)(Display *dpy, GLXWindow win) ; +extern GLXDrawable VBOXGLXENTRYTAG(glXGetCurrentReadDrawable)(void) ; +extern int VBOXGLXENTRYTAG(glXGetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int *value) ; +extern GLXFBConfig * VBOXGLXENTRYTAG(glXGetFBConfigs)(Display *dpy, int screen, int *nelements) ; +extern void VBOXGLXENTRYTAG(glXGetSelectedEvent)(Display *dpy, GLXDrawable draw, unsigned long *event_mask) ; +extern XVisualInfo * VBOXGLXENTRYTAG(glXGetVisualFromFBConfig)(Display *dpy, GLXFBConfig config) ; +extern Bool VBOXGLXENTRYTAG(glXMakeContextCurrent)(Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx) ; +extern int VBOXGLXENTRYTAG(glXQueryContext)(Display *dpy, GLXContext ctx, int attribute, int *value) ; +extern void VBOXGLXENTRYTAG(glXQueryDrawable)(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value) ; +extern void VBOXGLXENTRYTAG(glXSelectEvent)(Display *dpy, GLXDrawable draw, unsigned long event_mask) ; +#else +/* Extern declarations for our asm stubs */ +# define GLXAPI_ENTRY(Func) \ + extern void vbox_glX##Func;\ + extern void vbox_glX##Func##_EndProc; +# include "fakedri_glxfuncsList.h" +# undef GLXAPI_ENTRY +#endif + +#endif /* !GA_INCLUDED_SRC_common_crOpenGL_fakedri_drv_h */ + diff --git a/src/VBox/Additions/common/crOpenGL/fakedri_glfuncsList.h b/src/VBox/Additions/common/crOpenGL/fakedri_glfuncsList.h new file mode 100644 index 00000000..6928a2ab --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/fakedri_glfuncsList.h @@ -0,0 +1,730 @@ +/* $Id: fakedri_glfuncsList.h $ */ +/** @file + * VBox OpenGL list of opengl functions common in Mesa and vbox opengl stub + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#ifndef GLAPI_ENTRY +#error GLAPI_ENTRY should be defined. +#endif + +GLAPI_ENTRY(NewList) +GLAPI_ENTRY(EndList) +GLAPI_ENTRY(CallList) +GLAPI_ENTRY(CallLists) +GLAPI_ENTRY(DeleteLists) +GLAPI_ENTRY(GenLists) +GLAPI_ENTRY(ListBase) +GLAPI_ENTRY(Begin) +GLAPI_ENTRY(Bitmap) +GLAPI_ENTRY(Color3b) +GLAPI_ENTRY(Color3bv) +GLAPI_ENTRY(Color3d) +GLAPI_ENTRY(Color3dv) +GLAPI_ENTRY(Color3f) +GLAPI_ENTRY(Color3fv) +GLAPI_ENTRY(Color3i) +GLAPI_ENTRY(Color3iv) +GLAPI_ENTRY(Color3s) +GLAPI_ENTRY(Color3sv) +GLAPI_ENTRY(Color3ub) +GLAPI_ENTRY(Color3ubv) +GLAPI_ENTRY(Color3ui) +GLAPI_ENTRY(Color3uiv) +GLAPI_ENTRY(Color3us) +GLAPI_ENTRY(Color3usv) +GLAPI_ENTRY(Color4b) +GLAPI_ENTRY(Color4bv) +GLAPI_ENTRY(Color4d) +GLAPI_ENTRY(Color4dv) +GLAPI_ENTRY(Color4f) +GLAPI_ENTRY(Color4fv) +GLAPI_ENTRY(Color4i) +GLAPI_ENTRY(Color4iv) +GLAPI_ENTRY(Color4s) +GLAPI_ENTRY(Color4sv) +GLAPI_ENTRY(Color4ub) +GLAPI_ENTRY(Color4ubv) +GLAPI_ENTRY(Color4ui) +GLAPI_ENTRY(Color4uiv) +GLAPI_ENTRY(Color4us) +GLAPI_ENTRY(Color4usv) +GLAPI_ENTRY(EdgeFlag) +GLAPI_ENTRY(EdgeFlagv) +GLAPI_ENTRY(End) +GLAPI_ENTRY(Indexd) +GLAPI_ENTRY(Indexdv) +GLAPI_ENTRY(Indexf) +GLAPI_ENTRY(Indexfv) +GLAPI_ENTRY(Indexi) +GLAPI_ENTRY(Indexiv) +GLAPI_ENTRY(Indexs) +GLAPI_ENTRY(Indexsv) +GLAPI_ENTRY(Normal3b) +GLAPI_ENTRY(Normal3bv) +GLAPI_ENTRY(Normal3d) +GLAPI_ENTRY(Normal3dv) +GLAPI_ENTRY(Normal3f) +GLAPI_ENTRY(Normal3fv) +GLAPI_ENTRY(Normal3i) +GLAPI_ENTRY(Normal3iv) +GLAPI_ENTRY(Normal3s) +GLAPI_ENTRY(Normal3sv) +GLAPI_ENTRY(RasterPos2d) +GLAPI_ENTRY(RasterPos2dv) +GLAPI_ENTRY(RasterPos2f) +GLAPI_ENTRY(RasterPos2fv) +GLAPI_ENTRY(RasterPos2i) +GLAPI_ENTRY(RasterPos2iv) +GLAPI_ENTRY(RasterPos2s) +GLAPI_ENTRY(RasterPos2sv) +GLAPI_ENTRY(RasterPos3d) +GLAPI_ENTRY(RasterPos3dv) +GLAPI_ENTRY(RasterPos3f) +GLAPI_ENTRY(RasterPos3fv) +GLAPI_ENTRY(RasterPos3i) +GLAPI_ENTRY(RasterPos3iv) +GLAPI_ENTRY(RasterPos3s) +GLAPI_ENTRY(RasterPos3sv) +GLAPI_ENTRY(RasterPos4d) +GLAPI_ENTRY(RasterPos4dv) +GLAPI_ENTRY(RasterPos4f) +GLAPI_ENTRY(RasterPos4fv) +GLAPI_ENTRY(RasterPos4i) +GLAPI_ENTRY(RasterPos4iv) +GLAPI_ENTRY(RasterPos4s) +GLAPI_ENTRY(RasterPos4sv) +GLAPI_ENTRY(Rectd) +GLAPI_ENTRY(Rectdv) +GLAPI_ENTRY(Rectf) +GLAPI_ENTRY(Rectfv) +GLAPI_ENTRY(Recti) +GLAPI_ENTRY(Rectiv) +GLAPI_ENTRY(Rects) +GLAPI_ENTRY(Rectsv) +GLAPI_ENTRY(TexCoord1d) +GLAPI_ENTRY(TexCoord1dv) +GLAPI_ENTRY(TexCoord1f) +GLAPI_ENTRY(TexCoord1fv) +GLAPI_ENTRY(TexCoord1i) +GLAPI_ENTRY(TexCoord1iv) +GLAPI_ENTRY(TexCoord1s) +GLAPI_ENTRY(TexCoord1sv) +GLAPI_ENTRY(TexCoord2d) +GLAPI_ENTRY(TexCoord2dv) +GLAPI_ENTRY(TexCoord2f) +GLAPI_ENTRY(TexCoord2fv) +GLAPI_ENTRY(TexCoord2i) +GLAPI_ENTRY(TexCoord2iv) +GLAPI_ENTRY(TexCoord2s) +GLAPI_ENTRY(TexCoord2sv) +GLAPI_ENTRY(TexCoord3d) +GLAPI_ENTRY(TexCoord3dv) +GLAPI_ENTRY(TexCoord3f) +GLAPI_ENTRY(TexCoord3fv) +GLAPI_ENTRY(TexCoord3i) +GLAPI_ENTRY(TexCoord3iv) +GLAPI_ENTRY(TexCoord3s) +GLAPI_ENTRY(TexCoord3sv) +GLAPI_ENTRY(TexCoord4d) +GLAPI_ENTRY(TexCoord4dv) +GLAPI_ENTRY(TexCoord4f) +GLAPI_ENTRY(TexCoord4fv) +GLAPI_ENTRY(TexCoord4i) +GLAPI_ENTRY(TexCoord4iv) +GLAPI_ENTRY(TexCoord4s) +GLAPI_ENTRY(TexCoord4sv) +GLAPI_ENTRY(Vertex2d) +GLAPI_ENTRY(Vertex2dv) +GLAPI_ENTRY(Vertex2f) +GLAPI_ENTRY(Vertex2fv) +GLAPI_ENTRY(Vertex2i) +GLAPI_ENTRY(Vertex2iv) +GLAPI_ENTRY(Vertex2s) +GLAPI_ENTRY(Vertex2sv) +GLAPI_ENTRY(Vertex3d) +GLAPI_ENTRY(Vertex3dv) +GLAPI_ENTRY(Vertex3f) +GLAPI_ENTRY(Vertex3fv) +GLAPI_ENTRY(Vertex3i) +GLAPI_ENTRY(Vertex3iv) +GLAPI_ENTRY(Vertex3s) +GLAPI_ENTRY(Vertex3sv) +GLAPI_ENTRY(Vertex4d) +GLAPI_ENTRY(Vertex4dv) +GLAPI_ENTRY(Vertex4f) +GLAPI_ENTRY(Vertex4fv) +GLAPI_ENTRY(Vertex4i) +GLAPI_ENTRY(Vertex4iv) +GLAPI_ENTRY(Vertex4s) +GLAPI_ENTRY(Vertex4sv) +GLAPI_ENTRY(ClipPlane) +GLAPI_ENTRY(ColorMaterial) +GLAPI_ENTRY(CullFace) +GLAPI_ENTRY(Fogf) +GLAPI_ENTRY(Fogfv) +GLAPI_ENTRY(Fogi) +GLAPI_ENTRY(Fogiv) +GLAPI_ENTRY(FrontFace) +GLAPI_ENTRY(Hint) +GLAPI_ENTRY(Lightf) +GLAPI_ENTRY(Lightfv) +GLAPI_ENTRY(Lighti) +GLAPI_ENTRY(Lightiv) +GLAPI_ENTRY(LightModelf) +GLAPI_ENTRY(LightModelfv) +GLAPI_ENTRY(LightModeli) +GLAPI_ENTRY(LightModeliv) +GLAPI_ENTRY(LineStipple) +GLAPI_ENTRY(LineWidth) +GLAPI_ENTRY(Materialf) +GLAPI_ENTRY(Materialfv) +GLAPI_ENTRY(Materiali) +GLAPI_ENTRY(Materialiv) +GLAPI_ENTRY(PointSize) +GLAPI_ENTRY(PolygonMode) +GLAPI_ENTRY(PolygonStipple) +GLAPI_ENTRY(Scissor) +GLAPI_ENTRY(ShadeModel) +GLAPI_ENTRY(TexParameterf) +GLAPI_ENTRY(TexParameterfv) +GLAPI_ENTRY(TexParameteri) +GLAPI_ENTRY(TexParameteriv) +GLAPI_ENTRY(TexImage1D) +GLAPI_ENTRY(TexImage2D) +GLAPI_ENTRY(TexEnvf) +GLAPI_ENTRY(TexEnvfv) +GLAPI_ENTRY(TexEnvi) +GLAPI_ENTRY(TexEnviv) +GLAPI_ENTRY(TexGend) +GLAPI_ENTRY(TexGendv) +GLAPI_ENTRY(TexGenf) +GLAPI_ENTRY(TexGenfv) +GLAPI_ENTRY(TexGeni) +GLAPI_ENTRY(TexGeniv) +GLAPI_ENTRY(FeedbackBuffer) +GLAPI_ENTRY(SelectBuffer) +GLAPI_ENTRY(RenderMode) +GLAPI_ENTRY(InitNames) +GLAPI_ENTRY(LoadName) +GLAPI_ENTRY(PassThrough) +GLAPI_ENTRY(PopName) +GLAPI_ENTRY(PushName) +GLAPI_ENTRY(DrawBuffer) +GLAPI_ENTRY(Clear) +GLAPI_ENTRY(ClearAccum) +GLAPI_ENTRY(ClearIndex) +GLAPI_ENTRY(ClearColor) +GLAPI_ENTRY(ClearStencil) +GLAPI_ENTRY(ClearDepth) +GLAPI_ENTRY(StencilMask) +GLAPI_ENTRY(ColorMask) +GLAPI_ENTRY(DepthMask) +GLAPI_ENTRY(IndexMask) +GLAPI_ENTRY(Accum) +GLAPI_ENTRY(Disable) +GLAPI_ENTRY(Enable) +GLAPI_ENTRY(Finish) +GLAPI_ENTRY(Flush) +GLAPI_ENTRY(PopAttrib) +GLAPI_ENTRY(PushAttrib) +GLAPI_ENTRY(Map1d) +GLAPI_ENTRY(Map1f) +GLAPI_ENTRY(Map2d) +GLAPI_ENTRY(Map2f) +GLAPI_ENTRY(MapGrid1d) +GLAPI_ENTRY(MapGrid1f) +GLAPI_ENTRY(MapGrid2d) +GLAPI_ENTRY(MapGrid2f) +GLAPI_ENTRY(EvalCoord1d) +GLAPI_ENTRY(EvalCoord1dv) +GLAPI_ENTRY(EvalCoord1f) +GLAPI_ENTRY(EvalCoord1fv) +GLAPI_ENTRY(EvalCoord2d) +GLAPI_ENTRY(EvalCoord2dv) +GLAPI_ENTRY(EvalCoord2f) +GLAPI_ENTRY(EvalCoord2fv) +GLAPI_ENTRY(EvalMesh1) +GLAPI_ENTRY(EvalPoint1) +GLAPI_ENTRY(EvalMesh2) +GLAPI_ENTRY(EvalPoint2) +GLAPI_ENTRY(AlphaFunc) +GLAPI_ENTRY(BlendFunc) +GLAPI_ENTRY(LogicOp) +GLAPI_ENTRY(StencilFunc) +GLAPI_ENTRY(StencilOp) +GLAPI_ENTRY(DepthFunc) +GLAPI_ENTRY(PixelZoom) +GLAPI_ENTRY(PixelTransferf) +GLAPI_ENTRY(PixelTransferi) +GLAPI_ENTRY(PixelStoref) +GLAPI_ENTRY(PixelStorei) +GLAPI_ENTRY(PixelMapfv) +GLAPI_ENTRY(PixelMapuiv) +GLAPI_ENTRY(PixelMapusv) +GLAPI_ENTRY(ReadBuffer) +GLAPI_ENTRY(CopyPixels) +GLAPI_ENTRY(ReadPixels) +GLAPI_ENTRY(DrawPixels) +GLAPI_ENTRY(GetBooleanv) +GLAPI_ENTRY(GetClipPlane) +GLAPI_ENTRY(GetDoublev) +GLAPI_ENTRY(GetError) +GLAPI_ENTRY(GetFloatv) +GLAPI_ENTRY(GetIntegerv) +GLAPI_ENTRY(GetLightfv) +GLAPI_ENTRY(GetLightiv) +GLAPI_ENTRY(GetMapdv) +GLAPI_ENTRY(GetMapfv) +GLAPI_ENTRY(GetMapiv) +GLAPI_ENTRY(GetMaterialfv) +GLAPI_ENTRY(GetMaterialiv) +GLAPI_ENTRY(GetPixelMapfv) +GLAPI_ENTRY(GetPixelMapuiv) +GLAPI_ENTRY(GetPixelMapusv) +GLAPI_ENTRY(GetPolygonStipple) +GLAPI_ENTRY(GetString) +GLAPI_ENTRY(GetTexEnvfv) +GLAPI_ENTRY(GetTexEnviv) +GLAPI_ENTRY(GetTexGendv) +GLAPI_ENTRY(GetTexGenfv) +GLAPI_ENTRY(GetTexGeniv) +GLAPI_ENTRY(GetTexImage) +GLAPI_ENTRY(GetTexParameterfv) +GLAPI_ENTRY(GetTexParameteriv) +GLAPI_ENTRY(GetTexLevelParameterfv) +GLAPI_ENTRY(GetTexLevelParameteriv) +GLAPI_ENTRY(IsEnabled) +GLAPI_ENTRY(IsList) +GLAPI_ENTRY(DepthRange) +GLAPI_ENTRY(Frustum) +GLAPI_ENTRY(LoadIdentity) +GLAPI_ENTRY(LoadMatrixf) +GLAPI_ENTRY(LoadMatrixd) +GLAPI_ENTRY(MatrixMode) +GLAPI_ENTRY(MultMatrixf) +GLAPI_ENTRY(MultMatrixd) +GLAPI_ENTRY(Ortho) +GLAPI_ENTRY(PopMatrix) +GLAPI_ENTRY(PushMatrix) +GLAPI_ENTRY(Rotated) +GLAPI_ENTRY(Rotatef) +GLAPI_ENTRY(Scaled) +GLAPI_ENTRY(Scalef) +GLAPI_ENTRY(Translated) +GLAPI_ENTRY(Translatef) +GLAPI_ENTRY(Viewport) +GLAPI_ENTRY(ArrayElement) +GLAPI_ENTRY(BindTexture) +GLAPI_ENTRY(ColorPointer) +GLAPI_ENTRY(DisableClientState) +GLAPI_ENTRY(DrawArrays) +GLAPI_ENTRY(DrawElements) +GLAPI_ENTRY(EdgeFlagPointer) +GLAPI_ENTRY(EnableClientState) +GLAPI_ENTRY(IndexPointer) +GLAPI_ENTRY(Indexub) +GLAPI_ENTRY(Indexubv) +GLAPI_ENTRY(InterleavedArrays) +GLAPI_ENTRY(NormalPointer) +GLAPI_ENTRY(PolygonOffset) +GLAPI_ENTRY(TexCoordPointer) +GLAPI_ENTRY(VertexPointer) +GLAPI_ENTRY(AreTexturesResident) +GLAPI_ENTRY(CopyTexImage1D) +GLAPI_ENTRY(CopyTexImage2D) +GLAPI_ENTRY(CopyTexSubImage1D) +GLAPI_ENTRY(CopyTexSubImage2D) +GLAPI_ENTRY(DeleteTextures) +GLAPI_ENTRY(GenTextures) +GLAPI_ENTRY(GetPointerv) +GLAPI_ENTRY(IsTexture) +GLAPI_ENTRY(PrioritizeTextures) +GLAPI_ENTRY(TexSubImage1D) +GLAPI_ENTRY(TexSubImage2D) +GLAPI_ENTRY(PopClientAttrib) +GLAPI_ENTRY(PushClientAttrib) +GLAPI_ENTRY(BlendColor) +GLAPI_ENTRY(BlendEquation) +GLAPI_ENTRY(DrawRangeElements) +GLAPI_ENTRY(ColorTable) +GLAPI_ENTRY(ColorTableParameterfv) +GLAPI_ENTRY(ColorTableParameteriv) +GLAPI_ENTRY(CopyColorTable) +GLAPI_ENTRY(GetColorTable) +GLAPI_ENTRY(GetColorTableParameterfv) +GLAPI_ENTRY(GetColorTableParameteriv) +GLAPI_ENTRY(ColorSubTable) +GLAPI_ENTRY(CopyColorSubTable) +GLAPI_ENTRY(ConvolutionFilter1D) +GLAPI_ENTRY(ConvolutionFilter2D) +GLAPI_ENTRY(ConvolutionParameterf) +GLAPI_ENTRY(ConvolutionParameterfv) +GLAPI_ENTRY(ConvolutionParameteri) +GLAPI_ENTRY(ConvolutionParameteriv) +GLAPI_ENTRY(CopyConvolutionFilter1D) +GLAPI_ENTRY(CopyConvolutionFilter2D) +GLAPI_ENTRY(GetConvolutionFilter) +GLAPI_ENTRY(GetConvolutionParameterfv) +GLAPI_ENTRY(GetConvolutionParameteriv) +GLAPI_ENTRY(GetSeparableFilter) +GLAPI_ENTRY(SeparableFilter2D) +GLAPI_ENTRY(GetHistogram) +GLAPI_ENTRY(GetHistogramParameterfv) +GLAPI_ENTRY(GetHistogramParameteriv) +GLAPI_ENTRY(GetMinmax) +GLAPI_ENTRY(GetMinmaxParameterfv) +GLAPI_ENTRY(GetMinmaxParameteriv) +GLAPI_ENTRY(Histogram) +GLAPI_ENTRY(Minmax) +GLAPI_ENTRY(ResetHistogram) +GLAPI_ENTRY(ResetMinmax) +GLAPI_ENTRY(TexImage3D) +GLAPI_ENTRY(TexSubImage3D) +GLAPI_ENTRY(CopyTexSubImage3D) +GLAPI_ENTRY(ActiveTextureARB) +GLAPI_ENTRY(ClientActiveTextureARB) +GLAPI_ENTRY(MultiTexCoord1dARB) +GLAPI_ENTRY(MultiTexCoord1dvARB) +GLAPI_ENTRY(MultiTexCoord1fARB) +GLAPI_ENTRY(MultiTexCoord1fvARB) +GLAPI_ENTRY(MultiTexCoord1iARB) +GLAPI_ENTRY(MultiTexCoord1ivARB) +GLAPI_ENTRY(MultiTexCoord1sARB) +GLAPI_ENTRY(MultiTexCoord1svARB) +GLAPI_ENTRY(MultiTexCoord2dARB) +GLAPI_ENTRY(MultiTexCoord2dvARB) +GLAPI_ENTRY(MultiTexCoord2fARB) +GLAPI_ENTRY(MultiTexCoord2fvARB) +GLAPI_ENTRY(MultiTexCoord2iARB) +GLAPI_ENTRY(MultiTexCoord2ivARB) +GLAPI_ENTRY(MultiTexCoord2sARB) +GLAPI_ENTRY(MultiTexCoord2svARB) +GLAPI_ENTRY(MultiTexCoord3dARB) +GLAPI_ENTRY(MultiTexCoord3dvARB) +GLAPI_ENTRY(MultiTexCoord3fARB) +GLAPI_ENTRY(MultiTexCoord3fvARB) +GLAPI_ENTRY(MultiTexCoord3iARB) +GLAPI_ENTRY(MultiTexCoord3ivARB) +GLAPI_ENTRY(MultiTexCoord3sARB) +GLAPI_ENTRY(MultiTexCoord3svARB) +GLAPI_ENTRY(MultiTexCoord4dARB) +GLAPI_ENTRY(MultiTexCoord4dvARB) +GLAPI_ENTRY(MultiTexCoord4fARB) +GLAPI_ENTRY(MultiTexCoord4fvARB) +GLAPI_ENTRY(MultiTexCoord4iARB) +GLAPI_ENTRY(MultiTexCoord4ivARB) +GLAPI_ENTRY(MultiTexCoord4sARB) +GLAPI_ENTRY(MultiTexCoord4svARB) +GLAPI_ENTRY(AttachShader) +GLAPI_ENTRY(CreateProgram) +GLAPI_ENTRY(CreateShader) +GLAPI_ENTRY(DeleteProgram) +GLAPI_ENTRY(DeleteShader) +GLAPI_ENTRY(DetachShader) +GLAPI_ENTRY(GetAttachedShaders) +GLAPI_ENTRY(GetProgramInfoLog) +GLAPI_ENTRY(GetProgramiv) +GLAPI_ENTRY(GetShaderInfoLog) +GLAPI_ENTRY(GetShaderiv) +GLAPI_ENTRY(IsProgram) +GLAPI_ENTRY(IsShader) +GLAPI_ENTRY(StencilFuncSeparate) +GLAPI_ENTRY(StencilMaskSeparate) +GLAPI_ENTRY(StencilOpSeparate) +GLAPI_ENTRY(UniformMatrix2x3fv) +GLAPI_ENTRY(UniformMatrix2x4fv) +GLAPI_ENTRY(UniformMatrix3x2fv) +GLAPI_ENTRY(UniformMatrix3x4fv) +GLAPI_ENTRY(UniformMatrix4x2fv) +GLAPI_ENTRY(UniformMatrix4x3fv) +GLAPI_ENTRY(LoadTransposeMatrixdARB) +GLAPI_ENTRY(LoadTransposeMatrixfARB) +GLAPI_ENTRY(MultTransposeMatrixdARB) +GLAPI_ENTRY(MultTransposeMatrixfARB) +GLAPI_ENTRY(SampleCoverageARB) +GLAPI_ENTRY(CompressedTexImage1DARB) +GLAPI_ENTRY(CompressedTexImage2DARB) +GLAPI_ENTRY(CompressedTexImage3DARB) +GLAPI_ENTRY(CompressedTexSubImage1DARB) +GLAPI_ENTRY(CompressedTexSubImage2DARB) +GLAPI_ENTRY(CompressedTexSubImage3DARB) +GLAPI_ENTRY(GetCompressedTexImageARB) +GLAPI_ENTRY(DisableVertexAttribArrayARB) +GLAPI_ENTRY(EnableVertexAttribArrayARB) +GLAPI_ENTRY(GetProgramEnvParameterdvARB) +GLAPI_ENTRY(GetProgramEnvParameterfvARB) +GLAPI_ENTRY(GetProgramLocalParameterdvARB) +GLAPI_ENTRY(GetProgramLocalParameterfvARB) +GLAPI_ENTRY(GetProgramStringARB) +GLAPI_ENTRY(GetProgramivARB) +GLAPI_ENTRY(GetVertexAttribdvARB) +GLAPI_ENTRY(GetVertexAttribfvARB) +GLAPI_ENTRY(GetVertexAttribivARB) +GLAPI_ENTRY(ProgramEnvParameter4dARB) +GLAPI_ENTRY(ProgramEnvParameter4dvARB) +GLAPI_ENTRY(ProgramEnvParameter4fARB) +GLAPI_ENTRY(ProgramEnvParameter4fvARB) +GLAPI_ENTRY(ProgramLocalParameter4dARB) +GLAPI_ENTRY(ProgramLocalParameter4dvARB) +GLAPI_ENTRY(ProgramLocalParameter4fARB) +GLAPI_ENTRY(ProgramLocalParameter4fvARB) +GLAPI_ENTRY(ProgramStringARB) +GLAPI_ENTRY(VertexAttrib1dARB) +GLAPI_ENTRY(VertexAttrib1dvARB) +GLAPI_ENTRY(VertexAttrib1fARB) +GLAPI_ENTRY(VertexAttrib1fvARB) +GLAPI_ENTRY(VertexAttrib1sARB) +GLAPI_ENTRY(VertexAttrib1svARB) +GLAPI_ENTRY(VertexAttrib2dARB) +GLAPI_ENTRY(VertexAttrib2dvARB) +GLAPI_ENTRY(VertexAttrib2fARB) +GLAPI_ENTRY(VertexAttrib2fvARB) +GLAPI_ENTRY(VertexAttrib2sARB) +GLAPI_ENTRY(VertexAttrib2svARB) +GLAPI_ENTRY(VertexAttrib3dARB) +GLAPI_ENTRY(VertexAttrib3dvARB) +GLAPI_ENTRY(VertexAttrib3fARB) +GLAPI_ENTRY(VertexAttrib3fvARB) +GLAPI_ENTRY(VertexAttrib3sARB) +GLAPI_ENTRY(VertexAttrib3svARB) +GLAPI_ENTRY(VertexAttrib4NbvARB) +GLAPI_ENTRY(VertexAttrib4NivARB) +GLAPI_ENTRY(VertexAttrib4NsvARB) +GLAPI_ENTRY(VertexAttrib4NubARB) +GLAPI_ENTRY(VertexAttrib4NubvARB) +GLAPI_ENTRY(VertexAttrib4NuivARB) +GLAPI_ENTRY(VertexAttrib4NusvARB) +GLAPI_ENTRY(VertexAttrib4bvARB) +GLAPI_ENTRY(VertexAttrib4dARB) +GLAPI_ENTRY(VertexAttrib4dvARB) +GLAPI_ENTRY(VertexAttrib4fARB) +GLAPI_ENTRY(VertexAttrib4fvARB) +GLAPI_ENTRY(VertexAttrib4ivARB) +GLAPI_ENTRY(VertexAttrib4sARB) +GLAPI_ENTRY(VertexAttrib4svARB) +GLAPI_ENTRY(VertexAttrib4ubvARB) +GLAPI_ENTRY(VertexAttrib4uivARB) +GLAPI_ENTRY(VertexAttrib4usvARB) +GLAPI_ENTRY(VertexAttribPointerARB) +GLAPI_ENTRY(BindBufferARB) +GLAPI_ENTRY(BufferDataARB) +GLAPI_ENTRY(BufferSubDataARB) +GLAPI_ENTRY(DeleteBuffersARB) +GLAPI_ENTRY(GenBuffersARB) +GLAPI_ENTRY(GetBufferParameterivARB) +GLAPI_ENTRY(GetBufferPointervARB) +GLAPI_ENTRY(GetBufferSubDataARB) +GLAPI_ENTRY(IsBufferARB) +GLAPI_ENTRY(MapBufferARB) +GLAPI_ENTRY(UnmapBufferARB) +GLAPI_ENTRY(BeginQueryARB) +GLAPI_ENTRY(DeleteQueriesARB) +GLAPI_ENTRY(EndQueryARB) +GLAPI_ENTRY(GenQueriesARB) +GLAPI_ENTRY(GetQueryObjectivARB) +GLAPI_ENTRY(GetQueryObjectuivARB) +GLAPI_ENTRY(GetQueryivARB) +GLAPI_ENTRY(IsQueryARB) +GLAPI_ENTRY(AttachObjectARB) +GLAPI_ENTRY(CompileShaderARB) +GLAPI_ENTRY(CreateProgramObjectARB) +GLAPI_ENTRY(CreateShaderObjectARB) +GLAPI_ENTRY(DeleteObjectARB) +GLAPI_ENTRY(DetachObjectARB) +GLAPI_ENTRY(GetActiveUniformARB) +GLAPI_ENTRY(GetAttachedObjectsARB) +GLAPI_ENTRY(GetHandleARB) +GLAPI_ENTRY(GetInfoLogARB) +GLAPI_ENTRY(GetObjectParameterfvARB) +GLAPI_ENTRY(GetObjectParameterivARB) +GLAPI_ENTRY(GetShaderSourceARB) +GLAPI_ENTRY(GetUniformLocationARB) +GLAPI_ENTRY(GetUniformfvARB) +GLAPI_ENTRY(GetUniformivARB) +GLAPI_ENTRY(LinkProgramARB) +GLAPI_ENTRY(ShaderSourceARB) +GLAPI_ENTRY(Uniform1fARB) +GLAPI_ENTRY(Uniform1fvARB) +GLAPI_ENTRY(Uniform1iARB) +GLAPI_ENTRY(Uniform1ivARB) +GLAPI_ENTRY(Uniform2fARB) +GLAPI_ENTRY(Uniform2fvARB) +GLAPI_ENTRY(Uniform2iARB) +GLAPI_ENTRY(Uniform2ivARB) +GLAPI_ENTRY(Uniform3fARB) +GLAPI_ENTRY(Uniform3fvARB) +GLAPI_ENTRY(Uniform3iARB) +GLAPI_ENTRY(Uniform3ivARB) +GLAPI_ENTRY(Uniform4fARB) +GLAPI_ENTRY(Uniform4fvARB) +GLAPI_ENTRY(Uniform4iARB) +GLAPI_ENTRY(Uniform4ivARB) +GLAPI_ENTRY(UniformMatrix2fvARB) +GLAPI_ENTRY(UniformMatrix3fvARB) +GLAPI_ENTRY(UniformMatrix4fvARB) +GLAPI_ENTRY(UseProgramObjectARB) +GLAPI_ENTRY(ValidateProgramARB) +GLAPI_ENTRY(BindAttribLocationARB) +GLAPI_ENTRY(GetActiveAttribARB) +GLAPI_ENTRY(GetAttribLocationARB) +//GLAPI_ENTRY(DrawBuffersARB) +//GLAPI_ENTRY(PolygonOffsetEXT) +//GLAPI_ENTRY(GetPixelTexGenParameterfvSGIS) +//GLAPI_ENTRY(GetPixelTexGenParameterivSGIS) +//GLAPI_ENTRY(PixelTexGenParameterfSGIS) +//GLAPI_ENTRY(PixelTexGenParameterfvSGIS) +//GLAPI_ENTRY(PixelTexGenParameteriSGIS) +//GLAPI_ENTRY(PixelTexGenParameterivSGIS) +GLAPI_ENTRY(PointParameterfEXT) +GLAPI_ENTRY(PointParameterfvEXT) +GLAPI_ENTRY(LockArraysEXT) +GLAPI_ENTRY(UnlockArraysEXT) +//GLAPI_ENTRY(CullParameterdvEXT) +//GLAPI_ENTRY(CullParameterfvEXT) +GLAPI_ENTRY(SecondaryColor3bEXT) +GLAPI_ENTRY(SecondaryColor3bvEXT) +GLAPI_ENTRY(SecondaryColor3dEXT) +GLAPI_ENTRY(SecondaryColor3dvEXT) +GLAPI_ENTRY(SecondaryColor3fEXT) +GLAPI_ENTRY(SecondaryColor3fvEXT) +GLAPI_ENTRY(SecondaryColor3iEXT) +GLAPI_ENTRY(SecondaryColor3ivEXT) +GLAPI_ENTRY(SecondaryColor3sEXT) +GLAPI_ENTRY(SecondaryColor3svEXT) +GLAPI_ENTRY(SecondaryColor3ubEXT) +GLAPI_ENTRY(SecondaryColor3ubvEXT) +GLAPI_ENTRY(SecondaryColor3uiEXT) +GLAPI_ENTRY(SecondaryColor3uivEXT) +GLAPI_ENTRY(SecondaryColor3usEXT) +GLAPI_ENTRY(SecondaryColor3usvEXT) +GLAPI_ENTRY(SecondaryColorPointerEXT) +GLAPI_ENTRY(MultiDrawArraysEXT) +GLAPI_ENTRY(MultiDrawElementsEXT) +GLAPI_ENTRY(FogCoordPointerEXT) +GLAPI_ENTRY(FogCoorddEXT) +GLAPI_ENTRY(FogCoorddvEXT) +GLAPI_ENTRY(FogCoordfEXT) +GLAPI_ENTRY(FogCoordfvEXT) +//GLAPI_ENTRY(PixelTexGenSGIX) +GLAPI_ENTRY(BlendFuncSeparateEXT) +GLAPI_ENTRY(FlushVertexArrayRangeNV) +GLAPI_ENTRY(VertexArrayRangeNV) +GLAPI_ENTRY(CombinerInputNV) +GLAPI_ENTRY(CombinerOutputNV) +GLAPI_ENTRY(CombinerParameterfNV) +GLAPI_ENTRY(CombinerParameterfvNV) +GLAPI_ENTRY(CombinerParameteriNV) +GLAPI_ENTRY(CombinerParameterivNV) +GLAPI_ENTRY(FinalCombinerInputNV) +GLAPI_ENTRY(GetCombinerInputParameterfvNV) +GLAPI_ENTRY(GetCombinerInputParameterivNV) +GLAPI_ENTRY(GetCombinerOutputParameterfvNV) +GLAPI_ENTRY(GetCombinerOutputParameterivNV) +GLAPI_ENTRY(GetFinalCombinerInputParameterfvNV) +GLAPI_ENTRY(GetFinalCombinerInputParameterivNV) +GLAPI_ENTRY(DeleteFencesNV) +GLAPI_ENTRY(FinishFenceNV) +GLAPI_ENTRY(GenFencesNV) +GLAPI_ENTRY(GetFenceivNV) +GLAPI_ENTRY(IsFenceNV) +GLAPI_ENTRY(SetFenceNV) +GLAPI_ENTRY(TestFenceNV) +GLAPI_ENTRY(AreProgramsResidentNV) +GLAPI_ENTRY(BindProgramNV) +GLAPI_ENTRY(DeleteProgramsNV) +GLAPI_ENTRY(ExecuteProgramNV) +GLAPI_ENTRY(GenProgramsNV) +GLAPI_ENTRY(GetProgramParameterdvNV) +GLAPI_ENTRY(GetProgramParameterfvNV) +GLAPI_ENTRY(GetProgramStringNV) +GLAPI_ENTRY(GetProgramivNV) +GLAPI_ENTRY(GetTrackMatrixivNV) +GLAPI_ENTRY(GetVertexAttribPointervNV) +GLAPI_ENTRY(GetVertexAttribdvNV) +GLAPI_ENTRY(GetVertexAttribfvNV) +GLAPI_ENTRY(GetVertexAttribivNV) +GLAPI_ENTRY(IsProgramNV) +GLAPI_ENTRY(LoadProgramNV) +GLAPI_ENTRY(ProgramParameters4dvNV) +GLAPI_ENTRY(ProgramParameters4fvNV) +GLAPI_ENTRY(RequestResidentProgramsNV) +GLAPI_ENTRY(TrackMatrixNV) +GLAPI_ENTRY(VertexAttrib1dNV) +GLAPI_ENTRY(VertexAttrib1dvNV) +GLAPI_ENTRY(VertexAttrib1fNV) +GLAPI_ENTRY(VertexAttrib1fvNV) +GLAPI_ENTRY(VertexAttrib1sNV) +GLAPI_ENTRY(VertexAttrib1svNV) +GLAPI_ENTRY(VertexAttrib2dNV) +GLAPI_ENTRY(VertexAttrib2dvNV) +GLAPI_ENTRY(VertexAttrib2fNV) +GLAPI_ENTRY(VertexAttrib2fvNV) +GLAPI_ENTRY(VertexAttrib2sNV) +GLAPI_ENTRY(VertexAttrib2svNV) +GLAPI_ENTRY(VertexAttrib3dNV) +GLAPI_ENTRY(VertexAttrib3dvNV) +GLAPI_ENTRY(VertexAttrib3fNV) +GLAPI_ENTRY(VertexAttrib3fvNV) +GLAPI_ENTRY(VertexAttrib3sNV) +GLAPI_ENTRY(VertexAttrib3svNV) +GLAPI_ENTRY(VertexAttrib4dNV) +GLAPI_ENTRY(VertexAttrib4dvNV) +GLAPI_ENTRY(VertexAttrib4fNV) +GLAPI_ENTRY(VertexAttrib4fvNV) +GLAPI_ENTRY(VertexAttrib4sNV) +GLAPI_ENTRY(VertexAttrib4svNV) +GLAPI_ENTRY(VertexAttrib4ubNV) +GLAPI_ENTRY(VertexAttrib4ubvNV) +GLAPI_ENTRY(VertexAttribPointerNV) +GLAPI_ENTRY(VertexAttribs1dvNV) +GLAPI_ENTRY(VertexAttribs1fvNV) +GLAPI_ENTRY(VertexAttribs1svNV) +GLAPI_ENTRY(VertexAttribs2dvNV) +GLAPI_ENTRY(VertexAttribs2fvNV) +GLAPI_ENTRY(VertexAttribs2svNV) +GLAPI_ENTRY(VertexAttribs3dvNV) +GLAPI_ENTRY(VertexAttribs3fvNV) +GLAPI_ENTRY(VertexAttribs3svNV) +GLAPI_ENTRY(VertexAttribs4dvNV) +GLAPI_ENTRY(VertexAttribs4fvNV) +GLAPI_ENTRY(VertexAttribs4svNV) +GLAPI_ENTRY(VertexAttribs4ubvNV) +GLAPI_ENTRY(PointParameteriNV) +GLAPI_ENTRY(PointParameterivNV) +GLAPI_ENTRY(GetProgramNamedParameterdvNV) +GLAPI_ENTRY(GetProgramNamedParameterfvNV) +GLAPI_ENTRY(ProgramNamedParameter4dNV) +GLAPI_ENTRY(ProgramNamedParameter4dvNV) +GLAPI_ENTRY(ProgramNamedParameter4fNV) +GLAPI_ENTRY(ProgramNamedParameter4fvNV) +//GLAPI_ENTRY(BlendEquationSeparateEXT) +GLAPI_ENTRY(BindFramebufferEXT) +GLAPI_ENTRY(BindRenderbufferEXT) +GLAPI_ENTRY(CheckFramebufferStatusEXT) +GLAPI_ENTRY(DeleteFramebuffersEXT) +GLAPI_ENTRY(DeleteRenderbuffersEXT) +GLAPI_ENTRY(FramebufferRenderbufferEXT) +GLAPI_ENTRY(FramebufferTexture1DEXT) +GLAPI_ENTRY(FramebufferTexture2DEXT) +GLAPI_ENTRY(FramebufferTexture3DEXT) +GLAPI_ENTRY(GenFramebuffersEXT) +GLAPI_ENTRY(GenRenderbuffersEXT) +GLAPI_ENTRY(GenerateMipmapEXT) +GLAPI_ENTRY(GetFramebufferAttachmentParameterivEXT) +GLAPI_ENTRY(GetRenderbufferParameterivEXT) +GLAPI_ENTRY(IsFramebufferEXT) +GLAPI_ENTRY(IsRenderbufferEXT) +GLAPI_ENTRY(RenderbufferStorageEXT) + diff --git a/src/VBox/Additions/common/crOpenGL/fakedri_glxfuncsList.h b/src/VBox/Additions/common/crOpenGL/fakedri_glxfuncsList.h new file mode 100644 index 00000000..c1e7274d --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/fakedri_glxfuncsList.h @@ -0,0 +1,93 @@ +/* $Id: fakedri_glxfuncsList.h $ */ +/** @file + * VBox OpenGL list of opengl functions common in Mesa and vbox opengl stub + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#ifndef GLXAPI_ENTRY +#error GLXAPI_ENTRY should be defined. +#endif + +/*This should match glX* entries which are exported by Mesa's libGL.so, + * use something like the following to get the list: + * objdump -T libGL.so|grep glX|grep -v __|awk '{print $7;};'|sed 's/glX//'|awk '{OFS=""; print "GLXAPI_ENTRY(",$1,")"}' + */ + +/* #######Note: if you change the list, don't forget to change Linux_i386_glxapi_exports.py####### */ + +GLXAPI_ENTRY(CopyContext) +GLXAPI_ENTRY(UseXFont) +/*GLXAPI_ENTRY(GetDriverConfig)*/ +GLXAPI_ENTRY(GetProcAddress) +GLXAPI_ENTRY(QueryExtension) +GLXAPI_ENTRY(IsDirect) +GLXAPI_ENTRY(DestroyGLXPbufferSGIX) +GLXAPI_ENTRY(QueryGLXPbufferSGIX) +GLXAPI_ENTRY(CreateGLXPixmap) +GLXAPI_ENTRY(CreateGLXPixmapWithConfigSGIX) +GLXAPI_ENTRY(QueryContext) +GLXAPI_ENTRY(CreateContextWithConfigSGIX) +GLXAPI_ENTRY(SwapBuffers) +GLXAPI_ENTRY(CreateNewContext) +GLXAPI_ENTRY(SelectEventSGIX) +GLXAPI_ENTRY(GetCurrentDrawable) +GLXAPI_ENTRY(ChooseFBConfig) +GLXAPI_ENTRY(WaitGL) +GLXAPI_ENTRY(GetFBConfigs) +GLXAPI_ENTRY(CreatePixmap) +GLXAPI_ENTRY(GetSelectedEventSGIX) +GLXAPI_ENTRY(GetCurrentReadDrawable) +GLXAPI_ENTRY(GetCurrentDisplay) +GLXAPI_ENTRY(QueryServerString) +GLXAPI_ENTRY(CreateWindow) +GLXAPI_ENTRY(SelectEvent) +GLXAPI_ENTRY(GetVisualFromFBConfigSGIX) +GLXAPI_ENTRY(GetFBConfigFromVisualSGIX) +GLXAPI_ENTRY(QueryDrawable) +GLXAPI_ENTRY(CreateContext) +GLXAPI_ENTRY(GetConfig) +GLXAPI_ENTRY(CreateGLXPbufferSGIX) +GLXAPI_ENTRY(CreatePbuffer) +GLXAPI_ENTRY(ChooseFBConfigSGIX) +GLXAPI_ENTRY(WaitX) +GLXAPI_ENTRY(GetVisualFromFBConfig) +/*GLXAPI_ENTRY(GetScreenDriver)*/ +GLXAPI_ENTRY(GetFBConfigAttrib) +GLXAPI_ENTRY(GetCurrentContext) +GLXAPI_ENTRY(GetClientString) +GLXAPI_ENTRY(DestroyPixmap) +GLXAPI_ENTRY(MakeCurrent) +GLXAPI_ENTRY(DestroyContext) +GLXAPI_ENTRY(GetProcAddressARB) +GLXAPI_ENTRY(GetSelectedEvent) +GLXAPI_ENTRY(DestroyPbuffer) +GLXAPI_ENTRY(DestroyWindow) +GLXAPI_ENTRY(DestroyGLXPixmap) +GLXAPI_ENTRY(QueryVersion) +GLXAPI_ENTRY(ChooseVisual) +GLXAPI_ENTRY(MakeContextCurrent) +GLXAPI_ENTRY(QueryExtensionsString) +GLXAPI_ENTRY(GetFBConfigAttribSGIX) +#ifdef VBOXOGL_FAKEDRI +GLXAPI_ENTRY(FreeMemoryMESA) +GLXAPI_ENTRY(QueryContextInfoEXT) +GLXAPI_ENTRY(ImportContextEXT) +GLXAPI_ENTRY(GetContextIDEXT) +GLXAPI_ENTRY(MakeCurrentReadSGI) +GLXAPI_ENTRY(AllocateMemoryMESA) +GLXAPI_ENTRY(GetMemoryOffsetMESA) +GLXAPI_ENTRY(CreateGLXPixmapMESA) +GLXAPI_ENTRY(GetCurrentDisplayEXT) +GLXAPI_ENTRY(FreeContextEXT) +#endif diff --git a/src/VBox/Additions/common/crOpenGL/feedback/Makefile.kup b/src/VBox/Additions/common/crOpenGL/feedback/Makefile.kup new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/feedback/Makefile.kup diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedback.def b/src/VBox/Additions/common/crOpenGL/feedback/feedback.def new file mode 100644 index 00000000..9edc7163 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/feedback/feedback.def @@ -0,0 +1,6 @@ +; Copyright (c) 2001, Stanford University +; All rights reserved. +; +; See the file LICENSE.txt for information on redistributing this software. +EXPORTS +SPULoad diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedback.py b/src/VBox/Additions/common/crOpenGL/feedback/feedback.py new file mode 100755 index 00000000..181b23fd --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/feedback/feedback.py @@ -0,0 +1,270 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - generated by feedback.py */ +#include <stdio.h> +#include "cr_spu.h" +#include "feedbackspu.h" +#include "feedbackspu_proto.h" +#include "cr_packfunctions.h" +#include "cr_glstate.h" + +""") + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +for func_name in keys: + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + if apiutil.FindSpecial( "feedback", func_name ): + print('static %s FEEDBACKSPU_APIENTRY feedbackspu_%s(%s)' % ( return_type, func_name, apiutil.MakeDeclarationString(params) )) + print('{') + print('\tfeedback_spu.super.%s(%s);' % ( func_name, apiutil.MakeCallString(params) )) + print('}') + + + +print(""" +#define CHANGE(name, func) crSPUChangeInterface((void *)&(feedback_spu.self), (void *)feedback_spu.self.name, (void *)((SPUGenericFunction) func)) +#define CHANGESWAP(name, swapfunc, regfunc) crSPUChangeInterface( (void *)&(feedback_spu.self), (void *)feedback_spu.self.name, (void *)((SPUGenericFunction) (feedback_spu.swap ? swapfunc: regfunc ))) + +static void __loadFeedbackAPI( void ) +{ +""") +for func_name in keys: + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + if apiutil.FindSpecial( "feedback", func_name ): + print('\tCHANGE(%s, crStateFeedback%s);' % (func_name, func_name )) +print(""" +} + +static void __loadSelectAPI( void ) +{ +""") +for func_name in keys: + if apiutil.FindSpecial( "select", func_name ): + print('\tCHANGE(%s, crStateSelect%s);' % (func_name, func_name )) + elif apiutil.FindSpecial( "feedback", func_name ): + print('\tCHANGE(%s, feedbackspu_%s);' % (func_name, func_name )) +print(""" +} + +static void __loadRenderAPI( void ) +{ +""") + +for func_name in keys: + return_type = apiutil.ReturnType(func_name) + if apiutil.FindSpecial( "feedback", func_name ) or apiutil.FindSpecial( "select", func_name ): + print('\tCHANGE(%s, feedbackspu_%s);' % (func_name, func_name )) +print(""" +} +""") + +print(""" +static GLint FEEDBACKSPU_APIENTRY feedbackspu_RenderMode ( GLenum mode ) +{ + feedback_spu.render_mode = mode; + + switch (mode) { + case GL_FEEDBACK: + /*printf("Switching to Feedback API\\n");*/ + __loadFeedbackAPI( ); + break; + case GL_SELECT: + /*printf("Switching to Selection API\\n");*/ + __loadSelectAPI( ); + break; + case GL_RENDER: + /*printf("Switching to Render API\\n");*/ + __loadRenderAPI( ); + break; + } + + return crStateRenderMode( mode ); +} + +static void FEEDBACKSPU_APIENTRY feedbackspu_Begin ( GLenum mode ) +{ + if (feedback_spu.render_mode == GL_FEEDBACK) + crStateFeedbackBegin( mode ); + else if (feedback_spu.render_mode == GL_SELECT) + crStateSelectBegin( mode ); + else + { + crStateBegin( mode ); + feedback_spu.super.Begin( mode ); + } +} + +static void FEEDBACKSPU_APIENTRY feedbackspu_End ( void ) +{ + if (feedback_spu.render_mode == GL_FEEDBACK) + crStateFeedbackEnd( ); + else if (feedback_spu.render_mode == GL_SELECT) + crStateSelectEnd( ); + else + { + crStateEnd( ); + feedback_spu.super.End( ); + } +} + +static void FEEDBACKSPU_APIENTRY feedbackspu_Bitmap ( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap ) +{ + crStateBitmap( width, height, xorig, yorig, xmove, ymove, bitmap ); + + if (feedback_spu.render_mode == GL_FEEDBACK) + crStateFeedbackBitmap( width, height, xorig, yorig, xmove, ymove, bitmap ); + else if (feedback_spu.render_mode == GL_SELECT) + crStateSelectBitmap( width, height, xorig, yorig, xmove, ymove, bitmap ); + else + feedback_spu.super.Bitmap( width, height, xorig, yorig, xmove, ymove, bitmap ); +} + +static void FEEDBACKSPU_APIENTRY feedbackspu_CopyPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLenum type ) +{ + if (feedback_spu.render_mode == GL_FEEDBACK) + crStateFeedbackCopyPixels( x, y, width, height, type ); + else if (feedback_spu.render_mode == GL_SELECT) + crStateSelectCopyPixels( x, y, width, height, type ); + else + feedback_spu.super.CopyPixels( x, y, width, height, type ); +} + +static void FEEDBACKSPU_APIENTRY feedbackspu_DrawPixels( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) +{ + if (feedback_spu.render_mode == GL_FEEDBACK) + crStateFeedbackDrawPixels( width, height, format, type, pixels ); + else if (feedback_spu.render_mode == GL_SELECT) + crStateSelectDrawPixels( width, height, format, type, pixels ); + else + feedback_spu.super.DrawPixels( width, height, format, type, pixels ); +} + +static void FEEDBACKSPU_APIENTRY feedbackspu_GetBooleanv( GLenum pname, GLboolean *params ) + +{ + if (pname == GL_FEEDBACK_BUFFER_SIZE || + pname == GL_FEEDBACK_BUFFER_TYPE || + pname == GL_SELECTION_BUFFER_SIZE) + crStateFeedbackGetBooleanv( pname, params ); + else + if (pname == GL_VIEWPORT && feedback_spu.default_viewport) + crStateGetBooleanv( pname, params ); + else + feedback_spu.super.GetBooleanv( pname, params ); +} + +static void FEEDBACKSPU_APIENTRY feedbackspu_GetDoublev( GLenum pname, GLdouble *params ) + +{ + if (pname == GL_FEEDBACK_BUFFER_SIZE || + pname == GL_FEEDBACK_BUFFER_TYPE || + pname == GL_SELECTION_BUFFER_SIZE) + crStateFeedbackGetDoublev( pname, params ); + else + if (pname == GL_VIEWPORT && feedback_spu.default_viewport) + crStateGetDoublev( pname, params ); + else + feedback_spu.super.GetDoublev( pname, params ); +} + +static void FEEDBACKSPU_APIENTRY feedbackspu_GetFloatv( GLenum pname, GLfloat *params ) + +{ + if (pname == GL_FEEDBACK_BUFFER_SIZE || + pname == GL_FEEDBACK_BUFFER_TYPE || + pname == GL_SELECTION_BUFFER_SIZE) + crStateFeedbackGetFloatv( pname, params ); + else + if (pname == GL_VIEWPORT && feedback_spu.default_viewport) + crStateGetFloatv( pname, params ); + else + feedback_spu.super.GetFloatv( pname, params ); +} + +static void FEEDBACKSPU_APIENTRY feedbackspu_GetIntegerv( GLenum pname, GLint *params ) + +{ + if (pname == GL_FEEDBACK_BUFFER_SIZE || + pname == GL_FEEDBACK_BUFFER_TYPE || + pname == GL_SELECTION_BUFFER_SIZE) + crStateFeedbackGetIntegerv( pname, params ); + else + if (pname == GL_VIEWPORT && feedback_spu.default_viewport) + crStateGetIntegerv( pname, params ); + else + feedback_spu.super.GetIntegerv( pname, params ); +} + +SPUNamedFunctionTable _cr_feedback_table[] = { +""") + +for func_name in keys: + if apiutil.FindSpecial( "feedback_state", func_name ): + print('\t{ "%s", (SPUGenericFunction) feedbackspu_%s }, ' % ( func_name, func_name )) +print(""" + { "GetBooleanv", (SPUGenericFunction) feedbackspu_GetBooleanv }, + { "GetDoublev", (SPUGenericFunction) feedbackspu_GetDoublev }, + { "GetFloatv", (SPUGenericFunction) feedbackspu_GetFloatv }, + { "GetIntegerv", (SPUGenericFunction) feedbackspu_GetIntegerv }, + { "FeedbackBuffer", (SPUGenericFunction) crStateFeedbackBuffer }, + { "SelectBuffer", (SPUGenericFunction) crStateSelectBuffer }, + { "InitNames", (SPUGenericFunction) crStateInitNames }, + { "LoadName", (SPUGenericFunction) crStateLoadName }, + { "PushName", (SPUGenericFunction) crStatePushName }, + { "PopName", (SPUGenericFunction) crStatePopName }, + { "Begin", (SPUGenericFunction) feedbackspu_Begin }, + { "End", (SPUGenericFunction) feedbackspu_End }, + { "Bitmap", (SPUGenericFunction) feedbackspu_Bitmap }, + { "CopyPixels", (SPUGenericFunction) feedbackspu_CopyPixels }, + { "DrawPixels", (SPUGenericFunction) feedbackspu_DrawPixels }, + { "TexCoord1d", (SPUGenericFunction) feedbackspu_TexCoord1d }, + { "TexCoord1dv", (SPUGenericFunction) feedbackspu_TexCoord1dv }, + { "TexCoord1f", (SPUGenericFunction) feedbackspu_TexCoord1f }, + { "TexCoord1fv", (SPUGenericFunction) feedbackspu_TexCoord1fv }, + { "TexCoord1s", (SPUGenericFunction) feedbackspu_TexCoord1s }, + { "TexCoord1sv", (SPUGenericFunction) feedbackspu_TexCoord1sv }, + { "TexCoord1i", (SPUGenericFunction) feedbackspu_TexCoord1i }, + { "TexCoord1iv", (SPUGenericFunction) feedbackspu_TexCoord1iv }, + { "TexCoord2d", (SPUGenericFunction) feedbackspu_TexCoord2d }, + { "TexCoord2dv", (SPUGenericFunction) feedbackspu_TexCoord2dv }, + { "TexCoord2f", (SPUGenericFunction) feedbackspu_TexCoord2f }, + { "TexCoord2fv", (SPUGenericFunction) feedbackspu_TexCoord2fv }, + { "TexCoord2s", (SPUGenericFunction) feedbackspu_TexCoord2s }, + { "TexCoord2sv", (SPUGenericFunction) feedbackspu_TexCoord2sv }, + { "TexCoord2i", (SPUGenericFunction) feedbackspu_TexCoord2i }, + { "TexCoord2iv", (SPUGenericFunction) feedbackspu_TexCoord2iv }, + { "TexCoord3d", (SPUGenericFunction) feedbackspu_TexCoord3d }, + { "TexCoord3dv", (SPUGenericFunction) feedbackspu_TexCoord3dv }, + { "TexCoord3f", (SPUGenericFunction) feedbackspu_TexCoord3f }, + { "TexCoord3fv", (SPUGenericFunction) feedbackspu_TexCoord3fv }, + { "TexCoord3s", (SPUGenericFunction) feedbackspu_TexCoord3s }, + { "TexCoord3sv", (SPUGenericFunction) feedbackspu_TexCoord3sv }, + { "TexCoord3i", (SPUGenericFunction) feedbackspu_TexCoord3i }, + { "TexCoord3iv", (SPUGenericFunction) feedbackspu_TexCoord3iv }, + { "TexCoord4d", (SPUGenericFunction) feedbackspu_TexCoord4d }, + { "TexCoord4dv", (SPUGenericFunction) feedbackspu_TexCoord4dv }, + { "TexCoord4f", (SPUGenericFunction) feedbackspu_TexCoord4f }, + { "TexCoord4fv", (SPUGenericFunction) feedbackspu_TexCoord4fv }, + { "TexCoord4s", (SPUGenericFunction) feedbackspu_TexCoord4s }, + { "TexCoord4sv", (SPUGenericFunction) feedbackspu_TexCoord4sv }, + { "TexCoord4i", (SPUGenericFunction) feedbackspu_TexCoord4i }, + { "TexCoord4iv", (SPUGenericFunction) feedbackspu_TexCoord4iv }, + { "RenderMode", (SPUGenericFunction) feedbackspu_RenderMode }, + { NULL, NULL } +}; +""") diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedback_context.c b/src/VBox/Additions/common/crOpenGL/feedback/feedback_context.c new file mode 100644 index 00000000..11158b5a --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/feedback/feedback_context.c @@ -0,0 +1,131 @@ +/* $Id: feedback_context.c $ */ +/** @file + * VBox feedback spu, context tracking. + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include "cr_spu.h" +#include "cr_error.h" +#include "feedbackspu.h" + +/** @todo r=bird: None of the code here is referenced externally, so I've + * just prototyped the function here at the top of the file to make + * the compiler happy. */ +GLint FEEDBACKSPU_APIENTRY feedbackspu_VBoxCreateContext( GLint con, const char *dpyName, GLint visual, GLint shareCtx ); +GLint FEEDBACKSPU_APIENTRY feedbackspu_CreateContext( const char *dpyName, GLint visual, GLint shareCtx ); +void FEEDBACKSPU_APIENTRY feedbackspu_MakeCurrent( GLint window, GLint nativeWindow, GLint ctx ); +void FEEDBACKSPU_APIENTRY feedbackspu_DestroyContext( GLint ctx ); + + +/** @todo Multithreading case. (See feedback_spu.self.RenderMode)*/ + +GLint FEEDBACKSPU_APIENTRY +feedbackspu_VBoxCreateContext( GLint con, const char *dpyName, GLint visual, GLint shareCtx ) +{ + GLint ctx, slot; + +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&feedback_spu.mutex); +#endif + + ctx = feedback_spu.child.VBoxCreateContext(con, dpyName, visual, shareCtx); + + /* find an empty context slot */ + for (slot = 0; slot < feedback_spu.numContexts; slot++) { + if (!feedback_spu.context[slot].clientState) { + /* found empty slot */ + break; + } + } + if (slot == feedback_spu.numContexts) { + feedback_spu.numContexts++; + } + + feedback_spu.context[slot].clientState = crStateCreateContext(NULL, visual, NULL); + feedback_spu.context[slot].clientCtx = ctx; + +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&feedback_spu.mutex); +#endif + + return ctx; +} + +GLint FEEDBACKSPU_APIENTRY +feedbackspu_CreateContext( const char *dpyName, GLint visual, GLint shareCtx ) +{ + return feedbackspu_VBoxCreateContext( 0, dpyName, visual, shareCtx ); +} + +void FEEDBACKSPU_APIENTRY +feedbackspu_MakeCurrent( GLint window, GLint nativeWindow, GLint ctx ) +{ +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&feedback_spu.mutex); +#endif + feedback_spu.child.MakeCurrent(window, nativeWindow, ctx); + + if (ctx) { + int slot; + GLint oldmode; + + for (slot=0; slot<feedback_spu.numContexts; ++slot) + if (feedback_spu.context[slot].clientCtx == ctx) break; + CRASSERT(slot < feedback_spu.numContexts); + + crStateMakeCurrent(feedback_spu.context[slot].clientState); + + crStateGetIntegerv(GL_RENDER_MODE, &oldmode); + + if (oldmode!=feedback_spu.render_mode) + { + feedback_spu.self.RenderMode(oldmode); + } + } + else + { + crStateMakeCurrent(NULL); + } + +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&feedback_spu.mutex); +#endif +} + +void FEEDBACKSPU_APIENTRY +feedbackspu_DestroyContext( GLint ctx ) +{ +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&feedback_spu.mutex); +#endif + feedback_spu.child.DestroyContext(ctx); + + if (ctx) { + int slot; + + for (slot=0; slot<feedback_spu.numContexts; ++slot) + if (feedback_spu.context[slot].clientCtx == ctx) break; + CRASSERT(slot < feedback_spu.numContexts); + + crStateDestroyContext(feedback_spu.context[slot].clientState); + + feedback_spu.context[slot].clientState = NULL; + feedback_spu.context[slot].clientCtx = 0; + } + +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&feedback_spu.mutex); +#endif +} + diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedback_funcs.py b/src/VBox/Additions/common/crOpenGL/feedback/feedback_funcs.py new file mode 100755 index 00000000..d3c40833 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/feedback/feedback_funcs.py @@ -0,0 +1,40 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - THIS FILE AUTOMATICALLY GENERATED BY feedback_funcs.py SCRIPT */ +#ifndef CR_STATE_FEEDBACK_FUNCS_H +#define CR_STATE_FEEDBACK_FUNCS_H + +#include "cr_error.h" + +#if defined(WINDOWS) +#define STATE_APIENTRY __stdcall +#else +#define STATE_APIENTRY +#endif + +#define STATE_UNUSED(x) ((void)x)""") + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +for func_name in apiutil.AllSpecials( "feedback" ): + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + print('%s STATE_APIENTRY crStateFeedback%s(%s);' % (return_type, func_name, apiutil.MakeDeclarationString(params))) + +for func_name in apiutil.AllSpecials( "select" ): + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + print('%s STATE_APIENTRY crStateSelect%s(%s);' % (return_type, func_name, apiutil.MakeDeclarationString(params))) +print('\n#endif /* CR_STATE_FEEDBACK_FUNCS_H */') diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedback_special b/src/VBox/Additions/common/crOpenGL/feedback/feedback_special new file mode 100644 index 00000000..75eb7f8f --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/feedback/feedback_special @@ -0,0 +1,64 @@ +Vertex2d +Vertex2dv +Vertex2f +Vertex2fv +Vertex2i +Vertex2iv +Vertex2s +Vertex2sv +Vertex3d +Vertex3dv +Vertex3f +Vertex3fv +Vertex3i +Vertex3iv +Vertex3s +Vertex3sv +Vertex4d +Vertex4dv +Vertex4f +Vertex4fv +Vertex4i +Vertex4iv +Vertex4s +Vertex4sv +Rectf +Recti +Rectd +Rects +Rectiv +Rectfv +Rectdv +Rectsv +TexCoord1d +TexCoord1dv +TexCoord1f +TexCoord1fv +TexCoord1i +TexCoord1iv +TexCoord1s +TexCoord1sv +TexCoord2d +TexCoord2dv +TexCoord2f +TexCoord2fv +TexCoord2i +TexCoord2iv +TexCoord2s +TexCoord2sv +TexCoord3d +TexCoord3dv +TexCoord3f +TexCoord3fv +TexCoord3i +TexCoord3iv +TexCoord3s +TexCoord3sv +TexCoord4d +TexCoord4dv +TexCoord4f +TexCoord4fv +TexCoord4i +TexCoord4iv +TexCoord4s +TexCoord4sv diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedback_state.py b/src/VBox/Additions/common/crOpenGL/feedback/feedback_state.py new file mode 100755 index 00000000..01bab425 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/feedback/feedback_state.py @@ -0,0 +1,34 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + + +apiutil.CopyrightC() + +print(""" +#include "cr_server.h" +#include "feedbackspu.h" +#include "feedbackspu_proto.h" +""") +custom = ["CreateContext", "VBoxCreateContext", "MakeCurrent", "DestroyContext"] + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +for func_name in keys: + if apiutil.FindSpecial( "feedback_state", func_name ): + if func_name in custom: + continue + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + print('%s FEEDBACKSPU_APIENTRY feedbackspu_%s(%s)' % (return_type, func_name, apiutil.MakeDeclarationString(params))) + print('{') + print('\tcrState%s(%s);' % (func_name, apiutil.MakeCallString(params))) + print('') + print('\tfeedback_spu.super.%s(%s);' % (func_name, apiutil.MakeCallString(params))) + print('}') diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedback_state_special b/src/VBox/Additions/common/crOpenGL/feedback/feedback_state_special new file mode 100644 index 00000000..15bec65d --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/feedback/feedback_state_special @@ -0,0 +1,66 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +ClipPlane +MatrixMode +LoadIdentity +PopMatrix +PushMatrix +LoadMatrixf +LoadMatrixd +MultMatrixf +MultMatrixd +LoadTransposeMatrixfARB +LoadTransposeMatrixdARB +MultTransposeMatrixfARB +MultTransposeMatrixdARB +Translatef +Translated +Rotatef +Rotated +Scalef +Scaled +Frustum +Ortho +Viewport +DepthRange +Scissor +PushAttrib +PopAttrib +PassThrough +PolygonMode +Color4f +Color4fv +Color3f +Color3fv +RasterPos2d +RasterPos2dv +RasterPos2f +RasterPos2fv +RasterPos2i +RasterPos2iv +RasterPos2s +RasterPos2sv +RasterPos3d +RasterPos3dv +RasterPos3f +RasterPos3fv +RasterPos3i +RasterPos3iv +RasterPos3s +RasterPos3sv +RasterPos4d +RasterPos4dv +RasterPos4f +RasterPos4fv +RasterPos4i +RasterPos4iv +RasterPos4s +RasterPos4sv +CreateContext +MakeCurrent +DestroyContext +VBoxAttachThread +VBoxDetachThread +VBoxCreateContext diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu.h b/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu.h new file mode 100644 index 00000000..7d72a70b --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu.h @@ -0,0 +1,58 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved. + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#ifndef GA_INCLUDED_SRC_common_crOpenGL_feedback_feedbackspu_h +#define GA_INCLUDED_SRC_common_crOpenGL_feedback_feedbackspu_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#ifdef WINDOWS +#define FEEDBACKSPU_APIENTRY __stdcall +#else +#define FEEDBACKSPU_APIENTRY +#endif + +#include "cr_spu.h" +#include "cr_timer.h" +#include "cr_glstate.h" + +typedef struct context_info_t ContextInfo; + +struct context_info_t { + CRContext *clientState; /* used to store client-side GL state */ + GLint clientCtx; /* client context ID */ +}; + +typedef struct { + int id; + int has_child; + SPUDispatchTable self, child, super; + + int render_mode; + + int default_viewport; + + CRCurrentStatePointers current; + + CRContext *defaultctx; + int numContexts; + ContextInfo context[CR_MAX_CONTEXTS]; + +#ifdef CHROMIUM_THREADSAFE + CRmutex mutex; +#endif +} feedbackSPU; + +extern feedbackSPU feedback_spu; + +extern SPUNamedFunctionTable _cr_feedback_table[]; + +extern SPUOptions feedbackSPUOptions[]; + +extern void feedbackspuGatherConfiguration( void ); + +#endif /* !GA_INCLUDED_SRC_common_crOpenGL_feedback_feedbackspu_h */ diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu.rc b/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu.rc new file mode 100644 index 00000000..b9db8122 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu.rc @@ -0,0 +1,69 @@ +/* $Id: feedbackspu.rc $ */ +/** @file + * VBoxOGLfeedbackspu - Resource file containing version info and icon. + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include <windows.h> +#include <VBox/version.h> + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VBOX_RC_FILE_VERSION + PRODUCTVERSION VBOX_RC_FILE_VERSION + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS VBOX_RC_FILE_FLAGS + FILEOS VBOX_RC_FILE_OS + FILETYPE VBOX_RC_TYPE_DRV + FILESUBTYPE VFT2_DRV_DISPLAY +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "VirtualBox crOpenGL ICD\0" + VALUE "InternalName", "VBoxOGLfeedbackpu\0" +#ifdef VBOX_WDDM_WOW64 + VALUE "OriginalFilename", "VBoxOGLfeedbackpu-x86.dll\0" +#else + VALUE "OriginalFilename", "VBoxOGLfeedbackpu.dll\0" +#endif + VALUE "CompanyName", VBOX_RC_COMPANY_NAME + VALUE "FileVersion", VBOX_RC_FILE_VERSION_STR + VALUE "LegalCopyright", VBOX_RC_LEGAL_COPYRIGHT + VALUE "ProductName", VBOX_RC_PRODUCT_NAME_GA_STR + VALUE "ProductVersion", VBOX_RC_PRODUCT_VERSION_STR + VBOX_RC_MORE_STRINGS + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +1 RCDATA +BEGIN +// Machine dependent parameters + 17, // Height of vertical thumb + 17, // Width of horizontal thumb + 2, // Icon horiz compression factor + 2, // Icon vert compression factor + 1, // Cursor horz compression factor + 1, // Cursor vert compression factor + 0, // Kanji window height + 1, // cxBorder (thickness of vertical lines) + 1 // cyBorder (thickness of horizontal lines) +END diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu_config.c b/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu_config.c new file mode 100644 index 00000000..9449a2bb --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu_config.c @@ -0,0 +1,44 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_string.h" +#include "cr_environment.h" +#include "cr_error.h" +#include "cr_mem.h" +#include "feedbackspu.h" + +#include <stdio.h> +#ifndef WINDOWS +#include <unistd.h> +#endif + +static void __setDefaults( void ) +{ + feedback_spu.render_mode = GL_RENDER; +} + +static void set_default_viewport( void *foo, const char *response ) +{ + (void) foo; + sscanf( response, "%d", &(feedback_spu.default_viewport) ); +} + +/* option, type, nr, default, min, max, title, callback + */ +SPUOptions feedbackSPUOptions[] = { + + { "default_viewport", CR_BOOL, 1, "0", "0", "1", + "Return default viewport parameters", (SPUOptionCB)set_default_viewport }, + + { NULL, CR_BOOL, 0, NULL, NULL, NULL, NULL, NULL }, + +}; + + +void feedbackspuGatherConfiguration( void ) +{ + __setDefaults(); +} diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu_init.c b/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu_init.c new file mode 100644 index 00000000..f264763c --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu_init.c @@ -0,0 +1,86 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_spu.h" +#include "cr_environment.h" +#include "cr_string.h" +#include "cr_error.h" +#include "cr_mem.h" +#include "cr_server.h" +#include "feedbackspu.h" +#include <fcntl.h> +#ifndef WINDOWS +#include <unistd.h> +#endif + +feedbackSPU feedback_spu; + +static SPUFunctions feedback_functions = { + NULL, /* CHILD COPY */ + NULL, /* DATA */ + _cr_feedback_table /* THE ACTUAL FUNCTIONS */ +}; + +static SPUFunctions *feedbackSPUInit( int id, SPU *child, SPU *self, + unsigned int context_id, + unsigned int num_contexts ) +{ + (void) context_id; + (void) num_contexts; + +#ifdef CHROMIUM_THREADSAFE + crInitMutex(&feedback_spu.mutex); +#endif + + feedback_spu.id = id; + feedback_spu.has_child = 0; + if (child) + { + crSPUInitDispatchTable( &(feedback_spu.child) ); + crSPUCopyDispatchTable( &(feedback_spu.child), &(child->dispatch_table) ); + feedback_spu.has_child = 1; + } + crSPUInitDispatchTable( &(feedback_spu.super) ); + crSPUCopyDispatchTable( &(feedback_spu.super), &(self->superSPU->dispatch_table) ); + feedbackspuGatherConfiguration(); + + /* create/init default state tracker */ + crStateInit(); + + feedback_spu.defaultctx = crStateCreateContext(NULL, 0, NULL); + crStateSetCurrent(feedback_spu.defaultctx); + + feedback_spu.numContexts = 0; + crMemZero(feedback_spu.context, CR_MAX_CONTEXTS * sizeof(ContextInfo)); + + return &feedback_functions; +} + +static void feedbackSPUSelfDispatch(SPUDispatchTable *self) +{ + crSPUInitDispatchTable( &(feedback_spu.self) ); + crSPUCopyDispatchTable( &(feedback_spu.self), self ); +} + +static int feedbackSPUCleanup(void) +{ + return 1; +} + +int SPULoad( char **name, char **super, SPUInitFuncPtr *init, + SPUSelfDispatchFuncPtr *self, SPUCleanupFuncPtr *cleanup, + SPUOptionsPtr *options, int *flags ) +{ + *name = "feedback"; + *super = "passthrough"; + *init = feedbackSPUInit; + *self = feedbackSPUSelfDispatch; + *cleanup = feedbackSPUCleanup; + *options = feedbackSPUOptions; + *flags = (SPU_NO_PACKER|SPU_NOT_TERMINAL|SPU_MAX_SERVERS_ZERO); + + return 1; +} diff --git a/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu_proto.py b/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu_proto.py new file mode 100755 index 00000000..92a5c1ce --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/feedback/feedbackspu_proto.py @@ -0,0 +1,35 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - generated by feedback.py */ + +#ifndef FEEDBACKSPU_PROTO_H +#define FEEDBACKSPU_PROTO_H + +#include "feedbackspu.h" + +""") + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +for func_name in keys: + if apiutil.FindSpecial( "feedback_state", func_name ): + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + print('extern %s FEEDBACKSPU_APIENTRY feedbackspu_%s(%s);' % (return_type, func_name, apiutil.MakeDeclarationString(params))) + + +print(""" +#endif +""") diff --git a/src/VBox/Additions/common/crOpenGL/feedback/select_special b/src/VBox/Additions/common/crOpenGL/feedback/select_special new file mode 100644 index 00000000..f35dba0a --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/feedback/select_special @@ -0,0 +1,56 @@ +Vertex2d +Vertex2dv +Vertex2f +Vertex2fv +Vertex2i +Vertex2iv +Vertex2s +Vertex2sv +Vertex3d +Vertex3dv +Vertex3f +Vertex3fv +Vertex3i +Vertex3iv +Vertex3s +Vertex3sv +Vertex4d +Vertex4dv +Vertex4f +Vertex4fv +Vertex4i +Vertex4iv +Vertex4s +Vertex4sv +Rectf +Recti +Rectd +Rects +Rectiv +Rectfv +Rectdv +Rectsv +RasterPos2d +RasterPos2dv +RasterPos2f +RasterPos2fv +RasterPos2i +RasterPos2iv +RasterPos2s +RasterPos2sv +RasterPos3d +RasterPos3dv +RasterPos3f +RasterPos3fv +RasterPos3i +RasterPos3iv +RasterPos3s +RasterPos3sv +RasterPos4d +RasterPos4dv +RasterPos4f +RasterPos4fv +RasterPos4i +RasterPos4iv +RasterPos4s +RasterPos4sv diff --git a/src/VBox/Additions/common/crOpenGL/getprocaddress.py b/src/VBox/Additions/common/crOpenGL/getprocaddress.py new file mode 100755 index 00000000..39cfdf94 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/getprocaddress.py @@ -0,0 +1,125 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - THIS FILE GENERATED BY THE getprocaddress.py SCRIPT */ + +#include "chromium.h" +#include "cr_error.h" +#include "cr_string.h" +#include "cr_version.h" +#include "stub.h" +#include "dri_glx.h" +#if defined(VBOXOGL_DRI) || defined(VBOXOGL_FAKEDRI) +#include "cr_gl.h" +#include "fakedri_drv.h" +#endif + +struct name_address { + const char *name; + CR_PROC address; +}; + +static struct name_address functions[] = { +""") + + +keys = apiutil.GetAllFunctions(sys.argv[1]+"/APIspec.txt") +for func_name in keys: + if "Chromium" == apiutil.Category(func_name): + continue + if "VBox" == apiutil.Category(func_name): + continue + if func_name == "BoundsInfoCR": + continue + if "GL_chromium" == apiutil.Category(func_name): + pass #continue + + wrap = apiutil.GetCategoryWrapper(func_name) + name = "gl" + func_name + address = "VBOXGLTAG(gl" + func_name + ")" + if wrap: + print('#ifdef CR_%s' % wrap) + print('\t{ "%s", (CR_PROC) %s },' % (name, address)) + if wrap: + print('#endif') + + +print("\t/* Chromium binding/glue functions */") + +for func_name in keys: + if (func_name == "Writeback" or + func_name == "BoundsInfoCR" or + func_name == "GetUniformsLocations" or + func_name == "GetAttribsLocations"): + continue + if apiutil.Category(func_name) == "Chromium": + print('\t{ "cr%s", (CR_PROC) cr%s },' % (func_name, func_name)) + + +print(""" + { NULL, NULL } +}; + +CR_PROC CR_APIENTRY crGetProcAddress( const char *name ) +{ + int i; + stubInit(); + + for (i = 0; functions[i].name; i++) { + if (crStrcmp(name, functions[i].name) == 0) { + return functions[i].address; + } + } + + +#define GLXAPI_ENTRY(Func) if (!crStrcmp(name, "glX"#Func)) return (CR_PROC) &VBOXGLXENTRYTAG(glX##Func); +#include "fakedri_glxfuncsList.h" +#undef GLXAPI_ENTRY + + /*CR_EXT_texture_from_pixmap*/ + if (!crStrcmp(name, "glXBindTexImageEXT")) return (CR_PROC) VBOXGLXTAG(glXBindTexImageEXT); + if (!crStrcmp(name, "glXReleaseTexImageEXT")) return (CR_PROC) VBOXGLXTAG(glXReleaseTexImageEXT); + +#if defined(Linux) && defined(CR_EXT_framebuffer_blit) + /* Hacky way to make gnome3 happy on ubuntu 11.04, even though glBlitFramebuffer is part of OpenGL 3.0 spec, + * it expects to find glBlitFramebuffer and not glBlitFramebufferEXT after checking for EXT_framebuffer_blit support. + * Untill 3.0 support, it's better to go this way instead of adding an alias to src/VBox/GuestHost/OpenGL/glapi_parser/apispec.txt. + */ + if (!crStrcmp(name, "glBlitFramebuffer")) return crGetProcAddress("glBlitFramebufferEXT"); +#endif + + if (name) crDebug("Returning NULL for %s", name); + return NULL; +} + +""") + + + +# XXX should crGetProcAddress really handle WGL/GLX functions??? + +print_foo = """ +/* As these are Windows specific (i.e. wgl), define these now.... */ +#ifdef WINDOWS + { + wglGetExtensionsStringEXTFunc_t wglGetExtensionsStringEXT = NULL; + wglChoosePixelFormatFunc_t wglChoosePixelFormatEXT = NULL; + wglGetPixelFormatAttribivEXTFunc_t wglGetPixelFormatAttribivEXT = NULL; + wglGetPixelFormatAttribfvEXTFunc_t wglGetPixelFormatAttribfvEXT = NULL; + if (!crStrcmp(name, "wglGetExtensionsStringEXT")) return (CR_PROC) wglGetExtensionsStringEXT; + if (!crStrcmp(name, "wglChoosePixelFormatEXT")) return (CR_PROC) wglChoosePixelFormatEXT; + if (!crStrcmp(name, "wglGetPixelFormatAttribivEXT")) return (CR_PROC) wglGetPixelFormatAttribivEXT; + if (!crStrcmp(name, "wglGetPixelFormatAttribfvEXT")) return (CR_PROC) wglGetPixelFormatAttribfvEXT; + } +#endif +""" diff --git a/src/VBox/Additions/common/crOpenGL/glx.c b/src/VBox/Additions/common/crOpenGL/glx.c new file mode 100644 index 00000000..eb102877 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/glx.c @@ -0,0 +1,2113 @@ +/* $Id: glx.c $ */ +/** @file + * VBox OpenGL GLX implementation + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * -------------------------------------------------------------------- + * Original copyright notice: + * + * Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +/* opengl_stub/glx.c */ +#include "chromium.h" +#include "cr_error.h" +#include "cr_spu.h" +#include "cr_mem.h" +#include "cr_string.h" +#include "stub.h" +#include "dri_glx.h" +#include "GL/internal/glcore.h" +#include "cr_glstate.h" + +#include <X11/Xregion.h> + +/* Force full pixmap update if there're more damaged regions than this number*/ +#define CR_MAX_DAMAGE_REGIONS_TRACKED 50 + +/* Force "bigger" update (full or clip) if it's reducing number of regions updated + * but doesn't increase updated area more than given number + */ +#define CR_MIN_DAMAGE_PROFIT_SIZE 64*64 + +/** @todo combine it in some other place*/ +/* Size of pack spu buffer - some delta for commands packing, see pack/packspu_config.c*/ + +/** Ramshankar: Solaris compiz fix */ +#ifdef RT_OS_SOLARIS +# define CR_MAX_TRANSFER_SIZE 20*1024*1024 +#else +# define CR_MAX_TRANSFER_SIZE 4*1024*1024 +#endif + +/** For optimizing glXMakeCurrent */ +static Display *currentDisplay = NULL; +static GLXDrawable currentDrawable = 0; +static GLXDrawable currentReadDrawable = 0; + +static void stubXshmUpdateImageRect(Display *dpy, GLXDrawable draw, GLX_Pixmap_t *pGlxPixmap, XRectangle *pRect); +static void stubQueryXDamageExtension(Display *dpy, ContextInfo *pContext); + +static bool isGLXVisual(Display *dpy, XVisualInfo *vis) +{ + return vis->visualid == XVisualIDFromVisual(DefaultVisual(dpy, vis->screen)); +} + +static GLXFBConfig fbConfigFromVisual(Display *dpy, XVisualInfo *vis) +{ + (void)dpy; + + if (!isGLXVisual(dpy, vis)) + return 0; + return (GLXFBConfig)vis->visualid; +} + +static GLXFBConfig defaultFBConfigForScreen(Display *dpy, int screen) +{ + return (GLXFBConfig) XVisualIDFromVisual(DefaultVisual(dpy, screen)); +} + +static XVisualInfo *visualInfoFromFBConfig(Display *dpy, GLXFBConfig config) +{ + XVisualInfo info, *pret; + int nret; + + info.visualid = (VisualID)config; + pret = XGetVisualInfo(dpy, VisualIDMask, &info, &nret); + if (nret == 1) + return pret; + XFree(pret); + return NULL; +} + +DECLEXPORT(XVisualInfo *) +VBOXGLXTAG(glXChooseVisual)( Display *dpy, int screen, int *attribList ) +{ + bool useRGBA = false; + int *attrib; + XVisualInfo searchvis, *pret; + int nvisuals; + stubInit(); + + for (attrib = attribList; *attrib != None; attrib++) + { + switch (*attrib) + { + case GLX_USE_GL: + /* ignored, this is mandatory */ + break; + + case GLX_BUFFER_SIZE: + /* this is for color-index visuals, which we don't support */ + attrib++; + break; + + case GLX_LEVEL: + if (attrib[1] != 0) + goto err_exit; + attrib++; + break; + + case GLX_RGBA: + useRGBA = true; + break; + + case GLX_STEREO: + goto err_exit; + /* + crWarning( "glXChooseVisual: stereo unsupported" ); + return NULL; + */ + break; + + case GLX_AUX_BUFFERS: + if (attrib[1] != 0) + goto err_exit; + attrib++; + break; + + case GLX_RED_SIZE: + case GLX_GREEN_SIZE: + case GLX_BLUE_SIZE: + if (attrib[1] > 8) + goto err_exit; + attrib++; + break; + + case GLX_ALPHA_SIZE: + if (attrib[1] > 8) + goto err_exit; + attrib++; + break; + + case GLX_DEPTH_SIZE: + if (attrib[1] > 24) + goto err_exit; + attrib++; + break; + + case GLX_STENCIL_SIZE: + if (attrib[1] > 8) + goto err_exit; + attrib++; + break; + + case GLX_ACCUM_RED_SIZE: + case GLX_ACCUM_GREEN_SIZE: + case GLX_ACCUM_BLUE_SIZE: + case GLX_ACCUM_ALPHA_SIZE: + if (attrib[1] > 16) + goto err_exit; + attrib++; + break; + + case GLX_SAMPLE_BUFFERS_SGIS: /* aka GLX_SAMPLES_ARB */ + if (attrib[1] > 0) + goto err_exit; + attrib++; + break; + case GLX_SAMPLES_SGIS: /* aka GLX_SAMPLES_ARB */ + if (attrib[1] > 0) + goto err_exit; + attrib++; + break; + + case GLX_DOUBLEBUFFER: /* @todo, check if we support it */ + break; + +#ifdef GLX_VERSION_1_3 + case GLX_X_VISUAL_TYPE: + case GLX_TRANSPARENT_TYPE_EXT: + case GLX_TRANSPARENT_INDEX_VALUE_EXT: + case GLX_TRANSPARENT_RED_VALUE_EXT: + case GLX_TRANSPARENT_GREEN_VALUE_EXT: + case GLX_TRANSPARENT_BLUE_VALUE_EXT: + case GLX_TRANSPARENT_ALPHA_VALUE_EXT: + /* ignore */ + crWarning("glXChooseVisual: ignoring attribute 0x%x", *attrib); + attrib++; + break; +#endif + + default: + crWarning( "glXChooseVisual: bad attrib=0x%x, ignoring", *attrib ); + attrib++; + //return NULL; + } + } + + if (!useRGBA) + return NULL; + + XLOCK(dpy); + searchvis.visualid = XVisualIDFromVisual(DefaultVisual(dpy, screen)); + pret = XGetVisualInfo(dpy, VisualIDMask, &searchvis, &nvisuals); + XUNLOCK(dpy); + + if (nvisuals!=1) crWarning("glXChooseVisual: XGetVisualInfo returned %i visuals for %x", nvisuals, (unsigned int) searchvis.visualid); + if (pret) + crDebug("glXChooseVisual returned %x depth=%i", (unsigned int)pret->visualid, pret->depth); + return pret; + +err_exit: + crDebug("glXChooseVisual returning NULL, due to attrib=0x%x, next=0x%x", attrib[0], attrib[1]); + return NULL; +} + +/** + ** There is a problem with glXCopyContext. + ** IRIX and Mesa both define glXCopyContext + ** to have the mask argument being a + ** GLuint. XFree 4 and oss.sgi.com + ** define it to be an unsigned long. + ** Solution: We don't support + ** glXCopyContext anyway so we'll just + ** \#ifdef out the code. + */ +DECLEXPORT(void) +VBOXGLXTAG(glXCopyContext)( Display *dpy, GLXContext src, GLXContext dst, +#if defined(AIX) || defined(PLAYSTATION2) +GLuint mask +#elif defined(SunOS) +unsigned long mask +#else +unsigned long mask +#endif +) +{ + (void) dpy; + (void) src; + (void) dst; + (void) mask; + crWarning( "Unsupported GLX Call: glXCopyContext()" ); +} + + +/** + * Get the display string for the given display pointer. + * Never return just ":0.0". In that case, prefix with our host name. + */ +static void +stubGetDisplayString( Display *dpy, char *nameResult, int maxResult ) +{ + const char *dpyName = DisplayString(dpy); + char host[1000]; + + host[0] = 0; + if (crStrlen(host) + crStrlen(dpyName) >= maxResult - 1) + { + /* return null string */ + crWarning("Very long host / display name string in stubDisplayString!"); + nameResult[0] = 0; + } + else + { + /* return host concatenated with dpyName */ + crStrcpy(nameResult, host); + crStrcat(nameResult, dpyName); + } +} + + + +DECLEXPORT(GLXContext) +VBOXGLXTAG(glXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext share, Bool direct) +{ + char dpyName[MAX_DPY_NAME]; + ContextInfo *context; + int visBits = CR_RGB_BIT | CR_DOUBLE_BIT | CR_DEPTH_BIT; /* default vis */ + + (void)vis; + stubInit(); + + CRASSERT(stub.contextTable); + + /* + { + int i, numExt; + char **list; + + list = XListExtensions(dpy, &numExt); + crDebug("X extensions [%i]:", numExt); + for (i=0; i<numExt; ++i) + { + crDebug("%s", list[i]); + } + XFreeExtensionList(list); + } + */ + + stubGetDisplayString(dpy, dpyName, MAX_DPY_NAME); + + context = stubNewContext(dpyName, visBits, UNDECIDED, (unsigned long) share); + if (!context) + return 0; + + context->dpy = dpy; + context->direct = direct; + + stubQueryXDamageExtension(dpy, context); + + return (GLXContext) context->id; +} + + +DECLEXPORT(void) VBOXGLXTAG(glXDestroyContext)( Display *dpy, GLXContext ctx ) +{ + (void) dpy; + stubDestroyContext( (unsigned long) ctx ); +} + +typedef struct _stubFindPixmapParms_t { + ContextInfo *pCtx; + GLX_Pixmap_t *pGlxPixmap; + GLXDrawable draw; +} stubFindPixmapParms_t; + +static void stubFindPixmapCB(unsigned long key, void *data1, void *data2) +{ + ContextInfo *pCtx = (ContextInfo *) data1; + stubFindPixmapParms_t *pParms = (stubFindPixmapParms_t *) data2; + GLX_Pixmap_t *pGlxPixmap = (GLX_Pixmap_t *) crHashtableSearch(pCtx->pGLXPixmapsHash, (unsigned int) pParms->draw); + (void)key; + + if (pGlxPixmap) + { + pParms->pCtx = pCtx; + pParms->pGlxPixmap = pGlxPixmap; + } +} + +DECLEXPORT(Bool) VBOXGLXTAG(glXMakeCurrent)( Display *dpy, GLXDrawable drawable, GLXContext ctx ) +{ + ContextInfo *context; + WindowInfo *window; + Bool retVal; + + /*crDebug("glXMakeCurrent(%p, 0x%x, 0x%x)", (void *) dpy, (int) drawable, (int) ctx);*/ + + /*check if passed drawable is GLXPixmap and not X Window*/ + if (drawable) + { + GLX_Pixmap_t *pGlxPixmap = (GLX_Pixmap_t *) crHashtableSearch(stub.pGLXPixmapsHash, (unsigned int) drawable); + + if (!pGlxPixmap) + { + stubFindPixmapParms_t parms; + parms.pGlxPixmap = NULL; + parms.draw = drawable; + crHashtableWalk(stub.contextTable, stubFindPixmapCB, &parms); + pGlxPixmap = parms.pGlxPixmap; + } + + if (pGlxPixmap) + { + /** @todo */ + crWarning("Unimplemented glxMakeCurrent call with GLXPixmap passed, unexpected things might happen."); + } + } + + if (ctx && drawable) + { + crHashtableLock(stub.windowTable); + crHashtableLock(stub.contextTable); + + context = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) ctx); + window = stubGetWindowInfo(dpy, drawable); + + if (context && context->type == UNDECIDED) { + XLOCK(dpy); + XSync(dpy, 0); /* sync to force window creation on the server */ + XUNLOCK(dpy); + } + } + else + { + dpy = NULL; + window = NULL; + context = NULL; + } + + currentDisplay = dpy; + currentDrawable = drawable; + + retVal = stubMakeCurrent(window, context); + + if (ctx && drawable) + { + crHashtableUnlock(stub.contextTable); + crHashtableUnlock(stub.windowTable); + } + + return retVal; +} + +DECLEXPORT(GLXPixmap) VBOXGLXTAG(glXCreateGLXPixmap)( Display *dpy, XVisualInfo *vis, Pixmap pixmap ) +{ + stubInit(); + return VBOXGLXTAG(glXCreatePixmap)(dpy, fbConfigFromVisual(dpy, vis), pixmap, NULL); +} + +DECLEXPORT(void) VBOXGLXTAG(glXDestroyGLXPixmap)( Display *dpy, GLXPixmap pix ) +{ + VBOXGLXTAG(glXDestroyPixmap)(dpy, pix); +} + +DECLEXPORT(int) VBOXGLXTAG(glXGetConfig)( Display *dpy, XVisualInfo *vis, int attrib, int *value ) +{ + if (!vis) { + /* SGI OpenGL Performer hits this */ + crWarning("glXGetConfig called with NULL XVisualInfo"); + return GLX_BAD_VISUAL; + } + + stubInit(); + + *value = 0; /* For sanity */ + + switch ( attrib ) { + + case GLX_USE_GL: + *value = isGLXVisual(dpy, vis); + break; + + case GLX_BUFFER_SIZE: + *value = 32; + break; + + case GLX_LEVEL: + *value = 0; /* for now */ + break; + + case GLX_RGBA: + *value = 1; + break; + + case GLX_DOUBLEBUFFER: + *value = 1; + break; + + case GLX_STEREO: + *value = 1; + break; + + case GLX_AUX_BUFFERS: + *value = 0; + break; + + case GLX_RED_SIZE: + *value = 8; + break; + + case GLX_GREEN_SIZE: + *value = 8; + break; + + case GLX_BLUE_SIZE: + *value = 8; + break; + + case GLX_ALPHA_SIZE: + *value = 8; + break; + + case GLX_DEPTH_SIZE: + *value = 24; + break; + + case GLX_STENCIL_SIZE: + *value = 8; + break; + + case GLX_ACCUM_RED_SIZE: + *value = 16; + break; + + case GLX_ACCUM_GREEN_SIZE: + *value = 16; + break; + + case GLX_ACCUM_BLUE_SIZE: + *value = 16; + break; + + case GLX_ACCUM_ALPHA_SIZE: + *value = 16; + break; + + case GLX_SAMPLE_BUFFERS_SGIS: + *value = 0; /* fix someday */ + break; + + case GLX_SAMPLES_SGIS: + *value = 0; /* fix someday */ + break; + + case GLX_VISUAL_CAVEAT_EXT: + *value = GLX_NONE_EXT; + break; +#if defined(SunOS) || 1 + /* + I don't think this is even a valid attribute for glxGetConfig. + No idea why this gets called under SunOS but we simply ignore it + -- jw + */ + case GLX_X_VISUAL_TYPE: + crWarning ("Ignoring Unsupported GLX Call: glxGetConfig with attrib 0x%x", attrib); + break; +#endif + + case GLX_TRANSPARENT_TYPE: + *value = GLX_NONE_EXT; + break; + case GLX_TRANSPARENT_INDEX_VALUE: + *value = 0; + break; + case GLX_TRANSPARENT_RED_VALUE: + *value = 0; + break; + case GLX_TRANSPARENT_GREEN_VALUE: + *value = 0; + break; + case GLX_TRANSPARENT_BLUE_VALUE: + *value = 0; + break; + case GLX_TRANSPARENT_ALPHA_VALUE: + *value = 0; + break; + case GLX_DRAWABLE_TYPE: + *value = GLX_WINDOW_BIT; + break; + default: + crWarning( "Unsupported GLX Call: glXGetConfig with attrib 0x%x, ignoring...", attrib ); + //return GLX_BAD_ATTRIBUTE; + *value = 0; + } + + return 0; +} + +DECLEXPORT(GLXContext) VBOXGLXTAG(glXGetCurrentContext)( void ) +{ + ContextInfo *context = stubGetCurrentContext(); + if (context) + return (GLXContext) context->id; + else + return (GLXContext) NULL; +} + +DECLEXPORT(GLXDrawable) VBOXGLXTAG(glXGetCurrentDrawable)(void) +{ + return currentDrawable; +} + +DECLEXPORT(Display *) VBOXGLXTAG(glXGetCurrentDisplay)(void) +{ + return currentDisplay; +} + +DECLEXPORT(Bool) VBOXGLXTAG(glXIsDirect)(Display *dpy, GLXContext ctx) +{ + (void) dpy; + (void) ctx; + crDebug("->glXIsDirect"); + return True; +} + +DECLEXPORT(Bool) VBOXGLXTAG(glXQueryExtension)(Display *dpy, int *errorBase, int *eventBase) +{ + (void) dpy; + (void) errorBase; + (void) eventBase; + return 1; /* You BET we do... */ +} + +DECLEXPORT(Bool) VBOXGLXTAG(glXQueryVersion)( Display *dpy, int *major, int *minor ) +{ + (void) dpy; + *major = 1; + *minor = 3; + return 1; +} + +DECLEXPORT(void) VBOXGLXTAG(glXSwapBuffers)( Display *dpy, GLXDrawable drawable ) +{ + WindowInfo *window = stubGetWindowInfo(dpy, drawable); + stubSwapBuffers( window, 0 ); +} + +DECLEXPORT(void) VBOXGLXTAG(glXUseXFont)( Font font, int first, int count, int listBase ) +{ + ContextInfo *context = stubGetCurrentContext(); + Display *dpy = context->dpy; + if (dpy) { + stubUseXFont( dpy, font, first, count, listBase ); + } + else { + dpy = XOpenDisplay(NULL); + if (!dpy) + return; + stubUseXFont( dpy, font, first, count, listBase ); + XCloseDisplay(dpy); + } +} + +DECLEXPORT(void) VBOXGLXTAG(glXWaitGL)( void ) +{ + static int first_call = 1; + + if ( first_call ) + { + crDebug( "Ignoring unsupported GLX call: glXWaitGL()" ); + first_call = 0; + } +} + +DECLEXPORT(void) VBOXGLXTAG(glXWaitX)( void ) +{ + static int first_call = 1; + + if ( first_call ) + { + crDebug( "Ignoring unsupported GLX call: glXWaitX()" ); + first_call = 0; + } +} + +DECLEXPORT(const char *) VBOXGLXTAG(glXQueryExtensionsString)( Display *dpy, int screen ) +{ + /* XXX maybe also advertise GLX_SGIS_multisample? */ + + static const char *retval = "GLX_ARB_multisample GLX_EXT_texture_from_pixmap GLX_SGIX_fbconfig GLX_ARB_get_proc_address"; + + (void) dpy; + (void) screen; + + crDebug("->glXQueryExtensionsString"); + return retval; +} + +DECLEXPORT(const char *) VBOXGLXTAG(glXGetClientString)( Display *dpy, int name ) +{ + const char *retval; + (void) dpy; + (void) name; + + switch ( name ) { + + case GLX_VENDOR: + retval = "Chromium"; + break; + + case GLX_VERSION: + retval = "1.3 Chromium"; + break; + + case GLX_EXTENSIONS: + /** @todo should be a screen not a name...but it's not used anyway*/ + retval = glXQueryExtensionsString(dpy, name); + break; + + default: + retval = NULL; + } + + return retval; +} + +DECLEXPORT(const char *) VBOXGLXTAG(glXQueryServerString)( Display *dpy, int screen, int name ) +{ + const char *retval; + (void) dpy; + (void) screen; + + switch ( name ) { + + case GLX_VENDOR: + retval = "Chromium"; + break; + + case GLX_VERSION: + retval = "1.3 Chromium"; + break; + + case GLX_EXTENSIONS: + retval = glXQueryExtensionsString(dpy, screen); + break; + + default: + retval = NULL; + } + + return retval; +} + +DECLEXPORT(CR_GLXFuncPtr) VBOXGLXTAG(glXGetProcAddressARB)( const GLubyte *name ) +{ + return (CR_GLXFuncPtr) crGetProcAddress( (const char *) name ); +} + +DECLEXPORT(CR_GLXFuncPtr) VBOXGLXTAG(glXGetProcAddress)( const GLubyte *name ) +{ + return (CR_GLXFuncPtr) crGetProcAddress( (const char *) name ); +} + + +#if GLX_EXTRAS + +DECLEXPORT(GLXPbufferSGIX) +VBOXGLXTAG(glXCreateGLXPbufferSGIX)(Display *dpy, GLXFBConfigSGIX config, + unsigned int width, unsigned int height, + int *attrib_list) +{ + (void) dpy; + (void) config; + (void) width; + (void) height; + (void) attrib_list; + crWarning("glXCreateGLXPbufferSGIX not implemented by Chromium"); + return 0; +} + +DECLEXPORT(void) VBOXGLXTAG(glXDestroyGLXPbufferSGIX)(Display *dpy, GLXPbuffer pbuf) +{ + (void) dpy; + (void) pbuf; + crWarning("glXDestroyGLXPbufferSGIX not implemented by Chromium"); +} + +DECLEXPORT(void) VBOXGLXTAG(glXSelectEventSGIX)(Display *dpy, GLXDrawable drawable, unsigned long mask) +{ + (void) dpy; + (void) drawable; + (void) mask; +} + +DECLEXPORT(void) VBOXGLXTAG(glXGetSelectedEventSGIX)(Display *dpy, GLXDrawable drawable, unsigned long *mask) +{ + (void) dpy; + (void) drawable; + (void) mask; +} + +DECLEXPORT(int) VBOXGLXTAG(glXQueryGLXPbufferSGIX)(Display *dpy, GLXPbuffer pbuf, + int attribute, unsigned int *value) +{ + (void) dpy; + (void) pbuf; + (void) attribute; + (void) value; + crWarning("glXQueryGLXPbufferSGIX not implemented by Chromium"); + return 0; +} + +DECLEXPORT(int) VBOXGLXTAG(glXGetFBConfigAttribSGIX)(Display *dpy, GLXFBConfig config, + int attribute, int *value) +{ + return VBOXGLXTAG(glXGetFBConfigAttrib)(dpy, config, attribute, value); +} + +DECLEXPORT(GLXFBConfigSGIX *) +VBOXGLXTAG(glXChooseFBConfigSGIX)(Display *dpy, int screen, + int *attrib_list, int *nelements) +{ + return VBOXGLXTAG(glXChooseFBConfig)(dpy, screen, attrib_list, nelements); +} + +DECLEXPORT(GLXPixmap) +VBOXGLXTAG(glXCreateGLXPixmapWithConfigSGIX)(Display *dpy, + GLXFBConfig config, + Pixmap pixmap) +{ + return VBOXGLXTAG(glXCreatePixmap)(dpy, config, pixmap, NULL); +} + +DECLEXPORT(GLXContext) +VBOXGLXTAG(glXCreateContextWithConfigSGIX)(Display *dpy, GLXFBConfig config, + int render_type, + GLXContext share_list, + Bool direct) +{ + (void)config; + if (render_type!=GLX_RGBA_TYPE_SGIX) + { + crWarning("glXCreateContextWithConfigSGIX: Unsupported render type %i", render_type); + return NULL; + } + return VBOXGLXTAG(glXCreateContext)(dpy, NULL, share_list, direct); +} + +DECLEXPORT(XVisualInfo *) +VBOXGLXTAG(glXGetVisualFromFBConfigSGIX)(Display *dpy, + GLXFBConfig config) +{ + return visualInfoFromFBConfig(dpy, config); +} + +DECLEXPORT(GLXFBConfigSGIX) +VBOXGLXTAG(glXGetFBConfigFromVisualSGIX)(Display *dpy, XVisualInfo *vis) +{ + if (!vis) + { + return NULL; + } + /*Note: Caller is supposed to call XFree on returned value, so can't just return (GLXFBConfig)vis->visualid*/ + return (GLXFBConfigSGIX) visualInfoFromFBConfig(dpy, fbConfigFromVisual(dpy, vis)); +} + +/* + * GLX 1.3 functions + */ +DECLEXPORT(GLXFBConfig *) +VBOXGLXTAG(glXChooseFBConfig)(Display *dpy, int screen, ATTRIB_TYPE *attrib_list, int *nelements) +{ + ATTRIB_TYPE *attrib; + intptr_t fbconfig = 0; + + stubInit(); + + if (!attrib_list) + { + return VBOXGLXTAG(glXGetFBConfigs)(dpy, screen, nelements); + } + + for (attrib = attrib_list; *attrib != None; attrib++) + { + switch (*attrib) + { + case GLX_FBCONFIG_ID: + fbconfig = attrib[1]; + attrib++; + break; + + case GLX_BUFFER_SIZE: + /* this is ignored except for color-index visuals, which we don't support */ + attrib++; + break; + + case GLX_LEVEL: + if (attrib[1] != 0) + goto err_exit; + attrib++; + break; + + case GLX_AUX_BUFFERS: + if (attrib[1] != 0) + goto err_exit; + attrib++; + break; + + case GLX_DOUBLEBUFFER: /* @todo, check if we support it */ + attrib++; + break; + + case GLX_STEREO: + if (attrib[1] != 0) + goto err_exit; + attrib++; + break; + + case GLX_RED_SIZE: + case GLX_GREEN_SIZE: + case GLX_BLUE_SIZE: + case GLX_ALPHA_SIZE: + if (attrib[1] > 8) + goto err_exit; + attrib++; + break; + + case GLX_DEPTH_SIZE: + if (attrib[1] > 24) + goto err_exit; + attrib++; + break; + + case GLX_STENCIL_SIZE: + if (attrib[1] > 8) + goto err_exit; + attrib++; + break; + + case GLX_ACCUM_RED_SIZE: + case GLX_ACCUM_GREEN_SIZE: + case GLX_ACCUM_BLUE_SIZE: + case GLX_ACCUM_ALPHA_SIZE: + if (attrib[1] > 16) + goto err_exit; + attrib++; + break; + + case GLX_X_RENDERABLE: + case GLX_CONFIG_CAVEAT: + attrib++; + break; + + case GLX_RENDER_TYPE: + if (attrib[1]!=GLX_RGBA_BIT) + goto err_exit; + attrib++; + break; + + case GLX_DRAWABLE_TYPE: + if ( !(attrib[1] & GLX_WINDOW_BIT) + && !(attrib[1] & GLX_PIXMAP_BIT)) + goto err_exit; + attrib++; + break; + + case GLX_X_VISUAL_TYPE: + case GLX_TRANSPARENT_TYPE_EXT: + case GLX_TRANSPARENT_INDEX_VALUE_EXT: + case GLX_TRANSPARENT_RED_VALUE_EXT: + case GLX_TRANSPARENT_GREEN_VALUE_EXT: + case GLX_TRANSPARENT_BLUE_VALUE_EXT: + case GLX_TRANSPARENT_ALPHA_VALUE_EXT: + /* ignore */ + crWarning("glXChooseVisual: ignoring attribute 0x%x", *attrib); + attrib++; + break; + + break; + default: + crWarning( "glXChooseVisual: bad attrib=0x%x, ignoring", *attrib ); + attrib++; + break; + } + } + + if (fbconfig) + { + GLXFBConfig *pGLXFBConfigs; + + *nelements = 1; + pGLXFBConfigs = (GLXFBConfig *) crAlloc(*nelements * sizeof(GLXFBConfig)); + pGLXFBConfigs[0] = (GLXFBConfig)fbconfig; + return pGLXFBConfigs; + } + else + { + return VBOXGLXTAG(glXGetFBConfigs)(dpy, screen, nelements); + } + +err_exit: + crWarning("glXChooseFBConfig returning NULL, due to attrib=0x%x, next=0x%x", attrib[0], attrib[1]); + return NULL; +} + +DECLEXPORT(GLXContext) +VBOXGLXTAG(glXCreateNewContext)(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct) +{ + (void) dpy; + (void) config; + (void) render_type; + (void) share_list; + (void) direct; + + if (render_type != GLX_RGBA_TYPE) + { + crWarning("glXCreateNewContext, unsupported render_type %x", render_type); + return NULL; + } + + return VBOXGLXTAG(glXCreateContext)(dpy, NULL, share_list, direct); +} + +DECLEXPORT(GLXPbuffer) +VBOXGLXTAG(glXCreatePbuffer)(Display *dpy, GLXFBConfig config, ATTRIB_TYPE *attrib_list) +{ + (void) dpy; + (void) config; + (void) attrib_list; + crWarning("glXCreatePbuffer not implemented by Chromium"); + return 0; +} + +/* Note: there're examples where glxpixmaps are created without current context, so can't do much of the work here. + * Instead we'd do necessary initialization on first use of those pixmaps. + */ +DECLEXPORT(GLXPixmap) +VBOXGLXTAG(glXCreatePixmap)(Display *dpy, GLXFBConfig config, Pixmap pixmap, ATTRIB_TYPE *attrib_list) +{ + ATTRIB_TYPE *attrib; + GLX_Pixmap_t *pGlxPixmap; + (void) dpy; + (void) config; + +#if 0 + { + int x, y; + unsigned int w, h; + unsigned int border; + unsigned int depth; + Window root; + + crDebug("glXCreatePixmap called for %lu", pixmap); + + XLOCK(dpy); + if (!XGetGeometry(dpy, pixmap, &root, &x, &y, &w, &h, &border, &depth)) + { + XSync(dpy, False); + if (!XGetGeometry(dpy, pixmap, &root, &x, &y, &w, &h, &border, &depth)) + { + crDebug("fail"); + } + } + crDebug("root: %lu, [%i,%i %u,%u]", root, x, y, w, h); + XUNLOCK(dpy); + } +#endif + + pGlxPixmap = crCalloc(sizeof(GLX_Pixmap_t)); + if (!pGlxPixmap) + { + crWarning("glXCreatePixmap failed to allocate memory"); + return 0; + } + + pGlxPixmap->format = GL_RGBA; + pGlxPixmap->target = GL_TEXTURE_2D; + + if (attrib_list) + { + for (attrib = attrib_list; *attrib != None; attrib++) + { + switch (*attrib) + { + case GLX_TEXTURE_FORMAT_EXT: + attrib++; + switch (*attrib) + { + case GLX_TEXTURE_FORMAT_RGBA_EXT: + pGlxPixmap->format = GL_RGBA; + break; + case GLX_TEXTURE_FORMAT_RGB_EXT: + pGlxPixmap->format = GL_RGB; + break; + default: + crDebug("Unexpected GLX_TEXTURE_FORMAT_EXT 0x%x", (unsigned int) *attrib); + } + break; + case GLX_TEXTURE_TARGET_EXT: + attrib++; + switch (*attrib) + { + case GLX_TEXTURE_2D_EXT: + pGlxPixmap->target = GL_TEXTURE_2D; + break; + case GLX_TEXTURE_RECTANGLE_EXT: + pGlxPixmap->target = GL_TEXTURE_RECTANGLE_NV; + break; + default: + crDebug("Unexpected GLX_TEXTURE_TARGET_EXT 0x%x", (unsigned int) *attrib); + } + break; + default: attrib++; + } + } + } + + crHashtableAdd(stub.pGLXPixmapsHash, (unsigned int) pixmap, pGlxPixmap); + return (GLXPixmap) pixmap; +} + +DECLEXPORT(GLXWindow) +VBOXGLXTAG(glXCreateWindow)(Display *dpy, GLXFBConfig config, Window win, ATTRIB_TYPE *attrib_list) +{ + GLXFBConfig *realcfg; + int nconfigs; + (void) config; + + if (stub.wsInterface.glXGetFBConfigs) + { + realcfg = stub.wsInterface.glXGetFBConfigs(dpy, 0, &nconfigs); + if (!realcfg || nconfigs<1) + { + crWarning("glXCreateWindow !realcfg || nconfigs<1"); + return 0; + } + else + { + return stub.wsInterface.glXCreateWindow(dpy, realcfg[0], win, attrib_list); + } + } + else + { + if (attrib_list && *attrib_list!=None) + { + crWarning("Non empty attrib list in glXCreateWindow"); + return 0; + } + return (GLXWindow)win; + } +} + +DECLEXPORT(void) VBOXGLXTAG(glXDestroyPbuffer)(Display *dpy, GLXPbuffer pbuf) +{ + (void) dpy; + (void) pbuf; + crWarning("glXDestroyPbuffer not implemented by Chromium"); +} + +DECLEXPORT(void) VBOXGLXTAG(glXDestroyPixmap)(Display *dpy, GLXPixmap pixmap) +{ + stubFindPixmapParms_t parms; + + if (crHashtableSearch(stub.pGLXPixmapsHash, (unsigned int) pixmap)) + { + /*it's valid but never used glxpixmap, so simple free stored ptr*/ + crHashtableDelete(stub.pGLXPixmapsHash, (unsigned int) pixmap, crFree); + return; + } + else + { + /*it's either invalid glxpixmap or one which was already initialized, so it's stored in appropriate ctx hash*/ + parms.pCtx = NULL; + parms.pGlxPixmap = NULL; + parms.draw = pixmap; + crHashtableWalk(stub.contextTable, stubFindPixmapCB, &parms); + } + + if (!parms.pGlxPixmap) + { + crWarning("glXDestroyPixmap called for unknown glxpixmap 0x%x", (unsigned int) pixmap); + return; + } + + XLOCK(dpy); + if (parms.pGlxPixmap->gc) + { + XFreeGC(dpy, parms.pGlxPixmap->gc); + } + + if (parms.pGlxPixmap->hShmPixmap>0) + { + XFreePixmap(dpy, parms.pGlxPixmap->hShmPixmap); + } + XUNLOCK(dpy); + + if (parms.pGlxPixmap->hDamage>0) + { + //crDebug("Destroy: Damage for drawable 0x%x, handle 0x%x", (unsigned int) pixmap, (unsigned int) parms.pGlxPixmap->damage); + XDamageDestroy(dpy, parms.pGlxPixmap->hDamage); + } + + if (parms.pGlxPixmap->pDamageRegion) + { + XDestroyRegion(parms.pGlxPixmap->pDamageRegion); + } + + crHashtableDelete(parms.pCtx->pGLXPixmapsHash, (unsigned int) pixmap, crFree); +} + +DECLEXPORT(void) VBOXGLXTAG(glXDestroyWindow)(Display *dpy, GLXWindow win) +{ + (void) dpy; + (void) win; + /*crWarning("glXDestroyWindow not implemented by Chromium");*/ +} + +DECLEXPORT(GLXDrawable) VBOXGLXTAG(glXGetCurrentReadDrawable)(void) +{ + return currentReadDrawable; +} + +DECLEXPORT(int) VBOXGLXTAG(glXGetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int *value) +{ + XVisualInfo * pVisual; + const char * pExt; + + switch (attribute) + { + case GLX_DRAWABLE_TYPE: + *value = GLX_PIXMAP_BIT | GLX_WINDOW_BIT; + break; + case GLX_BIND_TO_TEXTURE_TARGETS_EXT: + *value = GLX_TEXTURE_2D_BIT_EXT; + pExt = (const char *) stub.spu->dispatch_table.GetString(GL_EXTENSIONS); + if (crStrstr(pExt, "GL_NV_texture_rectangle") + || crStrstr(pExt, "GL_ARB_texture_rectangle") + || crStrstr(pExt, "GL_EXT_texture_rectangle")) + { + *value |= GLX_TEXTURE_RECTANGLE_BIT_EXT; + } + break; + case GLX_BIND_TO_TEXTURE_RGBA_EXT: + *value = True; + break; + case GLX_BIND_TO_TEXTURE_RGB_EXT: + *value = True; + break; + case GLX_DOUBLEBUFFER: + //crDebug("attribute=GLX_DOUBLEBUFFER"); + *value = True; + break; + case GLX_Y_INVERTED_EXT: + *value = True; + break; + case GLX_ALPHA_SIZE: + //crDebug("attribute=GLX_ALPHA_SIZE"); + *value = 8; + break; + case GLX_BUFFER_SIZE: + //crDebug("attribute=GLX_BUFFER_SIZE"); + *value = 32; + break; + case GLX_STENCIL_SIZE: + //crDebug("attribute=GLX_STENCIL_SIZE"); + *value = 8; + break; + case GLX_DEPTH_SIZE: + *value = 24; + //crDebug("attribute=GLX_DEPTH_SIZE"); + break; + case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: + *value = 0; + break; + case GLX_RENDER_TYPE: + //crDebug("attribute=GLX_RENDER_TYPE"); + *value = GLX_RGBA_BIT; + break; + case GLX_CONFIG_CAVEAT: + //crDebug("attribute=GLX_CONFIG_CAVEAT"); + *value = GLX_NONE; + break; + case GLX_VISUAL_ID: + //crDebug("attribute=GLX_VISUAL_ID"); + pVisual = visualInfoFromFBConfig(dpy, config); + if (!pVisual) + { + crWarning("glXGetFBConfigAttrib for %p, failed to get XVisualInfo", config); + return GLX_BAD_ATTRIBUTE; + } + *value = pVisual->visualid; + XFree(pVisual); + break; + case GLX_FBCONFIG_ID: + *value = (int)(intptr_t)config; + break; + case GLX_RED_SIZE: + case GLX_GREEN_SIZE: + case GLX_BLUE_SIZE: + *value = 8; + break; + case GLX_LEVEL: + *value = 0; + break; + case GLX_STEREO: + *value = false; + break; + case GLX_AUX_BUFFERS: + *value = 0; + break; + case GLX_ACCUM_RED_SIZE: + case GLX_ACCUM_GREEN_SIZE: + case GLX_ACCUM_BLUE_SIZE: + case GLX_ACCUM_ALPHA_SIZE: + *value = 0; + break; + case GLX_X_VISUAL_TYPE: + *value = GLX_TRUE_COLOR; + break; + case GLX_TRANSPARENT_TYPE: + *value = GLX_NONE; + break; + case GLX_SAMPLE_BUFFERS: + case GLX_SAMPLES: + *value = 1; + break; + case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT: + *value = 0; + break; + default: + crDebug("glXGetFBConfigAttrib: unknown attribute=0x%x", attribute); + return GLX_BAD_ATTRIBUTE; + } + + return Success; +} + +DECLEXPORT(GLXFBConfig *) VBOXGLXTAG(glXGetFBConfigs)(Display *dpy, int screen, int *nelements) +{ + int i; + + GLXFBConfig *pGLXFBConfigs = crAlloc(sizeof(GLXFBConfig)); + + *nelements = 1; + XLOCK(dpy); + *pGLXFBConfigs = defaultFBConfigForScreen(dpy, screen); + XUNLOCK(dpy); + + crDebug("glXGetFBConfigs returned %i configs", *nelements); + for (i=0; i<*nelements; ++i) + { + crDebug("glXGetFBConfigs[%i]=0x%x", i, (unsigned)(uintptr_t) pGLXFBConfigs[i]); + } + return pGLXFBConfigs; +} + +DECLEXPORT(void) VBOXGLXTAG(glXGetSelectedEvent)(Display *dpy, GLXDrawable draw, unsigned long *event_mask) +{ + (void) dpy; + (void) draw; + (void) event_mask; + crWarning("glXGetSelectedEvent not implemented by Chromium"); +} + +DECLEXPORT(XVisualInfo *) VBOXGLXTAG(glXGetVisualFromFBConfig)(Display *dpy, GLXFBConfig config) +{ + return visualInfoFromFBConfig(dpy, config); +} + +DECLEXPORT(Bool) VBOXGLXTAG(glXMakeContextCurrent)(Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx) +{ + currentReadDrawable = read; + return VBOXGLXTAG(glXMakeCurrent)(display, draw, ctx); +} + +DECLEXPORT(int) VBOXGLXTAG(glXQueryContext)(Display *dpy, GLXContext ctx, int attribute, int *value) +{ + (void) dpy; + (void) ctx; + (void) attribute; + (void) value; + crWarning("glXQueryContext not implemented by Chromium"); + return 0; +} + +DECLEXPORT(void) VBOXGLXTAG(glXQueryDrawable)(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value) +{ + (void) dpy; + (void) draw; + (void) attribute; + (void) value; + crWarning("glXQueryDrawable not implemented by Chromium"); +} + +DECLEXPORT(void) VBOXGLXTAG(glXSelectEvent)(Display *dpy, GLXDrawable draw, unsigned long event_mask) +{ + (void) dpy; + (void) draw; + (void) event_mask; + crWarning("glXSelectEvent not implemented by Chromium"); +} + +#ifdef CR_EXT_texture_from_pixmap +/*typedef struct +{ + int x, y; + unsigned int w, h, border, depth; + Window root; + void *data; +} pminfo;*/ + +static void stubInitXSharedMemory(Display *dpy) +{ + int vma, vmi; + Bool pixmaps; + + if (stub.bShmInitFailed || stub.xshmSI.shmid>=0) + return; + + stub.bShmInitFailed = GL_TRUE; + + /* Check for extension and pixmaps format */ + XLOCK(dpy); + if (!XShmQueryExtension(dpy)) + { + crWarning("No XSHM extension"); + XUNLOCK(dpy); + return; + } + + if (!XShmQueryVersion(dpy, &vma, &vmi, &pixmaps) || !pixmaps) + { + crWarning("XSHM extension doesn't support pixmaps"); + XUNLOCK(dpy); + return; + } + + if (XShmPixmapFormat(dpy)!=ZPixmap) + { + crWarning("XSHM extension doesn't support ZPixmap format"); + XUNLOCK(dpy); + return; + } + XUNLOCK(dpy); + + /* Alloc shared memory, so far using hardcoded value...could fail for bigger displays one day */ + stub.xshmSI.readOnly = false; + stub.xshmSI.shmid = shmget(IPC_PRIVATE, 4*4096*2048, IPC_CREAT | 0600); + if (stub.xshmSI.shmid<0) + { + crWarning("XSHM Failed to create shared segment"); + return; + } + + stub.xshmSI.shmaddr = (char*) shmat(stub.xshmSI.shmid, NULL, 0); + if (stub.xshmSI.shmaddr==(void*)-1) + { + crWarning("XSHM Failed to attach shared segment"); + shmctl(stub.xshmSI.shmid, IPC_RMID, 0); + return; + } + + XLOCK(dpy); + if (!XShmAttach(dpy, &stub.xshmSI)) + { + crWarning("XSHM Failed to attach shared segment to XServer"); + shmctl(stub.xshmSI.shmid, IPC_RMID, 0); + shmdt(stub.xshmSI.shmaddr); + XUNLOCK(dpy); + return; + } + XUNLOCK(dpy); + + stub.bShmInitFailed = GL_FALSE; + crInfo("Using XSHM for GLX_EXT_texture_from_pixmap"); + + /*Anyway mark to be deleted when our process detaches it, in case of segfault etc*/ + +/* Ramshankar: Solaris compiz fix */ +#ifndef RT_OS_SOLARIS + shmctl(stub.xshmSI.shmid, IPC_RMID, 0); +#endif +} + +void stubQueryXDamageExtension(Display *dpy, ContextInfo *pContext) +{ + int erb, vma, vmi; + + CRASSERT(pContext); + + if (pContext->damageQueryFailed) + return; + + pContext->damageQueryFailed = True; + + if (!XDamageQueryExtension(dpy, &pContext->damageEventsBase, &erb) + || !XDamageQueryVersion(dpy, &vma, &vmi)) + { + crWarning("XDamage not found or old version (%i.%i), going to run *very* slow", vma, vmi); + return; + } + + crDebug("XDamage %i.%i", vma, vmi); + pContext->damageQueryFailed = False; +} + +static void stubFetchDamageOnDrawable(Display *dpy, GLX_Pixmap_t *pGlxPixmap) +{ + Damage damage = pGlxPixmap->hDamage; + + if (damage) + { + XRectangle *returnRects; + int nReturnRects; + + /* Get the damage region as a server region */ + XserverRegion serverDamageRegion = XFixesCreateRegion (dpy, NULL, 0); + + /* Unite damage region with server region and clear damage region */ + XDamageSubtract (dpy, + damage, + None, /* subtract all damage from this region */ + serverDamageRegion /* save in serverDamageRegion */); + + /* Fetch damage rectangles */ + returnRects = XFixesFetchRegion (dpy, serverDamageRegion, &nReturnRects); + + /* Delete region */ + XFixesDestroyRegion (dpy, serverDamageRegion); + + if (pGlxPixmap->pDamageRegion) + { + /* If it's dirty and regions are empty, it marked for full update, so do nothing.*/ + if (!pGlxPixmap->bPixmapImageDirty || !XEmptyRegion(pGlxPixmap->pDamageRegion)) + { + int i = 0; + for (; i < nReturnRects; ++i) + { + if (CR_MAX_DAMAGE_REGIONS_TRACKED <= pGlxPixmap->pDamageRegion->numRects) + { + /* Mark for full update */ + EMPTY_REGION(pGlxPixmap->pDamageRegion); + } + else + { + /* Add to damage regions */ + XUnionRectWithRegion(&returnRects[i], pGlxPixmap->pDamageRegion, pGlxPixmap->pDamageRegion); + } + } + } + } + + XFree(returnRects); + + pGlxPixmap->bPixmapImageDirty = True; + } +} + +static const CRPixelPackState defaultPacking = +{ + 0, /*rowLength*/ + 0, /*skipRows*/ + 0, /*skipPixels*/ + 1, /*alignment*/ + 0, /*imageHeight*/ + 0, /*skipImages*/ + GL_FALSE, /*swapBytes*/ + GL_FALSE /*lsbFirst*/ +}; + +static void stubGetUnpackState(CRPixelPackState *pUnpackState) +{ + stub.spu->dispatch_table.GetIntegerv(GL_UNPACK_ROW_LENGTH, &pUnpackState->rowLength); + stub.spu->dispatch_table.GetIntegerv(GL_UNPACK_SKIP_ROWS, &pUnpackState->skipRows); + stub.spu->dispatch_table.GetIntegerv(GL_UNPACK_SKIP_PIXELS, &pUnpackState->skipPixels); + stub.spu->dispatch_table.GetIntegerv(GL_UNPACK_ALIGNMENT, &pUnpackState->alignment); + stub.spu->dispatch_table.GetBooleanv(GL_UNPACK_SWAP_BYTES, &pUnpackState->swapBytes); + stub.spu->dispatch_table.GetBooleanv(GL_UNPACK_LSB_FIRST, &pUnpackState->psLSBFirst); +} + +static void stubSetUnpackState(const CRPixelPackState *pUnpackState) +{ + stub.spu->dispatch_table.PixelStorei(GL_UNPACK_ROW_LENGTH, pUnpackState->rowLength); + stub.spu->dispatch_table.PixelStorei(GL_UNPACK_SKIP_ROWS, pUnpackState->skipRows); + stub.spu->dispatch_table.PixelStorei(GL_UNPACK_SKIP_PIXELS, pUnpackState->skipPixels); + stub.spu->dispatch_table.PixelStorei(GL_UNPACK_ALIGNMENT, pUnpackState->alignment); + stub.spu->dispatch_table.PixelStorei(GL_UNPACK_SWAP_BYTES, pUnpackState->swapBytes); + stub.spu->dispatch_table.PixelStorei(GL_UNPACK_LSB_FIRST, pUnpackState->psLSBFirst); +} + +static GLX_Pixmap_t* stubInitGlxPixmap(GLX_Pixmap_t* pCreateInfoPixmap, Display *dpy, GLXDrawable draw, ContextInfo *pContext) +{ + int x, y; + unsigned int w, h; + unsigned int border; + unsigned int depth; + Window root; + GLX_Pixmap_t *pGlxPixmap; + + CRASSERT(pContext && pCreateInfoPixmap); + + XLOCK(dpy); + if (!XGetGeometry(dpy, (Pixmap)draw, &root, &x, &y, &w, &h, &border, &depth)) + { + XSync(dpy, False); + if (!XGetGeometry(dpy, (Pixmap)draw, &root, &x, &y, &w, &h, &border, &depth)) + { + crWarning("stubInitGlxPixmap failed in call to XGetGeometry for 0x%x", (int) draw); + XUNLOCK(dpy); + return NULL; + } + } + + pGlxPixmap = crAlloc(sizeof(GLX_Pixmap_t)); + if (!pGlxPixmap) + { + crWarning("stubInitGlxPixmap failed to allocate memory"); + XUNLOCK(dpy); + return NULL; + } + + pGlxPixmap->x = x; + pGlxPixmap->y = y; + pGlxPixmap->w = w; + pGlxPixmap->h = h; + pGlxPixmap->border = border; + pGlxPixmap->depth = depth; + pGlxPixmap->root = root; + pGlxPixmap->format = pCreateInfoPixmap->format; + pGlxPixmap->target = pCreateInfoPixmap->target; + + /* Try to allocate shared memory + * As we're allocating huge chunk of memory, do it in this function, only if this extension is really used + */ + if (!stub.bShmInitFailed && stub.xshmSI.shmid<0) + { + stubInitXSharedMemory(dpy); + } + + if (stub.xshmSI.shmid>=0) + { + XGCValues xgcv; + xgcv.graphics_exposures = False; + xgcv.subwindow_mode = IncludeInferiors; + pGlxPixmap->gc = XCreateGC(dpy, (Pixmap)draw, GCGraphicsExposures|GCSubwindowMode, &xgcv); + + pGlxPixmap->hShmPixmap = XShmCreatePixmap(dpy, pGlxPixmap->root, stub.xshmSI.shmaddr, &stub.xshmSI, + pGlxPixmap->w, pGlxPixmap->h, pGlxPixmap->depth); + } + else + { + pGlxPixmap->gc = NULL; + pGlxPixmap->hShmPixmap = 0; + } + XUNLOCK(dpy); + + /* If there's damage extension, then get handle for damage events related to this pixmap */ + if (!pContext->damageQueryFailed) + { + pGlxPixmap->hDamage = XDamageCreate(dpy, (Pixmap)draw, XDamageReportNonEmpty); + /*crDebug("Create: Damage for drawable 0x%x, handle 0x%x (level=%i)", + (unsigned int) draw, (unsigned int) pGlxPixmap->damage, (int) XDamageReportRawRectangles);*/ + pGlxPixmap->pDamageRegion = XCreateRegion(); + if (!pGlxPixmap->pDamageRegion) + { + crWarning("stubInitGlxPixmap failed to create empty damage region for drawable 0x%x", (unsigned int) draw); + } + + /*We have never seen this pixmap before, so mark it as dirty for first use*/ + pGlxPixmap->bPixmapImageDirty = True; + } + else + { + pGlxPixmap->hDamage = 0; + pGlxPixmap->pDamageRegion = NULL; + } + + /* glTexSubImage2D generates GL_INVALID_OP if texture array hasn't been defined by a call to glTexImage2D first. + * It's fine for small textures which would be updated in stubXshmUpdateWholeImage, but we'd never call glTexImage2D for big ones. + * Note that we're making empty texture by passing NULL as pixels pointer, so there's no overhead transferring data to host.*/ + if (CR_MAX_TRANSFER_SIZE < 4*pGlxPixmap->w*pGlxPixmap->h) + { + stub.spu->dispatch_table.TexImage2D(pGlxPixmap->target, 0, pGlxPixmap->format, pGlxPixmap->w, pGlxPixmap->h, 0, + GL_BGRA, GL_UNSIGNED_BYTE, NULL); + } + + crHashtableAdd(pContext->pGLXPixmapsHash, (unsigned int) draw, pGlxPixmap); + crHashtableDelete(stub.pGLXPixmapsHash, (unsigned int) draw, crFree); + + return pGlxPixmap; +} + +static void stubXshmUpdateWholeImage(Display *dpy, GLXDrawable draw, GLX_Pixmap_t *pGlxPixmap) +{ + /* To limit the size of transferring buffer, split bigger texture into regions + * which fit into connection buffer. Could be done in hgcm or packspu but implementation in this place allows to avoid + * unnecessary memcpy. + * This also workarounds guest driver failures when sending 6+mb texture buffers on linux. + */ + if (CR_MAX_TRANSFER_SIZE < 4*pGlxPixmap->w*pGlxPixmap->h) + { + XRectangle rect; + + rect.x = pGlxPixmap->x; + rect.y = pGlxPixmap->y; + rect.width = pGlxPixmap->w; + rect.height = CR_MAX_TRANSFER_SIZE/(4*pGlxPixmap->w); + + /*crDebug("Texture size too big, splitting in lower sized chunks. [%i,%i,%i,%i] (%i)", + pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h, rect.height);*/ + + for (; (rect.y+rect.height)<=(pGlxPixmap->y+(int)pGlxPixmap->h); rect.y+=rect.height) + { + stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect); + } + + if (rect.y!=(pGlxPixmap->y+(int)pGlxPixmap->h)) + { + rect.height=pGlxPixmap->h-rect.y; + stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect); + } + } + else + { + CRPixelPackState unpackState; + + XLOCK(dpy); + XCopyArea(dpy, (Pixmap)draw, pGlxPixmap->hShmPixmap, pGlxPixmap->gc, + pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h, 0, 0); + /* Have to make sure XCopyArea is processed */ + XSync(dpy, False); + XUNLOCK(dpy); + + stubGetUnpackState(&unpackState); + stubSetUnpackState(&defaultPacking); + stub.spu->dispatch_table.TexImage2D(pGlxPixmap->target, 0, pGlxPixmap->format, pGlxPixmap->w, pGlxPixmap->h, 0, + GL_BGRA, GL_UNSIGNED_BYTE, stub.xshmSI.shmaddr); + stubSetUnpackState(&unpackState); + /*crDebug("Sync texture for drawable 0x%x(dmg handle 0x%x) [%i,%i,%i,%i]", + (unsigned int) draw, (unsigned int)pGlxPixmap->hDamage, + pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h);*/ + } +} + +static void stubXshmUpdateImageRect(Display *dpy, GLXDrawable draw, GLX_Pixmap_t *pGlxPixmap, XRectangle *pRect) +{ + /* See comment in stubXshmUpdateWholeImage */ + if (CR_MAX_TRANSFER_SIZE < 4*pRect->width*pRect->height) + { + XRectangle rect; + + rect.x = pRect->x; + rect.y = pRect->y; + rect.width = pRect->width; + rect.height = CR_MAX_TRANSFER_SIZE/(4*pRect->width); + + /*crDebug("Region size too big, splitting in lower sized chunks. [%i,%i,%i,%i] (%i)", + pRect->x, pRect->y, pRect->width, pRect->height, rect.height);*/ + + for (; (rect.y+rect.height)<=(pRect->y+pRect->height); rect.y+=rect.height) + { + stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect); + } + + if (rect.y!=(pRect->y+pRect->height)) + { + rect.height=pRect->y+pRect->height-rect.y; + stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect); + } + } + else + { + CRPixelPackState unpackState; + + XLOCK(dpy); + XCopyArea(dpy, (Pixmap)draw, pGlxPixmap->hShmPixmap, pGlxPixmap->gc, + pRect->x, pRect->y, pRect->width, pRect->height, 0, 0); + /* Have to make sure XCopyArea is processed */ + XSync(dpy, False); + XUNLOCK(dpy); + + stubGetUnpackState(&unpackState); + stubSetUnpackState(&defaultPacking); + if (pRect->width!=pGlxPixmap->w) + { + stub.spu->dispatch_table.PixelStorei(GL_UNPACK_ROW_LENGTH, pGlxPixmap->w); + } + stub.spu->dispatch_table.TexSubImage2D(pGlxPixmap->target, 0, pRect->x, pRect->y, pRect->width, pRect->height, + GL_BGRA, GL_UNSIGNED_BYTE, stub.xshmSI.shmaddr); + stubSetUnpackState(&unpackState); + + /*crDebug("Region sync texture for drawable 0x%x(dmg handle 0x%x) [%i,%i,%i,%i]", + (unsigned int) draw, (unsigned int)pGlxPixmap->hDamage, + pRect->x, pRect->y, pRect->width, pRect->height);*/ + } +} + +#if 0 +Bool checkevents(Display *display, XEvent *event, XPointer arg) +{ + //crDebug("got type: 0x%x", event->type); + if (event->type==damage_evb+XDamageNotify) + { + ContextInfo *context = stubGetCurrentContext(); + XDamageNotifyEvent *e = (XDamageNotifyEvent *) event; + /* we're interested in pixmaps only...and those have e->drawable set to 0 or other strange value for some odd reason + * so have to walk glxpixmaps hashtable to find if we have damage event handle assigned to some pixmap + */ + /*crDebug("Event: Damage for drawable 0x%x, handle 0x%x (level=%i) [%i,%i,%i,%i]", + (unsigned int) e->drawable, (unsigned int) e->damage, (int) e->level, + e->area.x, e->area.y, e->area.width, e->area.height);*/ + CRASSERT(context); + crHashtableWalk(context->pGLXPixmapsHash, checkdamageCB, e); + } + return False; +} +#endif + +/** @todo check what error codes could we throw for failures here*/ +DECLEXPORT(void) VBOXGLXTAG(glXBindTexImageEXT)(Display *dpy, GLXDrawable draw, int buffer, const int *attrib_list) +{ + ContextInfo *context = stubGetCurrentContext(); + GLX_Pixmap_t *pGlxPixmap; + RT_NOREF(buffer, attrib_list); + + if (!context) + { + crWarning("glXBindTexImageEXT called without current context"); + return; + } + + pGlxPixmap = (GLX_Pixmap_t *) crHashtableSearch(context->pGLXPixmapsHash, (unsigned int) draw); + if (!pGlxPixmap) + { + pGlxPixmap = (GLX_Pixmap_t *) crHashtableSearch(stub.pGLXPixmapsHash, (unsigned int) draw); + if (!pGlxPixmap) + { + crDebug("Unknown drawable 0x%x in glXBindTexImageEXT!", (unsigned int) draw); + return; + } + pGlxPixmap = stubInitGlxPixmap(pGlxPixmap, dpy, draw, context); + if (!pGlxPixmap) + { + crDebug("glXBindTexImageEXT failed to get pGlxPixmap"); + return; + } + } + + /* If there's damage extension, then process incoming events as we need the information right now */ + if (!context->damageQueryFailed) + { + /* Sync connection */ + XLOCK(dpy); + XSync(dpy, False); + XUNLOCK(dpy); + + stubFetchDamageOnDrawable(dpy, pGlxPixmap); + } + + /* No shared memory? Rollback to use slow x protocol then */ + if (stub.xshmSI.shmid<0) + { + /** @todo add damage support here too*/ + XImage *pxim; + CRPixelPackState unpackState; + + XLOCK(dpy); + pxim = XGetImage(dpy, (Pixmap)draw, pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h, AllPlanes, ZPixmap); + XUNLOCK(dpy); + /*if (pxim) + { + if (!ptextable) + { + ptextable = crAllocHashtable(); + } + pm = crHashtableSearch(ptextable, (unsigned int) draw); + if (!pm) + { + pm = crCalloc(sizeof(pminfo)); + crHashtableAdd(ptextable, (unsigned int) draw, pm); + } + pm->w = w; + pm->h = h; + if (pm->data) crFree(pm->data); + pm->data = crAlloc(4*w*h); + crMemcpy(pm->data, (void*)(&(pxim->data[0])), 4*w*h); + }*/ + + if (NULL==pxim) + { + crWarning("Failed, to get pixmap data for 0x%x", (unsigned int) draw); + return; + } + + stubGetUnpackState(&unpackState); + stubSetUnpackState(&defaultPacking); + stub.spu->dispatch_table.TexImage2D(pGlxPixmap->target, 0, pGlxPixmap->format, pxim->width, pxim->height, 0, + GL_BGRA, GL_UNSIGNED_BYTE, (void*)(&(pxim->data[0]))); + stubSetUnpackState(&unpackState); + XDestroyImage(pxim); + } + else /* Use shm to get pixmap data */ + { + /* Check if we have damage extension */ + if (!context->damageQueryFailed) + { + if (pGlxPixmap->bPixmapImageDirty) + { + /* Either we failed to allocate damage region or this pixmap is marked for full update */ + if (!pGlxPixmap->pDamageRegion || XEmptyRegion(pGlxPixmap->pDamageRegion)) + { + /*crDebug("**FULL** update for 0x%x", (unsigned int)draw);*/ + stubXshmUpdateWholeImage(dpy, draw, pGlxPixmap); + } + else + { + long fullArea, damageArea=0, clipdamageArea, i; + XRectangle damageClipBox; + + fullArea = pGlxPixmap->w * pGlxPixmap->h; + XClipBox(pGlxPixmap->pDamageRegion, &damageClipBox); + clipdamageArea = damageClipBox.width * damageClipBox.height; + + //crDebug("FullSize [%i,%i,%i,%i]", pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h); + //crDebug("Clip [%i,%i,%i,%i]", damageClipBox.x, damageClipBox.y, damageClipBox.width, damageClipBox.height); + + for (i=0; i<pGlxPixmap->pDamageRegion->numRects; ++i) + { + BoxPtr pBox = &pGlxPixmap->pDamageRegion->rects[i]; + damageArea += (pBox->x2-pBox->x1)*(pBox->y2-pBox->y1); + //crDebug("Damage rect [%i,%i,%i,%i]", pBox->x1, pBox->y1, pBox->x2, pBox->y2); + } + + if (damageArea>clipdamageArea || clipdamageArea>fullArea) + { + crWarning("glXBindTexImageEXT, damage regions seems to be broken, forcing full update"); + /*crDebug("**FULL** update for 0x%x, numRect=%li, *FS*=%li, CS=%li, DS=%li", + (unsigned int)draw, pGlxPixmap->pDamageRegion->numRects, fullArea, clipdamageArea, damageArea);*/ + stubXshmUpdateWholeImage(dpy, draw, pGlxPixmap); + } + else /*We have corect damage info*/ + { + if (CR_MIN_DAMAGE_PROFIT_SIZE > (fullArea-damageArea)) + { + /*crDebug("**FULL** update for 0x%x, numRect=%li, *FS*=%li, CS=%li, DS=%li", + (unsigned int)draw, pGlxPixmap->pDamageRegion->numRects, fullArea, clipdamageArea, damageArea);*/ + stubXshmUpdateWholeImage(dpy, draw, pGlxPixmap); + } + else if (CR_MIN_DAMAGE_PROFIT_SIZE > (clipdamageArea-damageArea)) + { + /*crDebug("**PARTIAL** update for 0x%x, numRect=%li, FS=%li, *CS*=%li, DS=%li", + (unsigned int)draw, pGlxPixmap->pDamageRegion->numRects, fullArea, clipdamageArea, damageArea);*/ + stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &damageClipBox); + } + else + { + /*crDebug("**PARTIAL** update for 0x%x, numRect=*%li*, FS=%li, CS=%li, *DS*=%li", + (unsigned int)draw, pGlxPixmap->pDamageRegion->numRects, fullArea, clipdamageArea, damageArea);*/ + for (i=0; i<pGlxPixmap->pDamageRegion->numRects; ++i) + { + XRectangle rect; + BoxPtr pBox = &pGlxPixmap->pDamageRegion->rects[i]; + + rect.x = pBox->x1; + rect.y = pBox->y1; + rect.width = pBox->x2-pBox->x1; + rect.height = pBox->y2-pBox->y1; + + stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect); + } + } + } + } + + /* Clean dirty flag and damage region */ + pGlxPixmap->bPixmapImageDirty = False; + if (pGlxPixmap->pDamageRegion) + EMPTY_REGION(pGlxPixmap->pDamageRegion); + } + } + else + { + stubXshmUpdateWholeImage(dpy, draw, pGlxPixmap); + } + } +} + +DECLEXPORT(void) VBOXGLXTAG(glXReleaseTexImageEXT)(Display *dpy, GLXDrawable draw, int buffer) +{ + (void) dpy; + (void) draw; + (void) buffer; + //crDebug("glXReleaseTexImageEXT 0x%x", (unsigned int)draw); +} +#endif + +#endif /* GLX_EXTRAS */ + + +#ifdef GLX_SGIX_video_resize +/* more dummy funcs. These help when linking with older GLUTs */ + +DECLEXPORT(int) VBOXGLXTAG(glXBindChannelToWindowSGIX)(Display *dpy, int scrn, int chan, Window w) +{ + (void) dpy; + (void) scrn; + (void) chan; + (void) w; + crDebug("glXBindChannelToWindowSGIX"); + return 0; +} + +DECLEXPORT(int) VBOXGLXTAG(glXChannelRectSGIX)(Display *dpy, int scrn, int chan, int x , int y, int w, int h) +{ + (void) dpy; + (void) scrn; + (void) chan; + (void) x; + (void) y; + (void) w; + (void) h; + crDebug("glXChannelRectSGIX"); + return 0; +} + +DECLEXPORT(int) VBOXGLXTAG(glXQueryChannelRectSGIX)(Display *dpy, int scrn, int chan, int *x, int *y, int *w, int *h) +{ + (void) dpy; + (void) scrn; + (void) chan; + (void) x; + (void) y; + (void) w; + (void) h; + crDebug("glXQueryChannelRectSGIX"); + return 0; +} + +DECLEXPORT(int) VBOXGLXTAG(glXQueryChannelDeltasSGIX)(Display *dpy, int scrn, int chan, int *dx, int *dy, int *dw, int *dh) +{ + (void) dpy; + (void) scrn; + (void) chan; + (void) dx; + (void) dy; + (void) dw; + (void) dh; + crDebug("glXQueryChannelDeltasSGIX"); + return 0; +} + +DECLEXPORT(int) VBOXGLXTAG(glXChannelRectSyncSGIX)(Display *dpy, int scrn, int chan, GLenum synctype) +{ + (void) dpy; + (void) scrn; + (void) chan; + (void) synctype; + crDebug("glXChannelRectSyncSGIX"); + return 0; +} + +#endif /* GLX_SGIX_video_resize */ + +#ifdef VBOXOGL_FAKEDRI +DECLEXPORT(const char *) VBOXGLXTAG(glXGetDriverConfig)(const char *driverName) +{ + return NULL; +} + +DECLEXPORT(void) VBOXGLXTAG(glXFreeMemoryMESA)(Display *dpy, int scrn, void *pointer) +{ + (void) dpy; + (void) scrn; + (void) pointer; +} + +DECLEXPORT(GLXContext) VBOXGLXTAG(glXImportContextEXT)(Display *dpy, GLXContextID contextID) +{ + (void) dpy; + (void) contextID; + return NULL; +} + +DECLEXPORT(GLXContextID) VBOXGLXTAG(glXGetContextIDEXT)(const GLXContext ctx) +{ + (void) ctx; + return 0; +} + +DECLEXPORT(Bool) VBOXGLXTAG(glXMakeCurrentReadSGI)(Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx) +{ + return VBOXGLXTAG(glXMakeContextCurrent)(display, draw, read, ctx); +} + +DECLEXPORT(const char *) VBOXGLXTAG(glXGetScreenDriver)(Display *dpy, int scrNum) +{ + static char *screendriver = "vboxvideo"; + return screendriver; +} + +DECLEXPORT(Display *) VBOXGLXTAG(glXGetCurrentDisplayEXT)(void) +{ + return VBOXGLXTAG(glXGetCurrentDisplay()); +} + +DECLEXPORT(void) VBOXGLXTAG(glXFreeContextEXT)(Display *dpy, GLXContext ctx) +{ + VBOXGLXTAG(glXDestroyContext(dpy, ctx)); +} + +/*Mesa internal*/ +DECLEXPORT(int) VBOXGLXTAG(glXQueryContextInfoEXT)(Display *dpy, GLXContext ctx) +{ + (void) dpy; + (void) ctx; + return 0; +} + +DECLEXPORT(void *) VBOXGLXTAG(glXAllocateMemoryMESA)(Display *dpy, int scrn, + size_t size, float readFreq, + float writeFreq, float priority) +{ + (void) dpy; + (void) scrn; + (void) size; + (void) readFreq; + (void) writeFreq; + (void) priority; + return NULL; +} + +DECLEXPORT(GLuint) VBOXGLXTAG(glXGetMemoryOffsetMESA)(Display *dpy, int scrn, const void *pointer) +{ + (void) dpy; + (void) scrn; + (void) pointer; + return 0; +} + +DECLEXPORT(GLXPixmap) VBOXGLXTAG(glXCreateGLXPixmapMESA)(Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap) +{ + (void) dpy; + (void) visual; + (void) pixmap; + (void) cmap; + return 0; +} + +#endif /*VBOXOGL_FAKEDRI*/ diff --git a/src/VBox/Additions/common/crOpenGL/glx_c_exports.c b/src/VBox/Additions/common/crOpenGL/glx_c_exports.c new file mode 100644 index 00000000..c8068375 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/glx_c_exports.c @@ -0,0 +1,375 @@ +/* $Id: glx_c_exports.c $ */ +/** @file + * VirtualBox guest OpenGL DRI GLX C stubs + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include "stub.h" +#include "dri_glx.h" +#include "fakedri_drv.h" + + +#ifdef VBOXOGL_FAKEDRI +/*DECLEXPORT(void) VBOXGLXENTRYTAG(glXGetDriverConfig)(const char *driverName) +{ + return glxim.GetDriverConfig(driverName); +}*/ + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXFreeMemoryMESA)(Display *dpy, int scrn, void *pointer) +{ + return glxim.FreeMemoryMESA(dpy, scrn, pointer); +} + +DECLEXPORT(GLXContext) VBOXGLXENTRYTAG(glXImportContextEXT)(Display *dpy, GLXContextID contextID) +{ + return glxim.ImportContextEXT(dpy, contextID); +} + +DECLEXPORT(GLXContextID) VBOXGLXENTRYTAG(glXGetContextIDEXT)(const GLXContext ctx) +{ + return glxim.GetContextIDEXT(ctx); +} + +DECLEXPORT(Bool) VBOXGLXENTRYTAG(glXMakeCurrentReadSGI)(Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx) +{ + return glxim.MakeCurrentReadSGI(display, draw, read, ctx); +} + + +/*const char * VBOXGLXENTRYTAG(glXGetScreenDriver)(Display *dpy, int scrNum) +{ + return glxim.GetScreenDriver(dpy, scrNum); +}*/ + + +DECLEXPORT(Display*) VBOXGLXENTRYTAG(glXGetCurrentDisplayEXT)(void) +{ + return glxim.GetCurrentDisplayEXT(); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXFreeContextEXT)(Display *dpy, GLXContext ctx) +{ + return glxim.FreeContextEXT(dpy, ctx); +} + +/*Mesa internal*/ +DECLEXPORT(int) VBOXGLXENTRYTAG(glXQueryContextInfoEXT)(Display *dpy, GLXContext ctx) +{ + return glxim.QueryContextInfoEXT(dpy, ctx); +} + +DECLEXPORT(void *) VBOXGLXENTRYTAG(glXAllocateMemoryMESA)(Display *dpy, int scrn, + size_t size, float readFreq, + float writeFreq, float priority) +{ + return glxim.AllocateMemoryMESA(dpy, scrn, size, readFreq, writeFreq, priority); +} + +DECLEXPORT(GLuint) VBOXGLXENTRYTAG(glXGetMemoryOffsetMESA)(Display *dpy, int scrn, const void *pointer ) +{ + return glxim.GetMemoryOffsetMESA(dpy, scrn, pointer); +} + + +DECLEXPORT(GLXPixmap) VBOXGLXENTRYTAG(glXCreateGLXPixmapMESA)(Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap) +{ + return glxim.CreateGLXPixmapMESA(dpy, visual, pixmap, cmap); +} +#endif + +/*Common glX functions*/ +DECLEXPORT(void) VBOXGLXENTRYTAG(glXCopyContext)( Display *dpy, GLXContext src, GLXContext dst, unsigned long mask) +{ + return glxim.CopyContext(dpy, src, dst, mask); +} + + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXUseXFont)(Font font, int first, int count, int listBase) +{ + return glxim.UseXFont(font, first, count, listBase); +} + +DECLEXPORT(CR_GLXFuncPtr) VBOXGLXENTRYTAG(glXGetProcAddress)(const GLubyte *name) +{ + return glxim.GetProcAddress(name); +} + +DECLEXPORT(Bool) VBOXGLXENTRYTAG(glXQueryExtension)(Display *dpy, int *errorBase, int *eventBase) +{ + return glxim.QueryExtension(dpy, errorBase, eventBase); +} + +DECLEXPORT(Bool) VBOXGLXENTRYTAG(glXIsDirect)(Display *dpy, GLXContext ctx) +{ + return glxim.IsDirect(dpy, ctx); +} + +DECLEXPORT(GLXPixmap) VBOXGLXENTRYTAG(glXCreateGLXPixmap)(Display *dpy, XVisualInfo *vis, Pixmap pixmap) +{ + return glxim.CreateGLXPixmap(dpy, vis, pixmap); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXSwapBuffers)(Display *dpy, GLXDrawable drawable) +{ + return glxim.SwapBuffers(dpy, drawable); +} + + +DECLEXPORT(GLXDrawable) VBOXGLXENTRYTAG(glXGetCurrentDrawable)(void) +{ + return glxim.GetCurrentDrawable(); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXWaitGL)(void) +{ + return glxim.WaitGL(); +} + +DECLEXPORT(Display *) VBOXGLXENTRYTAG(glXGetCurrentDisplay)(void) +{ + return glxim.GetCurrentDisplay(); +} + +DECLEXPORT(const char *) VBOXGLXENTRYTAG(glXQueryServerString)(Display *dpy, int screen, int name) +{ + return glxim.QueryServerString(dpy, screen, name); +} + +DECLEXPORT(GLXContext) VBOXGLXENTRYTAG(glXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext share, Bool direct) +{ + return glxim.CreateContext(dpy, vis, share, direct); +} + +DECLEXPORT(int) VBOXGLXENTRYTAG(glXGetConfig)(Display *dpy, XVisualInfo *vis, int attrib, int *value) +{ + return glxim.GetConfig(dpy, vis, attrib, value); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXWaitX)(void) +{ + return glxim.WaitX(); +} + +DECLEXPORT(GLXContext) VBOXGLXENTRYTAG(glXGetCurrentContext)(void) +{ + return glxim.GetCurrentContext(); +} + +DECLEXPORT(const char *) VBOXGLXENTRYTAG(glXGetClientString)(Display *dpy, int name) +{ + return glxim.GetClientString(dpy, name); +} + +DECLEXPORT(Bool) VBOXGLXENTRYTAG(glXMakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx) +{ + return glxim.MakeCurrent(dpy, drawable, ctx); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXDestroyContext)(Display *dpy, GLXContext ctx) +{ + return glxim.DestroyContext(dpy, ctx); +} + +DECLEXPORT(CR_GLXFuncPtr) VBOXGLXENTRYTAG(glXGetProcAddressARB)(const GLubyte *name) +{ + return glxim.GetProcAddressARB(name); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXDestroyGLXPixmap)(Display *dpy, GLXPixmap pix) +{ + return glxim.DestroyGLXPixmap(dpy, pix); +} + +DECLEXPORT(Bool) VBOXGLXENTRYTAG(glXQueryVersion)(Display *dpy, int *major, int *minor) +{ + return glxim.QueryVersion(dpy, major, minor); +} + +DECLEXPORT(XVisualInfo *) VBOXGLXENTRYTAG(glXChooseVisual)(Display *dpy, int screen, int *attribList) +{ + return glxim.ChooseVisual(dpy, screen, attribList); +} + +DECLEXPORT(const char *) VBOXGLXENTRYTAG(glXQueryExtensionsString)(Display *dpy, int screen) +{ + return glxim.QueryExtensionsString(dpy, screen); +} + +#if GLX_EXTRAS +DECLEXPORT(GLXPbufferSGIX) VBOXGLXENTRYTAG(glXCreateGLXPbufferSGIX) +(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list) +{ + return glxim.CreateGLXPbufferSGIX(dpy, config, width, height, attrib_list); +} + +DECLEXPORT(int) VBOXGLXENTRYTAG(glXQueryGLXPbufferSGIX) +(Display *dpy, GLXPbuffer pbuf, int attribute, unsigned int *value) +{ + return glxim.QueryGLXPbufferSGIX(dpy, pbuf, attribute, value); +} + +DECLEXPORT(GLXFBConfigSGIX *) VBOXGLXENTRYTAG(glXChooseFBConfigSGIX) +(Display *dpy, int screen, int *attrib_list, int *nelements) +{ + return glxim.ChooseFBConfigSGIX(dpy, screen, attrib_list, nelements); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXDestroyGLXPbufferSGIX)(Display *dpy, GLXPbuffer pbuf) +{ + return glxim.DestroyGLXPbufferSGIX(dpy, pbuf); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXSelectEventSGIX)(Display *dpy, GLXDrawable drawable, unsigned long mask) +{ + return glxim.SelectEventSGIX(dpy, drawable, mask); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXGetSelectedEventSGIX)(Display *dpy, GLXDrawable drawable, unsigned long *mask) +{ + return glxim.GetSelectedEventSGIX(dpy, drawable, mask); +} + +DECLEXPORT(GLXFBConfigSGIX) VBOXGLXENTRYTAG(glXGetFBConfigFromVisualSGIX)(Display *dpy, XVisualInfo *vis) +{ + return glxim.GetFBConfigFromVisualSGIX(dpy, vis); +} + +DECLEXPORT(XVisualInfo *) VBOXGLXENTRYTAG(glXGetVisualFromFBConfigSGIX)(Display *dpy, GLXFBConfig config) +{ + return glxim.GetVisualFromFBConfigSGIX(dpy, config); +} + +DECLEXPORT(GLXContext) VBOXGLXENTRYTAG(glXCreateContextWithConfigSGIX) +(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct) +{ + return glxim.CreateContextWithConfigSGIX(dpy, config, render_type, share_list, direct); +} + +DECLEXPORT(GLXPixmap) VBOXGLXENTRYTAG(glXCreateGLXPixmapWithConfigSGIX)(Display *dpy, GLXFBConfig config, Pixmap pixmap) +{ + return glxim.CreateGLXPixmapWithConfigSGIX(dpy, config, pixmap); +} + +DECLEXPORT(int) VBOXGLXENTRYTAG(glXGetFBConfigAttribSGIX)(Display *dpy, GLXFBConfig config, int attribute, int *value) +{ + return glxim.GetFBConfigAttribSGIX(dpy, config, attribute, value); +} + + +/* + * GLX 1.3 functions + */ +DECLEXPORT(GLXFBConfig *) VBOXGLXENTRYTAG(glXChooseFBConfig)(Display *dpy, int screen, ATTRIB_TYPE *attrib_list, int *nelements) +{ + return glxim.ChooseFBConfig(dpy, screen, attrib_list, nelements); +} + +DECLEXPORT(GLXPbuffer) VBOXGLXENTRYTAG(glXCreatePbuffer)(Display *dpy, GLXFBConfig config, ATTRIB_TYPE *attrib_list) +{ + return glxim.CreatePbuffer(dpy, config, attrib_list); +} + +DECLEXPORT(GLXPixmap) VBOXGLXENTRYTAG(glXCreatePixmap)(Display *dpy, GLXFBConfig config, Pixmap pixmap, const ATTRIB_TYPE *attrib_list) +{ + return glxim.CreatePixmap(dpy, config, pixmap, attrib_list); +} + +DECLEXPORT(GLXWindow) VBOXGLXENTRYTAG(glXCreateWindow)(Display *dpy, GLXFBConfig config, Window win, ATTRIB_TYPE *attrib_list) +{ + return glxim.CreateWindow(dpy, config, win, attrib_list); +} + + +DECLEXPORT(GLXContext) VBOXGLXENTRYTAG(glXCreateNewContext) +(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct) +{ + return glxim.CreateNewContext(dpy, config, render_type, share_list, direct); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXDestroyPbuffer)(Display *dpy, GLXPbuffer pbuf) +{ + return glxim.DestroyPbuffer(dpy, pbuf); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXDestroyPixmap)(Display *dpy, GLXPixmap pixmap) +{ + return glxim.DestroyPixmap(dpy, pixmap); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXDestroyWindow)(Display *dpy, GLXWindow win) +{ + return glxim.DestroyWindow(dpy, win); +} + +DECLEXPORT(GLXDrawable) VBOXGLXENTRYTAG(glXGetCurrentReadDrawable)(void) +{ + return glxim.GetCurrentReadDrawable(); +} + +DECLEXPORT(int) VBOXGLXENTRYTAG(glXGetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int *value) +{ + return glxim.GetFBConfigAttrib(dpy, config, attribute, value); +} + +DECLEXPORT(GLXFBConfig *) VBOXGLXENTRYTAG(glXGetFBConfigs)(Display *dpy, int screen, int *nelements) +{ + return glxim.GetFBConfigs(dpy, screen, nelements); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXGetSelectedEvent)(Display *dpy, GLXDrawable draw, unsigned long *event_mask) +{ + return glxim.GetSelectedEvent(dpy, draw, event_mask); +} + +DECLEXPORT(XVisualInfo *) VBOXGLXENTRYTAG(glXGetVisualFromFBConfig)(Display *dpy, GLXFBConfig config) +{ + return glxim.GetVisualFromFBConfig(dpy, config); +} + +DECLEXPORT(Bool) VBOXGLXENTRYTAG(glXMakeContextCurrent)(Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx) +{ + return glxim.MakeContextCurrent(display, draw, read, ctx); +} + +DECLEXPORT(int) VBOXGLXENTRYTAG(glXQueryContext)(Display *dpy, GLXContext ctx, int attribute, int *value) +{ + return glxim.QueryContext(dpy, ctx, attribute, value); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXQueryDrawable)(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value) +{ + return glxim.QueryDrawable(dpy, draw, attribute, value); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXSelectEvent)(Display *dpy, GLXDrawable draw, unsigned long event_mask) +{ + return glxim.SelectEvent(dpy, draw, event_mask); +} + +/* +#ifdef CR_EXT_texture_from_pixmap +DECLEXPORT(void) VBOXGLXENTRYTAG(glXBindTexImageEXT)(Display *dpy, GLXDrawable draw, int buffer, const int *attrib_list) +{ + return glxim.BindTexImageEXT(dpy, draw, buffer, attrib_list); +} + +DECLEXPORT(void) VBOXGLXENTRYTAG(glXReleaseTexImageEXT)(Display *dpy, GLXDrawable draw, int buffer) +{ + return glxim.ReleaseTexImageEXT(dpy, draw, buffer); +} +#endif +*/ + +#endif /* GLX_EXTRAS */ + diff --git a/src/VBox/Additions/common/crOpenGL/glx_proto.h b/src/VBox/Additions/common/crOpenGL/glx_proto.h new file mode 100644 index 00000000..ee35dce1 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/glx_proto.h @@ -0,0 +1,149 @@ +/* $Id: glx_proto.h $ */ +/** @file + * VirtualBox guest OpenGL DRI GLX header C prototypes + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#ifndef GA_INCLUDED_SRC_common_crOpenGL_glx_proto_h +#define GA_INCLUDED_SRC_common_crOpenGL_glx_proto_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "chromium.h" +#include "stub.h" + +#if defined(VBOXOGL_FAKEDRI) || defined(VBOXOGL_DRI) +typedef const char * (*PGLXFUNC_GetDriverConfig)(const char *driverName); +typedef void (*PGLXFUNC_FreeMemoryMESA)(Display *dpy, int scrn, void *pointer); +typedef GLXContext (*PGLXFUNC_ImportContextEXT)(Display *dpy, GLXContextID contextID); +typedef GLXContextID (*PGLXFUNC_GetContextIDEXT)(const GLXContext ctx); +typedef Bool (*PGLXFUNC_MakeCurrentReadSGI)(Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef const char * (*PGLXFUNC_GetScreenDriver)(Display *dpy, int scrNum); +typedef Display * (*PGLXFUNC_GetCurrentDisplayEXT)(void); +typedef void (*PGLXFUNC_FreeContextEXT)(Display *dpy, GLXContext ctx); + +/*Mesa internal*/ +typedef int (*PGLXFUNC_QueryContextInfoEXT)(Display *dpy, GLXContext ctx); +typedef void * (*PGLXFUNC_AllocateMemoryMESA)(Display *dpy, int scrn, + size_t size, float readFreq, + float writeFreq, float priority); +typedef GLuint (*PGLXFUNC_GetMemoryOffsetMESA)(Display *dpy, int scrn, const void *pointer ); +typedef GLXPixmap (*PGLXFUNC_CreateGLXPixmapMESA)(Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap); +#endif + +/*Common glX functions*/ +typedef void (*PGLXFUNC_CopyContext)(Display *dpy, GLXContext src, GLXContext dst,unsigned long mask); +typedef void (*PGLXFUNC_UseXFont)(Font font, int first, int count, int listBase); +typedef CR_GLXFuncPtr (*PGLXFUNC_GetProcAddress)(const GLubyte *name); +typedef Bool (*PGLXFUNC_QueryExtension)(Display *dpy, int *errorBase, int *eventBase); +typedef Bool (*PGLXFUNC_IsDirect)(Display *dpy, GLXContext ctx); +typedef GLXPixmap (*PGLXFUNC_CreateGLXPixmap)(Display *dpy, XVisualInfo *vis, Pixmap pixmap); +typedef void (*PGLXFUNC_SwapBuffers)(Display *dpy, GLXDrawable drawable); +typedef GLXDrawable (*PGLXFUNC_GetCurrentDrawable)(void); +typedef void (*PGLXFUNC_WaitGL)(void); +typedef Display * (*PGLXFUNC_GetCurrentDisplay)(void); +typedef const char * (*PGLXFUNC_QueryServerString)(Display *dpy, int screen, int name); +typedef GLXContext (*PGLXFUNC_CreateContext)(Display *dpy, XVisualInfo *vis, GLXContext share, Bool direct); +typedef int (*PGLXFUNC_GetConfig)(Display *dpy, XVisualInfo *vis, int attrib, int *value); +typedef void (*PGLXFUNC_WaitX)(void); +typedef GLXContext (*PGLXFUNC_GetCurrentContext)(void); +typedef const char * (*PGLXFUNC_GetClientString)(Display *dpy, int name); +typedef Bool (*PGLXFUNC_MakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx); +typedef void (*PGLXFUNC_DestroyContext)(Display *dpy, GLXContext ctx); +typedef CR_GLXFuncPtr (*PGLXFUNC_GetProcAddressARB)(const GLubyte *name); +typedef void (*PGLXFUNC_DestroyGLXPixmap)(Display *dpy, GLXPixmap pix); +typedef Bool (*PGLXFUNC_QueryVersion)(Display *dpy, int *major, int *minor); +typedef XVisualInfo * (*PGLXFUNC_ChooseVisual)(Display *dpy, int screen, int *attribList); +typedef const char * (*PGLXFUNC_QueryExtensionsString)(Display *dpy, int screen); + +/** + * Set this to 1 if you want to build stub functions for the + * GL_SGIX_pbuffer and GLX_SGIX_fbconfig extensions. + * This used to be disabled, due to "messy compilation issues", + * according to the earlier comment; but they're needed just + * to resolve symbols for OpenInventor applications, and I + * haven't found any reference to exactly what the "messy compilation + * issues" are, so I'm re-enabling the code by default. + */ +#define GLX_EXTRAS 1 + +#define GLX_SGIX_video_resize 1 + +/** + * Prototypes, in case they're not in glx.h or glxext.h + * Unfortunately, there's some inconsistency between the extension + * specs, and the SGI, NVIDIA, XFree86 and common glxext.h header + * files. + */ +#if defined(GLX_GLXEXT_VERSION) +/* match glxext.h, XFree86, Mesa */ +#define ATTRIB_TYPE const int +#else +#define ATTRIB_TYPE int +#endif + +#if GLX_EXTRAS +typedef GLXPbufferSGIX (*PGLXFUNC_CreateGLXPbufferSGIX) +(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list); + +typedef int (*PGLXFUNC_QueryGLXPbufferSGIX) +(Display *dpy, GLXPbuffer pbuf, int attribute, unsigned int *value); + +typedef GLXFBConfigSGIX * (*PGLXFUNC_ChooseFBConfigSGIX) +(Display *dpy, int screen, int *attrib_list, int *nelements); + +typedef void (*PGLXFUNC_DestroyGLXPbufferSGIX)(Display *dpy, GLXPbuffer pbuf); +typedef void (*PGLXFUNC_SelectEventSGIX)(Display *dpy, GLXDrawable drawable, unsigned long mask); +typedef void (*PGLXFUNC_GetSelectedEventSGIX)(Display *dpy, GLXDrawable drawable, unsigned long *mask); + +typedef GLXFBConfigSGIX (*PGLXFUNC_GetFBConfigFromVisualSGIX)(Display *dpy, XVisualInfo *vis); +typedef XVisualInfo * (*PGLXFUNC_GetVisualFromFBConfigSGIX)(Display *dpy, GLXFBConfig config); +typedef GLXContext (*PGLXFUNC_CreateContextWithConfigSGIX) +(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); + +typedef GLXPixmap (*PGLXFUNC_CreateGLXPixmapWithConfigSGIX)(Display *dpy, GLXFBConfig config, Pixmap pixmap); +typedef int (*PGLXFUNC_GetFBConfigAttribSGIX)(Display *dpy, GLXFBConfig config, int attribute, int *value); + +/* + * GLX 1.3 functions + */ +typedef GLXFBConfig * (*PGLXFUNC_ChooseFBConfig)(Display *dpy, int screen, ATTRIB_TYPE *attrib_list, int *nelements); +typedef GLXPbuffer (*PGLXFUNC_CreatePbuffer)(Display *dpy, GLXFBConfig config, ATTRIB_TYPE *attrib_list); +typedef GLXPixmap (*PGLXFUNC_CreatePixmap)(Display *dpy, GLXFBConfig config, Pixmap pixmap, const ATTRIB_TYPE *attrib_list); +typedef GLXWindow (*PGLXFUNC_CreateWindow)(Display *dpy, GLXFBConfig config, Window win, ATTRIB_TYPE *attrib_list); +typedef GLXContext (*PGLXFUNC_CreateNewContext) +(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); + +typedef void (*PGLXFUNC_DestroyPbuffer)(Display *dpy, GLXPbuffer pbuf); +typedef void (*PGLXFUNC_DestroyPixmap)(Display *dpy, GLXPixmap pixmap); +typedef void (*PGLXFUNC_DestroyWindow)(Display *dpy, GLXWindow win); +typedef GLXDrawable (*PGLXFUNC_GetCurrentReadDrawable)(void); +typedef int (*PGLXFUNC_GetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int *value); +typedef GLXFBConfig * (*PGLXFUNC_GetFBConfigs)(Display *dpy, int screen, int *nelements); +typedef void (*PGLXFUNC_GetSelectedEvent)(Display *dpy, GLXDrawable draw, unsigned long *event_mask); +typedef XVisualInfo * (*PGLXFUNC_GetVisualFromFBConfig)(Display *dpy, GLXFBConfig config); +typedef Bool (*PGLXFUNC_MakeContextCurrent)(Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef int (*PGLXFUNC_QueryContext)(Display *dpy, GLXContext ctx, int attribute, int *value); +typedef void (*PGLXFUNC_QueryDrawable)(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); +typedef void (*PGLXFUNC_SelectEvent)(Display *dpy, GLXDrawable draw, unsigned long event_mask); + +#ifdef CR_EXT_texture_from_pixmap +typedef void (*PGLXFUNC_BindTexImageEXT)(Display *dpy, GLXDrawable draw, int buffer, const int *attrib_list); +typedef void (*PGLXFUNC_ReleaseTexImageEXT)(Display *dpy, GLXDrawable draw, int buffer); +#endif + +#endif /* GLX_EXTRAS */ + +#endif /* !GA_INCLUDED_SRC_common_crOpenGL_glx_proto_h */ diff --git a/src/VBox/Additions/common/crOpenGL/icd_drv.c b/src/VBox/Additions/common/crOpenGL/icd_drv.c new file mode 100644 index 00000000..3c54bb2f --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/icd_drv.c @@ -0,0 +1,398 @@ +/* $Id: icd_drv.c $ */ +/** @file + * VBox OpenGL windows ICD driver functions + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include "cr_error.h" +#include "icd_drv.h" +#include "cr_gl.h" +#include "stub.h" +#include "cr_mem.h" + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) +# include <VBoxCrHgsmi.h> +# include <VBoxUhgsmi.h> +#endif + +#include <iprt/win/windows.h> + +/// @todo consider +/* We can modify chronium dispatch table functions order to match the one required by ICD, + * but it'd render us incompatible with other chromium SPUs and require more changes. + * In current state, we can use unmodified binary chromium SPUs. Question is do we need it? +*/ + +#define GL_FUNC(func) cr_gl##func + +static ICDTABLE icdTable = { 336, { +#define ICD_ENTRY(func) (PROC)GL_FUNC(func), +#include "VBoxICDList.h" +#undef ICD_ENTRY +} }; + +/* Currently host part will misbehave re-creating context with proper visual bits + * if contexts with alternative visual bits is requested. + * For now we just report a superset of all visual bits to avoid that. + * Better to it on the host side as well? + * We could also implement properly multiple pixel formats, + * which should be done by implementing offscreen rendering or multiple host contexts. + * */ +#define VBOX_CROGL_USE_VBITS_SUPERSET + +#ifdef VBOX_CROGL_USE_VBITS_SUPERSET +static GLuint desiredVisual = CR_RGB_BIT | CR_ALPHA_BIT | CR_DEPTH_BIT | CR_STENCIL_BIT | CR_ACCUM_BIT | CR_DOUBLE_BIT; +#else +static GLuint desiredVisual = CR_RGB_BIT; +#endif + +#ifndef VBOX_CROGL_USE_VBITS_SUPERSET +/** + * Compute a mask of CR_*_BIT flags which reflects the attributes of + * the pixel format of the given hdc. + */ +static GLuint ComputeVisBits( HDC hdc ) +{ + PIXELFORMATDESCRIPTOR pfd; + int iPixelFormat; + GLuint b = 0; + + iPixelFormat = GetPixelFormat( hdc ); + + DescribePixelFormat( hdc, iPixelFormat, sizeof(pfd), &pfd ); + + if (pfd.cDepthBits > 0) + b |= CR_DEPTH_BIT; + if (pfd.cAccumBits > 0) + b |= CR_ACCUM_BIT; + if (pfd.cColorBits > 8) + b |= CR_RGB_BIT; + if (pfd.cStencilBits > 0) + b |= CR_STENCIL_BIT; + if (pfd.cAlphaBits > 0) + b |= CR_ALPHA_BIT; + if (pfd.dwFlags & PFD_DOUBLEBUFFER) + b |= CR_DOUBLE_BIT; + if (pfd.dwFlags & PFD_STEREO) + b |= CR_STEREO_BIT; + + return b; +} +#endif + +void APIENTRY DrvReleaseContext(HGLRC hglrc) +{ + CR_DDI_PROLOGUE(); + /*crDebug( "DrvReleaseContext(0x%x) called", hglrc );*/ + stubMakeCurrent( NULL, NULL ); +} + +BOOL APIENTRY DrvValidateVersion(DWORD version) +{ + CR_DDI_PROLOGUE(); + if (stubInit()) { + crDebug("DrvValidateVersion %x -> TRUE\n", version); + return TRUE; + } + + crDebug("DrvValidateVersion %x -> FALSE, going to use system default opengl32.dll\n", version); + return FALSE; +} + +//we're not going to change icdTable at runtime, so callback is unused +PICDTABLE APIENTRY DrvSetContext(HDC hdc, HGLRC hglrc, void *callback) +{ + ContextInfo *pContext; + WindowInfo *pWindowInfo; + BOOL ret = false; + + CR_DDI_PROLOGUE(); + + (void) (callback); + + crHashtableLock(stub.windowTable); + crHashtableLock(stub.contextTable); + + pContext = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) hglrc); + if (pContext) + { + pWindowInfo = stubGetWindowInfo(hdc); + if (pWindowInfo) + ret = stubMakeCurrent(pWindowInfo, pContext); + else + crError("no window info available."); + } + else + crError("No context found."); + + crHashtableUnlock(stub.contextTable); + crHashtableUnlock(stub.windowTable); + + return ret ? &icdTable : NULL; +} + +BOOL APIENTRY DrvSetPixelFormat(HDC hdc, int iPixelFormat) +{ + CR_DDI_PROLOGUE(); + crDebug( "DrvSetPixelFormat(0x%x, %i) called.", hdc, iPixelFormat ); + + if ( (iPixelFormat<1) || (iPixelFormat>2) ) { + crError( "wglSetPixelFormat: iPixelFormat=%d?", iPixelFormat ); + } + + return 1; +} + +HGLRC APIENTRY DrvCreateContext(HDC hdc) +{ + char dpyName[MAX_DPY_NAME]; + ContextInfo *context; +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + PVBOXUHGSMI pHgsmi = NULL; +#endif + + CR_DDI_PROLOGUE(); + + crDebug( "DrvCreateContext(0x%x) called.", hdc); + + stubInit(); + + CRASSERT(stub.contextTable); + + sprintf(dpyName, "%p", hdc); +#ifndef VBOX_CROGL_USE_VBITS_SUPERSET + if (stub.haveNativeOpenGL) + desiredVisual |= ComputeVisBits( hdc ); +#endif + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + pHgsmi = VBoxCrHgsmiCreate(); +#endif + + context = stubNewContext(dpyName, desiredVisual, UNDECIDED, 0 +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , pHgsmi +#endif + ); + if (!context) + return 0; + + return (HGLRC) context->id; +} + +HGLRC APIENTRY DrvCreateLayerContext(HDC hdc, int iLayerPlane) +{ + CR_DDI_PROLOGUE(); + crDebug( "DrvCreateLayerContext(0x%x, %i) called.", hdc, iLayerPlane); + //We don't support more than 1 layers. + if (iLayerPlane == 0) { + return DrvCreateContext(hdc); + } else { + crError( "DrvCreateLayerContext (%x,%x): unsupported", hdc, iLayerPlane); + return NULL; + } + +} + +BOOL APIENTRY DrvDescribeLayerPlane(HDC hdc,int iPixelFormat, + int iLayerPlane, UINT nBytes, + LPLAYERPLANEDESCRIPTOR plpd) +{ + CR_DDI_PROLOGUE(); + crWarning( "DrvDescribeLayerPlane: unimplemented" ); + CRASSERT(false); + return 0; +} + +int APIENTRY DrvGetLayerPaletteEntries(HDC hdc, int iLayerPlane, + int iStart, int cEntries, + COLORREF *pcr) +{ + CR_DDI_PROLOGUE(); + crWarning( "DrvGetLayerPaletteEntries: unsupported" ); + CRASSERT(false); + return 0; +} + +int APIENTRY DrvDescribePixelFormat(HDC hdc, int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR pfd) +{ + CR_DDI_PROLOGUE(); + if ( !pfd ) { + return 2; + } + + if ( nBytes != sizeof(*pfd) ) { + crWarning( "DrvDescribePixelFormat: nBytes=%u?", nBytes ); + return 2; + } + + if (iPixelFormat==1) + { + crMemZero(pfd, sizeof(*pfd)); + + pfd->nSize = sizeof(*pfd); + pfd->nVersion = 1; + pfd->dwFlags = (PFD_DRAW_TO_WINDOW | + PFD_SUPPORT_OPENGL | + PFD_DOUBLEBUFFER); + + pfd->dwFlags |= 0x8000; /* <- Needed for VSG Open Inventor to be happy */ + + pfd->iPixelType = PFD_TYPE_RGBA; + pfd->cColorBits = 32; + pfd->cRedBits = 8; + pfd->cRedShift = 24; + pfd->cGreenBits = 8; + pfd->cGreenShift = 16; + pfd->cBlueBits = 8; + pfd->cBlueShift = 8; + pfd->cAlphaBits = 8; + pfd->cAlphaShift = 0; + pfd->cAccumBits = 0; + pfd->cAccumRedBits = 0; + pfd->cAccumGreenBits = 0; + pfd->cAccumBlueBits = 0; + pfd->cAccumAlphaBits = 0; + pfd->cDepthBits = 32; + pfd->cStencilBits = 8; + pfd->cAuxBuffers = 0; + pfd->iLayerType = PFD_MAIN_PLANE; + pfd->bReserved = 0; + pfd->dwLayerMask = 0; + pfd->dwVisibleMask = 0; + pfd->dwDamageMask = 0; + } + else + { + crMemZero(pfd, sizeof(*pfd)); + pfd->nVersion = 1; + pfd->dwFlags = (PFD_DRAW_TO_WINDOW| + PFD_SUPPORT_OPENGL); + + pfd->iPixelType = PFD_TYPE_RGBA; + pfd->cColorBits = 32; + pfd->cRedBits = 8; + pfd->cRedShift = 16; + pfd->cGreenBits = 8; + pfd->cGreenShift = 8; + pfd->cBlueBits = 8; + pfd->cBlueShift = 0; + pfd->cAlphaBits = 0; + pfd->cAlphaShift = 0; + pfd->cAccumBits = 64; + pfd->cAccumRedBits = 16; + pfd->cAccumGreenBits = 16; + pfd->cAccumBlueBits = 16; + pfd->cAccumAlphaBits = 0; + pfd->cDepthBits = 16; + pfd->cStencilBits = 8; + pfd->cAuxBuffers = 0; + pfd->iLayerType = PFD_MAIN_PLANE; + pfd->bReserved = 0; + pfd->dwLayerMask = 0; + pfd->dwVisibleMask = 0; + pfd->dwDamageMask = 0; + } + + /* the max PFD index */ + return 2; +} + +BOOL APIENTRY DrvDeleteContext(HGLRC hglrc) +{ +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + ContextInfo *pContext; + PVBOXUHGSMI pHgsmi = NULL; +#endif + + CR_DDI_PROLOGUE(); + crDebug( "DrvDeleteContext(0x%x) called", hglrc ); + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + crHashtableLock(stub.contextTable); + + pContext = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) hglrc); + if (pContext) + pHgsmi = pContext->pHgsmi; + + crHashtableUnlock(stub.contextTable); +#endif + + stubDestroyContext( (unsigned long) hglrc ); + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + if (pHgsmi) + VBoxCrHgsmiDestroy(pHgsmi); +#endif + + return true; +} + +BOOL APIENTRY DrvCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask) +{ + CR_DDI_PROLOGUE(); + crWarning( "DrvCopyContext: unsupported" ); + return 0; +} + +DECLEXPORT(BOOL) WINAPI wglShareLists_prox( HGLRC hglrc1, HGLRC hglrc2 ); + +BOOL APIENTRY DrvShareLists(HGLRC hglrc1, HGLRC hglrc2) +{ + return wglShareLists_prox(hglrc1, hglrc2); +} + +int APIENTRY DrvSetLayerPaletteEntries(HDC hdc, int iLayerPlane, + int iStart, int cEntries, + CONST COLORREF *pcr) +{ + CR_DDI_PROLOGUE(); + crWarning( "DrvSetLayerPaletteEntries: unsupported" ); + return 0; +} + + +BOOL APIENTRY DrvRealizeLayerPalette(HDC hdc, int iLayerPlane, BOOL bRealize) +{ + CR_DDI_PROLOGUE(); + crWarning( "DrvRealizeLayerPalette: unsupported" ); + return 0; +} + +BOOL APIENTRY DrvSwapLayerBuffers(HDC hdc, UINT fuPlanes) +{ + CR_DDI_PROLOGUE(); + if (fuPlanes == 1) + { + return DrvSwapBuffers(hdc); + } + else + { + crWarning( "DrvSwapLayerBuffers: unsupported" ); + CRASSERT(false); + return 0; + } +} + +BOOL APIENTRY DrvSwapBuffers(HDC hdc) +{ + WindowInfo *window; + + CR_DDI_PROLOGUE(); + /*crDebug( "DrvSwapBuffers(0x%x) called", hdc );*/ + window = stubGetWindowInfo(hdc); + stubSwapBuffers( window, 0 ); + return 1; +} + diff --git a/src/VBox/Additions/common/crOpenGL/icd_drv.h b/src/VBox/Additions/common/crOpenGL/icd_drv.h new file mode 100644 index 00000000..97004bdd --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/icd_drv.h @@ -0,0 +1,55 @@ +/* $Id: icd_drv.h $ */ +/** @file + * VirtualBox Windows NT/2000/XP guest OpenGL ICD header + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#ifndef GA_INCLUDED_SRC_common_crOpenGL_icd_drv_h +#define GA_INCLUDED_SRC_common_crOpenGL_icd_drv_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/win/windows.h> + +typedef struct ICDTABLE +{ + DWORD size; + PROC table[336]; +} ICDTABLE, *PICDTABLE; + +void APIENTRY DrvReleaseContext(HGLRC hglrc); +BOOL APIENTRY DrvValidateVersion(DWORD version); +PICDTABLE APIENTRY DrvSetContext(HDC hdc, HGLRC hglrc, void *callback); +BOOL APIENTRY DrvSetPixelFormat(HDC hdc, int iPixelFormat); +HGLRC APIENTRY DrvCreateContext(HDC hdc); +HGLRC APIENTRY DrvCreateLayerContext(HDC hdc, int iLayerPlane); +BOOL APIENTRY DrvDescribeLayerPlane(HDC hdc,int iPixelFormat, + int iLayerPlane, UINT nBytes, + LPLAYERPLANEDESCRIPTOR plpd); +int APIENTRY DrvGetLayerPaletteEntries(HDC hdc, int iLayerPlane, + int iStart, int cEntries, + COLORREF *pcr); +int APIENTRY DrvDescribePixelFormat(HDC hdc, int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR pfd); +BOOL APIENTRY DrvDeleteContext(HGLRC hglrc); +BOOL APIENTRY DrvCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask); +BOOL APIENTRY DrvShareLists(HGLRC hglrc1, HGLRC hglrc2); +int APIENTRY DrvSetLayerPaletteEntries(HDC hdc, int iLayerPlane, + int iStart, int cEntries, + CONST COLORREF *pcr); +BOOL APIENTRY DrvRealizeLayerPalette(HDC hdc, int iLayerPlane, BOOL bRealize); +BOOL APIENTRY DrvSwapLayerBuffers(HDC hdc, UINT fuPlanes); +BOOL APIENTRY DrvSwapBuffers(HDC hdc); + +#endif /* !GA_INCLUDED_SRC_common_crOpenGL_icd_drv_h */ diff --git a/src/VBox/Additions/common/crOpenGL/load.c b/src/VBox/Additions/common/crOpenGL/load.c new file mode 100644 index 00000000..a4b0cf8c --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/load.c @@ -0,0 +1,1526 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_spu.h" +#include "cr_net.h" +#include "cr_error.h" +#include "cr_mem.h" +#include "cr_string.h" +#include "cr_net.h" +#include "cr_environment.h" +#include "cr_process.h" +#include "cr_rand.h" +#include "cr_netserver.h" +#include "stub.h" +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <iprt/initterm.h> +#include <iprt/thread.h> +#include <iprt/errcore.h> +#include <iprt/asm.h> +#ifndef WINDOWS +# include <sys/types.h> +# include <unistd.h> +#endif + +#ifdef VBOX_WITH_WDDM +#include <d3d9types.h> +#include <D3dumddi.h> +#endif + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) +# include <VBoxCrHgsmi.h> +#endif + +/** + * If you change this, see the comments in tilesortspu_context.c + */ +#define MAGIC_CONTEXT_BASE 500 + +#define CONFIG_LOOKUP_FILE ".crconfigs" + +#ifdef WINDOWS +#define PYTHON_EXE "python.exe" +#else +#define PYTHON_EXE "python" +#endif + +static bool stub_initialized = 0; +#ifdef WINDOWS +static CRmutex stub_init_mutex; +#define STUB_INIT_LOCK() do { crLockMutex(&stub_init_mutex); } while (0) +#define STUB_INIT_UNLOCK() do { crUnlockMutex(&stub_init_mutex); } while (0) +#else +#define STUB_INIT_LOCK() do { } while (0) +#define STUB_INIT_UNLOCK() do { } while (0) +#endif + +/* NOTE: 'SPUDispatchTable glim' is declared in NULLfuncs.py now */ +/* NOTE: 'SPUDispatchTable stubThreadsafeDispatch' is declared in tsfuncs.c */ +Stub stub; +#ifdef CHROMIUM_THREADSAFE +static bool g_stubIsCurrentContextTSDInited; +CRtsd g_stubCurrentContextTSD; +#endif + + +#ifndef VBOX_NO_NATIVEGL +static void stubInitNativeDispatch( void ) +{ +# define MAX_FUNCS 1000 + SPUNamedFunctionTable gl_funcs[MAX_FUNCS]; + int numFuncs; + + numFuncs = crLoadOpenGL( &stub.wsInterface, gl_funcs ); + + stub.haveNativeOpenGL = (numFuncs > 0); + + /* XXX call this after context binding */ + numFuncs += crLoadOpenGLExtensions( &stub.wsInterface, gl_funcs + numFuncs ); + + CRASSERT(numFuncs < MAX_FUNCS); + + crSPUInitDispatchTable( &stub.nativeDispatch ); + crSPUInitDispatch( &stub.nativeDispatch, gl_funcs ); + crSPUInitDispatchNops( &stub.nativeDispatch ); +# undef MAX_FUNCS +} +#endif /* !VBOX_NO_NATIVEGL */ + + +/** Pointer to the SPU's real glClear and glViewport functions */ +static ClearFunc_t origClear; +static ViewportFunc_t origViewport; +static SwapBuffersFunc_t origSwapBuffers; +static DrawBufferFunc_t origDrawBuffer; +static ScissorFunc_t origScissor; + +static void stubCheckWindowState(WindowInfo *window, GLboolean bFlushOnChange) +{ + bool bForceUpdate = false; + bool bChanged = false; + +#ifdef WINDOWS + /** @todo install hook and track for WM_DISPLAYCHANGE */ + { + DEVMODE devMode; + + devMode.dmSize = sizeof(DEVMODE); + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode); + + if (devMode.dmPelsWidth!=window->dmPelsWidth || devMode.dmPelsHeight!=window->dmPelsHeight) + { + crDebug("Resolution changed(%d,%d), forcing window Pos/Size update", devMode.dmPelsWidth, devMode.dmPelsHeight); + window->dmPelsWidth = devMode.dmPelsWidth; + window->dmPelsHeight = devMode.dmPelsHeight; + bForceUpdate = true; + } + } +#endif + + bChanged = stubUpdateWindowGeometry(window, bForceUpdate) || bForceUpdate; + +#if defined(GLX) || defined (WINDOWS) + if (stub.trackWindowVisibleRgn) + { + bChanged = stubUpdateWindowVisibileRegions(window) || bChanged; + } +#endif + + if (stub.trackWindowVisibility && window->type == CHROMIUM && window->drawable) { + const int mapped = stubIsWindowVisible(window); + if (mapped != window->mapped) { + crDebug("Dispatched: WindowShow(%i, %i)", window->spuWindow, mapped); + stub.spu->dispatch_table.WindowShow(window->spuWindow, mapped); + window->mapped = mapped; + bChanged = true; + } + } + + if (bFlushOnChange && bChanged) + { + stub.spu->dispatch_table.Flush(); + } +} + +static bool stubSystemWindowExist(WindowInfo *pWindow) +{ +#ifdef WINDOWS + if (pWindow->hWnd!=WindowFromDC(pWindow->drawable)) + { + return false; + } +#else + Window root; + int x, y; + unsigned int border, depth, w, h; + Display *dpy; + + dpy = stubGetWindowDisplay(pWindow); + + XLOCK(dpy); + if (!XGetGeometry(dpy, pWindow->drawable, &root, &x, &y, &w, &h, &border, &depth)) + { + XUNLOCK(dpy); + return false; + } + XUNLOCK(dpy); +#endif + + return true; +} + +static void stubCheckWindowsCB(unsigned long key, void *data1, void *data2) +{ + WindowInfo *pWindow = (WindowInfo *) data1; + ContextInfo *pCtx = (ContextInfo *) data2; + (void)key; + + if (pWindow == pCtx->currentDrawable + || pWindow->type!=CHROMIUM + || pWindow->pOwner!=pCtx) + { + return; + } + + if (!stubSystemWindowExist(pWindow)) + { +#ifdef WINDOWS + stubDestroyWindow(CR_CTX_CON(pCtx), (GLint)pWindow->hWnd); +#else + stubDestroyWindow(CR_CTX_CON(pCtx), (GLint)pWindow->drawable); +#endif + return; + } + + stubCheckWindowState(pWindow, GL_FALSE); +} + +static void stubCheckWindowsState(void) +{ + ContextInfo *context = stubGetCurrentContext(); + + CRASSERT(stub.trackWindowSize || stub.trackWindowPos); + + if (!context) + return; + +#if defined(WINDOWS) && defined(VBOX_WITH_WDDM) + if (stub.bRunningUnderWDDM) + return; +#endif + + /* Try to keep a consistent locking order. */ + crHashtableLock(stub.windowTable); +#if defined(CR_NEWWINTRACK) && !defined(WINDOWS) + crLockMutex(&stub.mutex); +#endif + + stubCheckWindowState(context->currentDrawable, GL_TRUE); + crHashtableWalkUnlocked(stub.windowTable, stubCheckWindowsCB, context); + +#if defined(CR_NEWWINTRACK) && !defined(WINDOWS) + crUnlockMutex(&stub.mutex); +#endif + crHashtableUnlock(stub.windowTable); +} + + +/** + * Override the head SPU's glClear function. + * We're basically trapping this function so that we can poll the + * application window size at a regular interval. + */ +static void SPU_APIENTRY trapClear(GLbitfield mask) +{ + stubCheckWindowsState(); + /* call the original SPU glClear function */ + origClear(mask); +} + +/** + * As above, but for glViewport. Most apps call glViewport before + * glClear when a window is resized. + */ +static void SPU_APIENTRY trapViewport(GLint x, GLint y, GLsizei w, GLsizei h) +{ + stubCheckWindowsState(); + /* call the original SPU glViewport function */ + origViewport(x, y, w, h); +} + +/*static void SPU_APIENTRY trapSwapBuffers(GLint window, GLint flags) +{ + stubCheckWindowsState(); + origSwapBuffers(window, flags); +} + +static void SPU_APIENTRY trapDrawBuffer(GLenum buf) +{ + stubCheckWindowsState(); + origDrawBuffer(buf); +}*/ + +#if 0 /* unused */ +static void SPU_APIENTRY trapScissor(GLint x, GLint y, GLsizei w, GLsizei h) +{ + int winX, winY; + unsigned int winW, winH; + WindowInfo *pWindow; + ContextInfo *context = stubGetCurrentContext(); + (void)x; (void)y; (void)w; (void)h; + + pWindow = context->currentDrawable; + stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH); + origScissor(0, 0, winW, winH); +} +#endif /* unused */ + +/** + * Use the GL function pointers in \<spu\> to initialize the static glim + * dispatch table. + */ +static void stubInitSPUDispatch(SPU *spu) +{ + crSPUInitDispatchTable( &stub.spuDispatch ); + crSPUCopyDispatchTable( &stub.spuDispatch, &(spu->dispatch_table) ); + + if (stub.trackWindowSize || stub.trackWindowPos || stub.trackWindowVisibleRgn) { + /* patch-in special glClear/Viewport function to track window sizing */ + origClear = stub.spuDispatch.Clear; + origViewport = stub.spuDispatch.Viewport; + origSwapBuffers = stub.spuDispatch.SwapBuffers; + origDrawBuffer = stub.spuDispatch.DrawBuffer; + origScissor = stub.spuDispatch.Scissor; + stub.spuDispatch.Clear = trapClear; + stub.spuDispatch.Viewport = trapViewport; + + /*stub.spuDispatch.SwapBuffers = trapSwapBuffers; + stub.spuDispatch.DrawBuffer = trapDrawBuffer;*/ + } + + crSPUCopyDispatchTable( &glim, &stub.spuDispatch ); +} + +#if 0 /** @todo stubSPUTearDown & stubSPUTearDownLocked are not referenced */ + +// Callback function, used to destroy all created contexts +static void hsWalkStubDestroyContexts(unsigned long key, void *data1, void *data2) +{ + (void)data1; (void)data2; + stubDestroyContext(key); +} + +/** + * This is called when we exit. + * We call all the SPU's cleanup functions. + */ +static void stubSPUTearDownLocked(void) +{ + crDebug("stubSPUTearDownLocked"); + +#ifdef WINDOWS +# ifndef CR_NEWWINTRACK + stubUninstallWindowMessageHook(); +# endif +#endif + +#ifdef CR_NEWWINTRACK + ASMAtomicWriteBool(&stub.bShutdownSyncThread, true); +#endif + + //delete all created contexts + stubMakeCurrent( NULL, NULL); + + /* the lock order is windowTable->contextTable (see wglMakeCurrent_prox, glXMakeCurrent) + * this is why we need to take a windowTable lock since we will later do stub.windowTable access & locking */ + crHashtableLock(stub.windowTable); + crHashtableWalk(stub.contextTable, hsWalkStubDestroyContexts, NULL); + crHashtableUnlock(stub.windowTable); + + /* shutdown, now trap any calls to a NULL dispatcher */ + crSPUCopyDispatchTable(&glim, &stubNULLDispatch); + + crSPUUnloadChain(stub.spu); + stub.spu = NULL; + +#ifndef Linux + crUnloadOpenGL(); +#endif + +#ifndef WINDOWS + crNetTearDown(); +#endif + +#ifdef GLX + if (stub.xshmSI.shmid>=0) + { + shmctl(stub.xshmSI.shmid, IPC_RMID, 0); + shmdt(stub.xshmSI.shmaddr); + } + crFreeHashtable(stub.pGLXPixmapsHash, crFree); +#endif + + crFreeHashtable(stub.windowTable, crFree); + crFreeHashtable(stub.contextTable, NULL); + + crMemset(&stub, 0, sizeof(stub)); + +} + +/** + * This is called when we exit. + * We call all the SPU's cleanup functions. + */ +static void stubSPUTearDown(void) +{ + STUB_INIT_LOCK(); + if (stub_initialized) + { + stubSPUTearDownLocked(); + stub_initialized = 0; + } + STUB_INIT_UNLOCK(); +} + +#endif /** @todo stubSPUTearDown & stubSPUTearDownLocked are not referenced */ + +static void stubSPUSafeTearDown(void) +{ +#ifdef CHROMIUM_THREADSAFE + CRmutex *mutex; +#endif + + if (!stub_initialized) return; + stub_initialized = 0; + +#ifdef CHROMIUM_THREADSAFE + mutex = &stub.mutex; + crLockMutex(mutex); +#endif + crDebug("stubSPUSafeTearDown"); + +#ifdef WINDOWS +# ifndef CR_NEWWINTRACK + stubUninstallWindowMessageHook(); +# endif +#endif + +#if defined(CR_NEWWINTRACK) + crUnlockMutex(mutex); +# if defined(WINDOWS) + if (stub.hSyncThread && RTThreadGetState(stub.hSyncThread)!=RTTHREADSTATE_TERMINATED) + { + HANDLE hNative; + DWORD ec=0; + + hNative = OpenThread(SYNCHRONIZE|THREAD_QUERY_INFORMATION|THREAD_TERMINATE, + false, RTThreadGetNative(stub.hSyncThread)); + if (!hNative) + { + crWarning("Failed to get handle for sync thread(%#x)", GetLastError()); + } + else + { + crDebug("Got handle %p for thread %#x", hNative, RTThreadGetNative(stub.hSyncThread)); + } + + ASMAtomicWriteBool(&stub.bShutdownSyncThread, true); + + if (PostThreadMessage(RTThreadGetNative(stub.hSyncThread), WM_QUIT, 0, 0)) + { + RTThreadWait(stub.hSyncThread, 1000, NULL); + + /*Same issue as on linux, RTThreadWait exits before system thread is terminated, which leads + * to issues as our dll goes to be unloaded. + *@todo + *We usually call this function from DllMain which seems to be holding some lock and thus we have to + * kill thread via TerminateThread. + */ + if (WaitForSingleObject(hNative, 100)==WAIT_TIMEOUT) + { + crDebug("Wait failed, terminating"); + if (!TerminateThread(hNative, 1)) + { + crDebug("TerminateThread failed"); + } + } + if (GetExitCodeThread(hNative, &ec)) + { + crDebug("Thread %p exited with ec=%i", hNative, ec); + } + else + { + crDebug("GetExitCodeThread failed(%#x)", GetLastError()); + } + } + else + { + crDebug("Sync thread killed before DLL_PROCESS_DETACH"); + } + + if (hNative) + { + CloseHandle(hNative); + } + } +#else + if (stub.hSyncThread!=NIL_RTTHREAD) + { + ASMAtomicWriteBool(&stub.bShutdownSyncThread, true); + { + int rc = RTThreadWait(stub.hSyncThread, RT_INDEFINITE_WAIT, NULL); + if (RT_FAILURE(rc)) + { + WARN(("RTThreadWait_join failed %i", rc)); + } + } + } +#endif + crLockMutex(mutex); +#endif + +#ifndef WINDOWS + crNetTearDown(); +#endif + +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(mutex); + crFreeMutex(mutex); +#endif + crMemset(&stub, 0, sizeof(stub)); +} + + +static void stubExitHandler(void) +{ + stubSPUSafeTearDown(); + signal(SIGTERM, SIG_DFL); + signal(SIGINT, SIG_DFL); +} + +/** + * Called when we receive a SIGTERM signal. + */ +static void stubSignalHandler(int signo) +{ + (void)signo; + stubSPUSafeTearDown(); + exit(0); /* this causes stubExitHandler() to be called */ +} + +#ifndef RT_OS_WINDOWS +# ifdef CHROMIUM_THREADSAFE +static void stubThreadTlsDtor(void *pvValue) +{ + ContextInfo *pCtx = (ContextInfo*)pvValue; + VBoxTlsRefRelease(pCtx); +} +# endif +#endif + + +/** + * Init variables in the stub structure, install signal handler. + */ +static void stubInitVars(void) +{ + WindowInfo *defaultWin; + +#ifdef CHROMIUM_THREADSAFE + crInitMutex(&stub.mutex); +#endif + + /* At the very least we want CR_RGB_BIT. */ + stub.haveNativeOpenGL = GL_FALSE; + stub.spu = NULL; + stub.appDrawCursor = 0; + stub.minChromiumWindowWidth = 0; + stub.minChromiumWindowHeight = 0; + stub.maxChromiumWindowWidth = 0; + stub.maxChromiumWindowHeight = 0; + stub.matchChromiumWindowCount = 0; + stub.matchChromiumWindowID = NULL; + stub.matchWindowTitle = NULL; + stub.ignoreFreeglutMenus = 0; + stub.threadSafe = GL_FALSE; + stub.trackWindowSize = 0; + stub.trackWindowPos = 0; + stub.trackWindowVisibility = 0; + stub.trackWindowVisibleRgn = 0; + stub.mothershipPID = 0; + stub.spu_dir = NULL; + + stub.freeContextNumber = MAGIC_CONTEXT_BASE; + stub.contextTable = crAllocHashtable(); +#ifndef RT_OS_WINDOWS +# ifdef CHROMIUM_THREADSAFE + if (!g_stubIsCurrentContextTSDInited) + { + crInitTSDF(&g_stubCurrentContextTSD, stubThreadTlsDtor); + g_stubIsCurrentContextTSDInited = true; + } +# endif +#endif + stubSetCurrentContext(NULL); + + stub.windowTable = crAllocHashtable(); + +#ifdef CR_NEWWINTRACK + stub.bShutdownSyncThread = false; + stub.hSyncThread = NIL_RTTHREAD; +#endif + + defaultWin = (WindowInfo *) crCalloc(sizeof(WindowInfo)); + defaultWin->type = CHROMIUM; + defaultWin->spuWindow = 0; /* window 0 always exists */ +#ifdef WINDOWS + defaultWin->hVisibleRegion = INVALID_HANDLE_VALUE; +#elif defined(GLX) + defaultWin->pVisibleRegions = NULL; + defaultWin->cVisibleRegions = 0; +#endif + crHashtableAdd(stub.windowTable, 0, defaultWin); + +#if 1 + atexit(stubExitHandler); + signal(SIGTERM, stubSignalHandler); + signal(SIGINT, stubSignalHandler); +#ifndef WINDOWS + signal(SIGPIPE, SIG_IGN); /* the networking code should catch this */ +#endif +#else + (void) stubExitHandler; + (void) stubSignalHandler; +#endif +} + + +#if 0 /* unused */ + +/** + * Return a free port number for the mothership to use, or -1 if we + * can't find one. + */ +static int +GenerateMothershipPort(void) +{ + const int MAX_PORT = 10100; + unsigned short port; + + /* generate initial port number randomly */ + crRandAutoSeed(); + port = (unsigned short) crRandInt(10001, MAX_PORT); + +#ifdef WINDOWS + /* XXX should implement a free port check here */ + return port; +#else + /* + * See if this port number really is free, try another if needed. + */ + { + struct sockaddr_in servaddr; + int so_reuseaddr = 1; + int sock, k; + + /* create socket */ + sock = socket(AF_INET, SOCK_STREAM, 0); + CRASSERT(sock > 2); + + /* deallocate socket/port when we exit */ + k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + (char *) &so_reuseaddr, sizeof(so_reuseaddr)); + CRASSERT(k == 0); + + /* initialize the servaddr struct */ + crMemset(&servaddr, 0, sizeof(servaddr) ); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + + while (port < MAX_PORT) { + /* Bind to the given port number, return -1 if we fail */ + servaddr.sin_port = htons((unsigned short) port); + k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr)); + if (k) { + /* failed to create port. try next one. */ + port++; + } + else { + /* free the socket/port now so mothership can make it */ + close(sock); + return port; + } + } + } +#endif /* WINDOWS */ + return -1; +} + + +/** + * Try to determine which mothership configuration to use for this program. + */ +static char ** +LookupMothershipConfig(const char *procName) +{ + const int procNameLen = crStrlen(procName); + FILE *f; + const char *home; + char configPath[1000]; + + /* first, check if the CR_CONFIG env var is set */ + { + const char *conf = crGetenv("CR_CONFIG"); + if (conf && crStrlen(conf) > 0) + return crStrSplit(conf, " "); + } + + /* second, look up config name from config file */ + home = crGetenv("HOME"); + if (home) + sprintf(configPath, "%s/%s", home, CONFIG_LOOKUP_FILE); + else + crStrcpy(configPath, CONFIG_LOOKUP_FILE); /* from current dir */ + /* Check if the CR_CONFIG_PATH env var is set. */ + { + const char *conf = crGetenv("CR_CONFIG_PATH"); + if (conf) + crStrcpy(configPath, conf); /* from env var */ + } + + f = fopen(configPath, "r"); + if (!f) { + return NULL; + } + + while (!feof(f)) { + char line[1000]; + char **args; + fgets(line, 999, f); + line[crStrlen(line) - 1] = 0; /* remove trailing newline */ + if (crStrncmp(line, procName, procNameLen) == 0 && + (line[procNameLen] == ' ' || line[procNameLen] == '\t')) + { + crWarning("Using Chromium configuration for %s from %s", + procName, configPath); + args = crStrSplit(line + procNameLen + 1, " "); + return args; + } + } + fclose(f); + return NULL; +} + + +static int Mothership_Awake = 0; + + +/** + * Signal handler to determine when mothership is ready. + */ +static void +MothershipPhoneHome(int signo) +{ + crDebug("Got signal %d: mothership is awake!", signo); + Mothership_Awake = 1; +} + +#endif /* 0 */ + +static void stubSetDefaultConfigurationOptions(void) +{ + unsigned char key[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + stub.appDrawCursor = 0; + stub.minChromiumWindowWidth = 0; + stub.minChromiumWindowHeight = 0; + stub.maxChromiumWindowWidth = 0; + stub.maxChromiumWindowHeight = 0; + stub.matchChromiumWindowID = NULL; + stub.numIgnoreWindowID = 0; + stub.matchWindowTitle = NULL; + stub.ignoreFreeglutMenus = 0; + stub.trackWindowSize = 1; + stub.trackWindowPos = 1; + stub.trackWindowVisibility = 1; + stub.trackWindowVisibleRgn = 1; + stub.matchChromiumWindowCount = 0; + stub.spu_dir = NULL; + crNetSetRank(0); + crNetSetContextRange(32, 35); + crNetSetNodeRange("iam0", "iamvis20"); + crNetSetKey(key,sizeof(key)); + stub.force_pbuffers = 0; + +#ifdef WINDOWS +# ifdef VBOX_WITH_WDDM + stub.bRunningUnderWDDM = false; +# endif +#endif +} + +#ifdef CR_NEWWINTRACK +# ifdef VBOX_WITH_WDDM +static void stubDispatchVisibleRegions(WindowInfo *pWindow) +{ + DWORD dwCount; + LPRGNDATA lpRgnData; + + dwCount = GetRegionData(pWindow->hVisibleRegion, 0, NULL); + lpRgnData = crAlloc(dwCount); + + if (lpRgnData) + { + GetRegionData(pWindow->hVisibleRegion, dwCount, lpRgnData); + crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, lpRgnData->rdh.nCount); + stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, lpRgnData->rdh.nCount, (GLint*) lpRgnData->Buffer); + crFree(lpRgnData); + } + else crWarning("GetRegionData failed, VisibleRegions update failed"); +} + +# endif /* VBOX_WITH_WDDM */ + +static void stubSyncTrCheckWindowsCB(unsigned long key, void *data1, void *data2) +{ + WindowInfo *pWindow = (WindowInfo *) data1; + (void)key; (void) data2; + + if (pWindow->type!=CHROMIUM || pWindow->spuWindow==0) + { + return; + } + + stub.spu->dispatch_table.VBoxPackSetInjectID(pWindow->u32ClientID); + + if (!stubSystemWindowExist(pWindow)) + { +#ifdef WINDOWS + stubDestroyWindow(0, (GLint)pWindow->hWnd); +#else + stubDestroyWindow(0, (GLint)pWindow->drawable); +#endif + /*No need to flush here as crWindowDestroy does it*/ + return; + } + +#if defined(WINDOWS) && defined(VBOX_WITH_WDDM) + if (stub.bRunningUnderWDDM) + return; +#endif + stubCheckWindowState(pWindow, GL_TRUE); +} + +static DECLCALLBACK(int) stubSyncThreadProc(RTTHREAD ThreadSelf, void *pvUser) +{ +#ifdef WINDOWS + MSG msg; +# ifdef VBOX_WITH_WDDM + HMODULE hVBoxD3D = NULL; + GLint spuConnection = 0; +# endif +#endif + + (void) pvUser; + + crDebug("Sync thread started"); +#ifdef WINDOWS + PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); +# ifdef VBOX_WITH_WDDM + hVBoxD3D = NULL; + if (!GetModuleHandleEx(0, VBOX_MODNAME_DISPD3D, &hVBoxD3D)) + { + crDebug("GetModuleHandleEx failed err %d", GetLastError()); + hVBoxD3D = NULL; + } + + if (hVBoxD3D) + { + crDebug("running with " VBOX_MODNAME_DISPD3D); + stub.trackWindowVisibleRgn = 0; + stub.bRunningUnderWDDM = true; + } +# endif /* VBOX_WITH_WDDM */ +#endif /* WINDOWS */ + + crLockMutex(&stub.mutex); +#if defined(WINDOWS) && defined(VBOX_WITH_WDDM) + spuConnection = +#endif + stub.spu->dispatch_table.VBoxPackSetInjectThread(NULL); +#if defined(WINDOWS) && defined(VBOX_WITH_WDDM) + if (stub.bRunningUnderWDDM && !spuConnection) + { + crError("VBoxPackSetInjectThread failed!"); + } +#endif + crUnlockMutex(&stub.mutex); + + RTThreadUserSignal(ThreadSelf); + + while(!stub.bShutdownSyncThread) + { +#ifdef WINDOWS + if (!PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { +# ifdef VBOX_WITH_WDDM + if (stub.bRunningUnderWDDM) + { + + } + else +# endif + { + crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL); + RTThreadSleep(50); + } + } + else + { + if (WM_QUIT==msg.message) + { + crDebug("Sync thread got WM_QUIT"); + break; + } + else + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +#else + /* Try to keep a consistent locking order. */ + crHashtableLock(stub.windowTable); + crLockMutex(&stub.mutex); + crHashtableWalkUnlocked(stub.windowTable, stubSyncTrCheckWindowsCB, NULL); + crUnlockMutex(&stub.mutex); + crHashtableUnlock(stub.windowTable); + RTThreadSleep(50); +#endif + } + +#ifdef VBOX_WITH_WDDM + if (spuConnection) + { + stub.spu->dispatch_table.VBoxConDestroy(spuConnection); + } + if (hVBoxD3D) + { + FreeLibrary(hVBoxD3D); + } +#endif + crDebug("Sync thread stopped"); + return 0; +} +#endif /* CR_NEWWINTRACK */ + +/** + * Do one-time initializations for the faker. + * Returns TRUE on success, FALSE otherwise. + */ +static bool +stubInitLocked(void) +{ + /* Here is where we contact the mothership to find out what we're supposed + * to be doing. Networking code in a DLL initializer. I sure hope this + * works :) + * + * HOW can I pass the mothership address to this if I already know it? + */ + + char response[1024]; + char **spuchain; + int num_spus; + int *spu_ids; + char **spu_names; + const char *app_id; + int i; + int disable_sync = 0; +#if defined(WINDOWS) && defined(VBOX_WITH_WDDM) + HMODULE hVBoxD3D = NULL; +#endif + + stubInitVars(); + + crGetProcName(response, 1024); + crDebug("Stub launched for %s", response); + +#if defined(CR_NEWWINTRACK) && !defined(WINDOWS) + /** @todo when vm boots with compiz turned on, new code causes hang in xcb_wait_for_reply in the sync thread + * as at the start compiz runs our code under XGrabServer. + */ + if (!crStrcmp(response, "compiz") || !crStrcmp(response, "compiz_real") || !crStrcmp(response, "compiz.real") + || !crStrcmp(response, "compiz-bin")) + { + disable_sync = 1; + } +#endif + + /** @todo check if it'd be of any use on other than guests, no use for windows */ + app_id = crGetenv( "CR_APPLICATION_ID_NUMBER" ); + + crNetInit( NULL, NULL ); + +#ifndef WINDOWS + { + CRNetServer ns; + + ns.name = "vboxhgcm://host:0"; + ns.buffer_size = 1024; + crNetServerConnect(&ns +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , NULL +#endif + ); + if (!ns.conn) + { + crWarning("Failed to connect to host. Make sure 3D acceleration is enabled for this VM."); +# ifdef VBOXOGL_FAKEDRI + return false; +# else + exit(1); +# endif + } + else + { + crNetFreeConnection(ns.conn); + } + } +#endif + + strcpy(response, "2 0 feedback 1 pack"); + spuchain = crStrSplit( response, " " ); + num_spus = crStrToInt( spuchain[0] ); + spu_ids = (int *) crAlloc( num_spus * sizeof( *spu_ids ) ); + spu_names = (char **) crAlloc( num_spus * sizeof( *spu_names ) ); + for (i = 0 ; i < num_spus ; i++) + { + spu_ids[i] = crStrToInt( spuchain[2*i+1] ); + spu_names[i] = crStrdup( spuchain[2*i+2] ); + crDebug( "SPU %d/%d: (%d) \"%s\"", i+1, num_spus, spu_ids[i], spu_names[i] ); + } + + stubSetDefaultConfigurationOptions(); + +#if defined(WINDOWS) && defined(VBOX_WITH_WDDM) + hVBoxD3D = NULL; + if (!GetModuleHandleEx(0, VBOX_MODNAME_DISPD3D, &hVBoxD3D)) + { + crDebug("GetModuleHandleEx failed err %d", GetLastError()); + hVBoxD3D = NULL; + } + + if (hVBoxD3D) + { + disable_sync = 1; + crDebug("running with %s", VBOX_MODNAME_DISPD3D); + stub.trackWindowVisibleRgn = 0; + /** @todo should we enable that? */ + stub.trackWindowSize = 0; + stub.trackWindowPos = 0; + stub.trackWindowVisibility = 0; + stub.bRunningUnderWDDM = true; + } +#endif + + stub.spu = crSPULoadChain( num_spus, spu_ids, spu_names, stub.spu_dir, NULL ); + + crFree( spuchain ); + crFree( spu_ids ); + for (i = 0; i < num_spus; ++i) + crFree(spu_names[i]); + crFree( spu_names ); + + // spu chain load failed somewhere + if (!stub.spu) { + return false; + } + + crSPUInitDispatchTable( &glim ); + + /* This is unlikely to change -- We still want to initialize our dispatch + * table with the functions of the first SPU in the chain. */ + stubInitSPUDispatch( stub.spu ); + + /* we need to plug one special stub function into the dispatch table */ + glim.GetChromiumParametervCR = stub_GetChromiumParametervCR; + +#if !defined(VBOX_NO_NATIVEGL) + /* Load pointers to native OpenGL functions into stub.nativeDispatch */ + stubInitNativeDispatch(); +#endif + +/*crDebug("stub init"); +raise(SIGINT);*/ + +#ifdef WINDOWS +# ifndef CR_NEWWINTRACK + stubInstallWindowMessageHook(); +# endif +#endif + +#ifdef CR_NEWWINTRACK + { + int rc; + + RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE); + + if (!disable_sync) + { + crDebug("Starting sync thread"); + + rc = RTThreadCreate(&stub.hSyncThread, stubSyncThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Sync"); + if (RT_FAILURE(rc)) + { + crError("Failed to start sync thread! (%x)", rc); + } + RTThreadUserWait(stub.hSyncThread, 60 * 1000); + RTThreadUserReset(stub.hSyncThread); + + crDebug("Going on"); + } + } +#endif + +#ifdef GLX + stub.xshmSI.shmid = -1; + stub.bShmInitFailed = GL_FALSE; + stub.pGLXPixmapsHash = crAllocHashtable(); + + stub.bXExtensionsChecked = GL_FALSE; + stub.bHaveXComposite = GL_FALSE; + stub.bHaveXFixes = GL_FALSE; +#endif + + return true; +} + +/** + * Do one-time initializations for the faker. + * Returns TRUE on success, FALSE otherwise. + */ +bool +stubInit(void) +{ + bool bRc = true; + /* we need to serialize the initialization, otherwise racing is possible + * for XPDM-based d3d when a d3d switcher is testing the gl lib in two or more threads + * NOTE: the STUB_INIT_LOCK/UNLOCK is a NOP for non-win currently */ + STUB_INIT_LOCK(); + if (!stub_initialized) + bRc = stub_initialized = stubInitLocked(); + STUB_INIT_UNLOCK(); + return bRc; +} + +/* Sigh -- we can't do initialization at load time, since Windows forbids + * the loading of other libraries from DLLMain. */ + +#ifdef WINDOWS +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#if 1//def DEBUG_misha + /* debugging: this is to be able to catch first-chance notifications + * for exceptions other than EXCEPTION_BREAKPOINT in kernel debugger */ +# define VDBG_VEHANDLER +#endif + +#ifdef VDBG_VEHANDLER +# include <dbghelp.h> +# include <cr_string.h> +static PVOID g_VBoxVehHandler = NULL; +static DWORD g_VBoxVehEnable = 0; + +/* generate a crash dump on exception */ +#define VBOXVEH_F_DUMP 0x00000001 +/* generate a debugger breakpoint exception */ +#define VBOXVEH_F_BREAK 0x00000002 +/* exit on exception */ +#define VBOXVEH_F_EXIT 0x00000004 + +static DWORD g_VBoxVehFlags = 0; + +typedef BOOL WINAPI FNVBOXDBG_MINIDUMPWRITEDUMP(HANDLE hProcess, + DWORD ProcessId, + HANDLE hFile, + MINIDUMP_TYPE DumpType, + PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, + PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, + PMINIDUMP_CALLBACK_INFORMATION CallbackParam); +typedef FNVBOXDBG_MINIDUMPWRITEDUMP *PFNVBOXDBG_MINIDUMPWRITEDUMP; + +static HMODULE g_hVBoxMdDbgHelp = NULL; +static PFNVBOXDBG_MINIDUMPWRITEDUMP g_pfnVBoxMdMiniDumpWriteDump = NULL; +static size_t g_cVBoxMdFilePrefixLen = 0; +static WCHAR g_aszwVBoxMdFilePrefix[MAX_PATH]; +static WCHAR g_aszwVBoxMdDumpCount = 0; +static MINIDUMP_TYPE g_enmVBoxMdDumpType = MiniDumpNormal + | MiniDumpWithDataSegs + | MiniDumpWithFullMemory + | MiniDumpWithHandleData +//// | MiniDumpFilterMemory +//// | MiniDumpScanMemory +// | MiniDumpWithUnloadedModules +//// | MiniDumpWithIndirectlyReferencedMemory +//// | MiniDumpFilterModulePaths +// | MiniDumpWithProcessThreadData +// | MiniDumpWithPrivateReadWriteMemory +//// | MiniDumpWithoutOptionalData +// | MiniDumpWithFullMemoryInfo +// | MiniDumpWithThreadInfo +// | MiniDumpWithCodeSegs +// | MiniDumpWithFullAuxiliaryState +// | MiniDumpWithPrivateWriteCopyMemory +// | MiniDumpIgnoreInaccessibleMemory +// | MiniDumpWithTokenInformation +//// | MiniDumpWithModuleHeaders +//// | MiniDumpFilterTriage + ; + + + +#define VBOXMD_DUMP_DIR_DEFAULT "C:\\dumps" +#define VBOXMD_DUMP_NAME_PREFIX_W L"VBoxDmp_" + +static HMODULE loadSystemDll(const char *pszName) +{ +#ifndef DEBUG + char szPath[MAX_PATH]; + UINT cchPath = GetSystemDirectoryA(szPath, sizeof(szPath)); + size_t cbName = strlen(pszName) + 1; + if (cchPath + 1 + cbName > sizeof(szPath)) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return NULL; + } + szPath[cchPath] = '\\'; + memcpy(&szPath[cchPath + 1], pszName, cbName); + return LoadLibraryA(szPath); +#else + return LoadLibraryA(pszName); +#endif +} + +static DWORD vboxMdMinidumpCreate(struct _EXCEPTION_POINTERS *pExceptionInfo) +{ + WCHAR aszwMdFileName[MAX_PATH]; + HANDLE hProcess = GetCurrentProcess(); + DWORD ProcessId = GetCurrentProcessId(); + MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo; + HANDLE hFile; + DWORD winErr = ERROR_SUCCESS; + + if (!g_pfnVBoxMdMiniDumpWriteDump) + { + if (!g_hVBoxMdDbgHelp) + { + g_hVBoxMdDbgHelp = loadSystemDll("DbgHelp.dll"); + if (!g_hVBoxMdDbgHelp) + return GetLastError(); + } + + g_pfnVBoxMdMiniDumpWriteDump = (PFNVBOXDBG_MINIDUMPWRITEDUMP)GetProcAddress(g_hVBoxMdDbgHelp, "MiniDumpWriteDump"); + if (!g_pfnVBoxMdMiniDumpWriteDump) + return GetLastError(); + } + + ++g_aszwVBoxMdDumpCount; + + memcpy(aszwMdFileName, g_aszwVBoxMdFilePrefix, g_cVBoxMdFilePrefixLen * sizeof (g_aszwVBoxMdFilePrefix[0])); + swprintf(aszwMdFileName + g_cVBoxMdFilePrefixLen, RT_ELEMENTS(aszwMdFileName) - g_cVBoxMdFilePrefixLen, L"%d_%d.dmp", ProcessId, g_aszwVBoxMdDumpCount); + + hFile = CreateFileW(aszwMdFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return GetLastError(); + + ExceptionInfo.ThreadId = GetCurrentThreadId(); + ExceptionInfo.ExceptionPointers = pExceptionInfo; + ExceptionInfo.ClientPointers = FALSE; + + if (!g_pfnVBoxMdMiniDumpWriteDump(hProcess, ProcessId, hFile, g_enmVBoxMdDumpType, &ExceptionInfo, NULL, NULL)) + winErr = GetLastError(); + + CloseHandle(hFile); + return winErr; +} + +LONG WINAPI vboxVDbgVectoredHandler(struct _EXCEPTION_POINTERS *pExceptionInfo) +{ + PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord; + PCONTEXT pContextRecord = pExceptionInfo->ContextRecord; + switch (pExceptionRecord->ExceptionCode) + { + case EXCEPTION_BREAKPOINT: + case EXCEPTION_ACCESS_VIOLATION: + case EXCEPTION_STACK_OVERFLOW: + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + case EXCEPTION_FLT_INVALID_OPERATION: + case EXCEPTION_INT_DIVIDE_BY_ZERO: + case EXCEPTION_ILLEGAL_INSTRUCTION: + if (g_VBoxVehFlags & VBOXVEH_F_BREAK) + { + BOOL fBreak = TRUE; +#ifndef DEBUG_misha + if (pExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT) + { + HANDLE hProcess = GetCurrentProcess(); + BOOL fDebuggerPresent = FALSE; + /* we do not want to generate breakpoint exceptions recursively, so do it only when running under debugger */ + if (CheckRemoteDebuggerPresent(hProcess, &fDebuggerPresent)) + fBreak = !!fDebuggerPresent; + else + fBreak = FALSE; /* <- the function has failed, don't break for sanity */ + } +#endif + + if (fBreak) + { + RT_BREAKPOINT(); + } + } + + if (g_VBoxVehFlags & VBOXVEH_F_DUMP) + vboxMdMinidumpCreate(pExceptionInfo); + + if (g_VBoxVehFlags & VBOXVEH_F_EXIT) + exit(1); + break; + default: + break; + } + return EXCEPTION_CONTINUE_SEARCH; +} + +void vboxVDbgVEHandlerRegister() +{ + CRASSERT(!g_VBoxVehHandler); + g_VBoxVehHandler = AddVectoredExceptionHandler(1,vboxVDbgVectoredHandler); + CRASSERT(g_VBoxVehHandler); +} + +void vboxVDbgVEHandlerUnregister() +{ + ULONG uResult; + if (g_VBoxVehHandler) + { + uResult = RemoveVectoredExceptionHandler(g_VBoxVehHandler); + CRASSERT(uResult); + g_VBoxVehHandler = NULL; + } +} +#endif + +/* Windows crap */ +BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved) +{ + (void) lpvReserved; + + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + { + CRNetServer ns; + const char * env; +#if defined(DEBUG_misha) + HMODULE hCrUtil; + char aName[MAX_PATH]; + + GetModuleFileNameA(hDLLInst, aName, RT_ELEMENTS(aName)); + crDbgCmdSymLoadPrint(aName, hDLLInst); + + hCrUtil = GetModuleHandleA("VBoxOGLcrutil.dll"); + Assert(hCrUtil); + crDbgCmdSymLoadPrint("VBoxOGLcrutil.dll", hCrUtil); +#endif +#ifdef CHROMIUM_THREADSAFE + crInitTSD(&g_stubCurrentContextTSD); +#endif + + crInitMutex(&stub_init_mutex); + +#ifdef VDBG_VEHANDLER + env = crGetenv("CR_DBG_VEH_ENABLE"); + g_VBoxVehEnable = crStrParseI32(env, +# ifdef DEBUG_misha + 1 +# else + 0 +# endif + ); + + if (g_VBoxVehEnable) + { + char procName[1024]; + size_t cProcName; + size_t cChars; + + env = crGetenv("CR_DBG_VEH_FLAGS"); + g_VBoxVehFlags = crStrParseI32(env, + 0 +# ifdef DEBUG_misha + | VBOXVEH_F_BREAK +# else + | VBOXVEH_F_DUMP +# endif + ); + + env = crGetenv("CR_DBG_VEH_DUMP_DIR"); + if (!env) + env = VBOXMD_DUMP_DIR_DEFAULT; + + g_cVBoxMdFilePrefixLen = strlen(env); + + if (RT_ELEMENTS(g_aszwVBoxMdFilePrefix) <= g_cVBoxMdFilePrefixLen + 26 + (sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)) / sizeof (WCHAR)) + { + g_cVBoxMdFilePrefixLen = 0; + env = ""; + } + + mbstowcs_s(&cChars, g_aszwVBoxMdFilePrefix, g_cVBoxMdFilePrefixLen + 1, env, _TRUNCATE); + + Assert(cChars == g_cVBoxMdFilePrefixLen + 1); + + g_cVBoxMdFilePrefixLen = cChars - 1; + + if (g_cVBoxMdFilePrefixLen && g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen - 1] != L'\\') + g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen++] = L'\\'; + + memcpy(g_aszwVBoxMdFilePrefix + g_cVBoxMdFilePrefixLen, VBOXMD_DUMP_NAME_PREFIX_W, sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)); + g_cVBoxMdFilePrefixLen += (sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)) / sizeof (WCHAR); + + crGetProcName(procName, RT_ELEMENTS(procName)); + cProcName = strlen(procName); + + if (RT_ELEMENTS(g_aszwVBoxMdFilePrefix) > g_cVBoxMdFilePrefixLen + cProcName + 1 + 26) + { + mbstowcs_s(&cChars, g_aszwVBoxMdFilePrefix + g_cVBoxMdFilePrefixLen, cProcName + 1, procName, _TRUNCATE); + Assert(cChars == cProcName + 1); + g_cVBoxMdFilePrefixLen += cChars - 1; + g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen++] = L'_'; + } + + /* sanity */ + g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen] = L'\0'; + + env = crGetenv("CR_DBG_VEH_DUMP_TYPE"); + + g_enmVBoxMdDumpType = crStrParseI32(env, + MiniDumpNormal + | MiniDumpWithDataSegs + | MiniDumpWithFullMemory + | MiniDumpWithHandleData + //// | MiniDumpFilterMemory + //// | MiniDumpScanMemory + // | MiniDumpWithUnloadedModules + //// | MiniDumpWithIndirectlyReferencedMemory + //// | MiniDumpFilterModulePaths + // | MiniDumpWithProcessThreadData + // | MiniDumpWithPrivateReadWriteMemory + //// | MiniDumpWithoutOptionalData + // | MiniDumpWithFullMemoryInfo + // | MiniDumpWithThreadInfo + // | MiniDumpWithCodeSegs + // | MiniDumpWithFullAuxiliaryState + // | MiniDumpWithPrivateWriteCopyMemory + // | MiniDumpIgnoreInaccessibleMemory + // | MiniDumpWithTokenInformation + //// | MiniDumpWithModuleHeaders + //// | MiniDumpFilterTriage + ); + + vboxVDbgVEHandlerRegister(); + } +#endif + + crNetInit(NULL, NULL); + ns.name = "vboxhgcm://host:0"; + ns.buffer_size = 1024; + crNetServerConnect(&ns +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , NULL +#endif +); + if (!ns.conn) + { + crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load."); +#ifdef VDBG_VEHANDLER + if (g_VBoxVehEnable) + vboxVDbgVEHandlerUnregister(); +#endif + return FALSE; + } + else + { + crNetFreeConnection(ns.conn); + } + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + VBoxCrHgsmiInit(); +#endif + break; + } + + case DLL_PROCESS_DETACH: + { + /* do exactly the same thing as for DLL_THREAD_DETACH since + * DLL_THREAD_DETACH is not called for the thread doing DLL_PROCESS_DETACH according to msdn docs */ + stubSetCurrentContext(NULL); + if (stub_initialized) + { + CRASSERT(stub.spu); + stub.spu->dispatch_table.VBoxDetachThread(); + } + + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + VBoxCrHgsmiTerm(); +#endif + + stubSPUSafeTearDown(); + +#ifdef CHROMIUM_THREADSAFE + crFreeTSD(&g_stubCurrentContextTSD); +#endif + +#ifdef VDBG_VEHANDLER + if (g_VBoxVehEnable) + vboxVDbgVEHandlerUnregister(); +#endif + break; + } + + case DLL_THREAD_ATTACH: + { + if (stub_initialized) + { + CRASSERT(stub.spu); + stub.spu->dispatch_table.VBoxAttachThread(); + } + break; + } + + case DLL_THREAD_DETACH: + { + stubSetCurrentContext(NULL); + if (stub_initialized) + { + CRASSERT(stub.spu); + stub.spu->dispatch_table.VBoxDetachThread(); + } + break; + } + + default: + break; + } + + return TRUE; +} +#endif diff --git a/src/VBox/Additions/common/crOpenGL/pack/Makefile.kup b/src/VBox/Additions/common/crOpenGL/pack/Makefile.kup new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/Makefile.kup diff --git a/src/VBox/Additions/common/crOpenGL/pack/pack.def b/src/VBox/Additions/common/crOpenGL/pack/pack.def new file mode 100644 index 00000000..9edc7163 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/pack.def @@ -0,0 +1,6 @@ +; Copyright (c) 2001, Stanford University +; All rights reserved. +; +; See the file LICENSE.txt for information on redistributing this software. +EXPORTS +SPULoad diff --git a/src/VBox/Additions/common/crOpenGL/pack/pack.py b/src/VBox/Additions/common/crOpenGL/pack/pack.py new file mode 100755 index 00000000..e25066be --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/pack.py @@ -0,0 +1,57 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - THIS FILE AUTOMATICALLY GENERATED BY pack.py SCRIPT */ +#include <stdio.h> +#include "cr_string.h" +#include "cr_spu.h" +#include "packspu.h" +#include "cr_packfunctions.h" +#include "packspu_proto.h" +""") + +num_funcs = len(keys) - len(apiutil.AllSpecials('packspu_unimplemented')) +print('SPUNamedFunctionTable _cr_pack_table[%d];' % (num_funcs+1)) + +print(""" +static void __fillin(int offset, char *name, SPUGenericFunction func) +{ + _cr_pack_table[offset].name = crStrdup(name); + _cr_pack_table[offset].fn = func; +}""") + +pack_specials = [] + +for func_name in keys: + if ("get" in apiutil.Properties(func_name) or + apiutil.FindSpecial( "packspu", func_name ) or + apiutil.FindSpecial( "packspu_flush", func_name ) or + apiutil.FindSpecial( "packspu_vertex", func_name )): + pack_specials.append( func_name ) + +print('\nvoid packspuCreateFunctions( void )') +print('{') +for index in range(len(keys)): + func_name = keys[index] + if apiutil.FindSpecial( "packspu_unimplemented", func_name ): + continue + if func_name in pack_specials: + print('\t__fillin(%3d, "%s", (SPUGenericFunction) packspu_%s);' % (index, func_name, func_name )) + else: + print('\t__fillin(%3d, "%s", (SPUGenericFunction) (pack_spu.swap ? crPack%sSWAP : crPack%s));' % (index, func_name, func_name, func_name )) +print('\t__fillin(%3d, NULL, NULL);' % num_funcs) +print('}') diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu.h b/src/VBox/Additions/common/crOpenGL/pack/packspu.h new file mode 100644 index 00000000..9774e35b --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu.h @@ -0,0 +1,185 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved. + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#ifndef GA_INCLUDED_SRC_common_crOpenGL_pack_packspu_h +#define GA_INCLUDED_SRC_common_crOpenGL_pack_packspu_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#ifdef WINDOWS +#define PACKSPU_APIENTRY __stdcall +#else +#define PACKSPU_APIENTRY +#endif + +#include "cr_glstate.h" +#include "cr_netserver.h" +#include "cr_pack.h" +#include "cr_spu.h" +#include "cr_threads.h" +#include "state/cr_client.h" +#ifdef VBOX_WITH_CRPACKSPU_DUMPER +# include "cr_dump.h" +#endif + +extern uint32_t g_u32VBoxHostCaps; + +typedef struct thread_info_t ThreadInfo; +typedef struct context_info_t ContextInfo; +typedef struct zvabuffer_info_t ZvaBufferInfo; + +struct zvabuffer_info_t +{ + /* GL_ARRAY_BUFFER_ARB buffer */ + GLuint idBuffer; + /* buffer length */ + GLuint cbBuffer; + /* number of values stored in the buffer currently */ + GLuint cValues; + /* current buffer value */ + union + { + GLfloat f[4]; + GLuint ui[4]; + GLubyte ub[4]; + GLshort s[4]; + GLushort us[4]; + } Value; +}; + +struct thread_info_t { + unsigned long id; + CRNetServer netServer; + CRPackBuffer buffer; + CRPackBuffer normBuffer; + CRPackBuffer BeginEndBuffer; + GLenum BeginEndMode; + int BeginEndState; + ContextInfo *currentContext; + CRPackContext *packer; + int writeback; + GLboolean bInjectThread; + GLboolean inUse; +}; + +struct context_info_t { + CRContext *clientState; /* used to store client-side GL state */ + GLint serverCtx; /* context ID returned by server */ + GLboolean fAutoFlush; + GLboolean fCheckZerroVertAttr; + ThreadInfo *currentThread; + ZvaBufferInfo zvaBufferInfo; + GLubyte glVersion[100]; /* GL_VERSION string */ + GLubyte pszRealVendor[100]; + GLubyte pszRealVersion[100]; + GLubyte pszRealRenderer[100]; +}; + +typedef struct { + int id; + int swap; + + /* config options */ + int emit_GATHER_POST_SWAPBUFFERS; + int swapbuffer_sync; + + int ReadPixels; + + char *name; + int buffer_size; + + int numThreads; /*number of used threads in the next array, doesn't need to be cont*/ + ThreadInfo thread[MAX_THREADS]; + int idxThreadInUse; /*index of any used thread*/ + +#if defined(WINDOWS) && defined(VBOX_WITH_WDDM) + bool bIsWDDMCrHgsmi; +#endif + + SPUDispatchTable self; + +#ifdef VBOX_WITH_CRPACKSPU_DUMPER + CR_RECORDER Recorder; + CR_DBGPRINT_DUMPER Dumper; +#endif + + int numContexts; + ContextInfo context[CR_MAX_CONTEXTS]; +} PackSPU; + +extern PackSPU pack_spu; + +#define THREAD_OFFSET_MAGIC 2000 + +#ifdef CHROMIUM_THREADSAFE +extern CRmutex _PackMutex; +extern CRtsd _PackTSD; +#define GET_THREAD_VAL() (crGetTSD(&_PackTSD)) +#define GET_THREAD_IDX(_id) ((_id) - THREAD_OFFSET_MAGIC) +#define GET_THREAD_VAL_ID(_id) (&(pack_spu.thread[GET_THREAD_IDX(_id)])) +#else +#define GET_THREAD_VAL() (&(pack_spu.thread[0])) +#endif +#define GET_THREAD(T) ThreadInfo *T = GET_THREAD_VAL() +#define GET_THREAD_ID(T, _id) ThreadInfo *T = GET_THREAD_VAL_ID(_id) + + + +#define GET_CONTEXT(C) \ + GET_THREAD(thread); \ + ContextInfo *C = thread->currentContext + +#ifdef DEBUG_misha +# define CRPACKSPU_WRITEBACK_ASSERT_ZERO(_writeback) Assert(!(_writeback)) +#else +# define CRPACKSPU_WRITEBACK_ASSERT_ZERO(_writeback) do {} while (0) +#endif + +#define CRPACKSPU_WRITEBACK_WAIT(_thread, _writeback) do {\ + if (g_u32VBoxHostCaps & CR_VBOX_CAP_CMDVBVA) { \ + CRPACKSPU_WRITEBACK_ASSERT_ZERO(_writeback); \ + (_writeback) = 0; \ + break; \ + } \ + CR_WRITEBACK_WAIT((_thread)->netServer.conn, _writeback); \ + } while (0) + +#if defined(WINDOWS) && defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) +# define CRPACKSPU_IS_WDDM_CRHGSMI() (pack_spu.bIsWDDMCrHgsmi) +#else +# define CRPACKSPU_IS_WDDM_CRHGSMI() (GL_FALSE) +#endif + +extern void packspuCreateFunctions( void ); +extern void packspuSetVBoxConfiguration( const SPU *child_spu ); +extern void packspuConnectToServer( CRNetServer *server +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , struct VBOXUHGSMI *pHgsmi +#endif + ); +extern void packspuFlush( void *arg ); +extern void packspuHuge( CROpcode opcode, void *buf ); + +extern void packspuInitStrings(void); + +extern GLboolean packspuSyncOnFlushes(void); + +extern ThreadInfo *packspuNewThread( +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + struct VBOXUHGSMI *pHgsmi +#else + void +#endif + ); + +extern ThreadInfo *packspuNewCtxThread( struct VBOXUHGSMI *pHgsmi ); + + + +#define MAGIC_OFFSET 3000 + +#endif /* !GA_INCLUDED_SRC_common_crOpenGL_pack_packspu_h */ diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu.rc b/src/VBox/Additions/common/crOpenGL/pack/packspu.rc new file mode 100644 index 00000000..b120f236 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu.rc @@ -0,0 +1,69 @@ +/* $Id: packspu.rc $ */ +/** @file + * VBoxOGLpackspu - Resource file containing version info and icon. + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include <windows.h> +#include <VBox/version.h> + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VBOX_RC_FILE_VERSION + PRODUCTVERSION VBOX_RC_FILE_VERSION + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS VBOX_RC_FILE_FLAGS + FILEOS VBOX_RC_FILE_OS + FILETYPE VBOX_RC_TYPE_DRV + FILESUBTYPE VFT2_DRV_DISPLAY +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "VirtualBox crOpenGL ICD\0" + VALUE "InternalName", "VBoxOGLpackspu\0" +#ifdef VBOX_WDDM_WOW64 + VALUE "OriginalFilename", "VBoxOGLpackspu-x86.dll\0" +#else + VALUE "OriginalFilename", "VBoxOGLpackspu.dll\0" +#endif + VALUE "CompanyName", VBOX_RC_COMPANY_NAME + VALUE "FileVersion", VBOX_RC_FILE_VERSION_STR + VALUE "LegalCopyright", VBOX_RC_LEGAL_COPYRIGHT + VALUE "ProductName", VBOX_RC_PRODUCT_NAME_GA_STR + VALUE "ProductVersion", VBOX_RC_PRODUCT_VERSION_STR + VBOX_RC_MORE_STRINGS + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +1 RCDATA +BEGIN +// Machine dependent parameters + 17, // Height of vertical thumb + 17, // Width of horizontal thumb + 2, // Icon horiz compression factor + 2, // Icon vert compression factor + 1, // Cursor horz compression factor + 1, // Cursor vert compression factor + 0, // Kanji window height + 1, // cxBorder (thickness of vertical lines) + 1 // cyBorder (thickness of horizontal lines) +END diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_beginend.py b/src/VBox/Additions/common/crOpenGL/pack/packspu_beginend.py new file mode 100755 index 00000000..2195cab5 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_beginend.py @@ -0,0 +1,177 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + + +apiutil.CopyrightC() + +print("""/* DO NOT EDIT - AUTOMATICALLY GENERATED BY packspu_beginend.py */ +#include "packspu.h" +#include "assert.h" +#include "cr_packfunctions.h" +#include "packspu_proto.h" + +void PACKSPU_APIENTRY packspu_Begin( GLenum mode ) +{ + CRPackBuffer *buf; +#if CR_ARB_vertex_buffer_object + GET_CONTEXT(ctx); +#else + GET_THREAD(thread); +#endif + + buf = &thread->BeginEndBuffer; + + /* XXX comparing mode >= 0 here is not needed since mode is unsigned */ + CRASSERT( /*mode >= GL_POINTS && */mode <= GL_POLYGON ); + +#if CR_ARB_vertex_buffer_object + { + GLboolean serverArrays = GL_FALSE; + if (ctx->clientState->extensions.ARB_vertex_buffer_object) + serverArrays = crStateUseServerArrays(); + if (serverArrays) { + CRClientState *clientState = &(ctx->clientState->client); + if (clientState->array.locked && !clientState->array.synced) + { + crPackLockArraysEXT(clientState->array.lockFirst, clientState->array.lockCount); + clientState->array.synced = GL_TRUE; + } + } + } +#endif + + if (pack_spu.swap) + { + crPackBeginSWAP( mode ); + } + else + { + crPackBegin( mode ); + } + + if ( thread->netServer.conn->Barf ) { + thread->BeginEndMode = mode; + thread->BeginEndState = -1; + if ( mode == GL_LINES || mode == GL_TRIANGLES || mode == GL_QUADS || mode == GL_POLYGON ) + { + CRASSERT(!buf->pack); + + crPackReleaseBuffer( thread->packer ); + buf->pack = crNetAlloc( thread->netServer.conn ); + crPackInitBuffer( buf, buf->pack, thread->netServer.conn->buffer_size, thread->netServer.conn->mtu ); + buf->holds_BeginEnd = 1; + buf->in_BeginEnd = 1; + crPackSetBuffer( thread->packer, buf ); + + thread->BeginEndState = 0; + } + } +} + +void PACKSPU_APIENTRY packspu_End( void ) +{ + GET_THREAD(thread); + CRPackBuffer *buf = &thread->BeginEndBuffer; + + if ( thread->netServer.conn->Barf && + (thread->BeginEndMode == GL_LINES + || thread->BeginEndMode == GL_TRIANGLES + || thread->BeginEndMode == GL_QUADS + || thread->BeginEndMode == GL_POLYGON ) ) + { + CRASSERT(buf->pack); + + crPackReleaseBuffer( thread->packer ); + crPackSetBuffer( thread->packer, &thread->normBuffer ); + if ( !crPackCanHoldBuffer( buf ) ) + packspuFlush( (void *) thread ); + + crPackAppendBuffer( buf ); + crNetFree( thread->netServer.conn, buf->pack ); + buf->pack = NULL; + } + + if (pack_spu.swap) + { + crPackEndSWAP(); + } + else + { + crPackEnd(); + } +} + +static void DoVertex( void ) +{ + GET_THREAD(thread); + CRPackBuffer *buf = &thread->BeginEndBuffer; + CRPackBuffer *gbuf = &thread->normBuffer; + int num_data; + int num_opcode; + + /*crDebug( "really doing Vertex" );*/ + crPackReleaseBuffer( thread->packer ); + num_data = buf->data_current - buf->data_start; + num_opcode = buf->opcode_start - buf->opcode_current; + crPackSetBuffer( thread->packer, gbuf ); + if ( !crPackCanHoldBuffer( buf ) ) + /* doesn't hold, first flush gbuf*/ + packspuFlush( (void *) thread ); + + crPackAppendBuffer( buf ); + crPackReleaseBuffer( thread->packer ); + crPackSetBuffer( thread->packer, buf ); + crPackResetPointers(thread->packer); +} + +static void RunState( void ) +{ + GET_THREAD(thread); + if (! thread->netServer.conn->Barf ) return; + if (thread->BeginEndState == -1) return; + switch(thread->BeginEndMode) { + case GL_POLYGON: + return; + case GL_LINES: + thread->BeginEndState = (thread->BeginEndState + 1) % 2; + if (thread->BeginEndState) + return; + break; + case GL_TRIANGLES: + thread->BeginEndState = (thread->BeginEndState + 1) % 3; + if (thread->BeginEndState) + return; + break; + case GL_QUADS: + thread->BeginEndState = (thread->BeginEndState + 1) % 4; + if (thread->BeginEndState) + return; + break; + } + DoVertex(); +} +""") + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +for func_name in apiutil.AllSpecials( "packspu_vertex" ): + params = apiutil.Parameters(func_name) + print('void PACKSPU_APIENTRY packspu_%s(%s)' % ( func_name, apiutil.MakeDeclarationString(params) )) + print('{') + print('\tif (pack_spu.swap)') + print('\t{') + print('\t\tcrPack%sSWAP(%s);' % ( func_name, apiutil.MakeCallString( params ) )) + print('\t}') + print('\telse') + print('\t{') + print('\t\tcrPack%s(%s);' % ( func_name, apiutil.MakeCallString( params ) )) + print('\t}') + print('\tRunState();') + print('}') diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_bufferobject.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_bufferobject.c new file mode 100644 index 00000000..65f64bd7 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_bufferobject.c @@ -0,0 +1,160 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_error.h" +#include "cr_mem.h" +#include "cr_string.h" +#include "packspu.h" +#include "packspu_proto.h" + +static void packspu_GetHostBufferSubDataARB( GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data ) +{ + GET_THREAD(thread); + int writeback = 1; + + crPackGetBufferSubDataARB(target, offset, size, data, &writeback); + + packspuFlush((void *) thread); + + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); +} + +void * PACKSPU_APIENTRY +packspu_MapBufferARB( GLenum target, GLenum access ) +{ + GET_CONTEXT(ctx); + void *buffer; + CRBufferObject *pBufObj; + + CRASSERT(GL_TRUE == ctx->clientState->bufferobject.retainBufferData); + buffer = crStateMapBufferARB(target, access); + +#ifdef CR_ARB_pixel_buffer_object + if (buffer) + { + pBufObj = crStateGetBoundBufferObject(target, &ctx->clientState->bufferobject); + CRASSERT(pBufObj); + + if (pBufObj->bResyncOnRead && + access != GL_WRITE_ONLY_ARB) + { + /*fetch data from host side*/ + packspu_GetHostBufferSubDataARB(target, 0, pBufObj->size, buffer); + } + } +#endif + + return buffer; +} + +void PACKSPU_APIENTRY packspu_GetBufferSubDataARB( GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data ) +{ + GET_CONTEXT(ctx); + +#ifdef CR_ARB_pixel_buffer_object + CRBufferObject *pBufObj; + + pBufObj = crStateGetBoundBufferObject(target, &ctx->clientState->bufferobject); + + if (pBufObj && pBufObj->bResyncOnRead) + { + packspu_GetHostBufferSubDataARB(target, offset, size, data); + return; + } +#endif + + crStateGetBufferSubDataARB(target, offset, size, data); +} + + +GLboolean PACKSPU_APIENTRY +packspu_UnmapBufferARB( GLenum target ) +{ + GET_CONTEXT(ctx); + +#if CR_ARB_vertex_buffer_object + CRBufferObject *bufObj; + + bufObj = crStateGetBoundBufferObject(target, &ctx->clientState->bufferobject); + + /* send new buffer contents to server */ + crPackBufferDataARB( target, bufObj->size, bufObj->pointer, bufObj->usage ); +#endif + + CRASSERT(GL_TRUE == ctx->clientState->bufferobject.retainBufferData); + crStateUnmapBufferARB( target ); + + return GL_TRUE; +} + + +void PACKSPU_APIENTRY +packspu_BufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage) +{ + /*crDebug("packspu_BufferDataARB size:%d", size);*/ + crStateBufferDataARB(target, size, data, usage); + crPackBufferDataARB(target, size, data, usage); +} + +void PACKSPU_APIENTRY +packspu_BufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data) +{ + /*crDebug("packspu_BufferSubDataARB size:%d", size);*/ + crStateBufferSubDataARB(target, offset, size, data); + crPackBufferSubDataARB(target, offset, size, data); +} + + +void PACKSPU_APIENTRY +packspu_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params) +{ + crStateGetBufferPointervARB( target, pname, params ); +} + + +void PACKSPU_APIENTRY +packspu_GetBufferParameterivARB( GLenum target, GLenum pname, GLint * params ) +{ + crStateGetBufferParameterivARB( target, pname, params ); +} + +/* + * Need to update our local state for vertex arrays. + */ +void PACKSPU_APIENTRY +packspu_BindBufferARB( GLenum target, GLuint buffer ) +{ + crStateBindBufferARB(target, buffer); + crPackBindBufferARB(target, buffer); +} + +void PACKSPU_APIENTRY packspu_GenBuffersARB( GLsizei n, GLuint * buffer ) +{ + GET_THREAD(thread); + int writeback = 1; + if (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network)) + { + crError( "packspu_GenBuffersARB doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!" ); + } + if (pack_spu.swap) + { + crPackGenBuffersARBSWAP( n, buffer, &writeback ); + } + else + { + crPackGenBuffersARB( n, buffer, &writeback ); + } + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + crStateRegBuffers(n, buffer); +} + +void PACKSPU_APIENTRY packspu_DeleteBuffersARB( GLsizei n, const GLuint * buffer ) +{ + crStateDeleteBuffersARB( n, buffer ); + crPackDeleteBuffersARB(n, buffer); +} diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_client.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_client.c new file mode 100644 index 00000000..19c11880 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_client.c @@ -0,0 +1,910 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "packspu.h" +#include "cr_packfunctions.h" +#include "cr_glstate.h" +#include "packspu_proto.h" +#include "cr_mem.h" + +void PACKSPU_APIENTRY packspu_FogCoordPointerEXT( GLenum type, GLsizei stride, const GLvoid *pointer ) +{ +#if CR_ARB_vertex_buffer_object + GET_CONTEXT(ctx); + if (ctx->clientState->extensions.ARB_vertex_buffer_object) { + if (pack_spu.swap) + crPackFogCoordPointerEXTSWAP( type, stride, pointer ); + else + crPackFogCoordPointerEXT( type, stride, pointer ); + } +#endif + crStateFogCoordPointerEXT( type, stride, pointer ); +} + +void PACKSPU_APIENTRY packspu_ColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) +{ +#if CR_ARB_vertex_buffer_object + GET_CONTEXT(ctx); + if (ctx->clientState->extensions.ARB_vertex_buffer_object) { + if (pack_spu.swap) + crPackColorPointerSWAP( size, type, stride, pointer ); + else + crPackColorPointer( size, type, stride, pointer ); + } +#endif + crStateColorPointer( size, type, stride, pointer ); +} + +void PACKSPU_APIENTRY packspu_SecondaryColorPointerEXT( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) +{ +#if CR_ARB_vertex_buffer_object + GET_CONTEXT(ctx); + if (ctx->clientState->extensions.ARB_vertex_buffer_object) { + if (pack_spu.swap) + crPackSecondaryColorPointerEXTSWAP( size, type, stride, pointer ); + else + crPackSecondaryColorPointerEXT( size, type, stride, pointer ); + } +#endif + crStateSecondaryColorPointerEXT( size, type, stride, pointer ); +} + +void PACKSPU_APIENTRY packspu_VertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) +{ +#if CR_ARB_vertex_buffer_object + GET_CONTEXT(ctx); + CRASSERT(ctx->clientState->extensions.ARB_vertex_buffer_object); + if (ctx->clientState->extensions.ARB_vertex_buffer_object) { + if (pack_spu.swap) + crPackVertexPointerSWAP( size, type, stride, pointer ); + else + crPackVertexPointer( size, type, stride, pointer ); + } +#endif + crStateVertexPointer( size, type, stride, pointer ); +} + +void PACKSPU_APIENTRY packspu_TexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) +{ +#if CR_ARB_vertex_buffer_object + GET_CONTEXT(ctx); + if (ctx->clientState->extensions.ARB_vertex_buffer_object) { + if (pack_spu.swap) + crPackTexCoordPointerSWAP( size, type, stride, pointer ); + else + crPackTexCoordPointer( size, type, stride, pointer ); + } +#endif + crStateTexCoordPointer( size, type, stride, pointer ); +} + +void PACKSPU_APIENTRY packspu_NormalPointer( GLenum type, GLsizei stride, const GLvoid *pointer ) +{ +#if CR_ARB_vertex_buffer_object + GET_CONTEXT(ctx); + if (ctx->clientState->extensions.ARB_vertex_buffer_object) { + if (pack_spu.swap) + crPackNormalPointerSWAP( type, stride, pointer ); + else + crPackNormalPointer( type, stride, pointer ); + } +#endif + crStateNormalPointer( type, stride, pointer ); +} + +void PACKSPU_APIENTRY packspu_EdgeFlagPointer( GLsizei stride, const GLvoid *pointer ) +{ +#if CR_ARB_vertex_buffer_object + GET_CONTEXT(ctx); + if (ctx->clientState->extensions.ARB_vertex_buffer_object) { + if (pack_spu.swap) + crPackEdgeFlagPointerSWAP( stride, pointer ); + else + crPackEdgeFlagPointer( stride, pointer ); + } +#endif + crStateEdgeFlagPointer( stride, pointer ); +} + +void PACKSPU_APIENTRY packspu_VertexAttribPointerARB( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer ) +{ +#if CR_ARB_vertex_buffer_object + GET_CONTEXT(ctx); + if (ctx->clientState->extensions.ARB_vertex_buffer_object) { + if (pack_spu.swap) + crPackVertexAttribPointerARBSWAP( index, size, type, normalized, stride, pointer ); + else + crPackVertexAttribPointerARB( index, size, type, normalized, stride, pointer ); + } +#endif + crStateVertexAttribPointerARB( index, size, type, normalized, stride, pointer ); +} + +void PACKSPU_APIENTRY packspu_VertexAttribPointerNV( GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) +{ +#if CR_ARB_vertex_buffer_object + GET_CONTEXT(ctx); + if (ctx->clientState->extensions.ARB_vertex_buffer_object) { + if (pack_spu.swap) + crPackVertexAttribPointerNVSWAP( index, size, type, stride, pointer ); + else + crPackVertexAttribPointerNV( index, size, type, stride, pointer ); + } +#endif + crStateVertexAttribPointerNV( index, size, type, stride, pointer ); +} + +void PACKSPU_APIENTRY packspu_IndexPointer( GLenum type, GLsizei stride, const GLvoid *pointer ) +{ +#if CR_ARB_vertex_buffer_object + GET_CONTEXT(ctx); + if (ctx->clientState->extensions.ARB_vertex_buffer_object) { + if (pack_spu.swap) + crPackIndexPointerSWAP( type, stride, pointer ); + else + crPackIndexPointer( type, stride, pointer ); + } +#endif + crStateIndexPointer(type, stride, pointer); +} + +void PACKSPU_APIENTRY packspu_GetPointerv( GLenum pname, GLvoid **params ) +{ + crStateGetPointerv( pname, params ); +} + +void PACKSPU_APIENTRY packspu_InterleavedArrays( GLenum format, GLsizei stride, const GLvoid *pointer ) +{ +#if CR_ARB_vertex_buffer_object + GET_CONTEXT(ctx); + if (ctx->clientState->extensions.ARB_vertex_buffer_object) { + if (pack_spu.swap) + crPackInterleavedArraysSWAP( format, stride, pointer ); + else + crPackInterleavedArrays( format, stride, pointer ); + } +#endif + + /*crDebug("packspu_InterleavedArrays");*/ + + crStateInterleavedArrays( format, stride, pointer ); +} + +#ifdef DEBUG_misha +/* debugging */ +//# define CR_FORCE_ZVA_SERVER_ARRAY +#endif +# define CR_FORCE_ZVA_EXPAND + + +static GLboolean packspuZvaCreate(ContextInfo *pCtx, const GLfloat *pValue, GLuint cValues) +{ + ZvaBufferInfo *pInfo = &pCtx->zvaBufferInfo; + GLuint cbValue = 4 * sizeof (*pValue); + GLuint cbValues = cValues * cbValue; + GLfloat *pBuffer; + uint8_t *pu8Buf; + GLuint i; + + /* quickly sort out if we can use the current value */ + if (pInfo->idBuffer + && pInfo->cValues >= cValues + && !crMemcmp(pValue, &pInfo->Value, cbValue)) + return GL_FALSE; + + pBuffer = (GLfloat*)crAlloc(cbValues); + if (!pBuffer) + { + WARN(("crAlloc for pBuffer failed")); + return GL_FALSE; + } + + pu8Buf = (uint8_t *)pBuffer; + for (i = 0; i < cValues; ++i) + { + crMemcpy(pu8Buf, pValue, cbValue); + pu8Buf += cbValue; + } + + /* */ + if (!pInfo->idBuffer) + { + pack_spu.self.GenBuffersARB(1, &pInfo->idBuffer); + Assert(pInfo->idBuffer); + } + + pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pInfo->idBuffer); + + if (pInfo->cbBuffer < cbValues) + { + pack_spu.self.BufferDataARB(GL_ARRAY_BUFFER_ARB, cbValues, pBuffer, GL_DYNAMIC_DRAW_ARB); + pInfo->cbBuffer = cbValues; + } + else + { + pack_spu.self.BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, cbValues, pBuffer); + } + + pInfo->cValues = cValues; + crMemcpy(&pInfo->Value, pValue, cbValue); + + crFree(pBuffer); + + return GL_TRUE; +} + +typedef struct +{ + ContextInfo *pCtx; + GLuint idBuffer; + CRClientPointer cp; +} CR_ZVA_RESTORE_CTX; + +static void packspuZvaEnable(ContextInfo *pCtx, const GLfloat *pValue, GLuint cValues, CR_ZVA_RESTORE_CTX *pRestoreCtx) +{ + CRContext *g = pCtx->clientState; + + Assert(0); + +#ifdef DEBUG + { + CRContext *pCurState = crStateGetCurrent(); + + Assert(g == pCurState); + } +#endif + + pRestoreCtx->pCtx = pCtx; + pRestoreCtx->idBuffer = g->bufferobject.arrayBuffer ? g->bufferobject.arrayBuffer->id : 0; + pRestoreCtx->cp = g->client.array.a[0]; + + Assert(!pRestoreCtx->cp.enabled); + + /* buffer ref count mechanism does not work actually atm, + * still ensure the buffer does not get destroyed if we fix it in the future */ + if (pRestoreCtx->cp.buffer) + pRestoreCtx->cp.buffer->refCount++; + + packspuZvaCreate(pCtx, pValue, cValues); + + pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pCtx->zvaBufferInfo.idBuffer); + + pack_spu.self.VertexAttribPointerARB(0, 4, GL_FLOAT, + GL_FALSE, /*normalized*/ + 0, /*stride*/ + NULL /*addr*/); + + pack_spu.self.EnableVertexAttribArrayARB(0); +} + +static void packspuZvaDisable(CR_ZVA_RESTORE_CTX *pRestoreCtx) +{ + if (pRestoreCtx->cp.buffer) + pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pRestoreCtx->cp.buffer->id); + else + pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + + pack_spu.self.VertexAttribPointerARB(0, pRestoreCtx->cp.size, pRestoreCtx->cp.type, + pRestoreCtx->cp.normalized, /*normalized*/ + pRestoreCtx->cp.stride, /*stride*/ + pRestoreCtx->cp.p); + + if (pRestoreCtx->cp.enabled) + pack_spu.self.EnableVertexAttribArrayARB(0); + else + pack_spu.self.DisableVertexAttribArrayARB(0); + + if (pRestoreCtx->cp.buffer) + { + if (pRestoreCtx->cp.buffer->id != pRestoreCtx->idBuffer) + pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pRestoreCtx->idBuffer); + + /* we have increased the refcount above, decrease it back */ + pRestoreCtx->cp.buffer->refCount--; + } + else + { + if (pRestoreCtx->idBuffer) + pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pRestoreCtx->idBuffer); + } + +#ifdef DEBUG + { + CRContext *g = pRestoreCtx->pCtx->clientState; + CRContext *pCurState = crStateGetCurrent(); + + Assert(g == pCurState); + + Assert(pRestoreCtx->cp.p == g->client.array.a[0].p); + Assert(pRestoreCtx->cp.size == g->client.array.a[0].size); + Assert(pRestoreCtx->cp.type == g->client.array.a[0].type); + Assert(pRestoreCtx->cp.stride == g->client.array.a[0].stride); + Assert(pRestoreCtx->cp.enabled == g->client.array.a[0].enabled); + Assert(pRestoreCtx->cp.normalized == g->client.array.a[0].normalized); + Assert(pRestoreCtx->cp.bytesPerIndex == g->client.array.a[0].bytesPerIndex); +# ifdef CR_ARB_vertex_buffer_object + Assert(pRestoreCtx->cp.buffer == g->client.array.a[0].buffer); +# endif +# ifdef CR_EXT_compiled_vertex_array + Assert(pRestoreCtx->cp.locked == g->client.array.a[0].locked); +# endif + Assert(pRestoreCtx->idBuffer == (g->bufferobject.arrayBuffer ? g->bufferobject.arrayBuffer->id : 0)); + } +#endif +} + +void PACKSPU_APIENTRY +packspu_ArrayElement( GLint index ) +{ +/** @todo cash guest/host pointers calculation and use appropriate path here without crStateUseServerArrays call*/ +#if 1 + GLboolean serverArrays = GL_FALSE; + GLuint cZvaValues = 0; + GLfloat aAttrib[4]; + +#if CR_ARB_vertex_buffer_object + { + GET_CONTEXT(ctx); + /*crDebug("packspu_ArrayElement index:%i", index);*/ + if (ctx->clientState->extensions.ARB_vertex_buffer_object) + { + serverArrays = crStateUseServerArrays(); + if (ctx->fCheckZerroVertAttr) + cZvaValues = crStateNeedDummyZeroVertexArray(thread->currentContext->clientState, &thread->packer->current, aAttrib); + } + } +#endif + + if (serverArrays +#ifdef CR_FORCE_ZVA_EXPAND + && !cZvaValues +#endif + ) { + CR_ZVA_RESTORE_CTX RestoreCtx; + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + + Assert(cZvaValues < UINT32_MAX/2); + + /* LockArraysEXT can not be executed between glBegin/glEnd pair, it also + * leads to vertexpointers being adjusted on the host side between glBegin/glEnd calls which + * produces unpredictable results. Locking is done before the glBegin call instead. + */ + CRASSERT(!clientState->array.locked || clientState->array.synced); + + if (cZvaValues) + packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx); + + /* Send the DrawArrays command over the wire */ + if (pack_spu.swap) + crPackArrayElementSWAP( index ); + else + crPackArrayElement( index ); + + if (cZvaValues) + packspuZvaDisable(&RestoreCtx); + } + else { + /* evaluate locally */ + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + +#ifdef CR_FORCE_ZVA_SERVER_ARRAY + CR_ZVA_RESTORE_CTX RestoreCtx; + + if (cZvaValues && cZvaValues < UINT32_MAX/2) + packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx); +#endif + + if (pack_spu.swap) + crPackExpandArrayElementSWAP( index, clientState, cZvaValues ? aAttrib : NULL ); + else + crPackExpandArrayElement( index, clientState, cZvaValues ? aAttrib : NULL ); + +#ifdef CR_FORCE_ZVA_SERVER_ARRAY + if (cZvaValues && cZvaValues < UINT32_MAX/2) + packspuZvaDisable(&RestoreCtx); +#endif + } +#else + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + crPackExpandArrayElement(index, clientState, NULL); +#endif +} + +/*#define CR_USE_LOCKARRAYS*/ +#ifdef CR_USE_LOCKARRAYS +# error "check Zero Vertex Attrib hack is supported properly!" +#endif + +void PACKSPU_APIENTRY +packspu_DrawElements( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices ) +{ + GLboolean serverArrays = GL_FALSE; + GLuint cZvaValues = 0; + GLfloat aAttrib[4]; + +#if CR_ARB_vertex_buffer_object + GLboolean lockedArrays = GL_FALSE; + CRBufferObject *elementsBuffer; + { + GET_CONTEXT(ctx); + elementsBuffer = crStateGetCurrent()->bufferobject.elementsBuffer; + /*crDebug("DrawElements count=%d, indices=%p", count, indices);*/ + if (ctx->clientState->extensions.ARB_vertex_buffer_object) + { + serverArrays = crStateUseServerArrays(); + if (ctx->fCheckZerroVertAttr) + cZvaValues = crStateNeedDummyZeroVertexArray(thread->currentContext->clientState, &thread->packer->current, aAttrib); + } + } + +# ifdef CR_USE_LOCKARRAYS + if (!serverArrays && !ctx->clientState->client.array.locked && (count>3) + && (!elementsBuffer || !elementsBuffer->id)) + { + GLuint min, max; + GLsizei i; + + switch (type) + { + case GL_UNSIGNED_BYTE: + { + GLubyte *pIdx = (GLubyte *)indices; + min = max = pIdx[0]; + for (i=0; i<count; ++i) + { + if (pIdx[i]<min) min = pIdx[i]; + else if (pIdx[i]>max) max = pIdx[i]; + } + break; + } + case GL_UNSIGNED_SHORT: + { + GLushort *pIdx = (GLushort *)indices; + min = max = pIdx[0]; + for (i=0; i<count; ++i) + { + if (pIdx[i]<min) min = pIdx[i]; + else if (pIdx[i]>max) max = pIdx[i]; + } + break; + } + case GL_UNSIGNED_INT: + { + GLuint *pIdx = (GLuint *)indices; + min = max = pIdx[0]; + for (i=0; i<count; ++i) + { + if (pIdx[i]<min) min = pIdx[i]; + else if (pIdx[i]>max) max = pIdx[i]; + } + break; + } + default: crError("Unknown type 0x%x", type); + } + + if ((max-min)<(GLuint)(2*count)) + { + crStateLockArraysEXT(min, max-min+1); + + serverArrays = crStateUseServerArrays(); + if (serverArrays) + { + lockedArrays = GL_TRUE; + } + else + { + crStateUnlockArraysEXT(); + } + } + } +# endif +#endif + + if (serverArrays +#ifdef CR_FORCE_ZVA_EXPAND + && !cZvaValues +#endif + ) { + CR_ZVA_RESTORE_CTX RestoreCtx; + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + + Assert(cZvaValues < UINT32_MAX/2); + + if (cZvaValues) + packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx); + + /*Note the comment in packspu_LockArraysEXT*/ + if (clientState->array.locked && !clientState->array.synced) + { + crPackLockArraysEXT(clientState->array.lockFirst, clientState->array.lockCount); + clientState->array.synced = GL_TRUE; + } + + /* Send the DrawArrays command over the wire */ + if (pack_spu.swap) + crPackDrawElementsSWAP( mode, count, type, indices ); + else + crPackDrawElements( mode, count, type, indices ); + + if (cZvaValues) + packspuZvaDisable(&RestoreCtx); + } + else { + /* evaluate locally */ + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + +#ifdef CR_FORCE_ZVA_SERVER_ARRAY + CR_ZVA_RESTORE_CTX RestoreCtx; + + if (cZvaValues && cZvaValues < UINT32_MAX/2) + packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx); +#endif + + if (pack_spu.swap) + crPackExpandDrawElementsSWAP( mode, count, type, indices, clientState, cZvaValues ? aAttrib : NULL ); + else + { + //packspu_Begin(mode); + crPackExpandDrawElements( mode, count, type, indices, clientState, cZvaValues ? aAttrib : NULL ); + //packspu_End(); + } + +#ifdef CR_FORCE_ZVA_SERVER_ARRAY + if (cZvaValues && cZvaValues < UINT32_MAX/2) + packspuZvaDisable(&RestoreCtx); +#endif + } + +#if CR_ARB_vertex_buffer_object + if (lockedArrays) + { + packspu_UnlockArraysEXT(); + } +#endif +} + + +void PACKSPU_APIENTRY +packspu_DrawRangeElements( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices ) +{ + GLboolean serverArrays = GL_FALSE; + GLuint cZvaValues = 0; + GLfloat aAttrib[4]; + +#if CR_ARB_vertex_buffer_object + { + GET_CONTEXT(ctx); + /*crDebug("DrawRangeElements count=%d", count);*/ + if (ctx->clientState->extensions.ARB_vertex_buffer_object) + { + serverArrays = crStateUseServerArrays(); + if (ctx->fCheckZerroVertAttr) + cZvaValues = crStateNeedDummyZeroVertexArray(thread->currentContext->clientState, &thread->packer->current, aAttrib); + } + } +#endif + + if (serverArrays +#ifdef CR_FORCE_ZVA_EXPAND + && !cZvaValues +#endif + ) { + CR_ZVA_RESTORE_CTX RestoreCtx; + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + + Assert(cZvaValues < UINT32_MAX/2); + + if (cZvaValues) + packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx); + + /*Note the comment in packspu_LockArraysEXT*/ + if (clientState->array.locked && !clientState->array.synced) + { + crPackLockArraysEXT(clientState->array.lockFirst, clientState->array.lockCount); + clientState->array.synced = GL_TRUE; + } + + /* Send the DrawRangeElements command over the wire */ + if (pack_spu.swap) + crPackDrawRangeElementsSWAP( mode, start, end, count, type, indices ); + else + crPackDrawRangeElements( mode, start, end, count, type, indices ); + + if (cZvaValues) + packspuZvaDisable(&RestoreCtx); + } + else { + /* evaluate locally */ + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); +#ifdef CR_FORCE_ZVA_SERVER_ARRAY + CR_ZVA_RESTORE_CTX RestoreCtx; + + if (cZvaValues && cZvaValues < UINT32_MAX/2) + packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx); +#endif + + if (pack_spu.swap) + crPackExpandDrawRangeElementsSWAP( mode, start, end, count, type, indices, clientState, cZvaValues ? aAttrib : NULL ); + else + { + crPackExpandDrawRangeElements( mode, start, end, count, type, indices, clientState, cZvaValues ? aAttrib : NULL ); + } + +#ifdef CR_FORCE_ZVA_SERVER_ARRAY + if (cZvaValues && cZvaValues < UINT32_MAX/2) + packspuZvaDisable(&RestoreCtx); +#endif + } +} + + +void PACKSPU_APIENTRY +packspu_DrawArrays( GLenum mode, GLint first, GLsizei count ) +{ + GLboolean serverArrays = GL_FALSE; + GLuint cZvaValues = 0; + GLfloat aAttrib[4]; + +#if CR_ARB_vertex_buffer_object + GLboolean lockedArrays = GL_FALSE; + { + GET_CONTEXT(ctx); + /*crDebug("DrawArrays count=%d", count);*/ + if (ctx->clientState->extensions.ARB_vertex_buffer_object) + { + serverArrays = crStateUseServerArrays(); + if (ctx->fCheckZerroVertAttr) + cZvaValues = crStateNeedDummyZeroVertexArray(thread->currentContext->clientState, &thread->packer->current, aAttrib); + } + } + +# ifdef CR_USE_LOCKARRAYS + if (!serverArrays && !ctx->clientState->client.array.locked && (count>3)) + { + crStateLockArraysEXT(first, count); + serverArrays = crStateUseServerArrays(); + if (serverArrays) + { + lockedArrays = GL_TRUE; + } + else + { + crStateUnlockArraysEXT(); + } + } +# endif +#endif + + if (serverArrays +#ifdef CR_FORCE_ZVA_EXPAND + && !cZvaValues +#endif + ) + { + CR_ZVA_RESTORE_CTX RestoreCtx; + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + + Assert(cZvaValues < UINT32_MAX/2); + + if (cZvaValues) + packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx); + + /*Note the comment in packspu_LockArraysEXT*/ + if (clientState->array.locked && !clientState->array.synced) + { + crPackLockArraysEXT(clientState->array.lockFirst, clientState->array.lockCount); + clientState->array.synced = GL_TRUE; + } + + /* Send the DrawArrays command over the wire */ + if (pack_spu.swap) + crPackDrawArraysSWAP( mode, first, count ); + else + crPackDrawArrays( mode, first, count ); + + if (cZvaValues) + packspuZvaDisable(&RestoreCtx); + } + else + { + /* evaluate locally */ + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); +#ifdef CR_FORCE_ZVA_SERVER_ARRAY + CR_ZVA_RESTORE_CTX RestoreCtx; + + if (cZvaValues && cZvaValues < UINT32_MAX/2) + packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx); +#endif + + if (pack_spu.swap) + crPackExpandDrawArraysSWAP( mode, first, count, clientState, cZvaValues ? aAttrib : NULL ); + else + crPackExpandDrawArrays( mode, first, count, clientState, cZvaValues ? aAttrib : NULL ); + +#ifdef CR_FORCE_ZVA_SERVER_ARRAY + if (cZvaValues && cZvaValues < UINT32_MAX/2) + packspuZvaDisable(&RestoreCtx); +#endif + + } + +#if CR_ARB_vertex_buffer_object + if (lockedArrays) + { + packspu_UnlockArraysEXT(); + } +#endif +} + + +#ifdef CR_EXT_multi_draw_arrays +void PACKSPU_APIENTRY packspu_MultiDrawArraysEXT( GLenum mode, GLint *first, GLsizei *count, GLsizei primcount ) +{ + GLint i; + for (i = 0; i < primcount; i++) { + if (count[i] > 0) { + packspu_DrawArrays(mode, first[i], count[i]); + } + } +} + +void PACKSPU_APIENTRY packspu_MultiDrawElementsEXT( GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount ) +{ + GLint i; + for (i = 0; i < primcount; i++) { + if (count[i] > 0) { + packspu_DrawElements(mode, count[i], type, indices[i]); + } + } +} +#endif + + +void PACKSPU_APIENTRY packspu_EnableClientState( GLenum array ) +{ + crStateEnableClientState(array); + crPackEnableClientState(array); +} + +void PACKSPU_APIENTRY packspu_DisableClientState( GLenum array ) +{ + crStateDisableClientState(array); + crPackDisableClientState(array); +} + +void PACKSPU_APIENTRY packspu_ClientActiveTextureARB( GLenum texUnit ) +{ + crStateClientActiveTextureARB(texUnit); + crPackClientActiveTextureARB(texUnit); +} + +void PACKSPU_APIENTRY packspu_EnableVertexAttribArrayARB(GLuint index) +{ + crStateEnableVertexAttribArrayARB(index); + crPackEnableVertexAttribArrayARB(index); +} + + +void PACKSPU_APIENTRY packspu_DisableVertexAttribArrayARB(GLuint index) +{ + crStateDisableVertexAttribArrayARB(index); + crPackDisableVertexAttribArrayARB(index); +} + +void PACKSPU_APIENTRY packspu_Enable( GLenum cap ) +{ + if (cap!=GL_LIGHT_MODEL_TWO_SIDE) + { + crStateEnable(cap); + + if (pack_spu.swap) + crPackEnableSWAP(cap); + else + crPackEnable(cap); + } + else + { + static int g_glmts1_warn=0; + if (!g_glmts1_warn) + { + crWarning("glEnable(GL_LIGHT_MODEL_TWO_SIDE) converted to valid glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,1)"); + g_glmts1_warn=1; + } + crStateLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1); + crPackLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1); + } +} + + +void PACKSPU_APIENTRY packspu_Disable( GLenum cap ) +{ + if (cap!=GL_LIGHT_MODEL_TWO_SIDE) + { + crStateDisable(cap); + + if (pack_spu.swap) + crPackDisableSWAP(cap); + else + crPackDisable(cap); + } + else + { + static int g_glmts0_warn=0; + if (!g_glmts0_warn) + { + crWarning("glDisable(GL_LIGHT_MODEL_TWO_SIDE) converted to valid glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,0)"); + g_glmts0_warn=1; + } + crStateLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); + crPackLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); + } +} + +GLboolean PACKSPU_APIENTRY packspu_IsEnabled(GLenum cap) +{ + GLboolean res = crStateIsEnabled(cap); +#ifdef DEBUG + { + GET_THREAD(thread); + int writeback = 1; + GLboolean return_val = (GLboolean) 0; + crPackIsEnabled(cap, &return_val, &writeback); + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + CRASSERT(return_val==res); + } +#endif + + return res; +} + +void PACKSPU_APIENTRY packspu_PushClientAttrib( GLbitfield mask ) +{ + crStatePushClientAttrib(mask); + crPackPushClientAttrib(mask); +} + +void PACKSPU_APIENTRY packspu_PopClientAttrib( void ) +{ + crStatePopClientAttrib(); + crPackPopClientAttrib(); +} + +void PACKSPU_APIENTRY packspu_LockArraysEXT(GLint first, GLint count) +{ + if (first>=0 && count>0) + { + crStateLockArraysEXT(first, count); + /*Note: this is a workaround for quake3 based apps. + It's modifying vertex data between glLockArraysEXT and glDrawElements calls, + so we'd pass data to host right before the glDrawSomething or glBegin call. + */ + /*crPackLockArraysEXT(first, count);*/ + } + else crDebug("Ignoring packspu_LockArraysEXT: first:%i, count:%i", first, count); +} + +void PACKSPU_APIENTRY packspu_UnlockArraysEXT() +{ + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + + if (clientState->array.locked && clientState->array.synced) + { + crPackUnlockArraysEXT(); + } + + crStateUnlockArraysEXT(); +} diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_config.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_config.c new file mode 100644 index 00000000..70d6f01c --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_config.c @@ -0,0 +1,60 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "packspu.h" +#include "cr_string.h" +#include "cr_error.h" +#include "cr_spu.h" +#include "cr_mem.h" + +#include <stdio.h> + +static void __setDefaults( void ) +{ + crMemZero(pack_spu.context, CR_MAX_CONTEXTS * sizeof(ContextInfo)); + pack_spu.numContexts = 0; + + crMemZero(pack_spu.thread, MAX_THREADS * sizeof(ThreadInfo)); + pack_spu.numThreads = 0; +} + + +static void set_emit( void *foo, const char *response ) +{ + RT_NOREF(foo); + sscanf( response, "%d", &(pack_spu.emit_GATHER_POST_SWAPBUFFERS) ); +} + +static void set_swapbuffer_sync( void *foo, const char *response ) +{ + RT_NOREF(foo); + sscanf( response, "%d", &(pack_spu.swapbuffer_sync) ); +} + + + +/* No SPU options yet. Well.. not really.. + */ +SPUOptions packSPUOptions[] = { + { "emit_GATHER_POST_SWAPBUFFERS", CR_BOOL, 1, "0", NULL, NULL, + "Emit a parameter after SwapBuffers", (SPUOptionCB)set_emit }, + + { "swapbuffer_sync", CR_BOOL, 1, "1", NULL, NULL, + "Sync on SwapBuffers", (SPUOptionCB) set_swapbuffer_sync }, + + { NULL, CR_BOOL, 0, NULL, NULL, NULL, NULL, NULL }, +}; + + +void packspuSetVBoxConfiguration( const SPU *child_spu ) +{ + RT_NOREF(child_spu); + __setDefaults(); + pack_spu.emit_GATHER_POST_SWAPBUFFERS = 0; + pack_spu.swapbuffer_sync = 0; + pack_spu.name = crStrdup("vboxhgcm://llp:7000"); + pack_spu.buffer_size = 5 * 1024 * 1024; +} diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_context.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_context.c new file mode 100644 index 00000000..26e81dbd --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_context.c @@ -0,0 +1,617 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "packspu.h" +#include "cr_mem.h" +#include "cr_packfunctions.h" +#include "cr_string.h" +#include "packspu_proto.h" + +/* + * Allocate a new ThreadInfo structure, setup a connection to the + * server, allocate/init a packer context, bind this ThreadInfo to + * the calling thread with crSetTSD(). + * We'll always call this function at least once even if we're not + * using threads. + */ +ThreadInfo *packspuNewThread( +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + struct VBOXUHGSMI *pHgsmi +#else + void +#endif +) +{ + ThreadInfo *thread=NULL; + int i; + +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&_PackMutex); +#else + CRASSERT(pack_spu.numThreads == 0); +#endif + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + CRASSERT(!CRPACKSPU_IS_WDDM_CRHGSMI() == !pHgsmi); +#endif + + CRASSERT(pack_spu.numThreads < MAX_THREADS); + for (i=0; i<MAX_THREADS; ++i) + { + if (!pack_spu.thread[i].inUse) + { + thread = &pack_spu.thread[i]; + break; + } + } + CRASSERT(thread); + + thread->inUse = GL_TRUE; + if (!CRPACKSPU_IS_WDDM_CRHGSMI()) + thread->id = crThreadID(); + else + thread->id = THREAD_OFFSET_MAGIC + i; + thread->currentContext = NULL; + thread->bInjectThread = GL_FALSE; + + /* connect to the server */ + thread->netServer.name = crStrdup( pack_spu.name ); + thread->netServer.buffer_size = pack_spu.buffer_size; + packspuConnectToServer( &(thread->netServer) +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , pHgsmi +#endif + ); + CRASSERT(thread->netServer.conn); + /* packer setup */ + CRASSERT(thread->packer == NULL); + thread->packer = crPackNewContext( pack_spu.swap ); + CRASSERT(thread->packer); + crPackInitBuffer( &(thread->buffer), crNetAlloc(thread->netServer.conn), + thread->netServer.conn->buffer_size, thread->netServer.conn->mtu ); + thread->buffer.canBarf = thread->netServer.conn->Barf ? GL_TRUE : GL_FALSE; + crPackSetBuffer( thread->packer, &thread->buffer ); + crPackFlushFunc( thread->packer, packspuFlush ); + crPackFlushArg( thread->packer, (void *) thread ); + crPackSendHugeFunc( thread->packer, packspuHuge ); + + if (!CRPACKSPU_IS_WDDM_CRHGSMI()) + { + crPackSetContext( thread->packer ); + } + + +#ifdef CHROMIUM_THREADSAFE + if (!CRPACKSPU_IS_WDDM_CRHGSMI()) + { + crSetTSD(&_PackTSD, thread); + } +#endif + + pack_spu.numThreads++; + +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&_PackMutex); +#endif + return thread; +} + +GLint PACKSPU_APIENTRY +packspu_VBoxConCreate(struct VBOXUHGSMI *pHgsmi) +{ +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + ThreadInfo * thread; + CRASSERT(CRPACKSPU_IS_WDDM_CRHGSMI()); + CRASSERT(pHgsmi); + + thread = packspuNewThread(pHgsmi); + + if (thread) + { + CRASSERT(thread->id); + CRASSERT(thread->id - THREAD_OFFSET_MAGIC < RT_ELEMENTS(pack_spu.thread) + && GET_THREAD_VAL_ID(thread->id) == thread); + return thread->id; + } + crError("packspuNewThread failed"); +#else + RT_NOREF(pHgsmi); +#endif + return 0; +} + +void PACKSPU_APIENTRY +packspu_VBoxConFlush(GLint con) +{ +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + GET_THREAD_ID(thread, con); + CRASSERT(con); + CRASSERT(CRPACKSPU_IS_WDDM_CRHGSMI()); + CRASSERT(thread->packer); + packspuFlush((void *) thread); +#else + RT_NOREF(con); + crError("VBoxConFlush not implemented!"); +#endif +} + +void PACKSPU_APIENTRY +packspu_VBoxConDestroy(GLint con) +{ +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + GET_THREAD_ID(thread, con); + CRASSERT(con); + CRASSERT(CRPACKSPU_IS_WDDM_CRHGSMI()); + CRASSERT(pack_spu.numThreads>0); + CRASSERT(thread->packer); + packspuFlush((void *) thread); + + crLockMutex(&_PackMutex); + + crPackDeleteContext(thread->packer); + + if (thread->buffer.pack) + { + crNetFree(thread->netServer.conn, thread->buffer.pack); + thread->buffer.pack = NULL; + } + + crNetFreeConnection(thread->netServer.conn); + + if (thread->netServer.name) + crFree(thread->netServer.name); + + pack_spu.numThreads--; + /*note can't shift the array here, because other threads have TLS references to array elements*/ + crMemZero(thread, sizeof(ThreadInfo)); + +#if 0 + if (&pack_spu.thread[pack_spu.idxThreadInUse]==thread) + { + int i; + crError("Should not be here since idxThreadInUse should be always 0 for the dummy connection created in packSPUInit!"); + for (i=0; i<MAX_THREADS; ++i) + { + if (pack_spu.thread[i].inUse) + { + pack_spu.idxThreadInUse=i; + break; + } + } + } +#endif + crUnlockMutex(&_PackMutex); +#else + RT_NOREF(con); +#endif +} + +GLvoid PACKSPU_APIENTRY +packspu_VBoxConChromiumParameteriCR(GLint con, GLenum param, GLint value) +{ + GET_THREAD(thread); + CRPackContext * curPacker = crPackGetContext(); + ThreadInfo *curThread = thread; + + CRASSERT(!curThread == !curPacker); + CRASSERT(!curThread || !curPacker || curThread->packer == curPacker); +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&_PackMutex); +#endif + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + CRASSERT(!con == !CRPACKSPU_IS_WDDM_CRHGSMI()); +#endif + + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + if (!con) + { + crError("connection should be specified!"); + return; + } + thread = GET_THREAD_VAL_ID(con); + } + else + { + CRASSERT(!con); + if (!thread) + { + thread = packspuNewThread( +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + NULL +#endif + ); + } + } + CRASSERT(thread); + CRASSERT(thread->packer); + + crPackSetContext( thread->packer ); + + packspu_ChromiumParameteriCR(param, value); + +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&_PackMutex); +#endif + + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + /* restore the packer context to the tls */ + crPackSetContext(curPacker); + } +} + +GLvoid PACKSPU_APIENTRY +packspu_VBoxConChromiumParametervCR(GLint con, GLenum target, GLenum type, GLsizei count, const GLvoid *values) +{ + GET_THREAD(thread); + CRPackContext * curPacker = crPackGetContext(); + ThreadInfo *curThread = thread; + + CRASSERT(!curThread == !curPacker); + CRASSERT(!curThread || !curPacker || curThread->packer == curPacker); +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&_PackMutex); +#endif + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + CRASSERT(!con == !CRPACKSPU_IS_WDDM_CRHGSMI()); +#endif + + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + if (!con) + { + crError("connection should be specified!"); + return; + } + thread = GET_THREAD_VAL_ID(con); + } + else + { + CRASSERT(!con); + if (!thread) + { + thread = packspuNewThread( +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + NULL +#endif + ); + } + } + CRASSERT(thread); + CRASSERT(thread->packer); + + crPackSetContext( thread->packer ); + + packspu_ChromiumParametervCR(target, type, count, values); + +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&_PackMutex); +#endif + + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + /* restore the packer context to the tls */ + crPackSetContext(curPacker); + } +} + +GLint PACKSPU_APIENTRY +packspu_VBoxCreateContext( GLint con, const char *dpyName, GLint visual, GLint shareCtx ) +{ + GET_THREAD(thread); + CRPackContext * curPacker = crPackGetContext(); + ThreadInfo *curThread = thread; + int writeback = 1; + GLint serverCtx = (GLint) -1; + int slot; + + CRASSERT(!curThread == !curPacker); + CRASSERT(!curThread || !curPacker || curThread->packer == curPacker); +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&_PackMutex); +#endif + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + CRASSERT(!con == !CRPACKSPU_IS_WDDM_CRHGSMI()); +#endif + + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + if (!con) + { + crError("connection should be specified!"); + return -1; + } + thread = GET_THREAD_VAL_ID(con); + } + else + { + CRASSERT(!con); + if (!thread) + { + thread = packspuNewThread( +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + NULL +#endif + ); + } + } + CRASSERT(thread); + CRASSERT(thread->packer); + + if (shareCtx > 0) { + /* translate to server ctx id */ + shareCtx -= MAGIC_OFFSET; + if (shareCtx >= 0 && shareCtx < pack_spu.numContexts) { + shareCtx = pack_spu.context[shareCtx].serverCtx; + } + } + + crPackSetContext( thread->packer ); + + /* Pack the command */ + if (pack_spu.swap) + crPackCreateContextSWAP( dpyName, visual, shareCtx, &serverCtx, &writeback ); + else + crPackCreateContext( dpyName, visual, shareCtx, &serverCtx, &writeback ); + + /* Flush buffer and get return value */ + packspuFlush(thread); + if (!(thread->netServer.conn->actual_network)) + { + /* HUMUNGOUS HACK TO MATCH SERVER NUMBERING + * + * The hack exists solely to make file networking work for now. This + * is totally gross, but since the server expects the numbers to start + * from 5000, we need to write them out this way. This would be + * marginally less gross if the numbers (500 and 5000) were maybe + * some sort of #define'd constants somewhere so the client and the + * server could be aware of how each other were numbering things in + * cases like file networking where they actually + * care. + * + * -Humper + * + */ + serverCtx = 5000; + } + else { + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + if (pack_spu.swap) { + serverCtx = (GLint) SWAP32(serverCtx); + } + if (serverCtx < 0) { +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&_PackMutex); +#endif + crWarning("Failure in packspu_CreateContext"); + + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + /* restore the packer context to the tls */ + crPackSetContext(curPacker); + } + return -1; /* failed */ + } + } + + /* find an empty context slot */ + for (slot = 0; slot < pack_spu.numContexts; slot++) { + if (!pack_spu.context[slot].clientState) { + /* found empty slot */ + break; + } + } + if (slot == pack_spu.numContexts) { + pack_spu.numContexts++; + } + + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + thread->currentContext = &pack_spu.context[slot]; + pack_spu.context[slot].currentThread = thread; + } + + /* Fill in the new context info */ + /* XXX fix-up sharedCtx param here */ + pack_spu.context[slot].clientState = crStateCreateContext(NULL, visual, NULL); + pack_spu.context[slot].clientState->bufferobject.retainBufferData = GL_TRUE; + pack_spu.context[slot].serverCtx = serverCtx; + +#ifdef CHROMIUM_THREADSAFE + crUnlockMutex(&_PackMutex); +#endif + + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + /* restore the packer context to the tls */ + crPackSetContext(curPacker); + } + + return MAGIC_OFFSET + slot; +} + +GLint PACKSPU_APIENTRY +packspu_CreateContext( const char *dpyName, GLint visual, GLint shareCtx ) +{ + return packspu_VBoxCreateContext( 0, dpyName, visual, shareCtx ); +} + + +void PACKSPU_APIENTRY packspu_DestroyContext( GLint ctx ) +{ + GET_THREAD(thread); + ThreadInfo *curThread = thread; + const int slot = ctx - MAGIC_OFFSET; + ContextInfo *context, *curContext; + CRPackContext * curPacker = crPackGetContext(); + + CRASSERT(slot >= 0); + CRASSERT(slot < pack_spu.numContexts); + + context = (slot >= 0 && slot < pack_spu.numContexts) ? &(pack_spu.context[slot]) : NULL; + curContext = curThread ? curThread->currentContext : NULL; + + if (context) + { + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + thread = context->currentThread; + if (thread) + { + crPackSetContext(thread->packer); + CRASSERT(!(thread->packer == curPacker) == !(thread == curThread)); + } + } + + if (pack_spu.swap) + crPackDestroyContextSWAP( context->serverCtx ); + else + crPackDestroyContext( context->serverCtx ); + + crStateDestroyContext( context->clientState ); + + context->clientState = NULL; + context->serverCtx = 0; + context->currentThread = NULL; + + crMemset (&context->zvaBufferInfo, 0, sizeof (context->zvaBufferInfo)); + } + + if (curContext == context) + { + if (!CRPACKSPU_IS_WDDM_CRHGSMI()) + { + curThread->currentContext = NULL; + } + else + { + CRASSERT(thread == curThread); + crSetTSD(&_PackTSD, NULL); + crPackSetContext(NULL); + } + crStateMakeCurrent( NULL ); + } + else + { + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + crPackSetContext(curPacker); + } + } +} + +void PACKSPU_APIENTRY packspu_MakeCurrent( GLint window, GLint nativeWindow, GLint ctx ) +{ + ThreadInfo *thread = NULL; + GLint serverCtx; + ContextInfo *newCtx = NULL; + + if (!CRPACKSPU_IS_WDDM_CRHGSMI()) + { + thread = GET_THREAD_VAL(); + if (!thread) { + thread = packspuNewThread( +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + NULL +#endif + ); + } + CRASSERT(thread); + CRASSERT(thread->packer); + } + + if (ctx) { + const int slot = ctx - MAGIC_OFFSET; + + CRASSERT(slot >= 0); + CRASSERT(slot < pack_spu.numContexts); + + newCtx = &pack_spu.context[slot]; + CRASSERT(newCtx); + CRASSERT(newCtx->clientState); /* verify valid */ + + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + thread = newCtx->currentThread; + CRASSERT(thread); + crSetTSD(&_PackTSD, thread); + crPackSetContext( thread->packer ); + } + else + { + CRASSERT(thread); + if (newCtx->fAutoFlush) + { + if (newCtx->currentThread && newCtx->currentThread != thread) + { + crLockMutex(&_PackMutex); + /* do a flush for the previously assigned thread + * to ensure all commands issued there are submitted */ + if (newCtx->currentThread + && newCtx->currentThread->inUse + && newCtx->currentThread->netServer.conn + && newCtx->currentThread->packer && newCtx->currentThread->packer->currentBuffer) + { + packspuFlush((void *) newCtx->currentThread); + } + crUnlockMutex(&_PackMutex); + } + newCtx->currentThread = thread; + } + + if (thread->currentContext && newCtx != thread->currentContext && thread->currentContext->fCheckZerroVertAttr) + crStateCurrentRecoverNew(thread->currentContext->clientState, &thread->packer->current); + + thread->currentContext = newCtx; + crPackSetContext( thread->packer ); + } + + crStateMakeCurrent( newCtx->clientState ); + //crStateSetCurrentPointers(newCtx->clientState, &thread->packer->current); + serverCtx = pack_spu.context[slot].serverCtx; + } + else { + crStateMakeCurrent( NULL ); + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + thread = GET_THREAD_VAL(); + if (!thread) + { + CRASSERT(crPackGetContext() == NULL); + return; + } + CRASSERT(thread->currentContext); + CRASSERT(thread->packer == crPackGetContext()); + } + else + { + thread->currentContext = NULL; + } + newCtx = NULL; + serverCtx = 0; + } + + if (pack_spu.swap) + crPackMakeCurrentSWAP( window, nativeWindow, serverCtx ); + else + crPackMakeCurrent( window, nativeWindow, serverCtx ); + + if (serverCtx) + { + packspuInitStrings(); + } + + { + GET_THREAD(t); + (void) t; + CRASSERT(t); + } +} diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_flush.py b/src/VBox/Additions/common/crOpenGL/pack/packspu_flush.py new file mode 100755 index 00000000..5742bcb0 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_flush.py @@ -0,0 +1,42 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - this file generated by packspu_flush.py script */ + +/* These are otherwise ordinary functions which require that the buffer be + * flushed immediately after packing the function. + */ +#include "cr_glstate.h" +#include "cr_packfunctions.h" +#include "packspu.h" +#include "packspu_proto.h" +""") + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +for func_name in apiutil.AllSpecials( "packspu_flush" ): + params = apiutil.Parameters(func_name) + print('void PACKSPU_APIENTRY packspu_%s(%s)' % ( func_name, apiutil.MakeDeclarationString(params))) + print('{') + print('\tGET_THREAD(thread);') + print('\tif (pack_spu.swap)') + print('\t{') + print('\t\tcrPack%sSWAP(%s);' % ( func_name, apiutil.MakeCallString( params ) )) + print('\t}') + print('\telse') + print('\t{') + print('\t\tcrPack%s(%s);' % ( func_name, apiutil.MakeCallString( params ) )) + print('\t}') + print('\tpackspuFlush( (void *) thread );') + print('}\n') diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_flush_special b/src/VBox/Additions/common/crOpenGL/pack/packspu_flush_special new file mode 100644 index 00000000..a4896826 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_flush_special @@ -0,0 +1,9 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +BarrierCreateCR +BarrierExecCR +SemaphoreCreateCR +SemaphorePCR +SemaphoreVCR diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_framebuffer.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_framebuffer.c new file mode 100644 index 00000000..e94c0444 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_framebuffer.c @@ -0,0 +1,143 @@ +/* $Id: packspu_framebuffer.c $ */ + +/** @file + * VBox OpenGL FBO related functions + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include "packspu.h" +#include "cr_packfunctions.h" +#include "cr_net.h" +#include "packspu_proto.h" + +void PACKSPU_APIENTRY +packspu_FramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + crStateFramebufferTexture1DEXT(target, attachment, textarget, texture, level); + crPackFramebufferTexture1DEXT(target, attachment, textarget, texture, level); +} + +void PACKSPU_APIENTRY +packspu_FramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + crStateFramebufferTexture2DEXT(target, attachment, textarget, texture, level); + crPackFramebufferTexture2DEXT(target, attachment, textarget, texture, level); +} + +void PACKSPU_APIENTRY +packspu_FramebufferTexture3DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) +{ + crStateFramebufferTexture3DEXT(target, attachment, textarget, texture, level, zoffset); + crPackFramebufferTexture3DEXT(target, attachment, textarget, texture, level, zoffset); +} + +void PACKSPU_APIENTRY +packspu_BindFramebufferEXT(GLenum target, GLuint framebuffer) +{ + crStateBindFramebufferEXT(target, framebuffer); + crPackBindFramebufferEXT(target, framebuffer); +} + +void PACKSPU_APIENTRY +packspu_DeleteFramebuffersEXT(GLsizei n, const GLuint * framebuffers) +{ + crStateDeleteFramebuffersEXT(n, framebuffers); + crPackDeleteFramebuffersEXT(n, framebuffers); +} + +void PACKSPU_APIENTRY +packspu_DeleteRenderbuffersEXT(GLsizei n, const GLuint * renderbuffers) +{ + crStateDeleteRenderbuffersEXT(n, renderbuffers); + crPackDeleteRenderbuffersEXT(n, renderbuffers); +} + +void PACKSPU_APIENTRY +packspu_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ + crStateFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, renderbuffer); + crPackFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, renderbuffer); +} + +void PACKSPU_APIENTRY +packspu_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) +{ + crStateBindRenderbufferEXT(target, renderbuffer); + crPackBindRenderbufferEXT(target, renderbuffer); +} + +GLenum PACKSPU_APIENTRY +packspu_CheckFramebufferStatusEXT(GLenum target) +{ + GET_THREAD(thread); + int writeback = 1; + GLenum status = crStateCheckFramebufferStatusEXT(target); + + if (status!=GL_FRAMEBUFFER_UNDEFINED) + { + return status; + } + + crPackCheckFramebufferStatusEXT(target, &status, &writeback); + + packspuFlush((void *) thread); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + crStateSetFramebufferStatus(target, status); + return status; +} + +void PACKSPU_APIENTRY packspu_GenFramebuffersEXT( GLsizei n, GLuint * framebuffers ) +{ + GET_THREAD(thread); + int writeback = 1; + if (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network)) + { + crError( "packspu_GenFramebuffersEXT doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!" ); + } + if (pack_spu.swap) + { + crPackGenFramebuffersEXTSWAP( n, framebuffers, &writeback ); + } + else + { + crPackGenFramebuffersEXT( n, framebuffers, &writeback ); + } + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + crStateRegFramebuffers(n, framebuffers); +} + +void PACKSPU_APIENTRY packspu_GenRenderbuffersEXT( GLsizei n, GLuint * renderbuffers ) +{ + GET_THREAD(thread); + int writeback = 1; + if (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network)) + { + crError( "packspu_GenRenderbuffersEXT doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!" ); + } + if (pack_spu.swap) + { + crPackGenRenderbuffersEXTSWAP( n, renderbuffers, &writeback ); + } + else + { + crPackGenRenderbuffersEXT( n, renderbuffers, &writeback ); + } + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + crStateRegRenderbuffers(n, renderbuffers); +} diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_get.py b/src/VBox/Additions/common/crOpenGL/pack/packspu_get.py new file mode 100755 index 00000000..371abeaa --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_get.py @@ -0,0 +1,250 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - THIS FILE AUTOMATICALLY GENERATED BY packspu_get.py SCRIPT */ +#include "packspu.h" +#include "cr_packfunctions.h" +#include "cr_net.h" +#include "cr_mem.h" +#include "packspu_proto.h" +""") + +print(""" +static GLboolean crPackIsPixelStoreParm(GLenum pname) +{ + if (pname == GL_UNPACK_ALIGNMENT + || pname == GL_UNPACK_ROW_LENGTH + || pname == GL_UNPACK_SKIP_PIXELS + || pname == GL_UNPACK_LSB_FIRST + || pname == GL_UNPACK_SWAP_BYTES +#ifdef CR_OPENGL_VERSION_1_2 + || pname == GL_UNPACK_IMAGE_HEIGHT +#endif + || pname == GL_UNPACK_SKIP_ROWS + || pname == GL_PACK_ALIGNMENT + || pname == GL_PACK_ROW_LENGTH + || pname == GL_PACK_SKIP_PIXELS + || pname == GL_PACK_LSB_FIRST + || pname == GL_PACK_SWAP_BYTES +#ifdef CR_OPENGL_VERSION_1_2 + || pname == GL_PACK_IMAGE_HEIGHT +#endif + || pname == GL_PACK_SKIP_ROWS) + { + return GL_TRUE; + } + return GL_FALSE; +} +""") + +from get_sizes import * + +easy_swaps = { + 'GenTextures': '(unsigned int) n', + 'GetClipPlane': '4', + 'GetPolygonStipple': '0' +} + +simple_funcs = [ 'GetIntegerv', 'GetFloatv', 'GetDoublev', 'GetBooleanv' ] +simple_swaps = [ 'SWAP32', 'SWAPFLOAT', 'SWAPDOUBLE', '(GLboolean) SWAP32' ] + +vertattr_get_funcs = [ 'GetVertexAttribdv' 'GetVertexAttribfv' 'GetVertexAttribiv' ] + +hard_funcs = { + 'GetLightfv': 'SWAPFLOAT', + 'GetLightiv': 'SWAP32', + 'GetMaterialfv': 'SWAPFLOAT', + 'GetMaterialiv': 'SWAP32', + 'GetTexEnvfv': 'SWAPFLOAT', + 'GetTexEnviv': 'SWAP32', + 'GetTexGendv': 'SWAPDOUBLE', + 'GetTexGenfv': 'SWAPFLOAT', + 'GetTexGeniv': 'SWAP32', + 'GetTexLevelParameterfv': 'SWAPFLOAT', + 'GetTexLevelParameteriv': 'SWAP32', + 'GetTexParameterfv': 'SWAPFLOAT', + 'GetTexParameteriv': 'SWAP32' } + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +for func_name in keys: + params = apiutil.Parameters(func_name) + return_type = apiutil.ReturnType(func_name) + if apiutil.FindSpecial( "packspu", func_name ): + continue + + if "get" in apiutil.Properties(func_name): + print('%s PACKSPU_APIENTRY packspu_%s(%s)' % ( return_type, func_name, apiutil.MakeDeclarationString( params ) )) + print('{') + print('\tGET_THREAD(thread);') + print('\tint writeback = 1;') + if return_type != 'void': + print('\t%s return_val = (%s) 0;' % (return_type, return_type)) + params.append( ("&return_val", "foo", 0) ) + if (func_name in easy_swaps and easy_swaps[func_name] != '0') or func_name in simple_funcs or func_name in hard_funcs: + print('\tunsigned int i;') + print('\tif (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network))') + print('\t{') + print('\t\tcrError( "packspu_%s doesn\'t work when there\'s no actual network involved!\\nTry using the simplequery SPU in your chain!" );' % func_name) + print('\t}') + if func_name in simple_funcs: + print(""" + if (crPackIsPixelStoreParm(pname) + || pname == GL_DRAW_BUFFER +#ifdef CR_OPENGL_VERSION_1_3 + || pname == GL_ACTIVE_TEXTURE +#endif +#ifdef CR_ARB_multitexture + || pname == GL_ACTIVE_TEXTURE_ARB +#endif + || pname == GL_TEXTURE_BINDING_1D + || pname == GL_TEXTURE_BINDING_2D +#ifdef CR_NV_texture_rectangle + || pname == GL_TEXTURE_BINDING_RECTANGLE_NV +#endif +#ifdef CR_ARB_texture_cube_map + || pname == GL_TEXTURE_BINDING_CUBE_MAP_ARB +#endif +#ifdef CR_ARB_vertex_program + || pname == GL_MAX_VERTEX_ATTRIBS_ARB +#endif +#ifdef GL_EXT_framebuffer_object + || pname == GL_FRAMEBUFFER_BINDING_EXT + || pname == GL_READ_FRAMEBUFFER_BINDING_EXT + || pname == GL_DRAW_FRAMEBUFFER_BINDING_EXT +#endif + || pname == GL_ARRAY_BUFFER_BINDING + || pname == GL_ELEMENT_ARRAY_BUFFER_BINDING + || pname == GL_PIXEL_PACK_BUFFER_BINDING + || pname == GL_PIXEL_UNPACK_BUFFER_BINDING + ) + { +#ifdef DEBUG + if (!crPackIsPixelStoreParm(pname) +#ifdef CR_ARB_vertex_program + && (pname!=GL_MAX_VERTEX_ATTRIBS_ARB) +#endif + ) + { + %s localparams; + localparams = (%s) crAlloc(__numValues(pname) * sizeof(*localparams)); + crState%s(pname, localparams); + crPack%s(%s, &writeback); + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + for (i=0; i<__numValues(pname); ++i) + { + if (localparams[i] != params[i]) + { + crWarning("Incorrect local state in %s for %%x param %%i", pname, i); + crWarning("Expected %%i but got %%i", (int)localparams[i], (int)params[i]); + } + } + crFree(localparams); + return; + } + else +#endif + { + crState%s(pname, params); + return; + } + + } + """ % (params[-1][1], params[-1][1], func_name, func_name, apiutil.MakeCallString(params), func_name, func_name)) + + if func_name in vertattr_get_funcs: + print(""" + if (pname != GL_CURRENT_VERTEX_ATTRIB_ARB) + { +#ifdef DEBUG + %s localparams; + localparams = (%s) crAlloc(__numValues(pname) * sizeof(*localparams)); + crState%s(index, pname, localparams); + crPack%s(index, %s, &writeback); + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + for (i=0; i<crStateHlpComponentsCount(pname); ++i) + { + if (localparams[i] != params[i]) + { + crWarning("Incorrect local state in %s for %%x param %%i", pname, i); + crWarning("Expected %%i but got %%i", (int)localparams[i], (int)params[i]); + } + } + crFree(localparams); +#else + crState%s(pname, params); +#endif + return; + } + """ % (params[-1][1], params[-1][1], func_name, func_name, apiutil.MakeCallString(params), func_name, func_name)) + + params.append( ("&writeback", "foo", 0) ) + print('\tif (pack_spu.swap)') + print('\t{') + print('\t\tcrPack%sSWAP(%s);' % (func_name, apiutil.MakeCallString( params ) )) + print('\t}') + print('\telse') + print('\t{') + print('\t\tcrPack%s(%s);' % (func_name, apiutil.MakeCallString( params ) )) + print('\t}') + print('\tpackspuFlush( (void *) thread );') + print('\tCRPACKSPU_WRITEBACK_WAIT(thread, writeback);') + + + + lastParamName = params[-2][0] + if return_type != 'void': + print('\tif (pack_spu.swap)') + print('\t{') + print('\t\treturn_val = (%s) SWAP32(return_val);' % return_type) + print('\t}') + print('\treturn return_val;') + if func_name in easy_swaps and easy_swaps[func_name] != '0': + limit = easy_swaps[func_name] + print('\tif (pack_spu.swap)') + print('\t{') + print('\t\tfor (i = 0; i < %s; i++)' % limit) + print('\t\t{') + if params[-2][1].find( "double" ) > -1: + print('\t\t\t%s[i] = SWAPDOUBLE(%s[i]);' % (lastParamName, lastParamName)) + else: + print('\t\t\t%s[i] = SWAP32(%s[i]);' % (lastParamName, lastParamName)) + print('\t\t}') + print('\t}') + for index in range(len(simple_funcs)): + if simple_funcs[index] == func_name: + print('\tif (pack_spu.swap)') + print('\t{') + print('\t\tfor (i = 0; i < __numValues(pname); i++)') + print('\t\t{') + if simple_swaps[index] == 'SWAPDOUBLE': + print('\t\t\t%s[i] = %s(%s[i]);' % (lastParamName, simple_swaps[index], lastParamName)) + else: + print('\t\t\t((GLuint *) %s)[i] = %s(%s[i]);' % (lastParamName, simple_swaps[index], lastParamName)) + print('\t\t}') + print('\t}') + if func_name in hard_funcs: + print('\tif (pack_spu.swap)') + print('\t{') + print('\t\tfor (i = 0; i < crStateHlpComponentsCount(pname); i++)') + print('\t\t{') + if hard_funcs[func_name] == 'SWAPDOUBLE': + print('\t\t\t%s[i] = %s(%s[i]);' % (lastParamName, hard_funcs[func_name], lastParamName)) + else: + print('\t\t\t((GLuint *) %s)[i] = %s(%s[i]);' % (lastParamName, hard_funcs[func_name], lastParamName)) + print('\t\t}') + print('\t}') + print('}\n') diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_getshaders.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_getshaders.c new file mode 100644 index 00000000..97150222 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_getshaders.c @@ -0,0 +1,214 @@ +/* $Id: packspu_getshaders.c $ */ + +/** @file + * VBox OpenGL GLSL related functions + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include "packspu.h" +#include "cr_packfunctions.h" +#include "cr_net.h" +#include "packspu_proto.h" +#include "cr_mem.h" +#include <iprt/assert.h> + +/** @todo combine with the one from server_getshaders.c*/ +typedef struct _crGetActive_t +{ + GLsizei length; + GLint size; + GLenum type; +} crGetActive_t; + +void PACKSPU_APIENTRY packspu_GetActiveAttrib(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, char * name) +{ + GET_THREAD(thread); + int writeback = 1; + crGetActive_t *pLocal; + + if (!size || !type || !name) return; + + pLocal = (crGetActive_t*) crAlloc(bufSize+sizeof(crGetActive_t)); + if (!pLocal) return; + + crPackGetActiveAttrib(program, index, bufSize, (GLsizei*)pLocal, NULL, NULL, NULL, &writeback); + + packspuFlush((void *) thread); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + if (length) *length = pLocal->length; + *size = pLocal->size; + *type = pLocal->type; + crMemcpy(name, (char*)&pLocal[1], pLocal->length+1); + crFree(pLocal); +} + +void PACKSPU_APIENTRY packspu_GetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, char * name) +{ + GET_THREAD(thread); + int writeback = 1; + crGetActive_t *pLocal; + + if (!size || !type || !name) return; + + pLocal = (crGetActive_t*) crAlloc(bufSize+sizeof(crGetActive_t)); + if (!pLocal) return; + + crPackGetActiveUniform(program, index, bufSize, (GLsizei*)pLocal, NULL, NULL, NULL, &writeback); + + packspuFlush((void *) thread); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + if (length) *length = pLocal->length; + *size = pLocal->size; + *type = pLocal->type; + crMemcpy(name, &pLocal[1], pLocal->length+1); + crFree(pLocal); +} + +void PACKSPU_APIENTRY packspu_GetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders) +{ + GET_THREAD(thread); + int writeback = 1; + GLsizei *pLocal; + + if (!shaders) return; + + pLocal = (GLsizei*) crAlloc(maxCount*sizeof(GLuint)+sizeof(GLsizei)); + if (!pLocal) return; + + crPackGetAttachedShaders(program, maxCount, pLocal, NULL, &writeback); + + packspuFlush((void *) thread); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + if (count) *count=*pLocal; + crMemcpy(shaders, &pLocal[1], *pLocal*sizeof(GLuint)); + crFree(pLocal); +} + +void PACKSPU_APIENTRY packspu_GetAttachedObjectsARB(VBoxGLhandleARB containerObj, GLsizei maxCount, GLsizei * count, VBoxGLhandleARB * obj) +{ + GET_THREAD(thread); + int writeback = 1; + GLsizei *pLocal; + + if (!obj) return; + + pLocal = (GLsizei*) crAlloc(maxCount*sizeof(VBoxGLhandleARB)+sizeof(GLsizei)); + if (!pLocal) return; + + crPackGetAttachedObjectsARB(containerObj, maxCount, pLocal, NULL, &writeback); + + packspuFlush((void *) thread); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + if (count) *count=*pLocal; + crMemcpy(obj, &pLocal[1], *pLocal*sizeof(VBoxGLhandleARB)); + crFree(pLocal); +} + +AssertCompile(sizeof(GLsizei) == 4); + +void PACKSPU_APIENTRY packspu_GetInfoLogARB(VBoxGLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog) +{ + GET_THREAD(thread); + int writeback = 1; + GLsizei *pLocal; + + if (!infoLog) return; + + pLocal = (GLsizei*) crAlloc(maxLength+sizeof(GLsizei)); + if (!pLocal) return; + + crPackGetInfoLogARB(obj, maxLength, pLocal, NULL, &writeback); + + packspuFlush((void *) thread); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + CRASSERT((pLocal[0]) <= maxLength); + + if (length) *length=*pLocal; + crMemcpy(infoLog, &pLocal[1], (maxLength >= (pLocal[0])) ? pLocal[0] : maxLength); + crFree(pLocal); +} + +void PACKSPU_APIENTRY packspu_GetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei * length, char * infoLog) +{ + GET_THREAD(thread); + int writeback = 1; + GLsizei *pLocal; + + if (!infoLog) return; + + pLocal = (GLsizei*) crAlloc(bufSize+sizeof(GLsizei)); + if (!pLocal) return; + + crPackGetProgramInfoLog(program, bufSize, pLocal, NULL, &writeback); + + packspuFlush((void *) thread); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + if (length) *length=*pLocal; + crMemcpy(infoLog, &pLocal[1], (bufSize >= pLocal[0]) ? pLocal[0] : bufSize); + crFree(pLocal); +} + +void PACKSPU_APIENTRY packspu_GetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei * length, char * infoLog) +{ + GET_THREAD(thread); + int writeback = 1; + GLsizei *pLocal; + + if (!infoLog) return; + + pLocal = (GLsizei*) crAlloc(bufSize+sizeof(GLsizei)); + if (!pLocal) return; + + crPackGetShaderInfoLog(shader, bufSize, pLocal, NULL, &writeback); + + packspuFlush((void *) thread); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + if (length) *length=*pLocal; + crMemcpy(infoLog, &pLocal[1], (bufSize >= pLocal[0]) ? pLocal[0] : bufSize); + crFree(pLocal); +} + +void PACKSPU_APIENTRY packspu_GetShaderSource(GLuint shader, GLsizei bufSize, GLsizei * length, char * source) +{ + GET_THREAD(thread); + int writeback = 1; + GLsizei *pLocal; + + if (!source) return; + + pLocal = (GLsizei*) crAlloc(bufSize+sizeof(GLsizei)); + if (!pLocal) return; + + crPackGetShaderSource(shader, bufSize, pLocal, NULL, &writeback); + + packspuFlush((void *) thread); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + if (length) *length=*pLocal; + crMemcpy(source, &pLocal[1], (bufSize >= pLocal[0]) ? pLocal[0] : bufSize); + + if (bufSize > pLocal[0]) + { + source[pLocal[0]] = 0; + } + + crFree(pLocal); +} diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_getstring.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_getstring.c new file mode 100644 index 00000000..c5890bfe --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_getstring.c @@ -0,0 +1,211 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "packspu.h" +#include "cr_packfunctions.h" +#include "state/cr_statefuncs.h" +#include "cr_string.h" +#include "packspu_proto.h" +#include "cr_mem.h" +#include <locale.h> + +static GLubyte gpszExtensions[10000]; +#ifdef CR_OPENGL_VERSION_2_0 +static GLubyte gpszShadingVersion[255]=""; +#endif + +static void GetString(GLenum name, GLubyte *pszStr) +{ + GET_THREAD(thread); + int writeback = 1; + + if (pack_spu.swap) + crPackGetStringSWAP(name, pszStr, &writeback); + else + crPackGetString(name, pszStr, &writeback); + packspuFlush( (void *) thread ); + + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); +} + +static GLfloat +GetVersionString(void) +{ + static GLboolean fInitialized = GL_FALSE; + static GLfloat version = 0.; + + if (!fInitialized) + { + GLubyte return_value[100]; + + GetString(GL_VERSION, return_value); + CRASSERT(crStrlen((char *)return_value) < 100); + + version = crStrToFloat((char *) return_value); + version = crStateComputeVersion(version); + + fInitialized = GL_TRUE; + } + + return version; +} + +static const GLubyte * +GetExtensions(void) +{ + static GLboolean fInitialized = GL_FALSE; + if (!fInitialized) + { + GLubyte return_value[10*1000]; + const GLubyte *extensions, *ext; + GET_THREAD(thread); + int writeback = 1; + + if (pack_spu.swap) + { + crPackGetStringSWAP( GL_EXTENSIONS, return_value, &writeback ); + } + else + { + crPackGetString( GL_EXTENSIONS, return_value, &writeback ); + } + packspuFlush( (void *) thread ); + + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + CRASSERT(crStrlen((char *)return_value) < 10*1000); + + /* OK, we got the result from the server. Now we have to + * intersect is with the set of extensions that Chromium understands + * and tack on the Chromium-specific extensions. + */ + extensions = return_value; + ext = crStateMergeExtensions(1, &extensions); + +#ifdef Linux + /** @todo + *That's a hack to allow running Unity, it uses libnux which is calling extension functions + *without checking if it's being supported/exported. + *glActiveStencilFaceEXT seems to be actually supported but the extension string isn't exported (for ex. on ATI HD4870), + *which leads to libglew setting function pointer to NULL and crashing Unity. + */ + sprintf((char*)gpszExtensions, "%s GL_EXT_stencil_two_side", ext); +#else + sprintf((char*)gpszExtensions, "%s", ext); +#endif + fInitialized = GL_TRUE; + } + + return gpszExtensions; +} + +#ifdef WINDOWS +static bool packspuRunningUnderWine(void) +{ + return NULL != GetModuleHandle("wined3d.dll") || NULL != GetModuleHandle("wined3dwddm.dll") || NULL != GetModuleHandle("wined3dwddm-x86.dll"); +} +#endif + +const GLubyte * PACKSPU_APIENTRY packspu_GetString( GLenum name ) +{ + GET_CONTEXT(ctx); + + switch(name) + { + case GL_EXTENSIONS: + return GetExtensions(); + case GL_VERSION: +#if 0 && defined(WINDOWS) + if (packspuRunningUnderWine()) + { + GetString(GL_REAL_VERSION, ctx->pszRealVersion); + return ctx->pszRealVersion; + } + else +#endif + { + char *oldlocale; + float version; + + oldlocale = setlocale(LC_NUMERIC, NULL); + oldlocale = crStrdup(oldlocale); + setlocale(LC_NUMERIC, "C"); + + version = GetVersionString(); + sprintf((char*)ctx->glVersion, "%.1f Chromium %s", version, CR_VERSION_STRING); + + if (oldlocale) + { + setlocale(LC_NUMERIC, oldlocale); + crFree(oldlocale); + } + + return ctx->glVersion; + } + case GL_VENDOR: +#ifdef WINDOWS + if (packspuRunningUnderWine()) + { + GetString(GL_REAL_VENDOR, ctx->pszRealVendor); + return ctx->pszRealVendor; + } + else +#endif + { + return crStateGetString(name); + } + case GL_RENDERER: +#ifdef WINDOWS + if (packspuRunningUnderWine()) + { + GetString(GL_REAL_RENDERER, ctx->pszRealRenderer); + return ctx->pszRealRenderer; + } + else +#endif + { + return crStateGetString(name); + } + +#ifdef CR_OPENGL_VERSION_2_0 + case GL_SHADING_LANGUAGE_VERSION: + { + static GLboolean fInitialized = GL_FALSE; + if (!fInitialized) + { + GetString(GL_SHADING_LANGUAGE_VERSION, gpszShadingVersion); + fInitialized = GL_TRUE; + } + return gpszShadingVersion; + } +#endif +#ifdef GL_CR_real_vendor_strings + case GL_REAL_VENDOR: + GetString(GL_REAL_VENDOR, ctx->pszRealVendor); + return ctx->pszRealVendor; + case GL_REAL_VERSION: + GetString(GL_REAL_VERSION, ctx->pszRealVersion); + return ctx->pszRealVersion; + case GL_REAL_RENDERER: + GetString(GL_REAL_RENDERER, ctx->pszRealRenderer); + return ctx->pszRealRenderer; +#endif + default: + return crStateGetString(name); + } +} + +void packspuInitStrings() +{ + static GLboolean fInitialized = GL_FALSE; + + if (!fInitialized) + { + packspu_GetString(GL_EXTENSIONS); + packspu_GetString(GL_VERSION); + fInitialized = GL_TRUE; + } +} diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_glsl.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_glsl.c new file mode 100644 index 00000000..1116b7d5 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_glsl.c @@ -0,0 +1,275 @@ +/* $Id: packspu_glsl.c $ */ + +/** @file + * VBox OpenGL GLSL related functions + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include "packspu.h" +#include "cr_packfunctions.h" +#include "cr_net.h" +#include "packspu_proto.h" +#include "cr_mem.h" + + +GLuint PACKSPU_APIENTRY packspu_CreateProgram(void) +{ + GET_THREAD(thread); + int writeback = 1; + GLuint return_val = (GLuint) 0; + if (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network)) + { + crError("packspu_CreateProgram doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!"); + } + if (pack_spu.swap) + { + crPackCreateProgramSWAP(&return_val, &writeback); + } + else + { + crPackCreateProgram(&return_val, &writeback); + } + packspuFlush((void *) thread); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + if (pack_spu.swap) + { + return_val = (GLuint) SWAP32(return_val); + } + + crStateCreateProgram(return_val); + + return return_val; +} + +static GLint packspu_GetUniformLocationUncached(GLuint program, const char * name) +{ + GET_THREAD(thread); + int writeback = 1; + GLint return_val = (GLint) 0; + if (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network)) + { + crError("packspu_GetUniformLocation doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!"); + } + if (pack_spu.swap) + { + crPackGetUniformLocationSWAP(program, name, &return_val, &writeback); + } + else + { + crPackGetUniformLocation(program, name, &return_val, &writeback); + } + packspuFlush((void *) thread); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + if (pack_spu.swap) + { + return_val = (GLint) SWAP32(return_val); + } + return return_val; +} + +GLint PACKSPU_APIENTRY packspu_GetUniformLocation(GLuint program, const char * name) +{ + if (!crStateIsProgramUniformsCached(program)) + { + GET_THREAD(thread); + int writeback = 1; + GLsizei maxcbData; + GLsizei *pData; + GLint mu; + + packspu_GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &mu); + maxcbData = 16*mu*sizeof(char); + + pData = (GLsizei *) crAlloc(maxcbData+sizeof(GLsizei)); + if (!pData) + { + crWarning("packspu_GetUniformLocation: not enough memory, fallback to single query"); + return packspu_GetUniformLocationUncached(program, name); + } + + crPackGetUniformsLocations(program, maxcbData, pData, NULL, &writeback); + + packspuFlush((void *) thread); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + crStateGLSLProgramCacheUniforms(program, pData[0], &pData[1]); + + CRASSERT(crStateIsProgramUniformsCached(program)); + + crFree(pData); + } + + /*crDebug("packspu_GetUniformLocation(%d, %s)=%i", program, name, crStateGetUniformLocation(program, name));*/ + return crStateGetUniformLocation(program, name); +} + +static GLint PACKSPU_APIENTRY packspu_GetAttribLocationUnchached( GLuint program, const char * name ) +{ + GET_THREAD(thread); + int writeback = 1; + GLint return_val = (GLint) 0; + if (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network)) + { + crError( "packspu_GetAttribLocation doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!" ); + } + if (pack_spu.swap) + { + crPackGetAttribLocationSWAP( program, name, &return_val, &writeback ); + } + else + { + crPackGetAttribLocation( program, name, &return_val, &writeback ); + } + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + if (pack_spu.swap) + { + return_val = (GLint) SWAP32(return_val); + } + return return_val; +} + +GLint PACKSPU_APIENTRY packspu_GetAttribLocation(GLuint program, const char * name) +{ + if (!(CR_VBOX_CAP_GETATTRIBSLOCATIONS & g_u32VBoxHostCaps)) + return packspu_GetAttribLocationUnchached(program, name); + + if (!crStateIsProgramAttribsCached(program)) + { + GET_THREAD(thread); + int writeback = 1; + GLsizei maxcbData; + GLsizei *pData; + GLint mu; + + packspu_GetIntegerv(GL_MAX_VERTEX_ATTRIBS, &mu); + maxcbData = 4*32*mu*sizeof(char); + + pData = (GLsizei *) crAlloc(maxcbData+sizeof(GLsizei)); + if (!pData) + { + crWarning("packspu_GetAttribLocation: not enough memory, fallback to single query"); + return packspu_GetAttribLocationUnchached(program, name); + } + + crPackGetAttribsLocations(program, maxcbData, pData, NULL, &writeback); + + packspuFlush((void *) thread); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + crStateGLSLProgramCacheAttribs(program, pData[0], &pData[1]); + + CRASSERT(crStateIsProgramAttribsCached(program)); + + crFree(pData); + } + + /*crDebug("packspu_GetAttribLocation(%d, %s)=%i", program, name, crStateGetAttribLocation(program, name));*/ + return crStateGetAttribLocation(program, name); +} + +void PACKSPU_APIENTRY packspu_GetUniformsLocations(GLuint program, GLsizei maxcbData, GLsizei * cbData, GLvoid * pData) +{ + (void) program; + (void) maxcbData; + (void) cbData; + (void) pData; + WARN(("packspu_GetUniformsLocations shouldn't be called directly")); +} + +void PACKSPU_APIENTRY packspu_GetAttribsLocations(GLuint program, GLsizei maxcbData, GLsizei * cbData, GLvoid * pData) +{ + (void) program; + (void) maxcbData; + (void) cbData; + (void) pData; + WARN(("packspu_GetAttribsLocations shouldn't be called directly")); +} + +void PACKSPU_APIENTRY packspu_DeleteProgram(GLuint program) +{ + crStateDeleteProgram(program); + crPackDeleteProgram(program); +} + +void PACK_APIENTRY packspu_DeleteObjectARB(VBoxGLhandleARB obj) +{ + GLuint hwid = crStateGetProgramHWID(obj); + + CRASSERT(obj); + + /* we do not track shader creation inside guest since it is not needed currently. + * this is why we only care about programs here */ + if (hwid) + { + crStateDeleteProgram(obj); + } + + crPackDeleteObjectARB(obj); +} + +#ifdef VBOX_WITH_CRPACKSPU_DUMPER +static void packspu_RecCheckInitRec() +{ + if (pack_spu.Recorder.pDumper) + return; + + crDmpDbgPrintInit(&pack_spu.Dumper); + + crRecInit(&pack_spu.Recorder, NULL /*pBlitter: we do not support blitter operations here*/, &pack_spu.self, &pack_spu.Dumper.Base); +} +#endif + +void PACKSPU_APIENTRY packspu_LinkProgram(GLuint program) +{ +#ifdef VBOX_WITH_CRPACKSPU_DUMPER + GLint linkStatus = 0; +#endif + + crStateLinkProgram(program); + crPackLinkProgram(program); + +#ifdef VBOX_WITH_CRPACKSPU_DUMPER + pack_spu.self.GetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &linkStatus); + Assert(linkStatus); + if (!linkStatus) + { + CRContext *ctx = crStateGetCurrent(); + packspu_RecCheckInitRec(); + crRecDumpProgram(&pack_spu.Recorder, ctx, program, program); + } +#endif +} + +void PACKSPU_APIENTRY packspu_CompileShader(GLuint shader) +{ +#ifdef VBOX_WITH_CRPACKSPU_DUMPER + GLint compileStatus = 0; +#endif + +// crStateCompileShader(shader); + crPackCompileShader(shader); + +#ifdef VBOX_WITH_CRPACKSPU_DUMPER + pack_spu.self.GetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus); + Assert(compileStatus); + if (!compileStatus) + { + CRContext *ctx = crStateGetCurrent(); + packspu_RecCheckInitRec(); + crRecDumpShader(&pack_spu.Recorder, ctx, shader, shader); + } +#endif +} + diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_init.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_init.c new file mode 100644 index 00000000..d5219950 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_init.c @@ -0,0 +1,152 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_mem.h" +#include "cr_spu.h" +#include "cr_glstate.h" +#include "packspu.h" +#include "cr_packfunctions.h" +#include <stdio.h> + +extern SPUNamedFunctionTable _cr_pack_table[]; + +SPUFunctions pack_functions = { + NULL, /* CHILD COPY */ + NULL, /* DATA */ + _cr_pack_table /* THE ACTUAL FUNCTIONS */ +}; + +PackSPU pack_spu; + +#ifdef CHROMIUM_THREADSAFE +CRtsd _PackTSD; +CRmutex _PackMutex; +#endif + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) +# include <VBoxCrHgsmi.h> +# include <VBoxUhgsmi.h> +#endif + +#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_WDDM) +static bool isVBoxWDDMCrHgsmi(void) +{ +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + PVBOXUHGSMI pHgsmi = VBoxCrHgsmiCreate(); + if (pHgsmi) + { + VBoxCrHgsmiDestroy(pHgsmi); + return true; + } +#endif + return false; +} +#endif /* RT_OS_WINDOWS && VBOX_WITH_WDDM */ + +static SPUFunctions * +packSPUInit( int id, SPU *child, SPU *self, + unsigned int context_id, + unsigned int num_contexts ) +{ + ThreadInfo *thread; + + (void) context_id; + (void) num_contexts; + (void) child; + (void) self; + +#if defined(CHROMIUM_THREADSAFE) && !defined(WINDOWS) + crInitMutex(&_PackMutex); +#endif + +#ifdef CHROMIUM_THREADSAFE + crInitTSD(&_PackerTSD); + crInitTSD(&_PackTSD); +#endif + + pack_spu.id = id; + + packspuSetVBoxConfiguration( child ); + +#if defined(WINDOWS) && defined(VBOX_WITH_WDDM) + pack_spu.bIsWDDMCrHgsmi = isVBoxWDDMCrHgsmi(); +#endif + +#ifdef VBOX_WITH_CRPACKSPU_DUMPER + memset(&pack_spu.Dumper, 0, sizeof (pack_spu.Dumper)); +#endif + + if (!CRPACKSPU_IS_WDDM_CRHGSMI()) + { + /* This connects to the server, sets up the packer, etc. */ + thread = packspuNewThread( +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + NULL +#endif + ); + + if (!thread) { + return NULL; + } + CRASSERT( thread == &(pack_spu.thread[0]) ); + pack_spu.idxThreadInUse = 0; + } + + packspuCreateFunctions(); + crStateInit(); + + return &pack_functions; +} + +static void +packSPUSelfDispatch(SPUDispatchTable *self) +{ + crSPUInitDispatchTable( &(pack_spu.self) ); + crSPUCopyDispatchTable( &(pack_spu.self), self ); +} + +static int +packSPUCleanup(void) +{ + int i; +#ifdef CHROMIUM_THREADSAFE + crLockMutex(&_PackMutex); +#endif + for (i=0; i<MAX_THREADS; ++i) + { + if (pack_spu.thread[i].inUse && pack_spu.thread[i].packer) + { + crPackDeleteContext(pack_spu.thread[i].packer); + } + } + +#ifdef CHROMIUM_THREADSAFE + crFreeTSD(&_PackerTSD); + crFreeTSD(&_PackTSD); + crUnlockMutex(&_PackMutex); +# ifndef WINDOWS + crFreeMutex(&_PackMutex); +# endif +#endif /* CHROMIUM_THREADSAFE */ + return 1; +} + +extern SPUOptions packSPUOptions[]; + +int SPULoad( char **name, char **super, SPUInitFuncPtr *init, + SPUSelfDispatchFuncPtr *self, SPUCleanupFuncPtr *cleanup, + SPUOptionsPtr *options, int *flags ) +{ + *name = "pack"; + *super = NULL; + *init = packSPUInit; + *self = packSPUSelfDispatch; + *cleanup = packSPUCleanup; + *options = packSPUOptions; + *flags = (SPU_HAS_PACKER|SPU_IS_TERMINAL|SPU_MAX_SERVERS_ONE); + + return 1; +} diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_misc.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_misc.c new file mode 100644 index 00000000..0b65be90 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_misc.c @@ -0,0 +1,856 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_packfunctions.h" +#include "packspu.h" +#include "packspu_proto.h" +#include "cr_mem.h" + +void PACKSPU_APIENTRY packspu_ChromiumParametervCR(GLenum target, GLenum type, GLsizei count, const GLvoid *values) +{ + + CRMessage msg; + int len; + GLint ai32ServerValues[2]; + GLboolean fFlush = GL_FALSE; + GET_THREAD(thread); + + + switch(target) + { + case GL_GATHER_PACK_CR: + /* flush the current pack buffer */ + packspuFlush( (void *) thread ); + + /* the connection is thread->server.conn */ + msg.header.type = CR_MESSAGE_GATHER; + msg.gather.offset = 69; + len = sizeof(CRMessageGather); + crNetSend(thread->netServer.conn, NULL, &msg, len); + return; + + case GL_SHARE_LISTS_CR: + { + ContextInfo *pCtx[2]; + GLint *ai32Values; + int i; + if (count != 2) + { + WARN(("GL_SHARE_LISTS_CR invalid cound %d", count)); + return; + } + + if (type != GL_UNSIGNED_INT && type != GL_INT) + { + WARN(("GL_SHARE_LISTS_CR invalid type %d", type)); + return; + } + + ai32Values = (GLint*)values; + + for (i = 0; i < 2; ++i) + { + const int slot = ai32Values[i] - MAGIC_OFFSET; + + if (slot < 0 || slot >= pack_spu.numContexts) + { + WARN(("GL_SHARE_LISTS_CR invalid value[%d] %d", i, ai32Values[i])); + return; + } + + pCtx[i] = &pack_spu.context[slot]; + if (!pCtx[i]->clientState) + { + WARN(("GL_SHARE_LISTS_CR invalid pCtx1 for value[%d] %d", i, ai32Values[i])); + return; + } + + ai32ServerValues[i] = pCtx[i]->serverCtx; + } + + crStateShareLists(pCtx[0]->clientState, pCtx[1]->clientState); + + values = ai32ServerValues; + + fFlush = GL_TRUE; + + break; + } + + default: + break; + } + + if (pack_spu.swap) + crPackChromiumParametervCRSWAP(target, type, count, values); + else + crPackChromiumParametervCR(target, type, count, values); + + if (fFlush) + packspuFlush( (void *) thread ); +} + +GLboolean packspuSyncOnFlushes(void) +{ +#if 1 /*Seems to still cause issues, always sync for now*/ + return 1; +#else + GLint buffer; + + crStateGetIntegerv(GL_DRAW_BUFFER, &buffer); + /*Usually buffer==GL_BACK, so put this extra check to simplify boolean eval on runtime*/ + return (buffer != GL_BACK) + && (buffer == GL_FRONT_LEFT + || buffer == GL_FRONT_RIGHT + || buffer == GL_FRONT + || buffer == GL_FRONT_AND_BACK + || buffer == GL_LEFT + || buffer == GL_RIGHT); +#endif +} + +void PACKSPU_APIENTRY packspu_DrawBuffer(GLenum mode) +{ + GLboolean hadtoflush; + + hadtoflush = packspuSyncOnFlushes(); + + crStateDrawBuffer(mode); + crPackDrawBuffer(mode); + + if (hadtoflush && !packspuSyncOnFlushes()) + packspu_Flush(); +} + +void PACKSPU_APIENTRY packspu_Finish( void ) +{ + GET_THREAD(thread); + GLint writeback = CRPACKSPU_IS_WDDM_CRHGSMI() ? 1 : pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network; + + if (pack_spu.swap) + { + crPackFinishSWAP(); + } + else + { + crPackFinish(); + } + + if (packspuSyncOnFlushes()) + { + if (writeback) + { + if (pack_spu.swap) + crPackWritebackSWAP(&writeback); + else + crPackWriteback(&writeback); + + packspuFlush( (void *) thread ); + + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + } + } +} + +void PACKSPU_APIENTRY packspu_Flush( void ) +{ + GET_THREAD(thread); + int writeback=1; + int found=0; + + if (!thread->bInjectThread) + { + crPackFlush(); + if (packspuSyncOnFlushes()) + { + crPackWriteback(&writeback); + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + } + } + else + { + int i; + + crLockMutex(&_PackMutex); + + /*Make sure we process commands in order they should appear, so flush other threads first*/ + for (i=0; i<MAX_THREADS; ++i) + { + if (pack_spu.thread[i].inUse + && (thread != &pack_spu.thread[i]) && pack_spu.thread[i].netServer.conn + && pack_spu.thread[i].packer && pack_spu.thread[i].packer->currentBuffer) + { + packspuFlush((void *) &pack_spu.thread[i]); + + if (pack_spu.thread[i].netServer.conn->u32ClientID == thread->netServer.conn->u32InjectClientID) + { + found=1; + } + + } + } + + if (!found) + { + /*Thread we're supposed to inject commands for has been detached, + so there's nothing to sync with and we should just pass commands through our own connection. + */ + thread->netServer.conn->u32InjectClientID=0; + } + + packspuFlush((void *) thread); + + crUnlockMutex(&_PackMutex); + } +} + +void PACKSPU_APIENTRY packspu_NewList(GLuint list, GLenum mode) +{ + crStateNewList(list, mode); + crPackNewList(list, mode); +} + +void PACKSPU_APIENTRY packspu_EndList() +{ + crStateEndList(); + crPackEndList(); +} + +void PACKSPU_APIENTRY packspu_VBoxWindowDestroy( GLint con, GLint window ) +{ + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + GET_THREAD(thread); + if (con) + { + CRPackContext * curPacker = crPackGetContext(); + CRASSERT(!thread || !thread->bInjectThread); + thread = GET_THREAD_VAL_ID(con); + crPackSetContext(thread->packer); + crPackWindowDestroy(window); + if (curPacker != thread->packer) + crPackSetContext(curPacker); + return; + } + CRASSERT(thread); + CRASSERT(thread->bInjectThread); + } + crPackWindowDestroy(window); +} + +GLint PACKSPU_APIENTRY packspu_VBoxWindowCreate( GLint con, const char *dpyName, GLint visBits ) +{ + GET_THREAD(thread); + static int num_calls = 0; + int writeback = CRPACKSPU_IS_WDDM_CRHGSMI() ? 1 : pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network; + GLint return_val = (GLint) 0; + ThreadInfo *curThread = thread; + GLint retVal; + + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + if (!con) + { + crError("connection expected!"); + return 0; + } + thread = GET_THREAD_VAL_ID(con); + } + else + { + CRASSERT(!con); + if (!thread) { + thread = packspuNewThread( +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + NULL +#endif + ); + } + } + CRASSERT(thread); + CRASSERT(thread->packer); + CRASSERT(crPackGetContext() == (curThread ? curThread->packer : NULL)); + + crPackSetContext(thread->packer); + + if (pack_spu.swap) + { + crPackWindowCreateSWAP( dpyName, visBits, &return_val, &writeback ); + } + else + { + crPackWindowCreate( dpyName, visBits, &return_val, &writeback ); + } + packspuFlush(thread); + if (!(thread->netServer.conn->actual_network)) + { + retVal = num_calls++; + } + else + { + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + if (pack_spu.swap) + { + return_val = (GLint) SWAP32(return_val); + } + retVal = return_val; + } + + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + if (thread != curThread) + { + if (curThread) + crPackSetContext(curThread->packer); + else + crPackSetContext(NULL); + } + } + + return retVal; +} + +GLint PACKSPU_APIENTRY packspu_WindowCreate( const char *dpyName, GLint visBits ) +{ + return packspu_VBoxWindowCreate( 0, dpyName, visBits ); +} + +GLboolean PACKSPU_APIENTRY +packspu_AreTexturesResident( GLsizei n, const GLuint * textures, + GLboolean * residences ) +{ + GET_THREAD(thread); + int writeback = 1; + GLboolean return_val = GL_TRUE; + GLsizei i; + + if (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network)) + { + crError( "packspu_AreTexturesResident doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!" ); + } + + if (pack_spu.swap) + { + crPackAreTexturesResidentSWAP( n, textures, residences, &return_val, &writeback ); + } + else + { + crPackAreTexturesResident( n, textures, residences, &return_val, &writeback ); + } + packspuFlush( (void *) thread ); + + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + /* Since the Chromium packer/unpacker can't return both 'residences' + * and the function's return value, compute the return value here. + */ + for (i = 0; i < n; i++) { + if (!residences[i]) { + return_val = GL_FALSE; + break; + } + } + + return return_val; +} + + +GLboolean PACKSPU_APIENTRY +packspu_AreProgramsResidentNV( GLsizei n, const GLuint * ids, + GLboolean * residences ) +{ + GET_THREAD(thread); + int writeback = 1; + GLboolean return_val = GL_TRUE; + GLsizei i; + + if (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network)) + { + crError( "packspu_AreProgramsResidentNV doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!" ); + } + if (pack_spu.swap) + { + crPackAreProgramsResidentNVSWAP( n, ids, residences, &return_val, &writeback ); + } + else + { + crPackAreProgramsResidentNV( n, ids, residences, &return_val, &writeback ); + } + packspuFlush( (void *) thread ); + + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + /* Since the Chromium packer/unpacker can't return both 'residences' + * and the function's return value, compute the return value here. + */ + for (i = 0; i < n; i++) { + if (!residences[i]) { + return_val = GL_FALSE; + break; + } + } + + return return_val; +} + +void PACKSPU_APIENTRY packspu_GetPolygonStipple( GLubyte * mask ) +{ + GET_THREAD(thread); + int writeback = 1; + + if (pack_spu.swap) + { + crPackGetPolygonStippleSWAP( mask, &writeback ); + } + else + { + crPackGetPolygonStipple( mask, &writeback ); + } + +#ifdef CR_ARB_pixel_buffer_object + if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) +#endif + { + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + } +} + +void PACKSPU_APIENTRY packspu_GetPixelMapfv( GLenum map, GLfloat * values ) +{ + GET_THREAD(thread); + int writeback = 1; + + if (pack_spu.swap) + { + crPackGetPixelMapfvSWAP( map, values, &writeback ); + } + else + { + crPackGetPixelMapfv( map, values, &writeback ); + } + +#ifdef CR_ARB_pixel_buffer_object + if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) +#endif + { + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + } +} + +void PACKSPU_APIENTRY packspu_GetPixelMapuiv( GLenum map, GLuint * values ) +{ + GET_THREAD(thread); + int writeback = 1; + + if (pack_spu.swap) + { + crPackGetPixelMapuivSWAP( map, values, &writeback ); + } + else + { + crPackGetPixelMapuiv( map, values, &writeback ); + } + +#ifdef CR_ARB_pixel_buffer_object + if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) +#endif + { + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + } +} + +void PACKSPU_APIENTRY packspu_GetPixelMapusv( GLenum map, GLushort * values ) +{ + GET_THREAD(thread); + int writeback = 1; + + if (pack_spu.swap) + { + crPackGetPixelMapusvSWAP( map, values, &writeback ); + } + else + { + crPackGetPixelMapusv( map, values, &writeback ); + } + +#ifdef CR_ARB_pixel_buffer_object + if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) +#endif + { + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + } +} + +static void packspuFluchOnThreadSwitch(GLboolean fEnable) +{ + GET_THREAD(thread); + if (thread->currentContext->fAutoFlush == fEnable) + return; + + thread->currentContext->fAutoFlush = fEnable; + thread->currentContext->currentThread = fEnable ? thread : NULL; +} + +static void packspuCheckZerroVertAttr(GLboolean fEnable) +{ + GET_THREAD(thread); + + thread->currentContext->fCheckZerroVertAttr = fEnable; +} + +void PACKSPU_APIENTRY packspu_ChromiumParameteriCR(GLenum target, GLint value) +{ + switch (target) + { + case GL_FLUSH_ON_THREAD_SWITCH_CR: + /* this is a pure packspu state, don't propagate it any further */ + packspuFluchOnThreadSwitch(value); + return; + case GL_CHECK_ZERO_VERT_ARRT: + packspuCheckZerroVertAttr(value); + return; + case GL_SHARE_CONTEXT_RESOURCES_CR: + crStateShareContext(value); + break; + case GL_RCUSAGE_TEXTURE_SET_CR: + { + Assert(value); + crStateSetTextureUsed(value, GL_TRUE); + break; + } + case GL_RCUSAGE_TEXTURE_CLEAR_CR: + { + Assert(value); +#ifdef DEBUG + { + CRContext *pCurState = crStateGetCurrent(); + CRTextureObj *tobj = (CRTextureObj*)crHashtableSearch(pCurState->shared->textureTable, value); + Assert(tobj); + } +#endif + crStateSetTextureUsed(value, GL_FALSE); + break; + } + default: + break; + } + crPackChromiumParameteriCR(target, value); +} + +GLenum PACKSPU_APIENTRY packspu_GetError( void ) +{ + GET_THREAD(thread); + int writeback = 1; + GLenum return_val = (GLenum) 0; + CRContext *pCurState = crStateGetCurrent(); + NOREF(pCurState); /* it's unused, but I don't know about side effects.. */ + + if (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network)) + { + crError( "packspu_GetError doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!" ); + } + if (pack_spu.swap) + { + crPackGetErrorSWAP( &return_val, &writeback ); + } + else + { + crPackGetError( &return_val, &writeback ); + } + + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + + if (pack_spu.swap) + { + return_val = (GLenum) SWAP32(return_val); + } + + return return_val; +} + +#ifdef CHROMIUM_THREADSAFE +GLint PACKSPU_APIENTRY packspu_VBoxPackSetInjectThread(struct VBOXUHGSMI *pHgsmi) +{ + GLint con = 0; + int i; + GET_THREAD(thread); + CRASSERT(!thread); + RT_NOREF(pHgsmi); + crLockMutex(&_PackMutex); + { + CRASSERT(CRPACKSPU_IS_WDDM_CRHGSMI() || (pack_spu.numThreads>0)); + CRASSERT(pack_spu.numThreads<MAX_THREADS); + for (i=0; i<MAX_THREADS; ++i) + { + if (!pack_spu.thread[i].inUse) + { + thread = &pack_spu.thread[i]; + break; + } + } + CRASSERT(thread); + + thread->inUse = GL_TRUE; + if (!CRPACKSPU_IS_WDDM_CRHGSMI()) + thread->id = crThreadID(); + else + thread->id = THREAD_OFFSET_MAGIC + i; + thread->currentContext = NULL; + thread->bInjectThread = GL_TRUE; + + thread->netServer.name = crStrdup(pack_spu.name); + thread->netServer.buffer_size = 64 * 1024; + + packspuConnectToServer(&(thread->netServer) +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , pHgsmi +#endif + ); + CRASSERT(thread->netServer.conn); + + CRASSERT(thread->packer == NULL); + thread->packer = crPackNewContext( pack_spu.swap ); + CRASSERT(thread->packer); + crPackInitBuffer(&(thread->buffer), crNetAlloc(thread->netServer.conn), + thread->netServer.conn->buffer_size, thread->netServer.conn->mtu); + thread->buffer.canBarf = thread->netServer.conn->Barf ? GL_TRUE : GL_FALSE; + + crPackSetBuffer( thread->packer, &thread->buffer ); + crPackFlushFunc( thread->packer, packspuFlush ); + crPackFlushArg( thread->packer, (void *) thread ); + crPackSendHugeFunc( thread->packer, packspuHuge ); + crPackSetContext( thread->packer ); + + crSetTSD(&_PackTSD, thread); + + pack_spu.numThreads++; + } + crUnlockMutex(&_PackMutex); + + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + CRASSERT(thread->id - THREAD_OFFSET_MAGIC < RT_ELEMENTS(pack_spu.thread) + && GET_THREAD_VAL_ID(thread->id) == thread); + con = thread->id; + } + return con; +} + +GLuint PACKSPU_APIENTRY packspu_VBoxPackGetInjectID(GLint con) +{ + GLuint ret; + + crLockMutex(&_PackMutex); + { + ThreadInfo *thread = NULL; + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + if (!con) + { + crError("connection expected!"); + return 0; + } + thread = GET_THREAD_VAL_ID(con); + } + else + { + CRASSERT(!con); + thread = GET_THREAD_VAL(); + } + CRASSERT(thread && thread->netServer.conn && thread->netServer.conn->type==CR_VBOXHGCM); + ret = thread->netServer.conn->u32ClientID; + } + crUnlockMutex(&_PackMutex); + + return ret; +} + +void PACKSPU_APIENTRY packspu_VBoxPackSetInjectID(GLuint id) +{ + crLockMutex(&_PackMutex); + { + GET_THREAD(thread); + + CRASSERT(thread && thread->netServer.conn && thread->netServer.conn->type==CR_VBOXHGCM && thread->bInjectThread); + thread->netServer.conn->u32InjectClientID = id; + } + crUnlockMutex(&_PackMutex); +} + +void PACKSPU_APIENTRY packspu_VBoxAttachThread() +{ +#if 0 + int i; + GET_THREAD(thread); + + for (i=0; i<MAX_THREADS; ++i) + { + if (pack_spu.thread[i].inUse && thread==&pack_spu.thread[i] && thread->id==crThreadID()) + { + crError("2nd attach to same thread"); + } + } +#endif + + crSetTSD(&_PackTSD, NULL); + + crStateVBoxAttachThread(); +} + +void PACKSPU_APIENTRY packspu_VBoxDetachThread() +{ + if (CRPACKSPU_IS_WDDM_CRHGSMI()) + { + crPackSetContext(NULL); + crSetTSD(&_PackTSD, NULL); + } + else + { + int i; + GET_THREAD(thread); + if (thread) + { + crLockMutex(&_PackMutex); + + for (i=0; i<MAX_THREADS; ++i) + { + if (pack_spu.thread[i].inUse && thread==&pack_spu.thread[i] + && thread->id==crThreadID() && thread->netServer.conn) + { + CRASSERT(pack_spu.numThreads>0); + + packspuFlush((void *) thread); + + if (pack_spu.thread[i].packer) + { + CR_LOCK_PACKER_CONTEXT(thread->packer); + crPackSetContext(NULL); + CR_UNLOCK_PACKER_CONTEXT(thread->packer); + crPackDeleteContext(pack_spu.thread[i].packer); + + if (pack_spu.thread[i].buffer.pack) + { + crNetFree(pack_spu.thread[i].netServer.conn, pack_spu.thread[i].buffer.pack); + pack_spu.thread[i].buffer.pack = NULL; + } + } + crNetFreeConnection(pack_spu.thread[i].netServer.conn); + + if (pack_spu.thread[i].netServer.name) + crFree(pack_spu.thread[i].netServer.name); + + pack_spu.numThreads--; + /*note can't shift the array here, because other threads have TLS references to array elements*/ + crMemZero(&pack_spu.thread[i], sizeof(ThreadInfo)); + + crSetTSD(&_PackTSD, NULL); + + if (i==pack_spu.idxThreadInUse) + { + for (i=0; i<MAX_THREADS; ++i) + { + if (pack_spu.thread[i].inUse) + { + pack_spu.idxThreadInUse=i; + break; + } + } + } + + break; + } + } + + for (i=0; i<CR_MAX_CONTEXTS; ++i) + { + ContextInfo *ctx = &pack_spu.context[i]; + if (ctx->currentThread == thread) + { + CRASSERT(ctx->fAutoFlush); + ctx->currentThread = NULL; + } + } + + crUnlockMutex(&_PackMutex); + } + } + + crStateVBoxDetachThread(); +} + +#ifdef WINDOWS +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved) +{ + (void) lpvReserved; + + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + { + crInitMutex(&_PackMutex); + break; + } + + case DLL_PROCESS_DETACH: + { + crFreeMutex(&_PackMutex); + crNetTearDown(); + break; + } + + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + default: + break; + } + + return TRUE; +} +#endif + +#else /*ifdef CHROMIUM_THREADSAFE*/ +GLint PACKSPU_APIENTRY packspu_VBoxPackSetInjectThread(struct VBOXUHGSMI *pHgsmi) +{ +} + +GLuint PACKSPU_APIENTRY packspu_VBoxPackGetInjectID(GLint con) +{ + return 0; +} + +void PACKSPU_APIENTRY packspu_VBoxPackSetInjectID(GLuint id) +{ + (void) id; +} + +void PACKSPU_APIENTRY packspu_VBoxPackAttachThread() +{ +} + +void PACKSPU_APIENTRY packspu_VBoxPackDetachThread() +{ +} +#endif /*CHROMIUM_THREADSAFE*/ + +void PACKSPU_APIENTRY packspu_VBoxPresentComposition(GLint win, const struct VBOXVR_SCR_COMPOSITOR * pCompositor, + const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry) +{ + RT_NOREF(win, pCompositor, pChangedEntry); +} + +void PACKSPU_APIENTRY packspu_StringMarkerGREMEDY(GLsizei len, const GLvoid *string) +{ + RT_NOREF(len, string); +} + diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_net.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_net.c new file mode 100644 index 00000000..6d5d41d6 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_net.c @@ -0,0 +1,284 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_pack.h" +#include "cr_mem.h" +#include "cr_net.h" +#include "cr_pixeldata.h" +#include "cr_protocol.h" +#include "cr_error.h" +#include "packspu.h" +#include "packspu_proto.h" + +uint32_t g_u32VBoxHostCaps = 0; + +static void +packspuWriteback( const CRMessageWriteback *wb ) +{ + int *writeback; + crMemcpy( &writeback, &(wb->writeback_ptr), sizeof( writeback ) ); + *writeback = 0; +} + +/** + * XXX Note that this routine is identical to crNetRecvReadback except + * we set *writeback=0 instead of decrementing it. Hmmm. + */ +static void +packspuReadback( const CRMessageReadback *rb, unsigned int len ) +{ + /* minus the header, the destination pointer, + * *and* the implicit writeback pointer at the head. */ + + int payload_len = len - sizeof( *rb ); + int *writeback; + void *dest_ptr; + crMemcpy( &writeback, &(rb->writeback_ptr), sizeof( writeback ) ); + crMemcpy( &dest_ptr, &(rb->readback_ptr), sizeof( dest_ptr ) ); + + *writeback = 0; + crMemcpy( dest_ptr, ((char *)rb) + sizeof(*rb), payload_len ); +} + +static void +packspuReadPixels( const CRMessageReadPixels *rp, unsigned int len ) +{ + crNetRecvReadPixels( rp, len ); + --pack_spu.ReadPixels; +} + +static int +packspuReceiveData( CRConnection *conn, CRMessage *msg, unsigned int len ) +{ + RT_NOREF(conn); + if (msg->header.type == CR_MESSAGE_REDIR_PTR) + msg = (CRMessage*) msg->redirptr.pMessage; + + switch( msg->header.type ) + { + case CR_MESSAGE_READ_PIXELS: + packspuReadPixels( &(msg->readPixels), len ); + break; + case CR_MESSAGE_WRITEBACK: + packspuWriteback( &(msg->writeback) ); + break; + case CR_MESSAGE_READBACK: + packspuReadback( &(msg->readback), len ); + break; + default: + /*crWarning( "Why is the pack SPU getting a message of type 0x%x?", msg->type ); */ + return 0; /* NOT HANDLED */ + } + return 1; /* HANDLED */ +} + +static CRMessageOpcodes * +__prependHeader( CRPackBuffer *buf, unsigned int *len, unsigned int senderID ) +{ + int num_opcodes; + CRMessageOpcodes *hdr; + RT_NOREF(senderID); + + CRASSERT( buf ); + CRASSERT( buf->opcode_current < buf->opcode_start ); + CRASSERT( buf->opcode_current >= buf->opcode_end ); + CRASSERT( buf->data_current > buf->data_start ); + CRASSERT( buf->data_current <= buf->data_end ); + + num_opcodes = buf->opcode_start - buf->opcode_current; + hdr = (CRMessageOpcodes *) + ( buf->data_start - ( ( num_opcodes + 3 ) & ~0x3 ) - sizeof(*hdr) ); + + CRASSERT( (void *) hdr >= buf->pack ); + + if (pack_spu.swap) + { + hdr->header.type = (CRMessageType) SWAP32(CR_MESSAGE_OPCODES); + hdr->numOpcodes = SWAP32(num_opcodes); + } + else + { + hdr->header.type = CR_MESSAGE_OPCODES; + hdr->numOpcodes = num_opcodes; + } + + *len = buf->data_current - (unsigned char *) hdr; + + return hdr; +} + + +/* + * This is called from either the Pack SPU and the packer library whenever + * we need to send a data buffer to the server. + */ +void packspuFlush(void *arg ) +{ + ThreadInfo *thread = (ThreadInfo *) arg; + ContextInfo *ctx; + unsigned int len; + CRMessageOpcodes *hdr; + CRPackBuffer *buf; + + /* we should _always_ pass a valid <arg> value */ + CRASSERT(thread && thread->inUse); +#ifdef CHROMIUM_THREADSAFE + CR_LOCK_PACKER_CONTEXT(thread->packer); +#endif + ctx = thread->currentContext; + buf = &(thread->buffer); + CRASSERT(buf); + + if (ctx && ctx->fCheckZerroVertAttr) + crStateCurrentRecoverNew(ctx->clientState, &thread->packer->current); + + /* We're done packing into the current buffer, unbind it */ + crPackReleaseBuffer( thread->packer ); + + /* + printf("%s thread=%p thread->id = %d thread->pc=%p t2->id=%d t2->pc=%p packbuf=%p packbuf=%p\n", + __FUNCTION__, (void*) thread, (int) thread->id, thread->packer, + (int) t2->id, t2->packer, + buf->pack, thread->packer->buffer.pack); + */ + + if ( buf->opcode_current == buf->opcode_start ) { + /* + printf("%s early return\n", __FUNCTION__); + */ + /* XXX these calls seem to help, but might be appropriate */ + crPackSetBuffer( thread->packer, buf ); + crPackResetPointers(thread->packer); +#ifdef CHROMIUM_THREADSAFE + CR_UNLOCK_PACKER_CONTEXT(thread->packer); +#endif + return; + } + + hdr = __prependHeader( buf, &len, 0 ); + + CRASSERT( thread->netServer.conn ); + + if ( buf->holds_BeginEnd ) + { + /*crDebug("crNetBarf %d, (%d)", len, buf->size);*/ + crNetBarf( thread->netServer.conn, &(buf->pack), hdr, len ); + } + else + { + /*crDebug("crNetSend %d, (%d)", len, buf->size);*/ + crNetSend( thread->netServer.conn, &(buf->pack), hdr, len ); + } + + buf->pack = crNetAlloc( thread->netServer.conn ); + + /* The network may have found a new mtu */ + buf->mtu = thread->netServer.conn->mtu; + + crPackSetBuffer( thread->packer, buf ); + + crPackResetPointers(thread->packer); + +#ifdef CHROMIUM_THREADSAFE + CR_UNLOCK_PACKER_CONTEXT(thread->packer); +#endif +} + + +/** + * XXX NOTE: there's a lot of duplicate code here common to the + * pack, tilesort and replicate SPUs. Try to simplify someday! + */ +void packspuHuge( CROpcode opcode, void *buf ) +{ + GET_THREAD(thread); + unsigned int len; + unsigned char *src; + CRMessageOpcodes *msg; + + CRASSERT(thread); + + /* packet length is indicated by the variable length field, and + includes an additional word for the opcode (with alignment) and + a header */ + len = ((unsigned int *) buf)[-1]; + if (pack_spu.swap) + { + /* It's already been swapped, swap it back. */ + len = SWAP32(len); + } + len += 4 + sizeof(CRMessageOpcodes); + + /* write the opcode in just before the length */ + ((unsigned char *) buf)[-5] = (unsigned char) opcode; + + /* fix up the pointer to the packet to include the length & opcode + & header */ + src = (unsigned char *) buf - 8 - sizeof(CRMessageOpcodes); + + msg = (CRMessageOpcodes *) src; + + if (pack_spu.swap) + { + msg->header.type = (CRMessageType) SWAP32(CR_MESSAGE_OPCODES); + msg->numOpcodes = SWAP32(1); + } + else + { + msg->header.type = CR_MESSAGE_OPCODES; + msg->numOpcodes = 1; + } + + CRASSERT( thread->netServer.conn ); + crNetSend( thread->netServer.conn, NULL, src, len ); +} + +static void packspuFirstConnectToServer( CRNetServer *server +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , struct VBOXUHGSMI *pHgsmi +#endif + ) +{ + crNetInit( packspuReceiveData, NULL ); + crNetServerConnect( server +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , pHgsmi +#endif + ); + if (server->conn) + { + g_u32VBoxHostCaps = crNetHostCapsGet(); + crPackCapsSet(g_u32VBoxHostCaps); + } +} + +void packspuConnectToServer( CRNetServer *server +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , struct VBOXUHGSMI *pHgsmi +#endif + ) +{ + if (pack_spu.numThreads == 0) { + packspuFirstConnectToServer( server +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , pHgsmi +#endif + ); + if (!server->conn) { + crError("packspuConnectToServer: no connection on first create!"); + return; + } + pack_spu.swap = server->conn->swap; + } + else { + /* a new pthread */ + crNetNewClient(server +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , pHgsmi +#endif + ); + } +} diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_pixel.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_pixel.c new file mode 100644 index 00000000..06734b1e --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_pixel.c @@ -0,0 +1,727 @@ +/* Copyright (c) 2001, Stanford University + All rights reserved. + + See the file LICENSE.txt for information on redistributing this software. */ + +#include "cr_packfunctions.h" +#include "cr_glstate.h" +#include "cr_pixeldata.h" +#include "cr_version.h" +#include "packspu.h" +#include "packspu_proto.h" + +static GLboolean packspu_CheckTexImageFormat(GLenum format) +{ + if (format!=GL_COLOR_INDEX + && format!=GL_RED + && format!=GL_GREEN + && format!=GL_BLUE + && format!=GL_ALPHA + && format!=GL_RGB + && format!=GL_BGR + && format!=GL_RGBA + && format!=GL_BGRA + && format!=GL_LUMINANCE + && format!=GL_LUMINANCE_ALPHA + && format!=GL_DEPTH_COMPONENT + && format!=GL_DEPTH_STENCIL) + { + /*crWarning("crPackCheckTexImageFormat FAILED format 0x%x isn't valid", format);*/ + return GL_FALSE; + } + + return GL_TRUE; +} + +static GLboolean packspu_CheckTexImageType(GLenum type) +{ + if (type!=GL_UNSIGNED_BYTE + && type!=GL_BYTE + && type!=GL_BITMAP + && type!=GL_UNSIGNED_SHORT + && type!=GL_SHORT + && type!=GL_UNSIGNED_INT + && type!=GL_INT + && type!=GL_FLOAT + && type!=GL_UNSIGNED_BYTE_3_3_2 + && type!=GL_UNSIGNED_BYTE_2_3_3_REV + && type!=GL_UNSIGNED_SHORT_5_6_5 + && type!=GL_UNSIGNED_SHORT_5_6_5_REV + && type!=GL_UNSIGNED_SHORT_4_4_4_4 + && type!=GL_UNSIGNED_SHORT_4_4_4_4_REV + && type!=GL_UNSIGNED_SHORT_5_5_5_1 + && type!=GL_UNSIGNED_SHORT_1_5_5_5_REV + && type!=GL_UNSIGNED_INT_8_8_8_8 + && type!=GL_UNSIGNED_INT_8_8_8_8_REV + && type!=GL_UNSIGNED_INT_10_10_10_2 + && type!=GL_UNSIGNED_INT_2_10_10_10_REV + && type!=GL_UNSIGNED_INT_24_8) + { + /*crWarning("crPackCheckTexImageType FAILED type 0x%x isn't valid", type);*/ + return GL_FALSE; + } + + return GL_TRUE; +} + +static GLboolean packspu_CheckTexImageInternalFormat(GLint internalformat) +{ + if (internalformat!=1 + && internalformat!=2 + && internalformat!=3 + && internalformat!=4 + && internalformat!=GL_ALPHA + && internalformat!=GL_ALPHA4 + && internalformat!=GL_ALPHA8 + && internalformat!=GL_ALPHA12 + && internalformat!=GL_ALPHA16 + && internalformat!=GL_COMPRESSED_ALPHA + && internalformat!=GL_COMPRESSED_LUMINANCE + && internalformat!=GL_COMPRESSED_LUMINANCE_ALPHA + && internalformat!=GL_COMPRESSED_INTENSITY + && internalformat!=GL_COMPRESSED_RGB + && internalformat!=GL_COMPRESSED_RGBA + && internalformat!=GL_DEPTH_COMPONENT + && internalformat!=GL_DEPTH_COMPONENT16 + && internalformat!=GL_DEPTH_COMPONENT24 + && internalformat!=GL_DEPTH_COMPONENT32 + && internalformat!=GL_DEPTH24_STENCIL8 + && internalformat!=GL_LUMINANCE + && internalformat!=GL_LUMINANCE4 + && internalformat!=GL_LUMINANCE8 + && internalformat!=GL_LUMINANCE12 + && internalformat!=GL_LUMINANCE16 + && internalformat!=GL_LUMINANCE_ALPHA + && internalformat!=GL_LUMINANCE4_ALPHA4 + && internalformat!=GL_LUMINANCE6_ALPHA2 + && internalformat!=GL_LUMINANCE8_ALPHA8 + && internalformat!=GL_LUMINANCE12_ALPHA4 + && internalformat!=GL_LUMINANCE12_ALPHA12 + && internalformat!=GL_LUMINANCE16_ALPHA16 + && internalformat!=GL_INTENSITY + && internalformat!=GL_INTENSITY4 + && internalformat!=GL_INTENSITY8 + && internalformat!=GL_INTENSITY12 + && internalformat!=GL_INTENSITY16 + && internalformat!=GL_R3_G3_B2 + && internalformat!=GL_RGB + && internalformat!=GL_RGB4 + && internalformat!=GL_RGB5 + && internalformat!=GL_RGB8 + && internalformat!=GL_RGB10 + && internalformat!=GL_RGB12 + && internalformat!=GL_RGB16 + && internalformat!=GL_RGBA + && internalformat!=GL_RGBA2 + && internalformat!=GL_RGBA4 + && internalformat!=GL_RGB5_A1 + && internalformat!=GL_RGBA8 + && internalformat!=GL_RGB10_A2 + && internalformat!=GL_RGBA12 + && internalformat!=GL_RGBA16 + && internalformat!=GL_SLUMINANCE + && internalformat!=GL_SLUMINANCE8 + && internalformat!=GL_SLUMINANCE_ALPHA + && internalformat!=GL_SLUMINANCE8_ALPHA8 + && internalformat!=GL_SRGB + && internalformat!=GL_SRGB8 + && internalformat!=GL_SRGB_ALPHA + && internalformat!=GL_SRGB8_ALPHA8 +#ifdef CR_EXT_texture_compression_s3tc + && internalformat!=GL_COMPRESSED_RGB_S3TC_DXT1_EXT + && internalformat!=GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + && internalformat!=GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + && internalformat!=GL_COMPRESSED_RGBA_S3TC_DXT5_EXT +# ifdef CR_EXT_texture_sRGB + && internalformat!=GL_COMPRESSED_SRGB_S3TC_DXT1_EXT + && internalformat!=GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT + && internalformat!=GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT + && internalformat!=GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT +# endif +#endif + /** @todo ARB_texture_float*/ + && internalformat!=GL_RGBA32F_ARB + && internalformat!=GL_RGB32F_ARB + && internalformat!=GL_ALPHA32F_ARB + && internalformat!=GL_INTENSITY32F_ARB + && internalformat!=GL_LUMINANCE32F_ARB + && internalformat!=GL_LUMINANCE_ALPHA32F_ARB + && internalformat!=GL_RGBA16F_ARB + && internalformat!=GL_RGB16F_ARB + && internalformat!=GL_ALPHA16F_ARB + && internalformat!=GL_INTENSITY16F_ARB + && internalformat!=GL_LUMINANCE16F_ARB + && internalformat!=GL_LUMINANCE_ALPHA16F_ARB + ) + { + /*crWarning("crPackCheckTexImageInternalFormat FAILED internalformat 0x%x isn't valid", internalformat);*/ + return GL_FALSE; + } + + return GL_TRUE; +} + +static GLboolean packspu_CheckTexImageParams(GLint internalformat, GLenum format, GLenum type) +{ + return packspu_CheckTexImageFormat(format) + && packspu_CheckTexImageType(type) + && packspu_CheckTexImageInternalFormat(internalformat); +} + +static GLboolean packspu_CheckTexImageFormatType(GLenum format, GLenum type) +{ + return packspu_CheckTexImageFormat(format) + && packspu_CheckTexImageType(type); +} + +static const CRPixelPackState _defaultPacking = { + 0, /* rowLength */ + 0, /* skipRows */ + 0, /* skipPixels */ + 1, /* alignment */ + 0, /* imageHeight */ + 0, /* skipImages */ + GL_FALSE, /* swapBytes */ + GL_FALSE, /* psLSBFirst */ +}; + +#define APPLY_IF_NEQ(state, field, enum) \ + if (state.field != _defaultPacking.field) \ + { \ + crPackPixelStorei(enum, state.field); \ + } + +#define RESTORE_IF_NEQ(state, field, enum) \ + if (state.field != _defaultPacking.field) \ + { \ + crPackPixelStorei(enum, _defaultPacking.field); \ + } + +static void packspu_ApplyUnpackState(void) +{ + GET_THREAD(thread); + ContextInfo *ctx = thread->currentContext; + CRClientState *clientState = &(ctx->clientState->client); + + APPLY_IF_NEQ(clientState->unpack, rowLength, GL_UNPACK_ROW_LENGTH); + APPLY_IF_NEQ(clientState->unpack, skipRows, GL_UNPACK_SKIP_ROWS); + APPLY_IF_NEQ(clientState->unpack, skipPixels, GL_UNPACK_SKIP_PIXELS); + APPLY_IF_NEQ(clientState->unpack, alignment, GL_UNPACK_ALIGNMENT); + APPLY_IF_NEQ(clientState->unpack, imageHeight, GL_UNPACK_IMAGE_HEIGHT); + APPLY_IF_NEQ(clientState->unpack, skipImages, GL_UNPACK_SKIP_IMAGES); + APPLY_IF_NEQ(clientState->unpack, swapBytes, GL_UNPACK_SWAP_BYTES); + APPLY_IF_NEQ(clientState->unpack, psLSBFirst, GL_UNPACK_LSB_FIRST); +} + +static void packspu_RestoreUnpackState(void) +{ + GET_THREAD(thread); + ContextInfo *ctx = thread->currentContext; + CRClientState *clientState = &(ctx->clientState->client); + + RESTORE_IF_NEQ(clientState->unpack, rowLength, GL_UNPACK_ROW_LENGTH); + RESTORE_IF_NEQ(clientState->unpack, skipRows, GL_UNPACK_SKIP_ROWS); + RESTORE_IF_NEQ(clientState->unpack, skipPixels, GL_UNPACK_SKIP_PIXELS); + RESTORE_IF_NEQ(clientState->unpack, alignment, GL_UNPACK_ALIGNMENT); + RESTORE_IF_NEQ(clientState->unpack, imageHeight, GL_UNPACK_IMAGE_HEIGHT); + RESTORE_IF_NEQ(clientState->unpack, skipImages, GL_UNPACK_SKIP_IMAGES); + RESTORE_IF_NEQ(clientState->unpack, swapBytes, GL_UNPACK_SWAP_BYTES); + RESTORE_IF_NEQ(clientState->unpack, psLSBFirst, GL_UNPACK_LSB_FIRST); +} + +static void packspu_ApplyPackState(void) +{ + GET_THREAD(thread); + ContextInfo *ctx = thread->currentContext; + CRClientState *clientState = &(ctx->clientState->client); + + APPLY_IF_NEQ(clientState->pack, rowLength, GL_PACK_ROW_LENGTH); + APPLY_IF_NEQ(clientState->pack, skipRows, GL_PACK_SKIP_ROWS); + APPLY_IF_NEQ(clientState->pack, skipPixels, GL_PACK_SKIP_PIXELS); + APPLY_IF_NEQ(clientState->pack, alignment, GL_PACK_ALIGNMENT); + APPLY_IF_NEQ(clientState->pack, imageHeight, GL_PACK_IMAGE_HEIGHT); + APPLY_IF_NEQ(clientState->pack, skipImages, GL_PACK_SKIP_IMAGES); + APPLY_IF_NEQ(clientState->pack, swapBytes, GL_PACK_SWAP_BYTES); + APPLY_IF_NEQ(clientState->pack, psLSBFirst, GL_PACK_LSB_FIRST); +} + +static void packspu_RestorePackState(void) +{ + GET_THREAD(thread); + ContextInfo *ctx = thread->currentContext; + CRClientState *clientState = &(ctx->clientState->client); + + RESTORE_IF_NEQ(clientState->pack, rowLength, GL_PACK_ROW_LENGTH); + RESTORE_IF_NEQ(clientState->pack, skipRows, GL_PACK_SKIP_ROWS); + RESTORE_IF_NEQ(clientState->pack, skipPixels, GL_PACK_SKIP_PIXELS); + RESTORE_IF_NEQ(clientState->pack, alignment, GL_PACK_ALIGNMENT); + RESTORE_IF_NEQ(clientState->pack, imageHeight, GL_PACK_IMAGE_HEIGHT); + RESTORE_IF_NEQ(clientState->pack, skipImages, GL_PACK_SKIP_IMAGES); + RESTORE_IF_NEQ(clientState->pack, swapBytes, GL_PACK_SWAP_BYTES); + RESTORE_IF_NEQ(clientState->pack, psLSBFirst, GL_PACK_LSB_FIRST); +} + +void PACKSPU_APIENTRY packspu_PixelStoref( GLenum pname, GLfloat param ) +{ + /* NOTE: we do not send pixel store parameters to the server! + * When we pack a glDrawPixels or glTexImage2D image we interpret + * the user's pixel store parameters at that time and pack the + * image in a canonical layout (see util/pixel.c). + */ + crStatePixelStoref( pname, param ); +} + +void PACKSPU_APIENTRY packspu_PixelStorei( GLenum pname, GLint param ) +{ + crStatePixelStorei( pname, param ); +} + +void PACKSPU_APIENTRY packspu_DrawPixels( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) +{ + GET_THREAD(thread); + ContextInfo *ctx = thread->currentContext; + CRClientState *clientState = &(ctx->clientState->client); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + crPackDrawPixels( width, height, format, type, pixels, &(clientState->unpack) ); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} + +void PACKSPU_APIENTRY packspu_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels ) +{ + GET_THREAD(thread); + ContextInfo *ctx = thread->currentContext; + CRClientState *clientState = &(ctx->clientState->client); + int writeback; + + if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) + { + packspu_ApplyPackState(); + } + + crPackReadPixels(x, y, width, height, format, type, pixels, &(clientState->pack), &writeback); + + if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) + { + packspu_RestorePackState(); + } + +#ifdef CR_ARB_pixel_buffer_object + if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) +#endif + { + pack_spu.ReadPixels++; + + packspuFlush((void *) thread); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + } +} + +/** @todo check with pbo's*/ +void PACKSPU_APIENTRY packspu_CopyPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLenum type ) +{ + GET_THREAD(thread); + if (pack_spu.swap) + crPackCopyPixelsSWAP( x, y, width, height, type ); + else + crPackCopyPixels( x, y, width, height, type ); + /* XXX why flush here? */ + packspuFlush( (void *) thread ); +} + +void PACKSPU_APIENTRY packspu_Bitmap( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap ) +{ + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + crPackBitmap(width, height, xorig, yorig, xmove, ymove, bitmap, &(clientState->unpack)); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} + +void PACKSPU_APIENTRY packspu_TexImage1D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) +{ + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + + if (!packspu_CheckTexImageParams(internalformat, format, type)) + { + if (pixels || crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + crWarning("packspu_TexImage1D invalid internalFormat(%x)/format(%x)/type(%x)", internalformat, format, type); + return; + } + internalformat = packspu_CheckTexImageInternalFormat(internalformat) ? internalformat:GL_RGBA; + format = packspu_CheckTexImageFormat(format) ? format:GL_RGBA; + type = packspu_CheckTexImageType(type) ? type:GL_UNSIGNED_BYTE; + } + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + if (pack_spu.swap) + crPackTexImage1DSWAP( target, level, internalformat, width, border, format, type, pixels, &(clientState->unpack) ); + else + crPackTexImage1D( target, level, internalformat, width, border, format, type, pixels, &(clientState->unpack) ); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} + +void PACKSPU_APIENTRY packspu_TexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) +{ + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + + if (!packspu_CheckTexImageParams(internalformat, format, type)) + { + if (pixels || crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + crWarning("packspu_TexImage2D invalid internalFormat(%x)/format(%x)/type(%x)", internalformat, format, type); + return; + } + internalformat = packspu_CheckTexImageInternalFormat(internalformat) ? internalformat:GL_RGBA; + format = packspu_CheckTexImageFormat(format) ? format:GL_RGBA; + type = packspu_CheckTexImageType(type) ? type:GL_UNSIGNED_BYTE; + } + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + if (pack_spu.swap) + crPackTexImage2DSWAP( target, level, internalformat, width, height, border, format, type, pixels, &(clientState->unpack) ); + else + crPackTexImage2D( target, level, internalformat, width, height, border, format, type, pixels, &(clientState->unpack) ); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} + +#ifdef GL_EXT_texture3D +void PACKSPU_APIENTRY packspu_TexImage3DEXT( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) +{ + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + if (pack_spu.swap) + crPackTexImage3DEXTSWAP( target, level, internalformat, width, height, depth, border, format, type, pixels, &(clientState->unpack) ); + else + crPackTexImage3DEXT( target, level, internalformat, width, height, depth, border, format, type, pixels, &(clientState->unpack) ); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} +#endif + +#ifdef CR_OPENGL_VERSION_1_2 +void PACKSPU_APIENTRY packspu_TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) +{ + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + if (pack_spu.swap) + crPackTexImage3DSWAP( target, level, internalformat, width, height, depth, border, format, type, pixels, &(clientState->unpack) ); + else + crPackTexImage3D( target, level, internalformat, width, height, depth, border, format, type, pixels, &(clientState->unpack) ); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} +#endif /* CR_OPENGL_VERSION_1_2 */ + +void PACKSPU_APIENTRY packspu_TexSubImage1D( GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels ) +{ + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + + if (!packspu_CheckTexImageFormatType(format, type)) + { + crWarning("packspu_TexSubImage1D invalid format(%x)/type(%x)", format, type); + return; + } + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + if (pack_spu.swap) + crPackTexSubImage1DSWAP( target, level, xoffset, width, format, type, pixels, &(clientState->unpack) ); + else + crPackTexSubImage1D( target, level, xoffset, width, format, type, pixels, &(clientState->unpack) ); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} + +void PACKSPU_APIENTRY packspu_TexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) +{ + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + + if (!packspu_CheckTexImageFormatType(format, type)) + { + crWarning("packspu_TexSubImage2D invalid format(%x)/type(%x)", format, type); + return; + } + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + if (pack_spu.swap) + crPackTexSubImage2DSWAP( target, level, xoffset, yoffset, width, height, format, type, pixels, &(clientState->unpack) ); + else + crPackTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, pixels, &(clientState->unpack) ); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} + +#ifdef CR_OPENGL_VERSION_1_2 +void PACKSPU_APIENTRY packspu_TexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels ) +{ + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + if (pack_spu.swap) + crPackTexSubImage3DSWAP( target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels, &(clientState->unpack) ); + else + crPackTexSubImage3D( target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels, &(clientState->unpack) ); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} +#endif /* CR_OPENGL_VERSION_1_2 */ + +void PACKSPU_APIENTRY packspu_ZPixCR( GLsizei width, GLsizei height, GLenum format, GLenum type, GLenum ztype, GLint zparm, GLint length, const GLvoid *pixels ) +{ + GET_CONTEXT(ctx); + CRClientState *clientState = &(ctx->clientState->client); + if (pack_spu.swap) + crPackZPixCRSWAP( width, height, format, type, ztype, zparm, length, pixels, &(clientState->unpack) ); + else + crPackZPixCR( width, height, format, type, ztype, zparm, length, pixels, &(clientState->unpack) ); +} + +void PACKSPU_APIENTRY packspu_GetTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels) +{ + GET_THREAD(thread); + ContextInfo *ctx = thread->currentContext; + CRClientState *clientState = &(ctx->clientState->client); + int writeback = 1; + + /* XXX note: we're not observing the pixel pack parameters here unless PACK PBO is bound + * To do so, we'd have to allocate a temporary image buffer (how large???) + * and copy the image to the user's buffer using the pixel pack params. + */ + + if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) + { + packspu_ApplyPackState(); + } + + if (pack_spu.swap) + crPackGetTexImageSWAP( target, level, format, type, pixels, &(clientState->pack), &writeback ); + else + crPackGetTexImage( target, level, format, type, pixels, &(clientState->pack), &writeback ); + + if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) + { + packspu_RestorePackState(); + } + +#ifdef CR_ARB_pixel_buffer_object + if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) +#endif + { + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + } +} + +void PACKSPU_APIENTRY packspu_GetCompressedTexImageARB( GLenum target, GLint level, GLvoid * img ) +{ + GET_THREAD(thread); + int writeback = 1; + + if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) + { + packspu_ApplyPackState(); + } + + if (pack_spu.swap) + { + crPackGetCompressedTexImageARBSWAP( target, level, img, &writeback ); + } + else + { + crPackGetCompressedTexImageARB( target, level, img, &writeback ); + } + + if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) + { + packspu_RestorePackState(); + } + +#ifdef CR_ARB_pixel_buffer_object + if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) +#endif + { + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + } +} + +void PACKSPU_APIENTRY +packspu_CompressedTexImage1DARB(GLenum target, GLint level, GLenum internalformat, GLsizei width, + GLint border, GLsizei imagesize, const GLvoid *data) +{ + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + crPackCompressedTexImage1DARB(target, level, internalformat, width, border, imagesize, data); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} + +void PACKSPU_APIENTRY +packspu_CompressedTexImage2DARB(GLenum target, GLint level, GLenum internalformat, GLsizei width, + GLsizei height, GLint border, GLsizei imagesize, const GLvoid *data) +{ + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + crPackCompressedTexImage2DARB(target, level, internalformat, width, height, border, imagesize, data); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} + +void PACKSPU_APIENTRY +packspu_CompressedTexImage3DARB(GLenum target, GLint level, GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, GLsizei imagesize, const GLvoid *data) +{ + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + crPackCompressedTexImage3DARB(target, level, internalformat, width, height, depth, border, imagesize, data); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} + +void PACKSPU_APIENTRY +packspu_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, GLsizei width, + GLenum format, GLsizei imagesize, const GLvoid *data) +{ + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + crPackCompressedTexSubImage1DARB(target, level, xoffset, width, format, imagesize, data); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} + +void PACKSPU_APIENTRY +packspu_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, GLenum format, GLsizei imagesize, const GLvoid *data) +{ + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + crPackCompressedTexSubImage2DARB(target, level, xoffset, yoffset, width, height, format, imagesize, data); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} + +void PACKSPU_APIENTRY +packspu_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imagesize, const GLvoid *data) +{ + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_ApplyUnpackState(); + } + + crPackCompressedTexSubImage3DARB(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imagesize, data); + + if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + packspu_RestoreUnpackState(); + } +} diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_proto.py b/src/VBox/Additions/common/crOpenGL/pack/packspu_proto.py new file mode 100755 index 00000000..5feed9a9 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_proto.py @@ -0,0 +1,50 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - THIS FILE AUTOMATICALLY GENERATED BY packspu_proto.py SCRIPT */ + +#ifndef PACKSPU_FUNCTIONS_H +#define PACKSPU_FUNCTIONS_H 1 + +#include <stdio.h> +#include "cr_string.h" +#include "cr_spu.h" +#include "packspu.h" +#include "cr_packfunctions.h" +""") + + +pack_specials = [] + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +# make list of special functions +for func_name in keys: + if ("get" in apiutil.Properties(func_name) or + apiutil.FindSpecial( "packspu", func_name ) or + apiutil.FindSpecial( "packspu_flush", func_name ) or + apiutil.FindSpecial( "packspu_vertex", func_name )): + pack_specials.append( func_name ) + +for func_name in keys: + if apiutil.FindSpecial( "packspu_unimplemented", func_name ): + continue + if func_name in pack_specials: + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + print('extern %s PACKSPU_APIENTRY packspu_%s(%s);' % ( return_type, func_name, apiutil.MakeDeclarationString(params) )) + + +print(""" +#endif +""") diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_special b/src/VBox/Additions/common/crOpenGL/pack/packspu_special new file mode 100644 index 00000000..13c3e0a2 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_special @@ -0,0 +1,138 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +AreTexturesResident +AreProgramsResidentNV +GetString +GetTexImage +EnableClientState +DisableClientState +Enable +Disable +ClientActiveTextureARB +ColorPointer +FogCoordPointerEXT +SecondaryColorPointerEXT +VertexAttribPointerARB +VertexAttribPointerNV +GetPointerv +VertexPointer +NormalPointer +TexCoordPointer +EdgeFlagPointer +IndexPointer +ArrayElement +DrawArrays +DrawElements +DrawRangeElements +InterleavedArrays +ReadPixels +DrawPixels +CopyPixels +Bitmap +SwapBuffers +Flush +Finish +PixelStorei +PixelStoref +PushClientAttrib +PopClientAttrib +CreateContext +WindowCreate +MakeCurrent +DestroyContext +Begin +End +TexImage1D +TexSubImage1D +TexImage2D +TexSubImage2D +TexImage3D +TexImage3DEXT +TexSubImage3D +ChromiumParametervCR +MultiDrawArraysEXT +MultiDrawElementsEXT +GetBufferPointervARB +GetBufferParameterivARB +MapBufferARB +UnmapBufferARB +BindBufferARB +BufferDataARB +ZPixCR +ActiveTextureARB +DrawBuffer +Flush +GetActiveAttrib +GetActiveUniform +GetAttachedShaders +GetShaderInfoLog +GetProgramInfoLog +GetShaderSource +GetAttachedObjectsARB +GetInfoLogARB +BufferSubDataARB +EnableVertexAttribArrayARB +DisableVertexAttribArrayARB +GetBufferSubDataARB +IsEnabled +LockArraysEXT +UnlockArraysEXT +CreateProgram +LinkProgram +DeleteProgram +GetUniformLocation +GetAttribLocation +GetUniformsLocations +GetAttribsLocations +BindFramebufferEXT +DeleteObjectARB +BindFramebufferEXT +DeleteFramebuffersEXT +FramebufferTexture1DEXT +FramebufferTexture2DEXT +FramebufferTexture3DEXT +FramebufferRenderbufferEXT +CheckFramebufferStatusEXT +BindTexture +DeleteTextures +GetPolygonStipple +GetPixelMapfv +GetPixelMapuiv +GetPixelMapusv +GetCompressedTexImageARB +BindRenderbufferEXT +VBoxPackSetInjectThread +VBoxPackGetInjectID +VBoxPackSetInjectID +VBoxAttachThread +VBoxDetachThread +VBoxCreateContext +VBoxConChromiumParameteriCR +VBoxConChromiumParametervCR +VBoxWindowCreate +VBoxWindowDestroy +VBoxConCreate +VBoxConDestroy +VBoxConFlush +VBoxPresentComposition +ChromiumParameteriCR +CompressedTexImage1DARB +CompressedTexImage2DARB +CompressedTexImage3DARB +CompressedTexSubImage1DARB +CompressedTexSubImage2DARB +CompressedTexSubImage3DARB +GenFramebuffersEXT +GenRenderbuffersEXT +DeleteFramebuffersEXT +DeleteRenderbuffersEXT +GenBuffersARB +DeleteBuffersARB +StringMarkerGREMEDY +GenTextures +CompileShader +NewList +EndList +GetError diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_swapbuf.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_swapbuf.c new file mode 100644 index 00000000..bc1895fe --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_swapbuf.c @@ -0,0 +1,102 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_packfunctions.h" +#include "cr_error.h" +#include "cr_net.h" +#include "packspu.h" +#include "packspu_proto.h" + +#if 0 + +void PACKSPU_APIENTRY packspu_SwapBuffers( GLint window, GLint flags ) +{ + GET_THREAD(thread); + if (pack_spu.swap) + { + crPackSwapBuffersSWAP( window, flags ); + } + else + { + crPackSwapBuffers( window, flags ); + } + packspuFlush( (void *) thread ); +} + + +#else + +void PACKSPU_APIENTRY packspu_SwapBuffers( GLint window, GLint flags ) +{ + GET_THREAD(thread); + + if (pack_spu.swap) + { + crPackSwapBuffersSWAP( window, flags ); + } + else + { + crPackSwapBuffers( window, flags ); + } + packspuFlush( (void *) thread ); + + if (!(thread->netServer.conn->actual_network)) + { + /* no synchronization needed */ + return; + } + + if (pack_spu.swapbuffer_sync) { + /* This won't block unless there has been more than 1 frame + * since we received a writeback acknowledgement. In the + * normal case there's no performance penalty for doing this + * (beyond the cost of packing the writeback request into the + * stream and receiving the reply), but it eliminates the + * problem of runaway rendering that can occur, eg when + * rendering frames consisting of a single large display list + * in a tight loop. + * + * Note that this is *not* the same as doing a sync after each + * swapbuffers, which would force a round-trip 'bubble' into + * the network stream under normal conditions. + * + * This is complicated because writeback in the pack spu is + * overridden to always set the value to zero when the + * reply is received, rather than decrementing it: + */ + switch( thread->writeback ) { + case 0: + /* Request writeback. + */ + thread->writeback = 1; + if (pack_spu.swap) + { + crPackWritebackSWAP( (GLint *) &thread->writeback ); + } + else + { + crPackWriteback( (GLint *) &thread->writeback ); + } + break; + case 1: + /* Make sure writeback from previous frame has been received. + */ + CRPACKSPU_WRITEBACK_WAIT(thread, thread->writeback); + break; + } + } + + /* want to emit a parameter here */ + if (pack_spu.emit_GATHER_POST_SWAPBUFFERS) + { + if (pack_spu.swap) + crPackChromiumParameteriCRSWAP(GL_GATHER_POST_SWAPBUFFERS_CR, 1); + else + crPackChromiumParameteriCR(GL_GATHER_POST_SWAPBUFFERS_CR, 1); + } +} + +#endif diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_texture.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_texture.c new file mode 100644 index 00000000..5057bcb3 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_texture.c @@ -0,0 +1,70 @@ +/* $Id: packspu_texture.c $ */ + +/** @file + * VBox OpenGL DRI driver functions + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include "packspu.h" +#include "cr_packfunctions.h" +#include "cr_glstate.h" +#include "packspu_proto.h" + +void PACKSPU_APIENTRY packspu_ActiveTextureARB(GLenum texture) +{ + crStateActiveTextureARB(texture); + crPackActiveTextureARB(texture); +} + +void PACKSPU_APIENTRY packspu_BindTexture(GLenum target, GLuint texture) +{ + crStateBindTexture(target, texture); + crPackBindTexture(target, texture); +} + +void PACKSPU_APIENTRY packspu_DeleteTextures(GLsizei n, const GLuint * textures) +{ + crStateDeleteTextures(n, textures); + crPackDeleteTextures(n, textures); +} + +void PACKSPU_APIENTRY packspu_GenTextures( GLsizei n, GLuint * textures ) +{ + GET_THREAD(thread); + int writeback = 1; + unsigned int i; + if (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network)) + { + crError( "packspu_GenTextures doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!" ); + } + if (pack_spu.swap) + { + crPackGenTexturesSWAP( n, textures, &writeback ); + } + else + { + crPackGenTextures( n, textures, &writeback ); + } + packspuFlush( (void *) thread ); + CRPACKSPU_WRITEBACK_WAIT(thread, writeback); + if (pack_spu.swap) + { + for (i = 0 ; i < (unsigned int) n ; i++) + { + textures[i] = SWAP32(textures[i]); + } + } + + crStateRegTextures(n, textures); +} diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_unimplemented_special b/src/VBox/Additions/common/crOpenGL/pack/packspu_unimplemented_special new file mode 100644 index 00000000..f71300c9 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_unimplemented_special @@ -0,0 +1,4 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_vertex_special b/src/VBox/Additions/common/crOpenGL/pack/packspu_vertex_special new file mode 100644 index 00000000..bbbc13d0 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_vertex_special @@ -0,0 +1,28 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +Vertex2d +Vertex2dv +Vertex2f +Vertex2fv +Vertex2i +Vertex2iv +Vertex2s +Vertex2sv +Vertex3d +Vertex3dv +Vertex3f +Vertex3fv +Vertex3i +Vertex3iv +Vertex3s +Vertex3sv +Vertex4d +Vertex4dv +Vertex4f +Vertex4fv +Vertex4i +Vertex4iv +Vertex4s +Vertex4sv diff --git a/src/VBox/Additions/common/crOpenGL/passthrough/Makefile.kup b/src/VBox/Additions/common/crOpenGL/passthrough/Makefile.kup new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/passthrough/Makefile.kup diff --git a/src/VBox/Additions/common/crOpenGL/passthrough/passthrough.def b/src/VBox/Additions/common/crOpenGL/passthrough/passthrough.def new file mode 100644 index 00000000..9edc7163 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/passthrough/passthrough.def @@ -0,0 +1,6 @@ +; Copyright (c) 2001, Stanford University +; All rights reserved. +; +; See the file LICENSE.txt for information on redistributing this software. +EXPORTS +SPULoad diff --git a/src/VBox/Additions/common/crOpenGL/passthrough/passthrough.py b/src/VBox/Additions/common/crOpenGL/passthrough/passthrough.py new file mode 100755 index 00000000..ec7e27c7 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/passthrough/passthrough.py @@ -0,0 +1,40 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + + +apiutil.CopyrightC() + +print("""#include <stdio.h> +#include "cr_error.h" +#include "cr_string.h" +#include "cr_spu.h" +#include "passthroughspu.h" +""") + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + + +print('SPUNamedFunctionTable _cr_passthrough_table[%d];' % ( len(keys) + 1 )) + +print(""" +static void __fillin(int offset, char *name, SPUGenericFunction func) +{ + _cr_passthrough_table[offset].name = crStrdup(name); + _cr_passthrough_table[offset].fn = func; +} + +void BuildPassthroughTable( SPU *child ) +{""") + +for index in range(len(keys)): + func_name = keys[index] + print('\t__fillin(%3d, "%s", (SPUGenericFunction) child->dispatch_table.%s);' % (index, func_name, func_name )) +print('\t__fillin(%3d, NULL, NULL);' % len(keys)) +print('}') diff --git a/src/VBox/Additions/common/crOpenGL/passthrough/passthroughspu.h b/src/VBox/Additions/common/crOpenGL/passthrough/passthroughspu.h new file mode 100644 index 00000000..a0e6b942 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/passthrough/passthroughspu.h @@ -0,0 +1,21 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#ifndef GA_INCLUDED_SRC_common_crOpenGL_passthrough_passthroughspu_h +#define GA_INCLUDED_SRC_common_crOpenGL_passthrough_passthroughspu_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + + +#include "cr_spu.h" + + +extern SPUNamedFunctionTable _cr_passthrough_table[]; +extern void BuildPassthroughTable( SPU *child ); + + +#endif /* !GA_INCLUDED_SRC_common_crOpenGL_passthrough_passthroughspu_h */ diff --git a/src/VBox/Additions/common/crOpenGL/passthrough/passthroughspu.rc b/src/VBox/Additions/common/crOpenGL/passthrough/passthroughspu.rc new file mode 100644 index 00000000..ad2034e5 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/passthrough/passthroughspu.rc @@ -0,0 +1,69 @@ +/* $Id: passthroughspu.rc $ */ +/** @file + * VBoxOGLpassthroughspu - Resource file containing version info and icon. + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include <windows.h> +#include <VBox/version.h> + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VBOX_RC_FILE_VERSION + PRODUCTVERSION VBOX_RC_FILE_VERSION + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS VBOX_RC_FILE_FLAGS + FILEOS VBOX_RC_FILE_OS + FILETYPE VBOX_RC_TYPE_DRV + FILESUBTYPE VFT2_DRV_DISPLAY +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "VirtualBox crOpenGL ICD\0" + VALUE "InternalName", "VBoxOGLpassthroughspu\0" +#ifdef VBOX_WDDM_WOW64 + VALUE "OriginalFilename", "VBoxOGLpassthroughspu-x86.dll\0" +#else + VALUE "OriginalFilename", "VBoxOGLpassthroughspu.dll\0" +#endif + VALUE "CompanyName", VBOX_RC_COMPANY_NAME + VALUE "FileVersion", VBOX_RC_FILE_VERSION_STR + VALUE "LegalCopyright", VBOX_RC_LEGAL_COPYRIGHT + VALUE "ProductName", VBOX_RC_PRODUCT_NAME_GA_STR + VALUE "ProductVersion", VBOX_RC_PRODUCT_VERSION_STR + VBOX_RC_MORE_STRINGS + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +1 RCDATA +BEGIN +// Machine dependent parameters + 17, // Height of vertical thumb + 17, // Width of horizontal thumb + 2, // Icon horiz compression factor + 2, // Icon vert compression factor + 1, // Cursor horz compression factor + 1, // Cursor vert compression factor + 0, // Kanji window height + 1, // cxBorder (thickness of vertical lines) + 1 // cyBorder (thickness of horizontal lines) +END diff --git a/src/VBox/Additions/common/crOpenGL/passthrough/passthroughspu_init.c b/src/VBox/Additions/common/crOpenGL/passthrough/passthroughspu_init.c new file mode 100644 index 00000000..c08a17a4 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/passthrough/passthroughspu_init.c @@ -0,0 +1,64 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_error.h" +#include "passthroughspu.h" + +static SPUFunctions passthrough_functions = { + NULL, /* CHILD COPY */ + NULL, /* DATA */ + _cr_passthrough_table /* THE ACTUAL FUNCTIONS */ +}; + +static SPUFunctions * +passthroughSPUInit( int id, SPU *child, SPU *self, + unsigned int context_id, + unsigned int num_contexts ) +{ + (void) id; + (void) self; + (void) context_id; + (void) num_contexts; + + if (child == NULL) + { + crError( "You can't load the passthrough SPU as the last SPU in a chain!" ); + } + BuildPassthroughTable( child ); + return &passthrough_functions; +} + +static void +passthroughSPUSelfDispatch(SPUDispatchTable *parent) +{ + (void)parent; +} + +static int +passthroughSPUCleanup(void) +{ + return 1; +} + +static SPUOptions passthroughSPUOptions[] = { + { NULL, CR_BOOL, 0, NULL, NULL, NULL, NULL, NULL }, +}; + + +int SPULoad( char **name, char **super, SPUInitFuncPtr *init, + SPUSelfDispatchFuncPtr *self, SPUCleanupFuncPtr *cleanup, + SPUOptionsPtr *options, int *flags ) +{ + *name = "passthrough"; + *super = NULL; + *init = passthroughSPUInit; + *self = passthroughSPUSelfDispatch; + *cleanup = passthroughSPUCleanup; + *options = passthroughSPUOptions; + *flags = (SPU_NO_PACKER|SPU_NOT_TERMINAL|SPU_MAX_SERVERS_ZERO); + + return 1; +} diff --git a/src/VBox/Additions/common/crOpenGL/stub.c b/src/VBox/Additions/common/crOpenGL/stub.c new file mode 100644 index 00000000..f5369c6e --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/stub.c @@ -0,0 +1,548 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_spu.h" +#include "cr_error.h" +#include "cr_mem.h" +#include "stub.h" +#include <iprt/thread.h> + +#ifdef GLX +Display* stubGetWindowDisplay(WindowInfo *pWindow) +{ +#if defined(CR_NEWWINTRACK) + if ((NIL_RTTHREAD!=stub.hSyncThread) && (RTThreadNativeSelf()==RTThreadGetNative(stub.hSyncThread))) + { + if (pWindow && pWindow->dpy && !pWindow->syncDpy) + { + crDebug("going to XOpenDisplay(%s)", pWindow->dpyName); + pWindow->syncDpy = XOpenDisplay(pWindow->dpyName); + if (!pWindow->syncDpy) + { + crWarning("Failed to open display %s", pWindow->dpyName); + } + return pWindow->syncDpy; + } + else + { + return pWindow ? pWindow->syncDpy:NULL; + } + } + else +#endif + { + return pWindow ? pWindow->dpy:NULL; + } +} +#endif + +/** + * Returns -1 on error + */ +GLint APIENTRY crCreateContext(char *dpyName, GLint visBits) +{ + ContextInfo *context; + stubInit(); + /* XXX in Chromium 1.5 and earlier, the last parameter was UNDECIDED. + * That didn't seem right so it was changed to CHROMIUM. (Brian) + */ + context = stubNewContext(dpyName, visBits, CHROMIUM, 0 +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , NULL +#endif + ); + return context ? (int) context->id : -1; +} + +void APIENTRY crDestroyContext( GLint context ) +{ + stubDestroyContext(context); +} + +void APIENTRY crMakeCurrent( GLint window, GLint context ) +{ + WindowInfo *winInfo = (WindowInfo *) + crHashtableSearch(stub.windowTable, (unsigned int) window); + ContextInfo *contextInfo = (ContextInfo *) + crHashtableSearch(stub.contextTable, context); + if (contextInfo && contextInfo->type == NATIVE) { + crWarning("Can't call crMakeCurrent with native GL context"); + return; + } + + stubMakeCurrent(winInfo, contextInfo); +} + +GLint APIENTRY crGetCurrentContext( void ) +{ + ContextInfo *context; + stubInit(); + context = stubGetCurrentContext(); + if (context) + return (GLint) context->id; + else + return 0; +} + +GLint APIENTRY crGetCurrentWindow( void ) +{ + ContextInfo *context; + stubInit(); + context = stubGetCurrentContext(); + if (context && context->currentDrawable) + return context->currentDrawable->spuWindow; + else + return -1; +} + +void APIENTRY crSwapBuffers( GLint window, GLint flags ) +{ + WindowInfo *winInfo = (WindowInfo *) + crHashtableSearch(stub.windowTable, (unsigned int) window); + if (winInfo) + stubSwapBuffers(winInfo, flags); +} + +/** + * Returns -1 on error + */ +GLint APIENTRY crWindowCreate( const char *dpyName, GLint visBits ) +{ + stubInit(); + return stubNewWindow( dpyName, visBits ); +} + +void APIENTRY crWindowDestroy( GLint window ) +{ + stubDestroyWindow( 0, window ); +} + +void APIENTRY crWindowSize( GLint window, GLint w, GLint h ) +{ + const WindowInfo *winInfo = (const WindowInfo *) + crHashtableSearch(stub.windowTable, (unsigned int) window); + if (winInfo && winInfo->type == CHROMIUM) + { + crDebug("Dispatched crWindowSize (%i)", window); + stub.spu->dispatch_table.WindowSize( window, w, h ); + } +} + +void APIENTRY crWindowPosition( GLint window, GLint x, GLint y ) +{ + const WindowInfo *winInfo = (const WindowInfo *) + crHashtableSearch(stub.windowTable, (unsigned int) window); + if (winInfo && winInfo->type == CHROMIUM) + { + crDebug("Dispatched crWindowPosition (%i)", window); + stub.spu->dispatch_table.WindowPosition( window, x, y ); + } +} + +void APIENTRY crWindowVisibleRegion( GLint window, GLint cRects, const void *pRects ) +{ + const WindowInfo *winInfo = (const WindowInfo *) + crHashtableSearch(stub.windowTable, (unsigned int) window); + if (winInfo && winInfo->type == CHROMIUM) + { + crDebug("Dispatched crWindowVisibleRegion (%i, cRects=%i)", window, cRects); + stub.spu->dispatch_table.WindowVisibleRegion( window, cRects, pRects ); + } +} + +void APIENTRY crVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects) +{ + RT_NOREF(texture, cfg, xPos, yPos, cRects, pRects); + crError("not expected!"); +} + +void APIENTRY crWindowShow( GLint window, GLint flag ) +{ + WindowInfo *winInfo = (WindowInfo *) + crHashtableSearch(stub.windowTable, (unsigned int) window); + if (winInfo && winInfo->type == CHROMIUM) + stub.spu->dispatch_table.WindowShow( window, flag ); + winInfo->mapped = flag ? GL_TRUE : GL_FALSE; +} + +void APIENTRY stub_GetChromiumParametervCR( GLenum target, GLuint index, GLenum type, GLsizei count, GLvoid *values ) +{ + char **ret; + switch( target ) + { + case GL_HEAD_SPU_NAME_CR: + ret = (char **) values; + *ret = stub.spu->name; + return; + default: + stub.spu->dispatch_table.GetChromiumParametervCR( target, index, type, count, values ); + break; + } +} + +/* + * Updates geometry info for given spu window. + * Returns GL_TRUE if it changed since last call, GL_FALSE otherwise. + * bForceUpdate - forces dispatching of geometry info even if it's unchanged + */ +GLboolean stubUpdateWindowGeometry(WindowInfo *pWindow, GLboolean bForceUpdate) +{ + int winX, winY; + unsigned int winW, winH; + GLboolean res = GL_FALSE; + + CRASSERT(pWindow); + + stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH); + + /** @todo remove "if (winW && winH)"?*/ + if (winW && winH) { + if (stub.trackWindowSize) { + if (bForceUpdate || winW != pWindow->width || winH != pWindow->height) { + crDebug("Dispatched WindowSize (%i)", pWindow->spuWindow); +#ifdef VBOX_WITH_WDDM + if (!stub.bRunningUnderWDDM || pWindow->mapped) +#endif + { + stub.spuDispatch.WindowSize(pWindow->spuWindow, winW, winH); + } + pWindow->width = winW; + pWindow->height = winH; + res = GL_TRUE; + } + } + if (stub.trackWindowPos) { + if (bForceUpdate || winX != pWindow->x || winY != pWindow->y) { + crDebug("Dispatched WindowPosition (%i)", pWindow->spuWindow); +#ifdef VBOX_WITH_WDDM + if (!stub.bRunningUnderWDDM || pWindow->mapped) +#endif + { + stub.spuDispatch.WindowPosition(pWindow->spuWindow, winX, winY); + } + pWindow->x = winX; + pWindow->y = winY; + res = GL_TRUE; + } + } + } + + return res; +} + +#ifdef WINDOWS +/* + * Updates visible regions for given spu window. + * Returns GL_TRUE if regions changed since last call, GL_FALSE otherwise. + */ +GLboolean stubUpdateWindowVisibileRegions(WindowInfo *pWindow) +{ + HRGN hVisRgn; + HWND hwnd; + DWORD dwCount; + LPRGNDATA lpRgnData; + POINT pt; + int iret; + + if (!pWindow) return GL_FALSE; + hwnd = pWindow->hWnd; + if (!hwnd) return GL_FALSE; + + if (hwnd!=WindowFromDC(pWindow->drawable)) + { + crWarning("Window(%i) DC is no longer valid", pWindow->spuWindow); + return GL_FALSE; + } + + hVisRgn = CreateRectRgn(0,0,0,0); + iret = GetRandomRgn(pWindow->drawable, hVisRgn, SYSRGN); + + if (iret==1) + { + /** @todo check win95/win98 here, as rects should be already in client space there*/ + /* Convert screen related rectangles to client related rectangles */ + pt.x = 0; + pt.y = 0; + ScreenToClient(hwnd, &pt); + OffsetRgn(hVisRgn, pt.x, pt.y); + + /* + dwCount = GetRegionData(hVisRgn, 0, NULL); + lpRgnData = crAlloc(dwCount); + crDebug("GetRandomRgn returned 1, dwCount=%d", dwCount); + GetRegionData(hVisRgn, dwCount, lpRgnData); + crDebug("Region consists of %d rects", lpRgnData->rdh.nCount); + + pRects = (RECT*) lpRgnData->Buffer; + for (i=0; i<lpRgnData->rdh.nCount; ++i) + { + crDebug("Rgn[%d] = (%d, %d, %d, %d)", i, pRects[i].left, pRects[i].top, pRects[i].right, pRects[i].bottom); + } + crFree(lpRgnData); + */ + + if (pWindow->hVisibleRegion==INVALID_HANDLE_VALUE + || !EqualRgn(pWindow->hVisibleRegion, hVisRgn)) + { + DeleteObject(pWindow->hVisibleRegion); + pWindow->hVisibleRegion = hVisRgn; + + dwCount = GetRegionData(hVisRgn, 0, NULL); + lpRgnData = crAlloc(dwCount); + + if (lpRgnData) + { + GetRegionData(hVisRgn, dwCount, lpRgnData); + crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, lpRgnData->rdh.nCount); + stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, lpRgnData->rdh.nCount, (GLint*) lpRgnData->Buffer); + crFree(lpRgnData); + return GL_TRUE; + } + else crWarning("GetRegionData failed, VisibleRegions update failed"); + } + else + { + DeleteObject(hVisRgn); + } + } + else + { + crWarning("GetRandomRgn returned (%d) instead of (1), VisibleRegions update failed", iret); + DeleteObject(hVisRgn); + } + + return GL_FALSE; +} + +# ifndef CR_NEWWINTRACK +static void stubCBCheckWindowsInfo(unsigned long key, void *data1, void *data2) +{ + WindowInfo *winInfo = (WindowInfo *) data1; + CWPRETSTRUCT *pMsgInfo = (PCWPRETSTRUCT) data2; + + (void) key; + + if (winInfo && pMsgInfo && winInfo->type == CHROMIUM) + { + switch (pMsgInfo->message) + { + case WM_MOVING: + case WM_SIZING: + case WM_MOVE: + case WM_CREATE: + case WM_SIZE: + { + GLboolean changed = stub.trackWindowVisibleRgn && stubUpdateWindowVisibileRegions(winInfo); + + if (stubUpdateWindowGeometry(winInfo, GL_FALSE) || changed) + { + stubForcedFlush(0); + } + break; + } + + case WM_SHOWWINDOW: + case WM_ACTIVATEAPP: + case WM_PAINT: + case WM_NCPAINT: + case WM_NCACTIVATE: + case WM_ERASEBKGND: + { + if (stub.trackWindowVisibleRgn && stubUpdateWindowVisibileRegions(winInfo)) + { + stubForcedFlush(0); + } + break; + } + + default: + { + if (stub.trackWindowVisibleRgn && stubUpdateWindowVisibileRegions(winInfo)) + { + crDebug("Visibility info updated due to unknown hooked message (%d)", pMsgInfo->message); + stubForcedFlush(0); + } + break; + } + } + } +} + +LRESULT CALLBACK stubCBWindowMessageHookProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + CWPRETSTRUCT *pMsgInfo = (PCWPRETSTRUCT) lParam; + + if (nCode>=0 && pMsgInfo) + { + switch (pMsgInfo->message) + { + case WM_MOVING: + case WM_SIZING: + case WM_MOVE: + case WM_ACTIVATEAPP: + case WM_NCPAINT: + case WM_NCACTIVATE: + case WM_ERASEBKGND: + case WM_CREATE: + case WM_SIZE: + case WM_SHOWWINDOW: + { + crHashtableWalk(stub.windowTable, stubCBCheckWindowsInfo, (void *) lParam); + break; + } + + /** @todo remove it*/ + default: + { + /*crDebug("hook: unknown message (%d)", pMsgInfo->message);*/ + crHashtableWalk(stub.windowTable, stubCBCheckWindowsInfo, (void *) lParam); + break; + } + } + } + + return CallNextHookEx(stub.hMessageHook, nCode, wParam, lParam); +} + +void stubInstallWindowMessageHook() +{ + stub.hMessageHook = SetWindowsHookEx(WH_CALLWNDPROCRET, stubCBWindowMessageHookProc, 0, crThreadID()); + + if (!stub.hMessageHook) + crWarning("Window message hook install failed! (not fatal)"); +} + +void stubUninstallWindowMessageHook() +{ + if (stub.hMessageHook) + UnhookWindowsHookEx(stub.hMessageHook); +} +# endif /*# ifndef CR_NEWWINTRACK*/ + +#elif defined(GLX) //#ifdef WINDOWS +void stubCheckXExtensions(WindowInfo *pWindow) +{ + int evb, erb, vmi=0, vma=0; + Display *dpy = stubGetWindowDisplay(pWindow); + + stub.bXExtensionsChecked = GL_TRUE; + stub.trackWindowVisibleRgn = 0; + + XLOCK(dpy); + if (XCompositeQueryExtension(dpy, &evb, &erb) + && XCompositeQueryVersion(dpy, &vma, &vmi) + && (vma>0 || vmi>=4)) + { + stub.bHaveXComposite = GL_TRUE; + crDebug("XComposite %i.%i", vma, vmi); + vma=0; + vmi=0; + if (XFixesQueryExtension(dpy, &evb, &erb) + && XFixesQueryVersion(dpy, &vma, &vmi) + && vma>=2) + { + crDebug("XFixes %i.%i", vma, vmi); + stub.bHaveXFixes = GL_TRUE; + stub.trackWindowVisibleRgn = 1; + XUNLOCK(dpy); + return; + } + else + { + crWarning("XFixes not found or old version (%i.%i), no VisibilityTracking", vma, vmi); + } + } + else + { + crWarning("XComposite not found or old version (%i.%i), no VisibilityTracking", vma, vmi); + } + XUNLOCK(dpy); + return; +} + +/* + * Updates visible regions for given spu window. + * Returns GL_TRUE if regions changed since last call, GL_FALSE otherwise. + */ +GLboolean stubUpdateWindowVisibileRegions(WindowInfo *pWindow) +{ + XserverRegion xreg; + int cRects, i; + XRectangle *pXRects; + GLint* pGLRects; + Display *dpy; + bool bNoUpdate = false; + + if (!stub.bXExtensionsChecked) + { + stubCheckXExtensions(pWindow); + if (!stub.trackWindowVisibleRgn) + { + return GL_FALSE; + } + } + + dpy = stubGetWindowDisplay(pWindow); + + /** @todo see comment regarding size/position updates and XSync, same applies to those functions but + * it seems there's no way to get even based updates for this. Or I've failed to find the appropriate extension. + */ + XLOCK(dpy); + xreg = XCompositeCreateRegionFromBorderClip(dpy, pWindow->drawable); + pXRects = XFixesFetchRegion(dpy, xreg, &cRects); + XFixesDestroyRegion(dpy, xreg); + XUNLOCK(dpy); + + /* Check for compiz main window */ + if (!pWindow->pVisibleRegions && !cRects) + { + bNoUpdate = true; + } + + if (!bNoUpdate + && (!pWindow->pVisibleRegions + || pWindow->cVisibleRegions!=cRects + || (pWindow->pVisibleRegions && crMemcmp(pWindow->pVisibleRegions, pXRects, cRects * sizeof(XRectangle))))) + { + if (pWindow->pVisibleRegions) + { + XFree(pWindow->pVisibleRegions); + } + + pWindow->pVisibleRegions = pXRects; + pWindow->cVisibleRegions = cRects; + + pGLRects = crAlloc(cRects ? 4*cRects*sizeof(GLint) : 4*sizeof(GLint)); + if (!pGLRects) + { + crWarning("stubUpdateWindowVisibileRegions: failed to allocate %lu bytes", + (unsigned long)(4*cRects*sizeof(GLint))); + return GL_FALSE; + } + + //crDebug("Got %i rects.", cRects); + for (i=0; i<cRects; ++i) + { + pGLRects[4*i+0] = pXRects[i].x; + pGLRects[4*i+1] = pXRects[i].y; + pGLRects[4*i+2] = pXRects[i].x+pXRects[i].width; + pGLRects[4*i+3] = pXRects[i].y+pXRects[i].height; + //crDebug("Rect[%i]=(%i,%i,%i,%i)", i, pGLRects[4*i+0], pGLRects[4*i+1], pGLRects[4*i+2], pGLRects[4*i+3]); + } + + crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, cRects); + stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, cRects, pGLRects); + crFree(pGLRects); + return GL_TRUE; + } + else + { + XFree(pXRects); + } + + return GL_FALSE; +} +#endif //#ifdef WINDOWS diff --git a/src/VBox/Additions/common/crOpenGL/stub.h b/src/VBox/Additions/common/crOpenGL/stub.h new file mode 100644 index 00000000..1dd5faa2 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/stub.h @@ -0,0 +1,370 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + + +/* + * How this all works... + * + * This directory implements three different interfaces to Chromium: + * + * 1. the Chromium interface - this is defined by the functions that start + * with the "cr" prefix and are defined in chromium.h and implemented in + * stub.c. Typically, this is used by parallel apps (like psubmit). + * + * 2. GLX emulation interface - the glX*() functions are emulated here. + * When glXCreateContext() is called we may either create a real, native + * GLX context or a Chromium context (depending on match_window_title and + * minimum_window_size). + * + * 3. WGL emulation interface - the wgl*() functions are emulated here. + * When wglCreateContext() is called we may either create a real, native + * WGL context or a Chromium context (depending on match_window_title and + * minimum_window_size). + * + * + */ + +#ifndef GA_INCLUDED_SRC_common_crOpenGL_stub_h +#define GA_INCLUDED_SRC_common_crOpenGL_stub_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "chromium.h" +#include "cr_version.h" +#include "cr_hash.h" +#include "cr_process.h" +#include "cr_spu.h" +#include "cr_threads.h" +#include "spu_dispatch_table.h" + +#ifdef GLX +#include <X11/extensions/XShm.h> +#include <sys/shm.h> +#include <X11/extensions/Xdamage.h> +#include <X11/extensions/Xcomposite.h> +#include <X11/extensions/Xfixes.h> +#endif + +#if defined(WINDOWS) || defined(Linux) || defined(SunOS) +# define CR_NEWWINTRACK +#endif + +#if !defined(CHROMIUM_THREADSAFE) && defined(CR_NEWWINTRACK) +# error CHROMIUM_THREADSAFE have to be defined +#endif + +#ifdef CHROMIUM_THREADSAFE +# include <cr_threads.h> +#endif + +#if 0 && defined(CR_NEWWINTRACK) && !defined(WINDOWS) +#define XLOCK(dpy) XLockDisplay(dpy) +#define XUNLOCK(dpy) XUnlockDisplay(dpy) +#else +#define XLOCK(dpy) +#define XUNLOCK(dpy) +#endif + +/* When we first create a rendering context we can't be sure whether + * it'll be handled by Chromium or as a native GLX/WGL context. So in + * CreateContext() we'll mark the ContextInfo object as UNDECIDED then + * switch it to either NATIVE or CHROMIUM the first time MakeCurrent() + * is called. In MakeCurrent() we can use a criteria like window size + * or window title to decide between CHROMIUM and NATIVE. + */ +typedef enum +{ + UNDECIDED, + CHROMIUM, + NATIVE +} ContextType; + +#define MAX_DPY_NAME 1000 + +typedef struct context_info_t ContextInfo; +typedef struct window_info_t WindowInfo; + +#ifdef GLX +typedef struct glxpixmap_info_t GLX_Pixmap_t; + +struct glxpixmap_info_t +{ + int x, y; + unsigned int w, h, border, depth; + GLenum format; + Window root; + GLenum target; + GC gc; + Pixmap hShmPixmap; /* Shared memory pixmap object, if it's supported*/ + Damage hDamage; /* damage xserver handle*/ + Bool bPixmapImageDirty; + Region pDamageRegion; +}; +#endif + +struct context_info_t +{ + char dpyName[MAX_DPY_NAME]; + GLint spuContext; /* returned by head SPU's CreateContext() */ + ContextType type; /* CHROMIUM, NATIVE or UNDECIDED */ + unsigned long id; /* the client-visible handle */ + GLint visBits; + WindowInfo *currentDrawable; + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + GLint spuConnection; + struct VBOXUHGSMI *pHgsmi; +#endif + +#ifdef CHROMIUM_THREADSAFE + VBOXTLSREFDATA +#endif + +#ifdef WINDOWS + HGLRC hglrc; +#elif defined(DARWIN) + ContextInfo *share; + CGLContextObj cglc; + + /* CGLContextEnable (CGLEnable, CGLDisable, and CGLIsEnabled) */ + unsigned int options; + + /* CGLContextParameter (CGLSetParameter and CGLGetParameter) */ + GLint parambits; + long swap_rect[4], swap_interval; + unsigned long client_storage; + long surf_order, surf_opacy; + + long disp_mask; +#elif defined(GLX) + Display *dpy; + ContextInfo *share; + Bool direct; + GLXContext glxContext; + CRHashTable *pGLXPixmapsHash; + Bool damageQueryFailed; + int damageEventsBase; +#endif +}; + +#ifdef DARWIN +enum { + VISBIT_SWAP_RECT, + VISBIT_SWAP_INTERVAL, + VISBIT_CLIENT_STORAGE +}; +#endif + +struct window_info_t +{ + char dpyName[MAX_DPY_NAME]; + int x, y; + unsigned int width, height; + ContextType type; + GLint spuWindow; /* returned by head SPU's WindowCreate() */ + ContextInfo *pOwner; /* ctx which created this window */ + GLboolean mapped; +#ifdef WINDOWS + HDC drawable; + HRGN hVisibleRegion; + DWORD dmPelsWidth; + DWORD dmPelsHeight; + HWND hWnd; +#elif defined(DARWIN) + CGSConnectionID connection; + CGSWindowID drawable; + CGSSurfaceID surface; +#elif defined(GLX) + Display *dpy; +# ifdef CR_NEWWINTRACK + Display *syncDpy; +# endif + GLXDrawable drawable; + XRectangle *pVisibleRegions; + GLint cVisibleRegions; +#endif +#ifdef CR_NEWWINTRACK + uint32_t u32ClientID; +#endif +}; + +/* "Global" variables for the stub library */ +typedef struct { + /* the first SPU in the SPU chain on this app node */ + SPU *spu; + + /* OpenGL/SPU dispatch tables */ + crOpenGLInterface wsInterface; + SPUDispatchTable spuDispatch; + SPUDispatchTable nativeDispatch; + GLboolean haveNativeOpenGL; + + /* config options */ + int appDrawCursor; + GLuint minChromiumWindowWidth; + GLuint minChromiumWindowHeight; + GLuint maxChromiumWindowWidth; + GLuint maxChromiumWindowHeight; + GLuint matchChromiumWindowCount; + GLuint matchChromiumWindowCounter; + GLuint *matchChromiumWindowID; + GLuint numIgnoreWindowID; + char *matchWindowTitle; + int ignoreFreeglutMenus; + int trackWindowSize; + int trackWindowPos; + int trackWindowVisibility; + int trackWindowVisibleRgn; + char *spu_dir; + int force_pbuffers; + + /* thread safety stuff */ + GLboolean threadSafe; +#ifdef CHROMIUM_THREADSAFE + CRtsd dispatchTSD; + CRmutex mutex; +#endif + + CRpid mothershipPID; + + /* contexts */ + int freeContextNumber; + CRHashTable *contextTable; +#ifndef CHROMIUM_THREADSAFE + ContextInfo *currentContext; /* may be NULL */ +#endif + + /* windows */ + CRHashTable *windowTable; + +#ifdef GLX + /* Shared memory, used to transfer XServer pixmaps data into client memory */ + XShmSegmentInfo xshmSI; + GLboolean bShmInitFailed; + + CRHashTable *pGLXPixmapsHash; + + GLboolean bXExtensionsChecked; + GLboolean bHaveXComposite; + GLboolean bHaveXFixes; +#endif + +#ifdef WINDOWS +# ifndef CR_NEWWINTRACK + HHOOK hMessageHook; +# endif +# ifdef VBOX_WITH_WDDM + bool bRunningUnderWDDM; +# endif +#endif + +#ifdef CR_NEWWINTRACK + RTTHREAD hSyncThread; + bool volatile bShutdownSyncThread; +#endif + +} Stub; + +#ifdef CHROMIUM_THREADSAFE +/* we place the g_stubCurrentContextTLS outside the Stub data because Stub data is inited by the client's call, + * while we need g_stubCurrentContextTLS the g_stubCurrentContextTLS to be valid at any time to be able to handle + * THREAD_DETACH cleanup on windows. + * Note that we can not do + * STUB_INIT_LOCK(); + * if (stub_initialized) stubSetCurrentContext(NULL); + * STUB_INIT_UNLOCK(); + * on THREAD_DETACH since it may cause deadlock, i.e. in this situation loader lock is acquired first and then the init lock, + * but since we use GetModuleFileName in crGetProcName called from stubInitLocked, the lock order might be the oposite. + * Note that GetModuleFileName acquires the loader lock. + * */ +extern CRtsd g_stubCurrentContextTSD; + +DECLINLINE(ContextInfo*) stubGetCurrentContext(void) +{ + ContextInfo* ctx; + VBoxTlsRefGetCurrentFunctional(ctx, ContextInfo, &g_stubCurrentContextTSD); + return ctx; +} +# define stubSetCurrentContext(_ctx) VBoxTlsRefSetCurrent(ContextInfo, &g_stubCurrentContextTSD, _ctx) +#else +# define stubGetCurrentContext() (stub.currentContext) +# define stubSetCurrentContext(_ctx) do { stub.currentContext = (_ctx); } while (0) +#endif + +extern Stub stub; + +extern DECLEXPORT(SPUDispatchTable) glim; +extern SPUDispatchTable stubThreadsafeDispatch; +extern DECLEXPORT(SPUDispatchTable) stubNULLDispatch; + +#if defined(GLX) || defined (WINDOWS) +extern GLboolean stubUpdateWindowVisibileRegions(WindowInfo *pWindow); +#endif + +#ifdef WINDOWS + +/* WGL versions */ +extern WindowInfo *stubGetWindowInfo( HDC drawable ); + +extern void stubInstallWindowMessageHook(); +extern void stubUninstallWindowMessageHook(); + +#elif defined(DARWIN) + +extern CGSConnectionID _CGSDefaultConnection(void); +extern OSStatus CGSGetWindowLevel( CGSConnectionID cid, CGSWindowID wid, CGWindowLevel *level ); +extern OSStatus CGSSetWindowAlpha( const CGSConnectionID cid, CGSWindowID wid, float alpha ); + +/* These don't seem to be included in the OSX glext.h ... */ +extern void glPointParameteri( GLenum pname, GLint param ); +extern void glPointParameteriv( GLenum pname, const GLint * param ); + +extern WindowInfo *stubGetWindowInfo( CGSWindowID drawable ); + +#elif defined(GLX) + +/* GLX versions */ +extern WindowInfo *stubGetWindowInfo( Display *dpy, GLXDrawable drawable ); +extern void stubUseXFont( Display *dpy, Font font, int first, int count, int listbase ); +extern Display* stubGetWindowDisplay(WindowInfo *pWindow); + +extern void stubCheckXExtensions(WindowInfo *pWindow); +#endif + + +extern ContextInfo *stubNewContext(char *dpyName, GLint visBits, ContextType type, unsigned long shareCtx +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , struct VBOXUHGSMI *pHgsmi +#endif + ); +extern void stubConChromiumParameteriCR(GLint con, GLenum param, GLint value); +extern void stubConChromiumParametervCR(GLint con, GLenum target, GLenum type, GLsizei count, const GLvoid *values); +extern GLboolean stubCtxCreate(ContextInfo *context); +extern GLboolean stubCtxCheckCreate(ContextInfo *context); +extern void stubDestroyContext( unsigned long contextId ); +extern GLboolean stubMakeCurrent( WindowInfo *window, ContextInfo *context ); +extern GLint stubNewWindow( const char *dpyName, GLint visBits ); +extern void stubDestroyWindow( GLint con, GLint window ); +extern void stubSwapBuffers(WindowInfo *window, GLint flags); +extern void stubGetWindowGeometry(WindowInfo *win, int *x, int *y, unsigned int *w, unsigned int *h); +extern GLboolean stubUpdateWindowGeometry(WindowInfo *pWindow, GLboolean bForceUpdate); +extern GLboolean stubIsWindowVisible(WindowInfo *win); +extern bool stubInit(void); + +extern void stubForcedFlush(GLint con); +extern void stubConFlush(GLint con); +extern void APIENTRY stub_GetChromiumParametervCR( GLenum target, GLuint index, GLenum type, GLsizei count, GLvoid *values ); + +extern void APIENTRY glBoundsInfoCR(const CRrecti *, const GLbyte *, GLint, GLint); + +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) +# define CR_CTX_CON(_pCtx) ((_pCtx)->spuConnection) +#else +# define CR_CTX_CON(_pCtx) (0) +#endif + +#endif /* !GA_INCLUDED_SRC_common_crOpenGL_stub_h */ diff --git a/src/VBox/Additions/common/crOpenGL/stub_common.py b/src/VBox/Additions/common/crOpenGL/stub_common.py new file mode 100755 index 00000000..05127343 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/stub_common.py @@ -0,0 +1,282 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys +curver = sys.version_info[0] + sys.version_info[1]/10.0 +if curver < 2.2: + print("Your python is version %g. Chromium requires at least"%(curver), file=sys.stderr) + print("version 2.2. Please upgrade your python installation.", file=sys.stderr) + sys.exit(1) + +import string; +import re; + +def CopyrightC( ): + print("""/* Copyright (c) 2001, Stanford University + All rights reserved. + + See the file LICENSE.txt for information on redistributing this software. */ + """) + +def CopyrightDef( ): + print("""; Copyright (c) 2001, Stanford University + ; All rights reserved. + ; + ; See the file LICENSE.txt for information on redistributing this software. + """) + +def DecoderName( glName ): + return "crUnpack" + glName + +def OpcodeName( glName ): + # This is a bit of a hack. We want to implement the glVertexAttrib*NV + # functions in terms of the glVertexAttrib*ARB opcodes. + m = re.search( "VertexAttrib([1234](ub|b|us|s|ui|i|f|d|)v?)NV", glName ) + if m: + dataType = m.group(1) + if dataType == "4ub": + dataType = "4Nub" + elif dataType == "4ubv": + dataType = "4Nubv" + glName = "VertexAttrib" + dataType + "ARB" + return "CR_" + string.upper( glName ) + "_OPCODE" + +def ExtendedOpcodeName( glName ): + return "CR_" + string.upper( glName ) + "_EXTEND_OPCODE" + +def PackFunction( glName ): + return "crPack" + glName + +def DoPackFunctionMapping( glName ): + return "__glpack_" + glName + +def DoStateFunctionMapping( glName ): + return "__glstate_" + glName + +def DoImmediateMapping( glName ): + return "__glim_" + glName + + + +# Annotations are a generalization of Specials (below). +# Each line of an annotation file is a set of words. +# The first word is a key; the remainder are all annotations +# for that key. This is a useful model for grouping keys +# (like GL function names) into overlapping subsets, all in +# a single file. +annotations = {} +def LoadAnnotations(filename): + table = {} + try: + f = open(filename, "r") + except: + annotations[filename] = {} + return {} + + for line in f.readlines(): + line = line.strip() + if line == "" or line[0] == '#': + continue + subtable = {} + words = line.split() + for word in words[1:]: + subtable[word] = 1 + table[words[0]] = subtable + + annotations[filename] = table + return table + +def GetAnnotations( filename, key ): + table = {} + try: + table = annotations[filename] + except KeyError: + table = LoadAnnotations(filename) + + try: + subtable = table[key] + except KeyError: + return [] + + return sorted(subtable.keys()) + +def FindAnnotation( filename, key, subkey ): + table = {} + try: + table = annotations[filename] + except KeyError: + table = LoadAnnotations(filename) + + try: + subtable = table[key] + except KeyError: + return 0 + + try: + return subtable[subkey] + except KeyError: + return 0 + + + +specials = {} + +def LoadSpecials( filename ): + table = {} + try: + f = open( filename, "r" ) + except: + specials[filename] = {} + return {} + + for line in f.readlines(): + line = string.strip(line) + if line == "" or line[0] == '#': + continue + table[line] = 1 + + specials[filename] = table + return table + +def FindSpecial( table_file, glName ): + table = {} + filename = table_file + "_special" + try: + table = specials[filename] + except KeyError: + table = LoadSpecials( filename ) + + try: + if (table[glName] == 1): + return 1 + else: + return 0 #should never happen + except KeyError: + return 0 + +def AllSpecials( table_file ): + table = {} + filename = table_file + "_special" + try: + table = specials[filename] + except KeyError: + table = LoadSpecials( filename ) + + return sorted(table.keys()) + +def AllSpecials( table_file ): + filename = table_file + "_special" + + table = {} + try: + table = specials[filename] + except KeyError: + table = LoadSpecials(filename) + + return sorted(table.keys()) + +def NumSpecials( table_file ): + filename = table_file + "_special" + + table = {} + try: + table = specials[filename] + except KeyError: + table = LoadSpecials(filename) + + return len(table.keys()) + +lengths = {} +lengths['GLbyte'] = 1 +lengths['GLubyte'] = 1 +lengths['GLshort'] = 2 +lengths['GLushort'] = 2 +lengths['GLint'] = 4 +lengths['GLuint'] = 4 +lengths['GLfloat'] = 4 +lengths['GLclampf'] = 4 +lengths['GLdouble'] = 8 +lengths['GLclampd'] = 8 + +lengths['GLenum'] = 4 +lengths['GLboolean'] = 1 +lengths['GLsizei'] = 4 +lengths['GLbitfield'] = 4 + +lengths['void'] = 0 +lengths['int'] = 4 + +align_types = 1 + +def FixAlignment( pos, alignment ): + # if we want double-alignment take word-alignment instead, + # yes, this is super-lame, but we know what we are doing + if alignment > 4: + alignment = 4 + if align_types and alignment and ( pos % alignment ): + pos += alignment - ( pos % alignment ) + return pos + +def WordAlign( pos ): + return FixAlignment( pos, 4 ) + +def PointerSize(): + return 8 # Leave room for a 64 bit pointer + +def PacketLength( arg_types ): + len = 0 + for arg in arg_types: + if string.find( arg, '*') != -1: + size = PointerSize() + else: + temp_arg = re.sub("const ", "", arg) + size = lengths[temp_arg] + len = FixAlignment( len, size ) + size + len = WordAlign( len ) + return len + +def InternalArgumentString( arg_names, arg_types ): + """Return string of C-style function declaration arguments.""" + output = '' + for index in range(0,len(arg_names)): + if len(arg_names) != 1 and arg_names[index] == '': + continue + output += arg_types[index] + if arg_types[index][-1:] != '*' and arg_names[index] != '': + output += " "; + output += arg_names[index] + if index != len(arg_names) - 1: + output += ", " + return output + +def ArgumentString( arg_names, arg_types ): + """Return InternalArgumentString inside parenthesis.""" + output = '( ' + InternalArgumentString(arg_names, arg_types) + ' )' + return output + +def InternalCallString( arg_names ): + output = '' + for index in range(0,len(arg_names)): + output += arg_names[index] + if arg_names[index] != '' and index != len(arg_names) - 1: + output += ", " + return output + +def CallString( arg_names ): + output = '( ' + output += InternalCallString(arg_names) + output += " )" + return output + +def IsVector ( func_name ) : + m = re.search( r"^(SecondaryColor|Color|EdgeFlag|EvalCoord|Index|Normal|TexCoord|MultiTexCoord|Vertex|RasterPos|VertexAttrib|FogCoord|WindowPos|ProgramParameter)([1234]?)N?(ub|b|us|s|ui|i|f|d|)v(ARB|EXT|NV)?$", func_name ) + if m : + if m.group(2) : + return string.atoi( m.group(2) ) + else: + return 1 + else: + return 0 diff --git a/src/VBox/Additions/common/crOpenGL/tsfuncs.py b/src/VBox/Additions/common/crOpenGL/tsfuncs.py new file mode 100755 index 00000000..020b5cc7 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/tsfuncs.py @@ -0,0 +1,47 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - THIS FILE GENERATED BY THE tsfuncs.py SCRIPT */ + +#include "stub.h" +""") + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +for func_name in keys: + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + + print("static %s SPULOAD_APIENTRY ts_%s(%s)" % (return_type, func_name, apiutil.MakeDeclarationString(params) )) + print("{") + print("\tSPUDispatchTable *tab = (SPUDispatchTable *) crGetTSD(&stub.dispatchTSD);") + + if return_type != "void": + print("\treturn ", end=" ") + + print("\ttab->%s(%s);" % (func_name, apiutil.MakeCallString(params))) + print("}") + print("") + + +print("SPUDispatchTable stubThreadsafeDispatch = {") + +for func_name in keys: + print("\tts_%s," % func_name) + +print("\tNULL, /* copyList */") +print("\tNULL, /* copy_of */") +print("\t0, /* mark */") +print("\tNULL /* server */") +print("};") diff --git a/src/VBox/Additions/common/crOpenGL/utils.c b/src/VBox/Additions/common/crOpenGL/utils.c new file mode 100644 index 00000000..a220d09d --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/utils.c @@ -0,0 +1,876 @@ +/* + * (C) Copyright IBM Corporation 2002, 2004 + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file utils.c + * Utility functions for DRI drivers. + * + * \author Ian Romanick <idr@us.ibm.com> + */ + +#include <string.h> +#include <stdlib.h> +#include "mtypes.h" +#include "extensions.h" +#include "utils.h" +#include "dispatch.h" + +int driDispatchRemapTable[ driDispatchRemapTable_size ]; + +#if defined(USE_X86_ASM) +#include "x86/common_x86_asm.h" +#endif + +#if defined(USE_PPC_ASM) +#include "ppc/common_ppc_features.h" +#endif + +unsigned +driParseDebugString( const char * debug, + const struct dri_debug_control * control ) +{ + unsigned flag; + + + flag = 0; + if ( debug != NULL ) { + while( control->string != NULL ) { + if ( !strcmp( debug, "all" ) || + strstr( debug, control->string ) != NULL ) { + flag |= control->flag; + } + + control++; + } + } + + return flag; +} + + + +/** + * Create the \c GL_RENDERER string for DRI drivers. + * + * Almost all DRI drivers use a \c GL_RENDERER string of the form: + * + * "Mesa DRI <chip> <driver date> <AGP speed) <CPU information>" + * + * Using the supplied chip name, driver data, and AGP speed, this function + * creates the string. + * + * \param buffer Buffer to hold the \c GL_RENDERER string. + * \param hardware_name Name of the hardware. + * \param driver_date Driver date. + * \param agp_mode AGP mode (speed). + * + * \returns + * The length of the string stored in \c buffer. This does \b not include + * the terminating \c NUL character. + */ +unsigned +driGetRendererString( char * buffer, const char * hardware_name, + const char * driver_date, GLuint agp_mode ) +{ +#define MAX_INFO 4 + const char * cpu[MAX_INFO]; + unsigned next = 0; + unsigned i; + unsigned offset; + + + offset = sprintf( buffer, "Mesa DRI %s %s", hardware_name, driver_date ); + + /* Append any AGP-specific information. + */ + switch ( agp_mode ) { + case 1: + case 2: + case 4: + case 8: + offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode ); + break; + + default: + break; + } + + /* Append any CPU-specific information. + */ +#ifdef USE_X86_ASM + if ( _mesa_x86_cpu_features ) { + cpu[next] = " x86"; + next++; + } +# ifdef USE_MMX_ASM + if ( cpu_has_mmx ) { + cpu[next] = (cpu_has_mmxext) ? "/MMX+" : "/MMX"; + next++; + } +# endif +# ifdef USE_3DNOW_ASM + if ( cpu_has_3dnow ) { + cpu[next] = (cpu_has_3dnowext) ? "/3DNow!+" : "/3DNow!"; + next++; + } +# endif +# ifdef USE_SSE_ASM + if ( cpu_has_xmm ) { + cpu[next] = (cpu_has_xmm2) ? "/SSE2" : "/SSE"; + next++; + } +# endif + +#elif defined(USE_SPARC_ASM) + + cpu[0] = " SPARC"; + next = 1; + +#elif defined(USE_PPC_ASM) + if ( _mesa_ppc_cpu_features ) { + cpu[next] = (cpu_has_64) ? " PowerPC 64" : " PowerPC"; + next++; + } + +# ifdef USE_VMX_ASM + if ( cpu_has_vmx ) { + cpu[next] = "/Altivec"; + next++; + } +# endif + + if ( ! cpu_has_fpu ) { + cpu[next] = "/No FPU"; + next++; + } +#endif + + for ( i = 0 ; i < next ; i++ ) { + const size_t len = strlen( cpu[i] ); + + strncpy( & buffer[ offset ], cpu[i], len ); + offset += len; + } + + return offset; +} + + + + +#define need_GL_ARB_multisample +#define need_GL_ARB_transpose_matrix +#define need_GL_ARB_window_pos +#define need_GL_EXT_compiled_vertex_array +#define need_GL_EXT_polygon_offset +#define need_GL_EXT_texture_object +#define need_GL_EXT_vertex_array +#define need_GL_MESA_window_pos + +/* These are needed in *all* drivers because Mesa internally implements + * certain functionality in terms of functions provided by these extensions. + * For example, glBlendFunc is implemented by calling glBlendFuncSeparateEXT. + */ +#define need_GL_EXT_blend_func_separate +#define need_GL_NV_vertex_program + +#include "extension_helper.h" + +static const struct dri_extension all_mesa_extensions[] = { + { "GL_ARB_multisample", GL_ARB_multisample_functions }, + { "GL_ARB_transpose_matrix", GL_ARB_transpose_matrix_functions }, + { "GL_ARB_window_pos", GL_ARB_window_pos_functions }, + { "GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions }, + { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions }, + { "GL_EXT_polygon_offset", GL_EXT_polygon_offset_functions }, + { "GL_EXT_texture_object", GL_EXT_texture_object_functions }, + { "GL_EXT_vertex_array", GL_EXT_vertex_array_functions }, + { "GL_MESA_window_pos", GL_MESA_window_pos_functions }, + { "GL_NV_vertex_program", GL_NV_vertex_program_functions }, + { NULL, NULL } +}; + + +/** + * Enable extensions supported by the driver. + * + * \bug + * ARB_imaging isn't handled properly. In Mesa, enabling ARB_imaging also + * enables all the sub-extensions that are folded into it. This means that + * we need to add entry-points (via \c driInitSingleExtension) for those + * new functions here. + */ +void driInitExtensions( GLcontext * ctx, + const struct dri_extension * extensions_to_enable, + GLboolean enable_imaging ) +{ + static int first_time = 1; + unsigned i; + + if ( first_time ) { + for ( i = 0 ; i < driDispatchRemapTable_size ; i++ ) { + driDispatchRemapTable[i] = -1; + } + + first_time = 0; + driInitExtensions( ctx, all_mesa_extensions, GL_FALSE ); + } + + if ( (ctx != NULL) && enable_imaging ) { + _mesa_enable_imaging_extensions( ctx ); + } + + for ( i = 0 ; extensions_to_enable[i].name != NULL ; i++ ) { + driInitSingleExtension( ctx, & extensions_to_enable[i] ); + } +} + + + + +/** + * Enable and add dispatch functions for a single extension + * + * \param ctx Context where extension is to be enabled. + * \param ext Extension that is to be enabled. + * + * \sa driInitExtensions, _mesa_enable_extension, _glapi_add_entrypoint + * + * \todo + * Determine if it would be better to use \c strlen instead of the hardcoded + * for-loops. + */ +void driInitSingleExtension( GLcontext * ctx, + const struct dri_extension * ext ) +{ + unsigned i; + + + if ( ext->functions != NULL ) { + for ( i = 0 ; ext->functions[i].strings != NULL ; i++ ) { + const char * functions[16]; + const char * parameter_signature; + const char * str = ext->functions[i].strings; + unsigned j; + unsigned offset; + + + /* Separate the parameter signature from the rest of the string. + * If the parameter signature is empty (i.e., the string starts + * with a NUL character), then the function has a void parameter + * list. + */ + parameter_signature = str; + while ( str[0] != '\0' ) { + str++; + } + str++; + + + /* Divide the string into the substrings that name each + * entry-point for the function. + */ + for ( j = 0 ; j < 16 ; j++ ) { + if ( str[0] == '\0' ) { + functions[j] = NULL; + break; + } + + functions[j] = str; + + while ( str[0] != '\0' ) { + str++; + } + str++; + } + + + /* Add each entry-point to the dispatch table. + */ + offset = _glapi_add_dispatch( functions, parameter_signature ); + if (offset == -1) { + fprintf(stderr, "DISPATCH ERROR! _glapi_add_dispatch failed " + "to add %s!\n", functions[0]); + } + else if (ext->functions[i].remap_index != -1) { + driDispatchRemapTable[ ext->functions[i].remap_index ] = + offset; + } + else if (ext->functions[i].offset != offset) { + fprintf(stderr, "DISPATCH ERROR! %s -> %u != %u\n", + functions[0], offset, ext->functions[i].offset); + } + } + } + + if ( ctx != NULL ) { + _mesa_enable_extension( ctx, ext->name ); + } +} + + +/** + * Utility function used by drivers to test the versions of other components. + * + * If one of the version requirements is not met, a message is logged using + * \c __driUtilMessage. + * + * \param driver_name Name of the driver. Used in error messages. + * \param driActual Actual DRI version supplied __driCreateNewScreen. + * \param driExpected Minimum DRI version required by the driver. + * \param ddxActual Actual DDX version supplied __driCreateNewScreen. + * \param ddxExpected Minimum DDX minor and range of DDX major version required by the driver. + * \param drmActual Actual DRM version supplied __driCreateNewScreen. + * \param drmExpected Minimum DRM version required by the driver. + * + * \returns \c GL_TRUE if all version requirements are met. Otherwise, + * \c GL_FALSE is returned. + * + * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions2, __driUtilMessage + * + * \todo + * Now that the old \c driCheckDriDdxDrmVersions function is gone, this + * function and \c driCheckDriDdxDrmVersions2 should be renamed. + */ +GLboolean +driCheckDriDdxDrmVersions3(const char * driver_name, + const __DRIversion * driActual, + const __DRIversion * driExpected, + const __DRIversion * ddxActual, + const __DRIutilversion2 * ddxExpected, + const __DRIversion * drmActual, + const __DRIversion * drmExpected) +{ + static const char format[] = "%s DRI driver expected %s version %d.%d.x " + "but got version %d.%d.%d\n"; + static const char format2[] = "%s DRI driver expected %s version %d-%d.%d.x " + "but got version %d.%d.%d\n"; + + + /* Check the DRI version */ + if ( (driActual->major != driExpected->major) + || (driActual->minor < driExpected->minor) ) { + fprintf(stderr, format, driver_name, "DRI", + driExpected->major, driExpected->minor, + driActual->major, driActual->minor, driActual->patch); + return GL_FALSE; + } + + /* Check that the DDX driver version is compatible */ + /* for miniglx we pass in -1 so we can ignore the DDX version */ + if ( (ddxActual->major != -1) && ((ddxActual->major < ddxExpected->major_min) + || (ddxActual->major > ddxExpected->major_max) + || (ddxActual->minor < ddxExpected->minor)) ) { + fprintf(stderr, format2, driver_name, "DDX", + ddxExpected->major_min, ddxExpected->major_max, ddxExpected->minor, + ddxActual->major, ddxActual->minor, ddxActual->patch); + return GL_FALSE; + } + + /* Check that the DRM driver version is compatible */ + if ( (drmActual->major != drmExpected->major) + || (drmActual->minor < drmExpected->minor) ) { + fprintf(stderr, format, driver_name, "DRM", + drmExpected->major, drmExpected->minor, + drmActual->major, drmActual->minor, drmActual->patch); + return GL_FALSE; + } + + return GL_TRUE; +} + +GLboolean +driCheckDriDdxDrmVersions2(const char * driver_name, + const __DRIversion * driActual, + const __DRIversion * driExpected, + const __DRIversion * ddxActual, + const __DRIversion * ddxExpected, + const __DRIversion * drmActual, + const __DRIversion * drmExpected) +{ + __DRIutilversion2 ddx_expected; + ddx_expected.major_min = ddxExpected->major; + ddx_expected.major_max = ddxExpected->major; + ddx_expected.minor = ddxExpected->minor; + ddx_expected.patch = ddxExpected->patch; + return driCheckDriDdxDrmVersions3(driver_name, driActual, + driExpected, ddxActual, & ddx_expected, + drmActual, drmExpected); +} + +GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer, + GLint *x, GLint *y, + GLsizei *width, GLsizei *height ) +{ + /* left clipping */ + if (*x < buffer->_Xmin) { + *width -= (buffer->_Xmin - *x); + *x = buffer->_Xmin; + } + + /* right clipping */ + if (*x + *width > buffer->_Xmax) + *width -= (*x + *width - buffer->_Xmax - 1); + + if (*width <= 0) + return GL_FALSE; + + /* bottom clipping */ + if (*y < buffer->_Ymin) { + *height -= (buffer->_Ymin - *y); + *y = buffer->_Ymin; + } + + /* top clipping */ + if (*y + *height > buffer->_Ymax) + *height -= (*y + *height - buffer->_Ymax - 1); + + if (*height <= 0) + return GL_FALSE; + + return GL_TRUE; +} + +/** + * Creates a set of \c __GLcontextModes that a driver will expose. + * + * A set of \c __GLcontextModes will be created based on the supplied + * parameters. The number of modes processed will be 2 * + * \c num_depth_stencil_bits * \c num_db_modes. + * + * For the most part, data is just copied from \c depth_bits, \c stencil_bits, + * \c db_modes, and \c visType into each \c __GLcontextModes element. + * However, the meanings of \c fb_format and \c fb_type require further + * explanation. The \c fb_format specifies which color components are in + * each pixel and what the default order is. For example, \c GL_RGB specifies + * that red, green, blue are available and red is in the "most significant" + * position and blue is in the "least significant". The \c fb_type specifies + * the bit sizes of each component and the actual ordering. For example, if + * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11] + * are the blue value, bits [10:5] are the green value, and bits [4:0] are + * the red value. + * + * One subtle issue is the combination of \c GL_RGB or \c GL_BGR and either + * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the + * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or + * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as + * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8 + * still uses 32-bits. + * + * If in doubt, look at the tables used in the function. + * + * \param ptr_to_modes Pointer to a pointer to a linked list of + * \c __GLcontextModes. Upon completion, a pointer to + * the next element to be process will be stored here. + * If the function fails and returns \c GL_FALSE, this + * value will be unmodified, but some elements in the + * linked list may be modified. + * \param fb_format Format of the framebuffer. Currently only \c GL_RGB, + * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported. + * \param fb_type Type of the pixels in the framebuffer. Currently only + * \c GL_UNSIGNED_SHORT_5_6_5, + * \c GL_UNSIGNED_SHORT_5_6_5_REV, + * \c GL_UNSIGNED_INT_8_8_8_8, and + * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported. + * \param depth_bits Array of depth buffer sizes to be exposed. + * \param stencil_bits Array of stencil buffer sizes to be exposed. + * \param num_depth_stencil_bits Number of entries in both \c depth_bits and + * \c stencil_bits. + * \param db_modes Array of buffer swap modes. If an element has a + * value of \c GLX_NONE, then it represents a + * single-buffered mode. Other valid values are + * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and + * \c GLX_SWAP_UNDEFINED_OML. See the + * GLX_OML_swap_method extension spec for more details. + * \param num_db_modes Number of entries in \c db_modes. + * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or + * \c GLX_DIRECT_COLOR. + * + * \returns + * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only + * cause of failure is a bad parameter (i.e., unsupported \c fb_format or + * \c fb_type). + * + * \todo + * There is currently no way to support packed RGB modes (i.e., modes with + * exactly 3 bytes per pixel) or floating-point modes. This could probably + * be done by creating some new, private enums with clever names likes + * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32, + * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it. + */ +__DRIconfig ** +driCreateConfigs(GLenum fb_format, GLenum fb_type, + const u_int8_t * depth_bits, const u_int8_t * stencil_bits, + unsigned num_depth_stencil_bits, + const GLenum * db_modes, unsigned num_db_modes) +{ + static const u_int8_t bits_table[4][4] = { + /* R G B A */ + { 3, 3, 2, 0 }, /* Any GL_UNSIGNED_BYTE_3_3_2 */ + { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */ + { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */ + { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */ + }; + + static const u_int32_t masks_table_rgb[6][4] = { + { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2 */ + { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV */ + { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */ + { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */ + { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, /* 8_8_8_8 */ + { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 } /* 8_8_8_8_REV */ + }; + + static const u_int32_t masks_table_rgba[6][4] = { + { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2 */ + { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV */ + { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */ + { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */ + { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF }, /* 8_8_8_8 */ + { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, /* 8_8_8_8_REV */ + }; + + static const u_int32_t masks_table_bgr[6][4] = { + { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2 */ + { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV */ + { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */ + { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */ + { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, /* 8_8_8_8 */ + { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, /* 8_8_8_8_REV */ + }; + + static const u_int32_t masks_table_bgra[6][4] = { + { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2 */ + { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV */ + { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */ + { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */ + { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, /* 8_8_8_8 */ + { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, /* 8_8_8_8_REV */ + }; + + static const u_int8_t bytes_per_pixel[6] = { + 1, /* 3_3_2 */ + 1, /* 2_3_3_REV */ + 2, /* 5_6_5 */ + 2, /* 5_6_5_REV */ + 4, /* 8_8_8_8 */ + 4 /* 8_8_8_8_REV */ + }; + + const u_int8_t * bits; + const u_int32_t * masks; + int index; + __DRIconfig **configs, **c; + __GLcontextModes *modes; + unsigned i; + unsigned j; + unsigned k; + unsigned num_modes; + unsigned num_accum_bits = 2; + + switch ( fb_type ) { + case GL_UNSIGNED_BYTE_3_3_2: + index = 0; + break; + case GL_UNSIGNED_BYTE_2_3_3_REV: + index = 1; + break; + case GL_UNSIGNED_SHORT_5_6_5: + index = 2; + break; + case GL_UNSIGNED_SHORT_5_6_5_REV: + index = 3; + break; + case GL_UNSIGNED_INT_8_8_8_8: + index = 4; + break; + case GL_UNSIGNED_INT_8_8_8_8_REV: + index = 5; + break; + default: + fprintf( stderr, "[%s:%d] Unknown framebuffer type 0x%04x.\n", + __FUNCTION__, __LINE__, fb_type ); + return NULL; + } + + + /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and + * the _REV versions. + * + * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA. + */ + + switch ( fb_format ) { + case GL_RGB: + masks = masks_table_rgb[ index ]; + break; + + case GL_RGBA: + masks = masks_table_rgba[ index ]; + break; + + case GL_BGR: + masks = masks_table_bgr[ index ]; + break; + + case GL_BGRA: + masks = masks_table_bgra[ index ]; + break; + + default: + fprintf( stderr, "[%s:%d] Unknown framebuffer format 0x%04x.\n", + __FUNCTION__, __LINE__, fb_format ); + return NULL; + } + + switch ( bytes_per_pixel[ index ] ) { + case 1: + bits = bits_table[0]; + break; + case 2: + bits = bits_table[1]; + break; + default: + bits = ((fb_format == GL_RGB) || (fb_format == GL_BGR)) + ? bits_table[2] + : bits_table[3]; + break; + } + + num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits; + configs = _mesa_calloc((num_modes + 1) * sizeof *configs); + if (configs == NULL) + return NULL; + + c = configs; + for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) { + for ( i = 0 ; i < num_db_modes ; i++ ) { + for ( j = 0 ; j < num_accum_bits ; j++ ) { + *c = _mesa_malloc (sizeof **c); + modes = &(*c)->modes; + c++; + + memset(modes, 0, sizeof *modes); + modes->redBits = bits[0]; + modes->greenBits = bits[1]; + modes->blueBits = bits[2]; + modes->alphaBits = bits[3]; + modes->redMask = masks[0]; + modes->greenMask = masks[1]; + modes->blueMask = masks[2]; + modes->alphaMask = masks[3]; + modes->rgbBits = modes->redBits + modes->greenBits + + modes->blueBits + modes->alphaBits; + + modes->accumRedBits = 16 * j; + modes->accumGreenBits = 16 * j; + modes->accumBlueBits = 16 * j; + modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0; + modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG; + + modes->stencilBits = stencil_bits[k]; + modes->depthBits = depth_bits[k]; + + modes->transparentPixel = GLX_NONE; + modes->transparentRed = GLX_DONT_CARE; + modes->transparentGreen = GLX_DONT_CARE; + modes->transparentBlue = GLX_DONT_CARE; + modes->transparentAlpha = GLX_DONT_CARE; + modes->transparentIndex = GLX_DONT_CARE; + modes->visualType = GLX_DONT_CARE; + modes->renderType = GLX_RGBA_BIT; + modes->drawableType = GLX_WINDOW_BIT; + modes->rgbMode = GL_TRUE; + + if ( db_modes[i] == GLX_NONE ) { + modes->doubleBufferMode = GL_FALSE; + } + else { + modes->doubleBufferMode = GL_TRUE; + modes->swapMethod = db_modes[i]; + } + + modes->haveAccumBuffer = ((modes->accumRedBits + + modes->accumGreenBits + + modes->accumBlueBits + + modes->accumAlphaBits) > 0); + modes->haveDepthBuffer = (modes->depthBits > 0); + modes->haveStencilBuffer = (modes->stencilBits > 0); + + modes->bindToTextureRgb = GL_TRUE; + modes->bindToTextureRgba = GL_TRUE; + modes->bindToMipmapTexture = GL_FALSE; + modes->bindToTextureTargets = modes->rgbMode ? + __DRI_ATTRIB_TEXTURE_1D_BIT | + __DRI_ATTRIB_TEXTURE_2D_BIT | + __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT : + 0; + } + } + } + *c = NULL; + + return configs; +} + +const __DRIconfig **driConcatConfigs(__DRIconfig **a, __DRIconfig **b) +{ + const __DRIconfig **all; + int i, j, index; + + i = 0; + while (a[i] != NULL) + i++; + j = 0; + while (b[j] != NULL) + j++; + + all = _mesa_malloc((i + j + 1) * sizeof *all); + index = 0; + for (i = 0; a[i] != NULL; i++) + all[index++] = a[i]; + for (j = 0; b[j] != NULL; j++) + all[index++] = b[j]; + all[index++] = NULL; + + _mesa_free(a); + _mesa_free(b); + + return all; +} + +#define __ATTRIB(attrib, field) \ + { attrib, offsetof(__GLcontextModes, field) } + +static const struct { unsigned int attrib, offset; } attribMap[] = { + __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), + __ATTRIB(__DRI_ATTRIB_LEVEL, level), + __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), + __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), + __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), + __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), + __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), + __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), + __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), + __ATTRIB(__DRI_ATTRIB_SAMPLES, samples), + __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), + __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), + __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentPixel), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), + __ATTRIB(__DRI_ATTRIB_FLOAT_MODE, floatMode), + __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), + __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), + __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), + __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), + __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), + __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), + __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), + __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), + __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), + __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), + __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), + __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), + __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture), + __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS, bindToTextureTargets), + __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted), + + /* The struct field doesn't matter here, these are handled by the + * switch in driGetConfigAttribIndex. We need them in the array + * so the iterator includes them though.*/ + __ATTRIB(__DRI_ATTRIB_RENDER_TYPE, level), + __ATTRIB(__DRI_ATTRIB_CONFIG_CAVEAT, level), + __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, level) +}; + +#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) + +static int +driGetConfigAttribIndex(const __DRIconfig *config, + unsigned int index, unsigned int *value) +{ + switch (attribMap[index].attrib) { + case __DRI_ATTRIB_RENDER_TYPE: + if (config->modes.rgbMode) + *value = __DRI_ATTRIB_RGBA_BIT; + else + *value = __DRI_ATTRIB_COLOR_INDEX_BIT; + break; + case __DRI_ATTRIB_CONFIG_CAVEAT: + if (config->modes.visualRating == GLX_NON_CONFORMANT_CONFIG) + *value = __DRI_ATTRIB_NON_CONFORMANT_CONFIG; + else if (config->modes.visualRating == GLX_SLOW_CONFIG) + *value = __DRI_ATTRIB_SLOW_BIT; + else + *value = 0; + break; + case __DRI_ATTRIB_SWAP_METHOD: + break; + + case __DRI_ATTRIB_FLOAT_MODE: + *value = config->modes.floatMode; + break; + + default: + *value = *(unsigned int *) + ((char *) &config->modes + attribMap[index].offset); + + break; + } + + return GL_TRUE; +} + +int +driGetConfigAttrib(const __DRIconfig *config, + unsigned int attrib, unsigned int *value) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(attribMap); i++) + if (attribMap[i].attrib == attrib) + return driGetConfigAttribIndex(config, i, value); + + return GL_FALSE; +} + +int +driIndexConfigAttrib(const __DRIconfig *config, int index, + unsigned int *attrib, unsigned int *value) +{ + if (index >= 0 && index < ARRAY_SIZE(attribMap)) { + *attrib = attribMap[index].attrib; + return driGetConfigAttribIndex(config, index, value); + } + + return GL_FALSE; +} diff --git a/src/VBox/Additions/common/crOpenGL/vboxdri_drv.c b/src/VBox/Additions/common/crOpenGL/vboxdri_drv.c new file mode 100644 index 00000000..e82975e3 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/vboxdri_drv.c @@ -0,0 +1,694 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* Minimal swrast-based dri loadable driver. + * + * Todo: + * -- Use malloced (rather than framebuffer) memory for backbuffer + * -- 32bpp is hardwired -- fix + * + * NOTES: + * -- No mechanism for cliprects or resize notification -- + * assumes this is a fullscreen device. + * -- No locking -- assumes this is the only driver accessing this + * device. + * -- Doesn't (yet) make use of any acceleration or other interfaces + * provided by fb. Would be entirely happy working against any + * fullscreen interface. + * -- HOWEVER: only a small number of pixelformats are supported, and + * the mechanism for choosing between them makes some assumptions + * that may not be valid everywhere. + */ + +#include "driver.h" +#include "drm.h" +#include "utils.h" +#include "drirenderbuffer.h" + +#include "buffers.h" +#include "extensions.h" +#include "framebuffer.h" +#include "renderbuffer.h" +#include "vbo/vbo.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" +#include "drivers/common/driverfuncs.h" + +#define need_GL_VERSION_1_3 +#define need_GL_VERSION_1_4 +#define need_GL_VERSION_1_5 +#define need_GL_VERSION_2_0 +#define need_GL_VERSION_2_1 + +/* sw extensions for imaging */ +#define need_GL_EXT_blend_color +#define need_GL_EXT_blend_minmax +#define need_GL_EXT_convolution +#define need_GL_EXT_histogram +#define need_GL_SGI_color_table + +/* sw extensions not associated with some GL version */ +#define need_GL_ARB_shader_objects +#define need_GL_ARB_vertex_program +#define need_GL_APPLE_vertex_array_object +#define need_GL_ATI_fragment_shader +#define need_GL_EXT_depth_bounds_test +#define need_GL_EXT_framebuffer_object +#define need_GL_EXT_framebuffer_blit +#define need_GL_EXT_gpu_program_parameters +#define need_GL_EXT_paletted_texture +#define need_GL_IBM_multimode_draw_arrays +#define need_GL_MESA_resize_buffers +#define need_GL_NV_vertex_program +#define need_GL_NV_fragment_program + +#include "extension_helper.h" + +const struct dri_extension card_extensions[] = +{ + { "GL_VERSION_1_3", GL_VERSION_1_3_functions }, + { "GL_VERSION_1_4", GL_VERSION_1_4_functions }, + { "GL_VERSION_1_5", GL_VERSION_1_5_functions }, + { "GL_VERSION_2_0", GL_VERSION_2_0_functions }, + { "GL_VERSION_2_1", GL_VERSION_2_1_functions }, + + { "GL_EXT_blend_color", GL_EXT_blend_color_functions }, + { "GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions }, + { "GL_EXT_convolution", GL_EXT_convolution_functions }, + { "GL_EXT_histogram", GL_EXT_histogram_functions }, + { "GL_SGI_color_table", GL_SGI_color_table_functions }, + + { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions }, + { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions }, + { "GL_APPLE_vertex_array_object", GL_APPLE_vertex_array_object_functions }, + { "GL_ATI_fragment_shader", GL_ATI_fragment_shader_functions }, + { "GL_EXT_depth_bounds_test", GL_EXT_depth_bounds_test_functions }, + { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions }, + { "GL_EXT_framebuffer_blit", GL_EXT_framebuffer_blit_functions }, + { "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions }, + { "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions }, + { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions }, + { "GL_MESA_resize_buffers", GL_MESA_resize_buffers_functions }, + { "GL_NV_vertex_program", GL_NV_vertex_program_functions }, + { "GL_NV_fragment_program", GL_NV_fragment_program_functions }, + { NULL, NULL } +}; + +void fbSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis); + +typedef struct { + GLcontext *glCtx; /* Mesa context */ + + struct { + __DRIcontextPrivate *context; + __DRIscreenPrivate *screen; + __DRIdrawablePrivate *drawable; /* drawable bound to this ctx */ + } dri; + +} fbContext, *fbContextPtr; + +#define FB_CONTEXT(ctx) ((fbContextPtr)(ctx->DriverCtx)) + + +static const GLubyte * +get_string(GLcontext *ctx, GLenum pname) +{ + (void) ctx; + switch (pname) { + case GL_RENDERER: + return (const GLubyte *) "Mesa dumb framebuffer"; + default: + return NULL; + } +} + + +static void +update_state( GLcontext *ctx, GLuint new_state ) +{ + /* not much to do here - pass it on */ + _swrast_InvalidateState( ctx, new_state ); + _swsetup_InvalidateState( ctx, new_state ); + _vbo_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); +} + + +/** + * Called by ctx->Driver.GetBufferSize from in core Mesa to query the + * current framebuffer size. + */ +static void +get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) +{ + GET_CURRENT_CONTEXT(ctx); + fbContextPtr fbmesa = FB_CONTEXT(ctx); + + *width = fbmesa->dri.drawable->w; + *height = fbmesa->dri.drawable->h; +} + + +static void +updateFramebufferSize(GLcontext *ctx) +{ + fbContextPtr fbmesa = FB_CONTEXT(ctx); + struct gl_framebuffer *fb = ctx->WinSysDrawBuffer; + if (fbmesa->dri.drawable->w != fb->Width || + fbmesa->dri.drawable->h != fb->Height) { + driUpdateFramebufferSize(ctx, fbmesa->dri.drawable); + } +} + +static void +viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) +{ + /* XXX this should be called after we acquire the DRI lock, not here */ + updateFramebufferSize(ctx); +} + + +static void +init_core_functions( struct dd_function_table *functions ) +{ + functions->GetString = get_string; + functions->UpdateState = update_state; + functions->GetBufferSize = get_buffer_size; + functions->Viewport = viewport; + + functions->Clear = _swrast_Clear; /* could accelerate with blits */ +} + + +/* + * Generate code for span functions. + */ + +/* 24-bit BGR */ +#define NAME(PREFIX) PREFIX##_B8G8R8 +#define RB_TYPE GLubyte +#define SPAN_VARS \ + driRenderbuffer *drb = (driRenderbuffer *) rb; +#define INIT_PIXEL_PTR(P, X, Y) \ + GLubyte *P = (GLubyte *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X) * 3; +#define INC_PIXEL_PTR(P) P += 3 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[0] = VALUE[BCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[2] = VALUE[RCOMP] +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = SRC[2]; \ + DST[GCOMP] = SRC[1]; \ + DST[BCOMP] = SRC[0]; \ + DST[ACOMP] = 0xff + +#include "swrast/s_spantemp.h" + + +/* 32-bit BGRA */ +#define NAME(PREFIX) PREFIX##_B8G8R8A8 +#define RB_TYPE GLubyte +#define SPAN_VARS \ + driRenderbuffer *drb = (driRenderbuffer *) rb; +#define INIT_PIXEL_PTR(P, X, Y) \ + GLubyte *P = (GLubyte *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X) * 4; +#define INC_PIXEL_PTR(P) P += 4 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[0] = VALUE[BCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[2] = VALUE[RCOMP]; \ + DST[3] = VALUE[ACOMP] +#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ + DST[0] = VALUE[BCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[2] = VALUE[RCOMP]; \ + DST[3] = 0xff +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = SRC[2]; \ + DST[GCOMP] = SRC[1]; \ + DST[BCOMP] = SRC[0]; \ + DST[ACOMP] = SRC[3] + +#include "swrast/s_spantemp.h" + + +/* 16-bit BGR (XXX implement dithering someday) */ +#define NAME(PREFIX) PREFIX##_B5G6R5 +#define RB_TYPE GLubyte +#define SPAN_VARS \ + driRenderbuffer *drb = (driRenderbuffer *) rb; +#define INIT_PIXEL_PTR(P, X, Y) \ + GLushort *P = (GLushort *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X) * 2; +#define INC_PIXEL_PTR(P) P += 1 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[0] = ( (((VALUE[RCOMP]) & 0xf8) << 8) | (((VALUE[GCOMP]) & 0xfc) << 3) | ((VALUE[BCOMP]) >> 3) ) +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = ( (((SRC[0]) >> 8) & 0xf8) | (((SRC[0]) >> 11) & 0x7) ); \ + DST[GCOMP] = ( (((SRC[0]) >> 3) & 0xfc) | (((SRC[0]) >> 5) & 0x3) ); \ + DST[BCOMP] = ( (((SRC[0]) << 3) & 0xf8) | (((SRC[0]) ) & 0x7) ); \ + DST[ACOMP] = 0xff + +#include "swrast/s_spantemp.h" + + +/* 15-bit BGR (XXX implement dithering someday) */ +#define NAME(PREFIX) PREFIX##_B5G5R5 +#define RB_TYPE GLubyte +#define SPAN_VARS \ + driRenderbuffer *drb = (driRenderbuffer *) rb; +#define INIT_PIXEL_PTR(P, X, Y) \ + GLushort *P = (GLushort *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X) * 2; +#define INC_PIXEL_PTR(P) P += 1 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[0] = ( (((VALUE[RCOMP]) & 0xf8) << 7) | (((VALUE[GCOMP]) & 0xf8) << 2) | ((VALUE[BCOMP]) >> 3) ) +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = ( (((SRC[0]) >> 7) & 0xf8) | (((SRC[0]) >> 10) & 0x7) ); \ + DST[GCOMP] = ( (((SRC[0]) >> 2) & 0xf8) | (((SRC[0]) >> 5) & 0x7) ); \ + DST[BCOMP] = ( (((SRC[0]) << 3) & 0xf8) | (((SRC[0]) ) & 0x7) ); \ + DST[ACOMP] = 0xff + +#include "swrast/s_spantemp.h" + + +/* 8-bit color index */ +#define NAME(PREFIX) PREFIX##_CI8 +#define CI_MODE +#define RB_TYPE GLubyte +#define SPAN_VARS \ + driRenderbuffer *drb = (driRenderbuffer *) rb; +#define INIT_PIXEL_PTR(P, X, Y) \ + GLubyte *P = (GLubyte *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X); +#define INC_PIXEL_PTR(P) P += 1 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + *DST = VALUE[0] +#define FETCH_PIXEL(DST, SRC) \ + DST = SRC[0] + +#include "swrast/s_spantemp.h" + + + +void +fbSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis) +{ + ASSERT(drb->Base.InternalFormat == GL_RGBA); + if (drb->Base.InternalFormat == GL_RGBA) { + if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) { + drb->Base.GetRow = get_row_B5G6R5; + drb->Base.GetValues = get_values_B5G6R5; + drb->Base.PutRow = put_row_B5G6R5; + drb->Base.PutMonoRow = put_mono_row_B5G6R5; + drb->Base.PutRowRGB = put_row_rgb_B5G6R5; + drb->Base.PutValues = put_values_B5G6R5; + drb->Base.PutMonoValues = put_mono_values_B5G6R5; + } + else if (vis->redBits == 5 && vis->greenBits == 5 && vis->blueBits == 5) { + drb->Base.GetRow = get_row_B5G5R5; + drb->Base.GetValues = get_values_B5G5R5; + drb->Base.PutRow = put_row_B5G5R5; + drb->Base.PutMonoRow = put_mono_row_B5G5R5; + drb->Base.PutRowRGB = put_row_rgb_B5G5R5; + drb->Base.PutValues = put_values_B5G5R5; + drb->Base.PutMonoValues = put_mono_values_B5G5R5; + } + else if (vis->redBits == 8 && vis->greenBits == 8 && vis->blueBits == 8 + && vis->alphaBits == 8) { + drb->Base.GetRow = get_row_B8G8R8A8; + drb->Base.GetValues = get_values_B8G8R8A8; + drb->Base.PutRow = put_row_B8G8R8A8; + drb->Base.PutMonoRow = put_mono_row_B8G8R8A8; + drb->Base.PutRowRGB = put_row_rgb_B8G8R8A8; + drb->Base.PutValues = put_values_B8G8R8A8; + drb->Base.PutMonoValues = put_mono_values_B8G8R8A8; + } + else if (vis->redBits == 8 && vis->greenBits == 8 && vis->blueBits == 8 + && vis->alphaBits == 0) { + drb->Base.GetRow = get_row_B8G8R8; + drb->Base.GetValues = get_values_B8G8R8; + drb->Base.PutRow = put_row_B8G8R8; + drb->Base.PutMonoRow = put_mono_row_B8G8R8; + drb->Base.PutRowRGB = put_row_rgb_B8G8R8; + drb->Base.PutValues = put_values_B8G8R8; + drb->Base.PutMonoValues = put_mono_values_B8G8R8; + } + else if (vis->indexBits == 8) { + drb->Base.GetRow = get_row_CI8; + drb->Base.GetValues = get_values_CI8; + drb->Base.PutRow = put_row_CI8; + drb->Base.PutMonoRow = put_mono_row_CI8; + drb->Base.PutValues = put_values_CI8; + drb->Base.PutMonoValues = put_mono_values_CI8; + } + } + else { + /* hardware z/stencil/etc someday */ + } +} + + +static void +fbDestroyScreen( __DRIscreenPrivate *sPriv ) +{ +} + + +static const __DRIconfig **fbFillInModes(unsigned pixel_bits, + unsigned depth_bits, + unsigned stencil_bits, + GLboolean have_back_buffer) +{ + unsigned deep = (depth_bits > 17); + + /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy + * enough to add support. Basically, if a context is created with an + * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping + * will never be used. + */ + + static const GLenum db_modes[2] = { GLX_NONE, GLX_SWAP_UNDEFINED_OML }; + uint8_t depth_bits_array[4]; + uint8_t stencil_bits_array[4]; + if(deep) { + depth_bits_array[0] = 0; + depth_bits_array[1] = 24; + stencil_bits_array[0] = 0; + stencil_bits_array[1] = 8; + } else { + depth_bits_array[0] = depth_bits; + depth_bits_array[1] = 0; + depth_bits_array[2] = depth_bits; + depth_bits_array[3] = 0; + stencil_bits_array[0] = 0; + stencil_bits_array[1] = 0; + stencil_bits_array[2] = 8; + stencil_bits_array[3] = 8; + } + + return driCreateConfigs( + deep ? GL_RGBA : GL_RGB, + deep ? GL_UNSIGNED_INT_8_8_8_8 : GL_UNSIGNED_SHORT_5_6_5, + depth_bits_array, + stencil_bits_array, + deep ? 2 : 4, + db_modes, 2); +} + +/** + * This is the driver specific part of the createNewScreen entry point. + * Called when using legacy DRI. + * + * return the __GLcontextModes supported by this driver + */ +static const __DRIconfig **fbInitScreen(__DRIscreenPrivate *psp) +{ + static const __DRIversion ddx_expected = { 1, 0, 0 }; + static const __DRIversion dri_expected = { 4, 0, 0 }; + static const __DRIversion drm_expected = { 1, 0, 0 }; + + + if ( ! driCheckDriDdxDrmVersions2( "vboxvideo", + & psp->dri_version, & dri_expected, + & psp->ddx_version, & ddx_expected, + & psp->drm_version, & drm_expected ) ) { + return NULL; + } + + driInitExtensions( NULL, card_extensions, GL_FALSE ); + + return fbFillInModes( psp->fbBPP, + (psp->fbBPP == 16) ? 16 : 24, + (psp->fbBPP == 16) ? 0 : 8, + 1); +} + +/* Create the device specific context. + */ +static GLboolean +fbCreateContext( const __GLcontextModes *glVisual, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate) +{ + fbContextPtr fbmesa; + GLcontext *ctx, *shareCtx; + struct dd_function_table functions; + + assert(glVisual); + assert(driContextPriv); + + /* Allocate the Fb context */ + fbmesa = (fbContextPtr) _mesa_calloc( sizeof(*fbmesa) ); + if ( !fbmesa ) + return GL_FALSE; + + /* Init default driver functions then plug in our FBdev-specific functions + */ + _mesa_init_driver_functions(&functions); + init_core_functions(&functions); + + /* Allocate the Mesa context */ + if (sharedContextPrivate) + shareCtx = ((fbContextPtr) sharedContextPrivate)->glCtx; + else + shareCtx = NULL; + + ctx = fbmesa->glCtx = _mesa_create_context(glVisual, shareCtx, + &functions, (void *) fbmesa); + if (!fbmesa->glCtx) { + _mesa_free(fbmesa); + return GL_FALSE; + } + driContextPriv->driverPrivate = fbmesa; + + /* Create module contexts */ + _swrast_CreateContext( ctx ); + _vbo_CreateContext( ctx ); + _tnl_CreateContext( ctx ); + _swsetup_CreateContext( ctx ); + _swsetup_Wakeup( ctx ); + + + /* use default TCL pipeline */ + { + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.RunPipeline = _tnl_run_pipeline; + } + + _mesa_enable_sw_extensions(ctx); + + return GL_TRUE; +} + + +static void +fbDestroyContext( __DRIcontextPrivate *driContextPriv ) +{ + GET_CURRENT_CONTEXT(ctx); + fbContextPtr fbmesa = (fbContextPtr) driContextPriv->driverPrivate; + fbContextPtr current = ctx ? FB_CONTEXT(ctx) : NULL; + + /* check if we're deleting the currently bound context */ + if (fbmesa == current) { + _mesa_make_current(NULL, NULL, NULL); + } + + /* Free fb context resources */ + if ( fbmesa ) { + _swsetup_DestroyContext( fbmesa->glCtx ); + _tnl_DestroyContext( fbmesa->glCtx ); + _vbo_DestroyContext( fbmesa->glCtx ); + _swrast_DestroyContext( fbmesa->glCtx ); + + /* free the Mesa context */ + fbmesa->glCtx->DriverCtx = NULL; + _mesa_destroy_context( fbmesa->glCtx ); + + _mesa_free( fbmesa ); + } +} + + +/* Create and initialize the Mesa and driver specific pixmap buffer + * data. + */ +static GLboolean +fbCreateBuffer( __DRIscreenPrivate *driScrnPriv, + __DRIdrawablePrivate *driDrawPriv, + const __GLcontextModes *mesaVis, + GLboolean isPixmap ) +{ + struct gl_framebuffer *mesa_framebuffer; + + if (isPixmap) { + return GL_FALSE; /* not implemented */ + } + else { + const GLboolean swDepth = mesaVis->depthBits > 0; + const GLboolean swAlpha = mesaVis->alphaBits > 0; + const GLboolean swAccum = mesaVis->accumRedBits > 0; + const GLboolean swStencil = mesaVis->stencilBits > 0; + + mesa_framebuffer = _mesa_create_framebuffer(mesaVis); + if (!mesa_framebuffer) + return 0; + + /* XXX double-check these parameters (bpp vs cpp, etc) */ + { + driRenderbuffer *drb = driNewRenderbuffer(GL_RGBA, + driScrnPriv->pFB, + driScrnPriv->fbBPP / 8, + driScrnPriv->fbOrigin, + driScrnPriv->fbStride, + driDrawPriv); + fbSetSpanFunctions(drb, mesaVis); + _mesa_add_renderbuffer(mesa_framebuffer, + BUFFER_FRONT_LEFT, &drb->Base); + } + if (mesaVis->doubleBufferMode) { + /* XXX what are the correct origin/stride values? */ + GLvoid *backBuf = _mesa_malloc(driScrnPriv->fbStride + * driScrnPriv->fbHeight); + driRenderbuffer *drb = driNewRenderbuffer(GL_RGBA, + backBuf, + driScrnPriv->fbBPP /8, + driScrnPriv->fbOrigin, + driScrnPriv->fbStride, + driDrawPriv); + fbSetSpanFunctions(drb, mesaVis); + _mesa_add_renderbuffer(mesa_framebuffer, + BUFFER_BACK_LEFT, &drb->Base); + } + + _mesa_add_soft_renderbuffers(mesa_framebuffer, + GL_FALSE, /* color */ + swDepth, + swStencil, + swAccum, + swAlpha, /* or always zero? */ + GL_FALSE /* aux */); + + driDrawPriv->driverPrivate = mesa_framebuffer; + + return 1; + } +} + + +static void +fbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) +{ + _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); +} + + + +/* If the backbuffer is on a videocard, this is extraordinarily slow! + */ +static void +fbSwapBuffers( __DRIdrawablePrivate *dPriv ) +{ + struct gl_framebuffer *mesa_framebuffer = (struct gl_framebuffer *)dPriv->driverPrivate; + struct gl_renderbuffer * front_renderbuffer = mesa_framebuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; + void *frontBuffer = front_renderbuffer->Data; + int currentPitch = ((driRenderbuffer *)front_renderbuffer)->pitch; + void *backBuffer = mesa_framebuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer->Data; + + if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { + fbContextPtr fbmesa = (fbContextPtr) dPriv->driContextPriv->driverPrivate; + GLcontext *ctx = fbmesa->glCtx; + + if (ctx->Visual.doubleBufferMode) { + int i; + int offset = 0; + char *tmp = _mesa_malloc(currentPitch); + + _mesa_notifySwapBuffers( ctx ); /* flush pending rendering commands */ + + ASSERT(frontBuffer); + ASSERT(backBuffer); + + for (i = 0; i < dPriv->h; i++) { + _mesa_memcpy(tmp, (char *) backBuffer + offset, + currentPitch); + _mesa_memcpy((char *) frontBuffer + offset, tmp, + currentPitch); + offset += currentPitch; + } + + _mesa_free(tmp); + } + } + else { + /* XXX this shouldn't be an error but we can't handle it for now */ + _mesa_problem(NULL, "fbSwapBuffers: drawable has no context!\n"); + } +} + + +/* Force the context `c' to be the current context and associate with it + * buffer `b'. + */ +static GLboolean +fbMakeCurrent( __DRIcontextPrivate *driContextPriv, + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv ) +{ + if ( driContextPriv ) { + fbContextPtr newFbCtx = + (fbContextPtr) driContextPriv->driverPrivate; + + newFbCtx->dri.drawable = driDrawPriv; + + _mesa_make_current( newFbCtx->glCtx, + driDrawPriv->driverPrivate, + driReadPriv->driverPrivate); + } else { + _mesa_make_current( NULL, NULL, NULL ); + } + + return GL_TRUE; +} + + +/* Force the context `c' to be unbound from its buffer. + */ +static GLboolean +fbUnbindContext( __DRIcontextPrivate *driContextPriv ) +{ + return GL_TRUE; +} + +const struct __DriverAPIRec driDriverAPI = { + .InitScreen = fbInitScreen, + .DestroyScreen = fbDestroyScreen, + .CreateContext = fbCreateContext, + .DestroyContext = fbDestroyContext, + .CreateBuffer = fbCreateBuffer, + .DestroyBuffer = fbDestroyBuffer, + .SwapBuffers = fbSwapBuffers, + .MakeCurrent = fbMakeCurrent, + .UnbindContext = fbUnbindContext, +}; diff --git a/src/VBox/Additions/common/crOpenGL/wgl.c b/src/VBox/Additions/common/crOpenGL/wgl.c new file mode 100644 index 00000000..fd2ea0a3 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/wgl.c @@ -0,0 +1,1015 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_error.h" +#include "cr_spu.h" +#include "cr_environment.h" +#include "cr_mem.h" +#include "stub.h" + +/* I *know* most of the parameters are unused, dammit. */ +#pragma warning( disable: 4100 ) + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <stdio.h> + +#include <iprt/cdefs.h> + +/* Currently host part will misbehave re-creating context with proper visual bits + * if contexts with alternative visual bits is requested. + * For now we just report a superset of all visual bits to avoid that. + * Better to it on the host side as well? + * We could also implement properly multiple pixel formats, + * which should be done by implementing offscreen rendering or multiple host contexts. + * */ +#define VBOX_CROGL_USE_VBITS_SUPERSET + +#ifdef VBOX_CROGL_USE_VBITS_SUPERSET +static GLuint desiredVisual = CR_RGB_BIT | CR_ALPHA_BIT | CR_DEPTH_BIT | CR_STENCIL_BIT | CR_ACCUM_BIT | CR_DOUBLE_BIT; +#else +static GLuint desiredVisual = CR_RGB_BIT; +#endif + +#ifndef VBOX_CROGL_USE_VBITS_SUPERSET +/** + * Compute a mask of CR_*_BIT flags which reflects the attributes of + * the pixel format of the given hdc. + */ +static GLuint ComputeVisBits( HDC hdc ) +{ + PIXELFORMATDESCRIPTOR pfd; + int iPixelFormat; + GLuint b = 0; + + iPixelFormat = GetPixelFormat( hdc ); + + DescribePixelFormat( hdc, iPixelFormat, sizeof(pfd), &pfd ); + + if (pfd.cDepthBits > 0) + b |= CR_DEPTH_BIT; + if (pfd.cAccumBits > 0) + b |= CR_ACCUM_BIT; + if (pfd.cColorBits > 8) + b |= CR_RGB_BIT; + if (pfd.cStencilBits > 0) + b |= CR_STENCIL_BIT; + if (pfd.cAlphaBits > 0) + b |= CR_ALPHA_BIT; + if (pfd.dwFlags & PFD_DOUBLEBUFFER) + b |= CR_DOUBLE_BIT; + if (pfd.dwFlags & PFD_STEREO) + b |= CR_STEREO_BIT; + + return b; +} +#endif + +DECLEXPORT(int) WINAPI wglChoosePixelFormat_prox( HDC hdc, CONST PIXELFORMATDESCRIPTOR *pfd ) +{ + DWORD okayFlags; + + CR_DDI_PROLOGUE(); + + stubInit(); + + /* + * NOTE!!! + * Here we're telling the renderspu not to use the GDI + * equivalent's of ChoosePixelFormat/DescribePixelFormat etc + * There are subtle differences in the use of these calls. + */ + crSetenv("CR_WGL_DO_NOT_USE_GDI", "yes"); + + if ( pfd->nSize != sizeof(*pfd) || pfd->nVersion != 1 ) { + crError( "wglChoosePixelFormat: bad pfd\n" ); + return 0; + } + + okayFlags = ( PFD_DRAW_TO_WINDOW | + PFD_SUPPORT_GDI | + PFD_SUPPORT_OPENGL | + PFD_DOUBLEBUFFER | + PFD_DOUBLEBUFFER_DONTCARE | + PFD_SWAP_EXCHANGE | + PFD_SWAP_COPY | + /** @todo this is disabled due to VSG Open Inventor interop issues + * it does not make any sense actually since reporting this + * as well as choosing a pixel format with this cap would not do anything + * since ICD stuff has its own pixelformat state var */ +// PFD_STEREO | + PFD_STEREO_DONTCARE | + PFD_DEPTH_DONTCARE ); + if ( pfd->dwFlags & ~okayFlags ) { + crWarning( "wglChoosePixelFormat: only support flags=0x%x, but you gave me flags=0x%x", okayFlags, pfd->dwFlags ); + return 0; + } + + if ( pfd->iPixelType != PFD_TYPE_RGBA ) { + crError( "wglChoosePixelFormat: only support RGBA\n" ); + } + + if ( pfd->cColorBits > 32 || + pfd->cRedBits > 8 || + pfd->cGreenBits > 8 || + pfd->cBlueBits > 8 || + pfd->cAlphaBits > 8 ) { + crWarning( "wglChoosePixelFormat: too much color precision requested\n" ); + } + + if ( pfd->dwFlags & PFD_DOUBLEBUFFER ) + desiredVisual |= CR_DOUBLE_BIT; + + if ( pfd->dwFlags & PFD_STEREO ) + desiredVisual |= CR_STEREO_BIT; + + if ( pfd->cColorBits > 8) + desiredVisual |= CR_RGB_BIT; + + if ( pfd->cAccumBits > 0 || + pfd->cAccumRedBits > 0 || + pfd->cAccumGreenBits > 0 || + pfd->cAccumBlueBits > 0 || + pfd->cAccumAlphaBits > 0 ) { + crWarning( "wglChoosePixelFormat: asked for accumulation buffer, ignoring\n" ); + } + + if ( pfd->cAccumBits > 0 ) + desiredVisual |= CR_ACCUM_BIT; + + if ( pfd->cDepthBits > 32 ) { + crError( "wglChoosePixelFormat; asked for too many depth bits\n" ); + } + + if ( pfd->cDepthBits > 0 ) + desiredVisual |= CR_DEPTH_BIT; + + if ( pfd->cStencilBits > 8 ) { + crError( "wglChoosePixelFormat: asked for too many stencil bits\n" ); + } + + if ( pfd->cStencilBits > 0 ) + desiredVisual |= CR_STENCIL_BIT; + + if ( pfd->cAuxBuffers > 0 ) { + crError( "wglChoosePixelFormat: asked for aux buffers\n" ); + } + + if ( pfd->iLayerType != PFD_MAIN_PLANE ) { + crError( "wglChoosePixelFormat: asked for a strange layer\n" ); + } + + return 1; +} + +DECLEXPORT(BOOL) WINAPI wglSetPixelFormat_prox( HDC hdc, int pixelFormat, + CONST PIXELFORMATDESCRIPTOR *pdf ) +{ + CR_DDI_PROLOGUE(); + + if ( pixelFormat != 1 ) { + crError( "wglSetPixelFormat: pixelFormat=%d?\n", pixelFormat ); + } + + return 1; +} + +DECLEXPORT(BOOL) WINAPI wglDeleteContext_prox( HGLRC hglrc ) +{ + CR_DDI_PROLOGUE(); + stubDestroyContext( (unsigned long) hglrc ); + return 1; +} + +DECLEXPORT(BOOL) WINAPI wglMakeCurrent_prox( HDC hdc, HGLRC hglrc ) +{ + ContextInfo *context; + WindowInfo *window; + BOOL ret; + + CR_DDI_PROLOGUE(); + + crHashtableLock(stub.windowTable); + crHashtableLock(stub.contextTable); + + context = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) hglrc); + window = stubGetWindowInfo(hdc); + + if (hglrc!=0 && !context) + { + crWarning("wglMakeCurrent got unexpected hglrc 0x%x", hglrc); + } + + ret = stubMakeCurrent( window, context ); + + crHashtableUnlock(stub.contextTable); + crHashtableUnlock(stub.windowTable); + + return ret; +} + +DECLEXPORT(HGLRC) WINAPI wglGetCurrentContext_prox( void ) +{ + ContextInfo *context = stubGetCurrentContext(); + CR_DDI_PROLOGUE(); + return (HGLRC) (context ? context->id : 0); +} + +DECLEXPORT(HDC) WINAPI wglGetCurrentDC_prox( void ) +{ + ContextInfo *context = stubGetCurrentContext(); + CR_DDI_PROLOGUE(); + if (context && context->currentDrawable) + return (HDC) context->currentDrawable->drawable; + else + return (HDC) NULL; +} + +DECLEXPORT(int) WINAPI wglGetPixelFormat_prox( HDC hdc ) +{ + CR_DDI_PROLOGUE(); + /* this is what we call our generic pixelformat, regardless of the HDC */ + return 1; +} + +DECLEXPORT(int) WINAPI wglDescribePixelFormat_prox( HDC hdc, int pixelFormat, UINT nBytes, + LPPIXELFORMATDESCRIPTOR pfd ) +{ + CR_DDI_PROLOGUE(); + +/* if ( pixelFormat != 1 ) { + * crError( "wglDescribePixelFormat: pixelFormat=%d?\n", pixelFormat ); + * return 0; + * } */ + + if ( !pfd ) { + crWarning( "wglDescribePixelFormat: pfd=NULL\n" ); + return 1; /* There's only one, baby */ + } + + if ( nBytes != sizeof(*pfd) ) { + crWarning( "wglDescribePixelFormat: nBytes=%u?\n", nBytes ); + return 1; /* There's only one, baby */ + } + + pfd->nSize = sizeof(*pfd); + pfd->nVersion = 1; + pfd->dwFlags = ( PFD_DRAW_TO_WINDOW | + PFD_SUPPORT_GDI | + PFD_SUPPORT_OPENGL | + PFD_DOUBLEBUFFER ); + pfd->iPixelType = PFD_TYPE_RGBA; + pfd->cColorBits = 32; + pfd->cRedBits = 8; + pfd->cRedShift = 24; + pfd->cGreenBits = 8; + pfd->cGreenShift = 16; + pfd->cBlueBits = 8; + pfd->cBlueShift = 8; + pfd->cAlphaBits = 8; + pfd->cAlphaShift = 0; + pfd->cAccumBits = 0; + pfd->cAccumRedBits = 0; + pfd->cAccumGreenBits = 0; + pfd->cAccumBlueBits = 0; + pfd->cAccumAlphaBits = 0; + pfd->cDepthBits = 32; + pfd->cStencilBits = 8; + pfd->cAuxBuffers = 0; + pfd->iLayerType = PFD_MAIN_PLANE; + pfd->bReserved = 0; + pfd->dwLayerMask = 0; + pfd->dwVisibleMask = 0; + pfd->dwDamageMask = 0; + + /* the max PFD index */ + return 1; +} + +DECLEXPORT(void) WINAPI VBoxCtxChromiumParameteriCR(HGLRC hglrc, GLenum param, GLint value) +{ + ContextInfo *context; + + CR_DDI_PROLOGUE(); + +// crHashtableLock(stub.windowTable); + crHashtableLock(stub.contextTable); + + context = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) hglrc); + + if (context) + { + stubCtxCheckCreate(context); + stubConChromiumParameteriCR(CR_CTX_CON(context), param, value); + } + else + crWarning("invalid context %#x", hglrc); + + crHashtableUnlock(stub.contextTable); +// crHashtableUnlock(stub.windowTable); +} + +DECLEXPORT(BOOL) WINAPI wglShareLists_prox( HGLRC hglrc1, HGLRC hglrc2 ) +{ + ContextInfo *context1, *context2; + GLint aSpuContexts[2]; + + CR_DDI_PROLOGUE(); + +// crHashtableLock(stub.windowTable); + crHashtableLock(stub.contextTable); + + context1 = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) hglrc1); + + if (!context1) + { + WARN(("invalid hglrc1")); + return FALSE; + } + + stubCtxCheckCreate(context1); + + context2 = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) hglrc2); + + if (!context2) + { + WARN(("invalid hglrc2")); + return FALSE; + } + + stubCtxCheckCreate(context2); + + aSpuContexts[0] = context1->spuContext; + aSpuContexts[1] = context2->spuContext; + + stubConChromiumParametervCR(CR_CTX_CON(context2), GL_SHARE_LISTS_CR, GL_INT, 2, aSpuContexts); + + crHashtableUnlock(stub.contextTable); + + return TRUE; +} + +DECLEXPORT(HGLRC) WINAPI VBoxCreateContext( HDC hdc, struct VBOXUHGSMI *pHgsmi ) +{ + char *dpyName; + ContextInfo *context; + + CR_DDI_PROLOGUE(); + + stubInit(); + + CRASSERT(stub.contextTable); + + dpyName = crCalloc(MAX_DPY_NAME); + if (dpyName) + { + crMemset(dpyName, 0, MAX_DPY_NAME); + sprintf(dpyName, "%p", hdc); + } +#ifndef VBOX_CROGL_USE_VBITS_SUPERSET + if (stub.haveNativeOpenGL) + desiredVisual |= ComputeVisBits( hdc ); +#endif + + context = stubNewContext(dpyName, desiredVisual, UNDECIDED, 0 +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , pHgsmi +#else + , NULL +#endif + ); + /* Not needed any more. */ + crFree(dpyName); + + if (!context) + return 0; + + return (HGLRC) context->id; +} + +DECLEXPORT(GLint) WINAPI VBoxGetWindowId( HDC hdc ) +{ + WindowInfo *window; + GLint winid = 0; + + CR_DDI_PROLOGUE(); + + crHashtableLock(stub.windowTable); + + window = stubGetWindowInfo(hdc); + if (!window) + { + crWarning("stubGetWindowInfo: window not found!"); + goto end; + } + if (!window->spuWindow) + { + crWarning("stubGetWindowInfo: window is null!"); + goto end; + } + + winid = window->spuWindow; + +end: + crHashtableUnlock(stub.windowTable); + return winid; +} + +DECLEXPORT(GLint) WINAPI VBoxGetContextId( HGLRC hglrc ) +{ + ContextInfo *context; + GLint ctxid = 0; + + CR_DDI_PROLOGUE(); + +// crHashtableLock(stub.windowTable); + crHashtableLock(stub.contextTable); + + context = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) hglrc); + if (!context) + { + crWarning("crHashtableSearch: context not found!"); + goto end; + } + + if (context->type != CHROMIUM) + { + crWarning("unexpected context type %d", context->type); + goto end; + } + + if (context->spuContext <= 0) + { + crWarning("no spuSontext defined"); + goto end; + } + + ctxid = context->spuContext; + +end: + crHashtableUnlock(stub.contextTable); + return ctxid; +} + + +DECLEXPORT(HGLRC) WINAPI wglCreateContext_prox( HDC hdc ) +{ + return VBoxCreateContext(hdc, NULL); +} + +DECLEXPORT(void) WINAPI VBoxFlushToHost ( HGLRC hglrc ) +{ + ContextInfo *context; + + CR_DDI_PROLOGUE(); + +// crHashtableLock(stub.windowTable); + crHashtableLock(stub.contextTable); + + context = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) hglrc); + + if (context) + stubConFlush(CR_CTX_CON(context)); + else + crWarning("invalid context %#x", hglrc); + + crHashtableUnlock(stub.contextTable); +// crHashtableUnlock(stub.windowTable); +} + +DECLEXPORT(BOOL) WINAPI +wglSwapBuffers_prox( HDC hdc ) +{ + WindowInfo *window = stubGetWindowInfo(hdc); + CR_DDI_PROLOGUE(); + stubSwapBuffers( window, 0 ); + return 1; +} + +DECLEXPORT(BOOL) WINAPI wglCopyContext_prox( HGLRC src, HGLRC dst, UINT mask ) +{ + CR_DDI_PROLOGUE(); + crWarning( "wglCopyContext: unsupported" ); + return 0; +} + +DECLEXPORT(HGLRC) WINAPI wglCreateLayerContext_prox( HDC hdc, int layerPlane ) +{ + CR_DDI_PROLOGUE(); + stubInit(); + crWarning( "wglCreateLayerContext: unsupported" ); + return 0; +} + +DECLEXPORT(PROC) WINAPI wglGetProcAddress_prox( LPCSTR name ) +{ + CR_DDI_PROLOGUE(); + return (PROC) crGetProcAddress( name ); +} + +DECLEXPORT(BOOL) WINAPI wglUseFontBitmapsA_prox( HDC hdc, DWORD first, DWORD count, DWORD listBase ) +{ + CR_DDI_PROLOGUE(); + crWarning( "wglUseFontBitmapsA: unsupported" ); + return 0; +} + +DECLEXPORT(BOOL) WINAPI wglUseFontBitmapsW_prox( HDC hdc, DWORD first, DWORD count, DWORD listBase ) +{ + CR_DDI_PROLOGUE(); + crWarning( "wglUseFontBitmapsW: unsupported" ); + return 0; +} + +DECLEXPORT(BOOL) WINAPI wglDescribeLayerPlane_prox( HDC hdc, int pixelFormat, int layerPlane, + UINT nBytes, LPLAYERPLANEDESCRIPTOR lpd ) +{ + CR_DDI_PROLOGUE(); + crWarning( "wglDescribeLayerPlane: unimplemented" ); + return 0; +} + +DECLEXPORT(int) WINAPI wglSetLayerPaletteEntries_prox( HDC hdc, int layerPlane, int start, + int entries, CONST COLORREF *cr ) +{ + CR_DDI_PROLOGUE(); + crWarning( "wglSetLayerPaletteEntries: unsupported" ); + return 0; +} + +DECLEXPORT(int) WINAPI wglGetLayerPaletteEntries_prox( HDC hdc, int layerPlane, int start, + int entries, COLORREF *cr ) +{ + CR_DDI_PROLOGUE(); + crWarning( "wglGetLayerPaletteEntries: unsupported" ); + return 0; +} + +DECLEXPORT(BOOL) WINAPI wglRealizeLayerPalette_prox( HDC hdc, int layerPlane, BOOL realize ) +{ + CR_DDI_PROLOGUE(); + crWarning( "wglRealizeLayerPalette: unsupported" ); + return 0; +} + +DECLEXPORT(DWORD) WINAPI wglSwapMultipleBuffers_prox( UINT a, CONST void *b ) +{ + CR_DDI_PROLOGUE(); + crWarning( "wglSwapMultipleBuffer: unsupported" ); + return 0; +} + +DECLEXPORT(BOOL) WINAPI wglUseFontOutlinesA_prox( HDC hdc, DWORD first, DWORD count, DWORD listBase, + FLOAT deviation, FLOAT extrusion, int format, + LPGLYPHMETRICSFLOAT gmf ) +{ + CR_DDI_PROLOGUE(); + crWarning( "wglUseFontOutlinesA: unsupported" ); + return 0; +} + +DECLEXPORT(BOOL) WINAPI wglUseFontOutlinesW_prox( HDC hdc, DWORD first, DWORD count, DWORD listBase, + FLOAT deviation, FLOAT extrusion, int format, + LPGLYPHMETRICSFLOAT gmf ) +{ + CR_DDI_PROLOGUE(); + crWarning( "wglUseFontOutlinesW: unsupported" ); + return 0; +} + +DECLEXPORT(BOOL) WINAPI wglSwapLayerBuffers_prox( HDC hdc, UINT planes ) +{ + CR_DDI_PROLOGUE(); + if (planes == WGL_SWAP_MAIN_PLANE) + { + return wglSwapBuffers_prox(hdc); + } + else + { + crWarning( "wglSwapLayerBuffers: unsupported" ); + return 0; + } +} + +DECLEXPORT(BOOL) WINAPI wglChoosePixelFormatEXT_prox +(HDC hdc, const int *piAttributes, const FLOAT *pfAttributes, UINT nMaxFormats, int *piFormats, UINT *nNumFormats) +{ + int *pi; + int wants_rgb = 0; + + CR_DDI_PROLOGUE(); + + stubInit(); + + /** @todo : Need to check pfAttributes too ! */ + + for ( pi = (int *)piAttributes; *pi != 0; pi++ ) + { + switch ( *pi ) + { + case WGL_COLOR_BITS_EXT: + if (pi[1] > 8) + wants_rgb = 1; + pi++; + break; + + case WGL_RED_BITS_EXT: + case WGL_GREEN_BITS_EXT: + case WGL_BLUE_BITS_EXT: + if (pi[1] > 3) + wants_rgb = 1; + pi++; + break; + + case WGL_ACCUM_ALPHA_BITS_EXT: + case WGL_ALPHA_BITS_EXT: + if (pi[1] > 0) + desiredVisual |= CR_ALPHA_BIT; + pi++; + break; + + case WGL_DOUBLE_BUFFER_EXT: + if (pi[1] > 0) + desiredVisual |= CR_DOUBLE_BIT; + pi++; + break; + + case WGL_STEREO_EXT: + if (pi[1] > 0) + { + /** @todo this is disabled due to VSG Open Inventor interop issues + * it does not make any sense actually since reporting this + * as well as choosing a pixel format with this cap would not do anything + * since ICD stuff has its own pixelformat state var */ + crWarning("WGL_STEREO_EXT not supporteed!"); + return 0; +// desiredVisual |= CR_STEREO_BIT; + } + pi++; + break; + + case WGL_DEPTH_BITS_EXT: + if (pi[1] > 0) + desiredVisual |= CR_DEPTH_BIT; + pi++; + break; + + case WGL_STENCIL_BITS_EXT: + if (pi[1] > 0) + desiredVisual |= CR_STENCIL_BIT; + pi++; + break; + + case WGL_ACCUM_RED_BITS_EXT: + case WGL_ACCUM_GREEN_BITS_EXT: + case WGL_ACCUM_BLUE_BITS_EXT: + if (pi[1] > 0) + desiredVisual |= CR_ACCUM_BIT; + pi++; + break; + + case WGL_SAMPLE_BUFFERS_EXT: + case WGL_SAMPLES_EXT: + if (pi[1] > 0) + { + /** @todo this is disabled due to VSG Open Inventor interop issues + * it does not make any sense actually since reporting this + * as well as choosing a pixel format with this cap would not do anything + * since ICD stuff has its own pixelformat state var */ + crWarning("WGL_SAMPLE_BUFFERS_EXT & WGL_SAMPLES_EXT not supporteed!"); + return 0; +// desiredVisual |= CR_MULTISAMPLE_BIT; + } + pi++; + break; + + case WGL_SUPPORT_OPENGL_ARB: + case WGL_DRAW_TO_WINDOW_ARB: + case WGL_ACCELERATION_ARB: + pi++; + break; + + case WGL_PIXEL_TYPE_ARB: + if(pi[1]!=WGL_TYPE_RGBA_ARB) + { + crWarning("WGL_PIXEL_TYPE 0x%x not supported!", pi[1]); + return 0; + } + pi++; + break; + + default: + crWarning( "wglChoosePixelFormatEXT: bad pi=0x%x", *pi ); + return 0; + } + } + + if (nNumFormats) *nNumFormats = 1; + if (nMaxFormats>0 && piFormats) + { + piFormats[0] = 1; + } + + return 1; +} + +DECLEXPORT(BOOL) WINAPI wglGetPixelFormatAttribivEXT_prox +(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *pValues) +{ + UINT i; + + CR_DDI_PROLOGUE(); + + if (!pValues || !piAttributes) return 0; + + if ((nAttributes!=1) || (piAttributes && piAttributes[0]!=WGL_NUMBER_PIXEL_FORMATS_ARB)) + { + if (iPixelFormat!=1) + { + crDebug("wglGetPixelFormatAttribivARB: bad pf:%i", iPixelFormat); + return 0; + } + } + + for (i=0; i<nAttributes; ++i) + { + switch (piAttributes[i]) + { + case WGL_NUMBER_PIXEL_FORMATS_ARB: + pValues[i] = 1; + break; + case WGL_DRAW_TO_WINDOW_ARB: + case WGL_SUPPORT_OPENGL_ARB: + case WGL_DOUBLE_BUFFER_ARB: + pValues[i] = 1; + break; + case WGL_STEREO_ARB: + /** @todo this is disabled due to VSG Open Inventor interop issues + * it does not make any sense actually since reporting this + * as well as choosing a pixel format with this cap would not do anything + * since ICD stuff has its own pixelformat state var */ + pValues[i] = 0; + break; + case WGL_DRAW_TO_BITMAP_ARB: + case WGL_NEED_PALETTE_ARB: + case WGL_NEED_SYSTEM_PALETTE_ARB: + case WGL_SWAP_LAYER_BUFFERS_ARB: + case WGL_NUMBER_OVERLAYS_ARB: + case WGL_NUMBER_UNDERLAYS_ARB: + case WGL_TRANSPARENT_ARB: + case WGL_TRANSPARENT_RED_VALUE_ARB: + case WGL_TRANSPARENT_GREEN_VALUE_ARB: + case WGL_TRANSPARENT_BLUE_VALUE_ARB: + case WGL_TRANSPARENT_ALPHA_VALUE_ARB: + case WGL_TRANSPARENT_INDEX_VALUE_ARB: + case WGL_SHARE_DEPTH_ARB: + case WGL_SHARE_STENCIL_ARB: + case WGL_SHARE_ACCUM_ARB: + case WGL_SUPPORT_GDI_ARB: + pValues[i] = 0; + break; + case WGL_ACCELERATION_ARB: + pValues[i] = WGL_FULL_ACCELERATION_ARB; + break; + case WGL_SWAP_METHOD_ARB: + pValues[i] = WGL_SWAP_UNDEFINED_ARB; + break; + case WGL_PIXEL_TYPE_ARB: + pValues[i] = WGL_TYPE_RGBA_ARB; + break; + case WGL_COLOR_BITS_ARB: + pValues[i] = 32; + break; + case WGL_RED_BITS_ARB: + case WGL_GREEN_BITS_ARB: + case WGL_BLUE_BITS_ARB: + case WGL_ALPHA_BITS_ARB: + pValues[i] = 8; + break; + case WGL_RED_SHIFT_ARB: + pValues[i] = 24; + break; + case WGL_GREEN_SHIFT_ARB: + pValues[i] = 16; + break; + case WGL_BLUE_SHIFT_ARB: + pValues[i] = 8; + break; + case WGL_ALPHA_SHIFT_ARB: + pValues[i] = 0; + break; + case WGL_ACCUM_BITS_ARB: + pValues[i] = 0; + break; + case WGL_ACCUM_RED_BITS_ARB: + pValues[i] = 0; + break; + case WGL_ACCUM_GREEN_BITS_ARB: + pValues[i] = 0; + break; + case WGL_ACCUM_BLUE_BITS_ARB: + pValues[i] = 0; + break; + case WGL_ACCUM_ALPHA_BITS_ARB: + pValues[i] = 0; + break; + case WGL_DEPTH_BITS_ARB: + pValues[i] = 32; + break; + case WGL_STENCIL_BITS_ARB: + pValues[i] = 8; + break; + case WGL_AUX_BUFFERS_ARB: + pValues[i] = 0; + break; + case WGL_SAMPLE_BUFFERS_EXT: + /** @todo this is disabled due to VSG Open Inventor interop issues + * it does not make any sense actually since reporting this + * as well as choosing a pixel format with this cap would not do anything + * since ICD stuff has its own pixelformat state var */ + pValues[i] = 0; + break; + case WGL_SAMPLES_EXT: + /** @todo this is disabled due to VSG Open Inventor interop issues + * it does not make any sense actually since reporting this + * as well as choosing a pixel format with this cap would not do anything + * since ICD stuff has its own pixelformat state var */ + pValues[i] = 0; + break; + case 0x202d: /* <- WGL_DRAW_TO_PBUFFER_ARB this is to make VSG Open Inventor happy */ + pValues[i] = 0; + break; + default: + crWarning("wglGetPixelFormatAttribivARB: bad attrib=0x%x", piAttributes[i]); + return 0; + } + } + + return 1; +} + +DECLEXPORT(BOOL) WINAPI wglGetPixelFormatAttribfvEXT_prox +(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, float *pValues) +{ + UINT i; + + CR_DDI_PROLOGUE(); + + if (!pValues || !piAttributes) return 0; + + if ((nAttributes!=1) || (piAttributes && piAttributes[0]!=WGL_NUMBER_PIXEL_FORMATS_ARB)) + { + if (iPixelFormat!=1) + { + crDebug("wglGetPixelFormatAttribivARB: bad pf:%i", iPixelFormat); + return 0; + } + } + + for (i=0; i<nAttributes; ++i) + { + switch (piAttributes[i]) + { + case WGL_NUMBER_PIXEL_FORMATS_ARB: + pValues[i] = 1.f; + break; + case WGL_DRAW_TO_WINDOW_ARB: + case WGL_SUPPORT_OPENGL_ARB: + case WGL_DOUBLE_BUFFER_ARB: + pValues[i] = 1.f; + break; + case WGL_STEREO_ARB: + /** @todo this is disabled due to VSG Open Inventor interop issues + * it does not make any sense actually since reporting this + * as well as choosing a pixel format with this cap would not do anything + * since ICD stuff has its own pixelformat state var */ + pValues[i] = 0.f; + break; + case WGL_DRAW_TO_BITMAP_ARB: + case WGL_NEED_PALETTE_ARB: + case WGL_NEED_SYSTEM_PALETTE_ARB: + case WGL_SWAP_LAYER_BUFFERS_ARB: + case WGL_NUMBER_OVERLAYS_ARB: + case WGL_NUMBER_UNDERLAYS_ARB: + case WGL_TRANSPARENT_ARB: + case WGL_TRANSPARENT_RED_VALUE_ARB: + case WGL_TRANSPARENT_GREEN_VALUE_ARB: + case WGL_TRANSPARENT_BLUE_VALUE_ARB: + case WGL_TRANSPARENT_ALPHA_VALUE_ARB: + case WGL_TRANSPARENT_INDEX_VALUE_ARB: + case WGL_SHARE_DEPTH_ARB: + case WGL_SHARE_STENCIL_ARB: + case WGL_SHARE_ACCUM_ARB: + case WGL_SUPPORT_GDI_ARB: + pValues[i] = 0.f; + break; + case WGL_ACCELERATION_ARB: + pValues[i] = WGL_FULL_ACCELERATION_ARB; + break; + case WGL_SWAP_METHOD_ARB: + pValues[i] = WGL_SWAP_UNDEFINED_ARB; + break; + case WGL_PIXEL_TYPE_ARB: + pValues[i] = WGL_TYPE_RGBA_ARB; + break; + case WGL_COLOR_BITS_ARB: + pValues[i] = 32.f; + break; + case WGL_RED_BITS_ARB: + case WGL_GREEN_BITS_ARB: + case WGL_BLUE_BITS_ARB: + case WGL_ALPHA_BITS_ARB: + pValues[i] = 8.f; + break; + case WGL_RED_SHIFT_ARB: + pValues[i] = 24.f; + break; + case WGL_GREEN_SHIFT_ARB: + pValues[i] = 16.f; + break; + case WGL_BLUE_SHIFT_ARB: + pValues[i] = 8.f; + break; + case WGL_ALPHA_SHIFT_ARB: + pValues[i] = 0.f; + break; + case WGL_ACCUM_BITS_ARB: + pValues[i] = 0.f; + break; + case WGL_ACCUM_RED_BITS_ARB: + pValues[i] = 0.f; + break; + case WGL_ACCUM_GREEN_BITS_ARB: + pValues[i] = 0.f; + break; + case WGL_ACCUM_BLUE_BITS_ARB: + pValues[i] = 0.f; + break; + case WGL_ACCUM_ALPHA_BITS_ARB: + pValues[i] = 0.f; + break; + case WGL_DEPTH_BITS_ARB: + pValues[i] = 32.f; + break; + case WGL_STENCIL_BITS_ARB: + pValues[i] = 8.f; + break; + case WGL_AUX_BUFFERS_ARB: + pValues[i] = 0.f; + break; + case WGL_SAMPLE_BUFFERS_EXT: + /** @todo this is disabled due to VSG Open Inventor interop issues + * it does not make any sense actually since reporting this + * as well as choosing a pixel format with this cap would not do anything + * since ICD stuff has its own pixelformat state var */ + pValues[i] = 0.f; + break; + case WGL_SAMPLES_EXT: + /** @todo this is disabled due to VSG Open Inventor interop issues + * it does not make any sense actually since reporting this + * as well as choosing a pixel format with this cap would not do anything + * since ICD stuff has its own pixelformat state var */ + pValues[i] = 0.f; + break; + case 0x202d: /* <- WGL_DRAW_TO_PBUFFER_ARB this is to make VSG Open Inventor happy */ + pValues[i] = 0.f; + break; + default: + crWarning("wglGetPixelFormatAttribivARB: bad attrib=0x%x", piAttributes[i]); + return 0; + } + } + + return 1; +} + +DECLEXPORT(BOOL) WINAPI wglSwapIntervalEXT_prox(int interval) +{ + CR_DDI_PROLOGUE(); + return TRUE; +} + +DECLEXPORT(int) WINAPI wglGetSwapIntervalEXT_prox() +{ + CR_DDI_PROLOGUE(); + return 1; +} + +static GLubyte *gsz_wgl_extensions = "WGL_EXT_pixel_format WGL_ARB_pixel_format WGL_ARB_multisample"; + +DECLEXPORT(const GLubyte *) WINAPI wglGetExtensionsStringEXT_prox() +{ + CR_DDI_PROLOGUE(); + return gsz_wgl_extensions; +} + +DECLEXPORT(const GLubyte *) WINAPI wglGetExtensionsStringARB_prox(HDC hdc) +{ + CR_DDI_PROLOGUE(); + (void) hdc; + + return gsz_wgl_extensions; +} diff --git a/src/VBox/Additions/common/crOpenGL/windows_exports.py b/src/VBox/Additions/common/crOpenGL/windows_exports.py new file mode 100755 index 00000000..974d482e --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/windows_exports.py @@ -0,0 +1,98 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + + +from __future__ import print_function +import sys + +import apiutil + + +def GenerateEntrypoints(): + + apiutil.CopyrightC() + + print('#include "chromium.h"') + print('#include "stub.h"') + print('') + print('#define NAKED __declspec(naked)') + print('#define UNUSED(x) ((void)(x))') + print('') + + + # Get sorted list of dispatched functions. + # The order is very important - it must match cr_opcodes.h + # and spu_dispatch_table.h + keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + + for index in range(len(keys)): + func_name = keys[index] + if apiutil.Category(func_name) == "Chromium": + continue + if apiutil.Category(func_name) == "VBox": + continue + + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + + print("NAKED %s cr_gl%s(%s)" % (return_type, func_name, + apiutil.MakeDeclarationString( params ))) + print("{") + print("\t__asm jmp [glim.%s]" % func_name) + for (name, type, vecSize) in params: + print("\tUNUSED(%s);" % name) + print("}") + print("") + + print('/*') + print('* Aliases') + print('*/') + + # Now loop over all the functions and take care of any aliases + allkeys = apiutil.GetAllFunctions(sys.argv[1]+"/APIspec.txt") + for func_name in allkeys: + if "omit" in apiutil.ChromiumProps(func_name): + continue + + if func_name in keys: + # we already processed this function earlier + continue + + # alias is the function we're aliasing + alias = apiutil.Alias(func_name) + if alias: + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + print("NAKED %s cr_gl%s(%s)" % (return_type, func_name, + apiutil.MakeDeclarationString( params ))) + print("{") + print("\t__asm jmp [glim.%s]" % alias) + for (name, type, vecSize) in params: + print("\tUNUSED(%s);" % name) + print("}") + print("") + + + print('/*') + print('* No-op stubs') + print('*/') + + # Now generate no-op stub functions + for func_name in allkeys: + if "stub" in apiutil.ChromiumProps(func_name): + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + print("NAKED %s cr_gl%s(%s)" % (return_type, func_name, apiutil.MakeDeclarationString(params))) + print("{") + if return_type != "void": + print("return (%s) 0" % return_type) + print("}") + print("") + + + + +GenerateEntrypoints() + diff --git a/src/VBox/Additions/common/crOpenGL/windows_getprocaddress.py b/src/VBox/Additions/common/crOpenGL/windows_getprocaddress.py new file mode 100755 index 00000000..0899d9d9 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/windows_getprocaddress.py @@ -0,0 +1,171 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +import apiutil + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - THIS FILE GENERATED BY THE getprocaddress.py SCRIPT */ +#include "chromium.h" +#include "cr_string.h" +#include "cr_version.h" +#include "stub.h" +#include "icd_drv.h" +#include "cr_gl.h" +#include "cr_error.h" + +#ifdef WINDOWS +#pragma warning( disable: 4055 ) +#endif + +""") + +print(""" +struct name_address { + const char *name; + CR_PROC address; +}; + +PROC WINAPI wglGetProcAddress_prox( LPCSTR name ); + +static struct name_address functions[] = { +""") + + +keys = apiutil.GetAllFunctionsAndOmittedAliases(sys.argv[1]+"/APIspec.txt") +for func_name in keys: + if "Chromium" == apiutil.Category(func_name): + continue + if "VBox" == apiutil.Category(func_name): + continue + if func_name == "BoundsInfoCR": + continue + if "GL_chromium" == apiutil.Category(func_name): + pass #continue + + # alias is the function we're aliasing + proc_name = func_name + if "omit" in apiutil.ChromiumProps(func_name): + alias = apiutil.Alias(func_name) + if alias: + proc_name = alias + + wrap = apiutil.GetCategoryWrapper(func_name) + name = "gl" + func_name + address = "cr_gl" + proc_name + if wrap: + print('#ifdef CR_%s' % wrap) + print('\t{ "%s", (CR_PROC) %s },' % (name, address)) + if wrap: + print('#endif') + + +print("\t/* Chromium binding/glue functions */") + +for func_name in keys: + if (func_name == "Writeback" or + func_name == "BoundsInfoCR" or + func_name == "GetUniformsLocations" or + func_name == "GetAttribsLocations"): + continue + if apiutil.Category(func_name) == "Chromium": + print('\t{ "cr%s", (CR_PROC) cr%s },' % (func_name, func_name)) + +print("\t/* Windows ICD functions */") + +for func_name in ( "CopyContext", + "CreateContext", + "CreateLayerContext", + "DeleteContext", + "DescribeLayerPlane", + "DescribePixelFormat", + "GetLayerPaletteEntries", + "RealizeLayerPalette", + "SetLayerPaletteEntries", + "SetPixelFormat", + "ShareLists", + "SwapBuffers", + "SwapLayerBuffers", + "ReleaseContext", + "SetContext", + "ValidateVersion"): + print('\t{ "Drv%s", (CR_PROC) Drv%s },' % (func_name, func_name)) + +print('\t{ "DrvGetProcAddress", (CR_PROC) wglGetProcAddress_prox },') + +print(""" + { NULL, NULL } +}; + +extern const GLubyte * WINAPI wglGetExtensionsStringEXT_prox(void); +extern const GLubyte * WINAPI wglGetExtensionsStringARB_prox(HDC hdc); +extern BOOL WINAPI wglChoosePixelFormatEXT_prox(HDC hdc, const int *piAttributes, const FLOAT *pfAttributes, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +extern BOOL WINAPI wglGetPixelFormatAttribivEXT_prox(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *pValues); +extern BOOL WINAPI wglGetPixelFormatAttribfvEXT_prox(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, float *pValues); + +BOOL WINAPI wglSwapIntervalEXT(int interval) +{ + return false; +} + +CR_PROC CR_APIENTRY crGetProcAddress( const char *name ) +{ + int i; + wglGetExtensionsStringEXTFunc_t wglGetExtensionsStringEXT = wglGetExtensionsStringEXT_prox; + wglGetExtensionsStringARBFunc_t wglGetExtensionsStringARB = wglGetExtensionsStringARB_prox; + wglChoosePixelFormatEXTFunc_t wglChoosePixelFormatEXT = wglChoosePixelFormatEXT_prox; + wglGetPixelFormatAttribivEXTFunc_t wglGetPixelFormatAttribivEXT = wglGetPixelFormatAttribivEXT_prox; + wglGetPixelFormatAttribfvEXTFunc_t wglGetPixelFormatAttribfvEXT = wglGetPixelFormatAttribfvEXT_prox; + + stubInit(); + + for (i = 0; functions[i].name; i++) { + if (crStrcmp(name, functions[i].name) == 0) { + /*crDebug("crGetProcAddress(%s) returns %p", name, functions[i].address);*/ + return functions[i].address; + } + } + + if (!crStrcmp(name, "wglGetExtensionsStringEXT")) return (CR_PROC) wglGetExtensionsStringEXT; + if (!crStrcmp(name, "wglGetExtensionsStringARB")) return (CR_PROC) wglGetExtensionsStringARB; + + if (!crStrcmp(name, "wglChoosePixelFormatEXT")) return (CR_PROC) wglChoosePixelFormatEXT; + if (!crStrcmp(name, "wglGetPixelFormatAttribivEXT")) return (CR_PROC) wglGetPixelFormatAttribivEXT; + if (!crStrcmp(name, "wglGetPixelFormatAttribfvEXT")) return (CR_PROC) wglGetPixelFormatAttribfvEXT; + + if (!crStrcmp(name, "wglChoosePixelFormatARB")) return (CR_PROC) wglChoosePixelFormatEXT; + if (!crStrcmp(name, "wglGetPixelFormatAttribivARB")) return (CR_PROC) wglGetPixelFormatAttribivEXT; + if (!crStrcmp(name, "wglGetPixelFormatAttribfvARB")) return (CR_PROC) wglGetPixelFormatAttribfvEXT; + + if (!crStrcmp(name, "wglSwapIntervalEXT")) return (CR_PROC) wglSwapIntervalEXT; + + crDebug("Returning GetProcAddress:NULL for %s", name); + return NULL; +} + +""") + + + +# XXX should crGetProcAddress really handle WGL/GLX functions??? +print_foo = """ +/* As these are Windows specific (i.e. wgl), define these now.... */ +#ifdef WINDOWS + { + wglGetExtensionsStringEXTFunc_t wglGetExtensionsStringEXT = NULL; + wglChoosePixelFormatFunc_t wglChoosePixelFormatEXT = NULL; + wglGetPixelFormatAttribivEXTFunc_t wglGetPixelFormatAttribivEXT = NULL; + wglGetPixelFormatAttribfvEXTFunc_t wglGetPixelFormatAttribfvEXT = NULL; + if (!crStrcmp(name, "wglGetExtensionsStringEXT")) return (CR_PROC) wglGetExtensionsStringEXT; + if (!crStrcmp(name, "wglChoosePixelFormatEXT")) return (CR_PROC) wglChoosePixelFormatEXT; + if (!crStrcmp(name, "wglGetPixelFormatAttribivEXT")) return (CR_PROC) wglGetPixelFormatAttribivEXT; + if (!crStrcmp(name, "wglGetPixelFormatAttribfvEXT")) return (CR_PROC) wglGetPixelFormatAttribfvEXT; + } +#endif +""" diff --git a/src/VBox/Additions/common/crOpenGL/windows_i386_exports.py b/src/VBox/Additions/common/crOpenGL/windows_i386_exports.py new file mode 100755 index 00000000..5a4e744e --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/windows_i386_exports.py @@ -0,0 +1,95 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + + +from __future__ import print_function +import sys + +import apiutil + + +def GenerateEntrypoints(): + + #apiutil.CopyrightC() + print('%include "iprt/asmdefs.mac"') + print("") + print("%ifdef RT_ARCH_AMD64") + print("extern glim") + print("%else ; X86") + print("extern _glim") + print("%endif") + print("") + + # Get sorted list of dispatched functions. + # The order is very important - it must match cr_opcodes.h + # and spu_dispatch_table.h + keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + + for index in range(len(keys)): + func_name = keys[index] + if apiutil.Category(func_name) == "Chromium": + continue + if apiutil.Category(func_name) == "VBox": + continue + + print("BEGINPROC_EXPORTED cr_gl%s" % func_name) + print("%ifdef RT_ARCH_AMD64") + print("\tmov \trax, qword glim+%d" % (8*index)) + print("\tjmp \t[rax]") + print("%else ; X86") + print("\tmov \teax, dword _glim+%d" % (4*index)) + print("\tjmp \t[eax]") + print("%endif") + print("ENDPROC cr_gl%s" % func_name) + print("") + + + print(';') + print('; Aliases') + print(';') + + # Now loop over all the functions and take care of any aliases + allkeys = apiutil.GetAllFunctions(sys.argv[1]+"/APIspec.txt") + for func_name in allkeys: + if "omit" in apiutil.ChromiumProps(func_name): + continue + + if func_name in keys: + # we already processed this function earlier + continue + + # alias is the function we're aliasing + alias = apiutil.Alias(func_name) + if alias: + # this dict lookup should never fail (raise an exception)! + index = keys.index(alias) + print("BEGINPROC_EXPORTED cr_gl%s" % func_name) + print("%ifdef RT_ARCH_AMD64") + print("\tmov \trax, qword glim+%d" % (8*index)) + print("\tjmp \t[rax]") + print("%else ; X86") + print("\tmov \teax, dword _glim+%d" % (4*index)) + print("\tjmp \t[eax]") + print("%endif") + print("ENDPROC cr_gl%s" % func_name) + print("") + + + print(';') + print('; No-op stubs') + print(';') + + # Now generate no-op stub functions + for func_name in allkeys: + if "stub" in apiutil.ChromiumProps(func_name): + print("BEGINPROC_EXPORTED cr_gl%s" % func_name) + print("\tleave") + print("\tret") + print("ENDPROC cr_gl%s" % func_name) + print("") + + +GenerateEntrypoints() + diff --git a/src/VBox/Additions/common/crOpenGL/xfont.c b/src/VBox/Additions/common/crOpenGL/xfont.c new file mode 100644 index 00000000..9451fa4a --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/xfont.c @@ -0,0 +1,244 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "chromium.h" +#include "cr_error.h" +#include "cr_mem.h" +#include "stub.h" + +/** code borrowed from Mesa */ + + +/** Fill a BITMAP with a character C from thew current font + in the graphics context GC. WIDTH is the width in bytes + and HEIGHT is the height in bits. + + Note that the generated bitmaps must be used with + + glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE); + glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + + Possible optimizations: + + * use only one reusable pixmap with the maximum dimensions. + * draw the entire font into a single pixmap (careful with + proportional fonts!). +*/ + + +/** + * Generate OpenGL-compatible bitmap. + */ +static void +fill_bitmap(Display *dpy, Window win, GC gc, + unsigned int width, unsigned int height, + int x0, int y0, unsigned int c, GLubyte *bitmap) +{ + XImage *image; + unsigned int x, y; + Pixmap pixmap; + XChar2b char2b; + + pixmap = XCreatePixmap(dpy, win, 8*width, height, 1); + XSetForeground(dpy, gc, 0); + XFillRectangle(dpy, pixmap, gc, 0, 0, 8*width, height); + XSetForeground(dpy, gc, 1); + + char2b.byte1 = (c >> 8) & 0xff; + char2b.byte2 = (c & 0xff); + + XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1); + + image = XGetImage(dpy, pixmap, 0, 0, 8*width, height, 1, XYPixmap); + if (image) { + /* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */ + for (y = 0; y < height; y++) + for (x = 0; x < 8*width; x++) + if (XGetPixel(image, x, y)) + bitmap[width*(height - y - 1) + x/8] |= (1 << (7 - (x % 8))); + XDestroyImage(image); + } + + XFreePixmap(dpy, pixmap); +} + +/* + * determine if a given glyph is valid and return the + * corresponding XCharStruct. + */ +static XCharStruct *isvalid(XFontStruct *fs, unsigned int which) +{ + unsigned int rows, pages; + unsigned int byte1 = 0, byte2 = 0; + int i, valid = 1; + + rows = fs->max_byte1 - fs->min_byte1 + 1; + pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; + + if (rows == 1) { + /* "linear" fonts */ + if ((fs->min_char_or_byte2 > which) || + (fs->max_char_or_byte2 < which)) valid = 0; + } + else { + /* "matrix" fonts */ + byte2 = which & 0xff; + byte1 = which >> 8; + if ((fs->min_char_or_byte2 > byte2) || + (fs->max_char_or_byte2 < byte2) || + (fs->min_byte1 > byte1) || + (fs->max_byte1 < byte1)) valid = 0; + } + + if (valid) { + if (fs->per_char) { + if (rows == 1) { + /* "linear" fonts */ + return fs->per_char + (which-fs->min_char_or_byte2); + } + else { + /* "matrix" fonts */ + i = ((byte1 - fs->min_byte1) * pages) + + (byte2 - fs->min_char_or_byte2); + return fs->per_char + i; + } + } + else { + return &fs->min_bounds; + } + } + return NULL; +} + + +void stubUseXFont( Display *dpy, Font font, int first, int count, int listbase ) +{ + Window win; + Pixmap pixmap; + GC gc; + XGCValues values; + unsigned long valuemask; + XFontStruct *fs; + GLint swapbytes, lsbfirst, rowlength; + GLint skiprows, skippixels, alignment; + unsigned int max_width, max_height, max_bm_width, max_bm_height; + GLubyte *bm; + int i; + + win = RootWindow(dpy, DefaultScreen(dpy)); + + fs = XQueryFont(dpy, font); + if (!fs) { + crWarning("Couldn't get font structure information"); + return; + } + + /* Allocate a bitmap that can fit all characters. */ + max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing; + max_height = fs->max_bounds.ascent + fs->max_bounds.descent; + max_bm_width = (max_width + 7) / 8; + max_bm_height = max_height; + + bm = (GLubyte *) crAlloc((max_bm_width * max_bm_height) * sizeof(GLubyte)); + if (!bm) { + XFreeFontInfo( NULL, fs, 1 ); + crWarning("Couldn't allocate bitmap in glXUseXFont()"); + return; + } + + /* Save the current packing mode for bitmaps. */ + glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes); + glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst); + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength); + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows); + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels); + glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); + + /* Enforce a standard packing mode which is compatible with + fill_bitmap() from above. This is actually the default mode, + except for the (non)alignment. */ + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + pixmap = XCreatePixmap(dpy, win, 10, 10, 1); + values.foreground = BlackPixel(dpy, DefaultScreen (dpy)); + values.background = WhitePixel(dpy, DefaultScreen (dpy)); + values.font = fs->fid; + valuemask = GCForeground | GCBackground | GCFont; + gc = XCreateGC(dpy, pixmap, valuemask, &values); + XFreePixmap(dpy, pixmap); + + for (i = 0; i < count; i++) { + unsigned int width, height, bm_width, bm_height; + GLfloat x0, y0, dx, dy; + XCharStruct *ch; + int x, y; + unsigned int c = first + i; + int list = listbase + i; + int valid; + + /* check on index validity and get the bounds */ + ch = isvalid(fs, c); + if (!ch) { + ch = &fs->max_bounds; + valid = 0; + } + else { + valid = 1; + } + + /* glBitmap()' parameters: + straight from the glXUseXFont(3) manpage. */ + width = ch->rbearing - ch->lbearing; + height = ch->ascent + ch->descent; + x0 = -ch->lbearing; + y0 = ch->descent - 0; /* XXX used to subtract 1 here */ + /* but that caused a conformance failure */ + dx = ch->width; + dy = 0; + + /* X11's starting point. */ + x = -ch->lbearing; + y = ch->ascent; + + /* Round the width to a multiple of eight. We will use this also + for the pixmap for capturing the X11 font. This is slightly + inefficient, but it makes the OpenGL part real easy. */ + bm_width = (width + 7) / 8; + bm_height = height; + + glNewList(list, GL_COMPILE); + if (valid && (bm_width > 0) && (bm_height > 0)) { + crMemset(bm, '\0', bm_width * bm_height); + fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm); + glBitmap(width, height, x0, y0, dx, dy, bm); + } + else { + glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL); + } + glEndList(); + } + + crFree(bm); + XFreeFontInfo(NULL, fs, 1); + XFreeGC(dpy, gc); + + /* Restore saved packing modes. */ + glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes); + glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst); + glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength); + glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels); + glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); +} |